getContainer()->get(InventoryService::class); // Act $records = $inventoryService->getAllInventoryRecords(); // Assert expect($records)->toBeArray(); }); test('getInventoryRecordsByDrinkType returns records for specific drink type', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Create a drink type $drinkType = new DrinkType(); $drinkType->setName('Test Drink Type for Inventory'); $drinkType->setDesiredStock(10); $em->persist($drinkType); $em->flush(); // Create inventory records $record1 = new InventoryRecord(); $record1->setDrinkType($drinkType); $record1->setQuantity(5); $em->persist($record1); $record2 = new InventoryRecord(); $record2->setDrinkType($drinkType); $record2->setQuantity(8); $em->persist($record2); $em->flush(); // Act $records = $inventoryService->getInventoryRecordsByDrinkType($drinkType); // Assert expect($records)->toBeArray(); expect(count($records))->toBeGreaterThanOrEqual(2); expect($records[0])->toBeInstanceOf(InventoryRecord::class); expect($records[0]->getDrinkType()->getId())->toBe($drinkType->getId()); }); test('getLatestInventoryRecord returns latest record for drink type', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Create a drink type $drinkType = new DrinkType(); $drinkType->setName('Test Drink Type for Latest Record'); $drinkType->setDesiredStock(10); $em->persist($drinkType); $em->flush(); // Create inventory records with different timestamps $record1 = new InventoryRecord(); $record1->setDrinkType($drinkType); $record1->setQuantity(5); $record1->setTimestamp(new DateTimeImmutable('-2 days')); $em->persist($record1); $record2 = new InventoryRecord(); $record2->setDrinkType($drinkType); $record2->setQuantity(8); $record2->setTimestamp(new DateTimeImmutable('-1 day')); $em->persist($record2); $record3 = new InventoryRecord(); $record3->setDrinkType($drinkType); $record3->setQuantity(12); $record3->setTimestamp(new DateTimeImmutable()); $em->persist($record3); $em->flush(); // Act $latestRecord = $inventoryService->getLatestInventoryRecord($drinkType); // Assert expect($latestRecord)->toBeInstanceOf(InventoryRecord::class); expect($latestRecord->getDrinkType()->getId())->toBe($drinkType->getId()); expect($latestRecord->getQuantity())->toBe(12); }); test('getLatestInventoryRecord creates new record if none exists', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); $repository = $this->getContainer()->get(InventoryRecordRepository::class); // Create a drink type with no inventory records $drinkType = new DrinkType(); $drinkType->setName('Test Drink Type with No Records'); $drinkType->setDesiredStock(10); $em->persist($drinkType); $em->flush(); // Delete any existing records for this drink type foreach ($repository->findByDrinkType($drinkType) as $record) { $em->remove($record); } $em->flush(); // Act $latestRecord = $inventoryService->getLatestInventoryRecord($drinkType); // Assert expect($latestRecord)->toBeInstanceOf(InventoryRecord::class); expect($latestRecord->getDrinkType()->getId())->toBe($drinkType->getId()); expect($latestRecord->getQuantity())->toBe(0); }); test('getCurrentStockLevel returns correct stock level', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Create a drink type $drinkType = new DrinkType(); $drinkType->setName('Test Drink Type for Stock Level'); $drinkType->setDesiredStock(10); $em->persist($drinkType); $em->flush(); // Create inventory record $record = new InventoryRecord(); $record->setDrinkType($drinkType); $record->setQuantity(15); $em->persist($record); $em->flush(); // Act $stockLevel = $inventoryService->getCurrentStockLevel($drinkType); // Assert expect($stockLevel)->toBe(15); }); test('updateStockLevel creates new inventory record', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Create a drink type $drinkType = new DrinkType(); $drinkType->setName('Test Drink Type for Update'); $drinkType->setDesiredStock(10); $em->persist($drinkType); $em->flush(); $newQuantity = 25; $timestamp = new DateTimeImmutable(); // Act $record = $inventoryService->updateStockLevel($drinkType, $newQuantity, $timestamp); // Assert expect($record)->toBeInstanceOf(InventoryRecord::class); expect($record->getDrinkType()->getId())->toBe($drinkType->getId()); expect($record->getQuantity())->toBe($newQuantity); expect($record->getTimestamp()->getTimestamp())->toBe($timestamp->getTimestamp()); // Verify the stock level was updated $currentLevel = $inventoryService->getCurrentStockLevel($drinkType); expect($currentLevel)->toBe($newQuantity); }); test('getAllDrinkTypesWithStockLevels returns all drink types with stock', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); $drinkTypeRepo = $this->getContainer()->get(DrinkTypeRepository::class); // Create drink types and inventory records $drinkType1 = new DrinkType(); $drinkType1->setName('Drink Type 1 for Stock Levels'); $drinkType1->setDesiredStock(10); $em->persist($drinkType1); $drinkType2 = new DrinkType(); $drinkType2->setName('Drink Type 2 for Stock Levels'); $drinkType2->setDesiredStock(0); // Zero desired stock $em->persist($drinkType2); $em->flush(); // Create inventory records $record1 = new InventoryRecord(); $record1->setDrinkType($drinkType1); $record1->setQuantity(5); $em->persist($record1); $record2 = new InventoryRecord(); $record2->setDrinkType($drinkType2); $record2->setQuantity(8); $em->persist($record2); $em->flush(); // Act - without zero desired stock $stockLevels1 = $inventoryService->getAllDrinkTypesWithStockLevels(false); // Act - with zero desired stock $stockLevels2 = $inventoryService->getAllDrinkTypesWithStockLevels(true); // Assert expect($stockLevels1)->toBeArray(); expect($stockLevels2)->toBeArray(); expect(count($stockLevels2))->toBeGreaterThanOrEqual(count($stockLevels1)); foreach ($stockLevels2 as $stockLevel) { expect($stockLevel)->toBeInstanceOf(DrinkStock::class); expect($stockLevel->record)->toBeInstanceOf(InventoryRecord::class); } }); test('getDrinkStock returns correct DrinkStock object with CRITICAL state', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $configService = $this->getContainer()->get(ConfigurationService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Set low stock multiplier $configService->setConfigValue(SystemSettingKey::STOCK_LOW_MULTIPLIER, '0.3'); // Create a drink type with zero quantity (CRITICAL) $drinkType = new DrinkType(); $drinkType->setName('Critical Stock Drink Type'); $drinkType->setDesiredStock(10); $em->persist($drinkType); $em->flush(); // Create inventory record with zero quantity $record = new InventoryRecord(); $record->setDrinkType($drinkType); $record->setQuantity(0); $em->persist($record); $em->flush(); // Act $drinkStock = $inventoryService->getDrinkStock($drinkType); // Assert expect($drinkStock)->toBeInstanceOf(DrinkStock::class); expect($drinkStock->record->getDrinkType()->getId())->toBe($drinkType->getId()); expect($drinkStock->stock)->toBe(StockState::CRITICAL); }); test('getDrinkStock returns correct DrinkStock object with LOW state', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $configService = $this->getContainer()->get(ConfigurationService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Set low stock multiplier $lowStockMultiplier = 0.3; $configService->setConfigValue(SystemSettingKey::STOCK_LOW_MULTIPLIER, (string) $lowStockMultiplier); // Create a drink type with low quantity $desiredStock = 10; $drinkType = new DrinkType(); $drinkType->setName('Low Stock Drink Type'); $drinkType->setDesiredStock($desiredStock); $em->persist($drinkType); $em->flush(); // Create inventory record with low quantity (between 0 and lowStockMultiplier * desiredStock) $lowQuantity = (int) ($desiredStock * $lowStockMultiplier) - 1; $record = new InventoryRecord(); $record->setDrinkType($drinkType); $record->setQuantity($lowQuantity); $em->persist($record); $em->flush(); // Act $drinkStock = $inventoryService->getDrinkStock($drinkType); // Assert expect($drinkStock)->toBeInstanceOf(DrinkStock::class); expect($drinkStock->record->getDrinkType()->getId())->toBe($drinkType->getId()); expect($drinkStock->stock)->toBe(StockState::LOW); }); test('getDrinkStock returns correct DrinkStock object with NORMAL state', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $configService = $this->getContainer()->get(ConfigurationService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Set low stock multiplier $lowStockMultiplier = 0.3; $configService->setConfigValue(SystemSettingKey::STOCK_LOW_MULTIPLIER, (string) $lowStockMultiplier); // Create a drink type with normal quantity $desiredStock = 10; $drinkType = new DrinkType(); $drinkType->setName('Normal Stock Drink Type'); $drinkType->setDesiredStock($desiredStock); $em->persist($drinkType); $em->flush(); // Create inventory record with normal quantity (between lowStockMultiplier * desiredStock and desiredStock) $normalQuantity = (int) ($desiredStock * $lowStockMultiplier) + 1; $record = new InventoryRecord(); $record->setDrinkType($drinkType); $record->setQuantity($normalQuantity); $em->persist($record); $em->flush(); // Act $drinkStock = $inventoryService->getDrinkStock($drinkType); // Assert expect($drinkStock)->toBeInstanceOf(DrinkStock::class); expect($drinkStock->record->getDrinkType()->getId())->toBe($drinkType->getId()); expect($drinkStock->stock)->toBe(StockState::NORMAL); }); test('getDrinkStock returns correct DrinkStock object with HIGH state', function (): void { // Arrange $inventoryService = $this->getContainer()->get(InventoryService::class); $configService = $this->getContainer()->get(ConfigurationService::class); $em = $this->getContainer()->get(EntityManagerInterface::class); // Set low stock multiplier $configService->setConfigValue(SystemSettingKey::STOCK_LOW_MULTIPLIER, '0.3'); // Create a drink type with high quantity $desiredStock = 10; $drinkType = new DrinkType(); $drinkType->setName('High Stock Drink Type'); $drinkType->setDesiredStock($desiredStock); $em->persist($drinkType); $em->flush(); // Create inventory record with high quantity (greater than desiredStock) $highQuantity = $desiredStock + 1; $record = new InventoryRecord(); $record->setDrinkType($drinkType); $record->setQuantity($highQuantity); $em->persist($record); $em->flush(); // Act $drinkStock = $inventoryService->getDrinkStock($drinkType); // Assert expect($drinkStock)->toBeInstanceOf(DrinkStock::class); expect($drinkStock->record->getDrinkType()->getId())->toBe($drinkType->getId()); expect($drinkStock->stock)->toBe(StockState::HIGH); });