Array of stock adjustment proposals */ public function proposeStockAdjustments(): array { $drinkTypes = $this->drinkTypeRepository->findAll(); $proposals = []; foreach ($drinkTypes as $drinkType) { $proposals[] = $this->proposeStockAdjustmentForDrinkType($drinkType); } return $proposals; } /** * Proposes an adjusted stock level for a specific drink type */ public function proposeStockAdjustmentForDrinkType(DrinkType $drinkType): StockAdjustmentProposal { $currentDesiredStock = $drinkType->getDesiredStock(); $lookbackOrders = (int) $this->systemConfigRepository->getValue(SystemSettingKey::STOCK_ADJUSTMENT_LOOKBACK_ORDERS); $increaseAmount = (int) $this->systemConfigRepository->getValue(SystemSettingKey::STOCK_INCREASE_AMOUNT); $decreaseAmount = (int) $this->systemConfigRepository->getValue(SystemSettingKey::STOCK_DECREASE_AMOUNT); // Get the last N orders for this drink type $lastOrders = $this->orderRepository->findLastOrdersForDrinkType($drinkType, $lookbackOrders); // If there are no orders, return the current desired stock if ($lastOrders === []) { return new StockAdjustmentProposal($drinkType, $currentDesiredStock); } // Check if stock was 0 in the last order $lastOrder = $lastOrders[0]; $lastOrderItems = $lastOrder->getOrderItems(); $stockWasZeroInLastOrder = false; foreach ($lastOrderItems as $orderItem) { if ($orderItem->getDrinkType()->getId() === $drinkType->getId()) { // Find the inventory record closest to the order creation date $inventoryRecords = $this->inventoryRecordRepository->findByDrinkType($drinkType); foreach ($inventoryRecords as $record) { if ($record->getTimestamp() <= $lastOrder->getCreatedAt()) { if ($record->getQuantity() === 0) { $stockWasZeroInLastOrder = true; } break; } } break; } } // If stock was 0 in the last order, increase desired stock if ($stockWasZeroInLastOrder) { return new StockAdjustmentProposal($drinkType, $currentDesiredStock + $increaseAmount); } // Check if stock was above zero in all lookback orders $stockWasAboveZeroInAllOrders = true; $ordersToCheck = min(count($lastOrders), $lookbackOrders); for ($i = 0; $i < $ordersToCheck; $i++) { $order = $lastOrders[$i]; $orderItems = $order->getOrderItems(); foreach ($orderItems as $orderItem) { if ($orderItem->getDrinkType()->getId() === $drinkType->getId()) { // Find the inventory record closest to the order creation date $inventoryRecords = $this->inventoryRecordRepository->findByDrinkType($drinkType); foreach ($inventoryRecords as $record) { if ($record->getTimestamp() <= $order->getCreatedAt()) { if ($record->getQuantity() === 0) { $stockWasAboveZeroInAllOrders = false; } break; } } break; } } if (!$stockWasAboveZeroInAllOrders) { break; } } // If stock was above zero in all lookback orders, decrease desired stock if ($stockWasAboveZeroInAllOrders && $ordersToCheck === $lookbackOrders) { $proposedStock = max(0, $currentDesiredStock - $decreaseAmount); return new StockAdjustmentProposal($drinkType, $proposedStock); } // Otherwise, keep the current desired stock return new StockAdjustmentProposal($drinkType, $currentDesiredStock); } }