mep
This commit is contained in:
parent
e958163a4a
commit
b8a5a1ff58
79 changed files with 15113 additions and 0 deletions
374
tests/Feature/Service/OrderServiceTest.php
Normal file
374
tests/Feature/Service/OrderServiceTest.php
Normal file
|
@ -0,0 +1,374 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\Service;
|
||||
|
||||
use Override;
|
||||
use Tests\TestCase;
|
||||
use App\Entity\DrinkType;
|
||||
use App\Entity\Order;
|
||||
use App\Entity\OrderItem;
|
||||
use App\Service\OrderService;
|
||||
use App\Repository\DrinkTypeRepository;
|
||||
use App\Repository\OrderRepository;
|
||||
use App\Repository\OrderItemRepository;
|
||||
use App\Service\InventoryService;
|
||||
use App\Service\ConfigurationService;
|
||||
use App\Enum\SystemSettingKey;
|
||||
use DateTimeImmutable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class OrderServiceTest extends TestCase
|
||||
{
|
||||
private OrderService $service;
|
||||
private OrderRepository $orderRepository;
|
||||
private OrderItemRepository $orderItemRepository;
|
||||
private DrinkTypeRepository $drinkTypeRepository;
|
||||
private InventoryService $inventoryService;
|
||||
private ConfigurationService $configService;
|
||||
private DrinkType $drinkType;
|
||||
|
||||
#[Override]
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->setUpDB();
|
||||
$this->orderRepository = $this->container->get(OrderRepository::class);
|
||||
$this->orderItemRepository = $this->container->get(OrderItemRepository::class);
|
||||
$this->drinkTypeRepository = $this->container->get(DrinkTypeRepository::class);
|
||||
$this->inventoryService = $this->container->get(InventoryService::class);
|
||||
$this->configService = $this->container->get(ConfigurationService::class);
|
||||
$this->service = $this->container->get(OrderService::class);
|
||||
|
||||
// Create a drink type for testing
|
||||
$this->drinkType = new DrinkType('Cola', 'Refreshing cola drink', 10);
|
||||
$this->drinkTypeRepository->save($this->drinkType);
|
||||
}
|
||||
|
||||
public function testGetAllOrders(): void
|
||||
{
|
||||
// Initially the repository should be empty
|
||||
$this->assertCount(0, $this->service->getAllOrders());
|
||||
|
||||
// Create some orders
|
||||
$order1 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-01'));
|
||||
$order2 = new Order(Order::STATUS_FULFILLED, new DateTimeImmutable('2023-01-02'));
|
||||
$this->orderRepository->save($order1);
|
||||
$this->orderRepository->save($order2);
|
||||
|
||||
// Now getAllOrders should return both orders
|
||||
$orders = $this->service->getAllOrders();
|
||||
$this->assertCount(2, $orders);
|
||||
$this->assertContainsOnlyInstancesOf(Order::class, $orders);
|
||||
}
|
||||
|
||||
public function testGetOrderById(): void
|
||||
{
|
||||
// Create an order
|
||||
$order = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-01'));
|
||||
$this->orderRepository->save($order);
|
||||
|
||||
// Get the ID
|
||||
$id = $order->getId();
|
||||
$this->assertNotNull($id);
|
||||
|
||||
// Find by ID
|
||||
$foundOrder = $this->service->getOrderById($id);
|
||||
$this->assertInstanceOf(Order::class, $foundOrder);
|
||||
$this->assertEquals(Order::STATUS_NEW, $foundOrder->getStatus());
|
||||
$this->assertEquals('2023-01-01', $foundOrder->getCreatedAt()->format('Y-m-d'));
|
||||
|
||||
// Try to find a non-existent ID
|
||||
$nonExistentId = 9999;
|
||||
$this->assertNull($this->service->getOrderById($nonExistentId));
|
||||
}
|
||||
|
||||
public function testGetOrdersByStatus(): void
|
||||
{
|
||||
// Create orders with different statuses
|
||||
$order1 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-01'));
|
||||
$order2 = new Order(Order::STATUS_IN_WORK, new DateTimeImmutable('2023-01-02'));
|
||||
$order3 = new Order(Order::STATUS_ORDERED, new DateTimeImmutable('2023-01-03'));
|
||||
$order4 = new Order(Order::STATUS_FULFILLED, new DateTimeImmutable('2023-01-04'));
|
||||
$order5 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-05'));
|
||||
$this->orderRepository->save($order1);
|
||||
$this->orderRepository->save($order2);
|
||||
$this->orderRepository->save($order3);
|
||||
$this->orderRepository->save($order4);
|
||||
$this->orderRepository->save($order5);
|
||||
|
||||
// Get orders by status
|
||||
$newOrders = $this->service->getOrdersByStatus(Order::STATUS_NEW);
|
||||
$this->assertCount(2, $newOrders);
|
||||
$this->assertContainsOnlyInstancesOf(Order::class, $newOrders);
|
||||
|
||||
// Check that the orders have the correct status
|
||||
foreach ($newOrders as $order) {
|
||||
$this->assertEquals(Order::STATUS_NEW, $order->getStatus());
|
||||
}
|
||||
|
||||
// Get orders by another status
|
||||
$fulfilledOrders = $this->service->getOrdersByStatus(Order::STATUS_FULFILLED);
|
||||
$this->assertCount(1, $fulfilledOrders);
|
||||
$this->assertEquals(Order::STATUS_FULFILLED, $fulfilledOrders[0]->getStatus());
|
||||
}
|
||||
|
||||
public function testGetOrdersByDateRange(): void
|
||||
{
|
||||
// Create orders with different dates
|
||||
$order1 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-01'));
|
||||
$order2 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-02'));
|
||||
$order3 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-03'));
|
||||
$order4 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-04'));
|
||||
$order5 = new Order(Order::STATUS_NEW, new DateTimeImmutable('2023-01-05'));
|
||||
$this->orderRepository->save($order1);
|
||||
$this->orderRepository->save($order2);
|
||||
$this->orderRepository->save($order3);
|
||||
$this->orderRepository->save($order4);
|
||||
$this->orderRepository->save($order5);
|
||||
|
||||
// Get orders in a specific date range
|
||||
$start = new DateTimeImmutable('2023-01-02');
|
||||
$end = new DateTimeImmutable('2023-01-04');
|
||||
$orders = $this->service->getOrdersByDateRange($start, $end);
|
||||
|
||||
$this->assertCount(3, $orders);
|
||||
|
||||
// Check that the orders are within the date range
|
||||
foreach ($orders as $order) {
|
||||
$createdAt = $order->getCreatedAt();
|
||||
$this->assertTrue($createdAt >= $start && $createdAt <= $end);
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreateOrder(): void
|
||||
{
|
||||
// Create an order with items
|
||||
$items = [
|
||||
['drinkTypeId' => $this->drinkType->getId(), 'quantity' => 5],
|
||||
];
|
||||
$order = $this->service->createOrder($items);
|
||||
|
||||
// Check that the order was created correctly
|
||||
$this->assertInstanceOf(Order::class, $order);
|
||||
$this->assertEquals(Order::STATUS_NEW, $order->getStatus());
|
||||
|
||||
// Refresh the order from the database
|
||||
$refreshedOrder = $this->service->getOrderById($order->getId());
|
||||
$this->assertInstanceOf(Order::class, $refreshedOrder);
|
||||
|
||||
// Check that the order items were created correctly
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(1, $orderItems);
|
||||
$orderItem = $orderItems->first();
|
||||
$this->assertEquals($this->drinkType->getId(), $orderItem->getDrinkType()->getId());
|
||||
$this->assertEquals(5, $orderItem->getQuantity());
|
||||
|
||||
// Try to create an order with an invalid drink type ID
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->service->createOrder([['drinkTypeId' => 9999, 'quantity' => 5]]);
|
||||
}
|
||||
|
||||
public function testCreateOrderFromStockLevels(): void
|
||||
{
|
||||
// Set the low stock threshold to 70% so that 3/5 (60%) is considered low stock
|
||||
$this->configService->setConfigValue(SystemSettingKey::LOW_STOCK_THRESHOLD->value, '70');
|
||||
|
||||
// Create a drink type with low stock
|
||||
$drinkType = new DrinkType('Fanta', 'Orange soda', 5);
|
||||
$this->drinkTypeRepository->save($drinkType);
|
||||
|
||||
// Create inventory records
|
||||
$this->inventoryService->updateStockLevel($this->drinkType, 15); // Excess stock
|
||||
$this->inventoryService->updateStockLevel($drinkType, 3); // Low stock
|
||||
|
||||
// Create an order from stock levels
|
||||
$order = $this->service->createOrderFromStockLevels();
|
||||
|
||||
// Check that the order was created correctly
|
||||
$this->assertInstanceOf(Order::class, $order);
|
||||
$this->assertEquals(Order::STATUS_NEW, $order->getStatus());
|
||||
|
||||
// Refresh the order from the database
|
||||
$refreshedOrder = $this->service->getOrderById($order->getId());
|
||||
$this->assertInstanceOf(Order::class, $refreshedOrder);
|
||||
|
||||
// Check that the order items were created correctly
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(1, $orderItems); // Only one drink type has low stock
|
||||
$orderItem = $orderItems->first();
|
||||
$this->assertEquals($drinkType->getId(), $orderItem->getDrinkType()->getId());
|
||||
$this->assertEquals(2, $orderItem->getQuantity()); // Shortage is 2
|
||||
}
|
||||
|
||||
public function testUpdateOrderStatus(): void
|
||||
{
|
||||
// Create an order
|
||||
$order = new Order(Order::STATUS_NEW);
|
||||
$this->orderRepository->save($order);
|
||||
|
||||
// Update the status
|
||||
$updatedOrder = $this->service->updateOrderStatus($order, Order::STATUS_IN_WORK);
|
||||
$this->assertEquals(Order::STATUS_IN_WORK, $updatedOrder->getStatus());
|
||||
|
||||
// Check that it was updated in the database
|
||||
$foundOrder = $this->service->getOrderById($order->getId());
|
||||
$this->assertEquals(Order::STATUS_IN_WORK, $foundOrder->getStatus());
|
||||
|
||||
// Update to fulfilled status
|
||||
$orderItem = new OrderItem($this->drinkType, 5, $foundOrder);
|
||||
$this->orderItemRepository->save($orderItem);
|
||||
|
||||
// Refresh the order from the database
|
||||
$refreshedOrder = $this->service->getOrderById($foundOrder->getId());
|
||||
$this->assertInstanceOf(Order::class, $refreshedOrder);
|
||||
$this->assertCount(1, $refreshedOrder->getOrderItems());
|
||||
|
||||
// Create an initial inventory record with a specific timestamp
|
||||
$timestamp1 = new DateTimeImmutable('2023-01-01 10:00:00');
|
||||
$this->inventoryService->updateStockLevel($this->drinkType, 10, $timestamp1);
|
||||
|
||||
// Update the status to fulfilled
|
||||
$updatedOrder = $this->service->updateOrderStatus($refreshedOrder, Order::STATUS_FULFILLED);
|
||||
$this->assertEquals(Order::STATUS_FULFILLED, $updatedOrder->getStatus());
|
||||
|
||||
// Check that the inventory was updated with a new record that has a later timestamp
|
||||
$currentStock = $this->inventoryService->getCurrentStockLevel($this->drinkType);
|
||||
$this->assertEquals(15, $currentStock); // 10 + 5 = 15
|
||||
|
||||
// Try to update to an invalid status
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->service->updateOrderStatus($updatedOrder, 'invalid_status');
|
||||
}
|
||||
|
||||
public function testAddOrderItem(): void
|
||||
{
|
||||
// Create an order
|
||||
$order = new Order(Order::STATUS_NEW);
|
||||
$this->orderRepository->save($order);
|
||||
|
||||
// Add an item
|
||||
$orderItem = $this->service->addOrderItem($order, $this->drinkType, 5);
|
||||
|
||||
// Check that the item was added correctly
|
||||
$this->assertInstanceOf(OrderItem::class, $orderItem);
|
||||
$this->assertEquals($this->drinkType->getId(), $orderItem->getDrinkType()->getId());
|
||||
$this->assertEquals(5, $orderItem->getQuantity());
|
||||
$this->assertEquals($order->getId(), $orderItem->getOrder()->getId());
|
||||
|
||||
// Refresh the order from the database
|
||||
$refreshedOrder = $this->service->getOrderById($order->getId());
|
||||
$this->assertInstanceOf(Order::class, $refreshedOrder);
|
||||
|
||||
// Check that the item is in the order
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(1, $orderItems);
|
||||
$this->assertEquals($orderItem->getId(), $orderItems->first()->getId());
|
||||
|
||||
// Add another item for the same drink type
|
||||
$orderItem2 = $this->service->addOrderItem($refreshedOrder, $this->drinkType, 3);
|
||||
|
||||
// Check that the quantity was updated
|
||||
$this->assertEquals(8, $orderItem2->getQuantity()); // 5 + 3 = 8
|
||||
|
||||
// Refresh the order again
|
||||
$refreshedOrder = $this->service->getOrderById($refreshedOrder->getId());
|
||||
|
||||
// Check that there's still only one item in the order
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(1, $orderItems);
|
||||
|
||||
// Create another drink type
|
||||
$anotherDrinkType = new DrinkType('Fanta', 'Orange soda', 5);
|
||||
$this->drinkTypeRepository->save($anotherDrinkType);
|
||||
|
||||
// Add an item for the new drink type
|
||||
$orderItem3 = $this->service->addOrderItem($refreshedOrder, $anotherDrinkType, 2);
|
||||
|
||||
// Check that the item was added correctly
|
||||
$this->assertInstanceOf(OrderItem::class, $orderItem3);
|
||||
$this->assertEquals($anotherDrinkType->getId(), $orderItem3->getDrinkType()->getId());
|
||||
$this->assertEquals(2, $orderItem3->getQuantity());
|
||||
|
||||
// Refresh the order again
|
||||
$refreshedOrder = $this->service->getOrderById($refreshedOrder->getId());
|
||||
|
||||
// Check that there are now two items in the order
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(2, $orderItems);
|
||||
|
||||
// Try to add an item to an order that's not in 'new' or 'in_work' status
|
||||
$refreshedOrder->setStatus(Order::STATUS_ORDERED);
|
||||
$this->orderRepository->save($refreshedOrder);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->service->addOrderItem($refreshedOrder, $this->drinkType, 1);
|
||||
}
|
||||
|
||||
public function testRemoveOrderItem(): void
|
||||
{
|
||||
// Create an order
|
||||
$order = new Order(Order::STATUS_NEW);
|
||||
$this->orderRepository->save($order);
|
||||
|
||||
// Add an item
|
||||
$orderItem = $this->service->addOrderItem($order, $this->drinkType, 5);
|
||||
|
||||
// Refresh the order from the database
|
||||
$refreshedOrder = $this->service->getOrderById($order->getId());
|
||||
$this->assertInstanceOf(Order::class, $refreshedOrder);
|
||||
|
||||
// Check that the item is in the order
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(1, $orderItems);
|
||||
$this->assertEquals($orderItem->getId(), $orderItems->first()->getId());
|
||||
|
||||
// Remove the item
|
||||
$this->service->removeOrderItem($refreshedOrder, $orderItem);
|
||||
|
||||
// Refresh the order again
|
||||
$refreshedOrder = $this->service->getOrderById($refreshedOrder->getId());
|
||||
|
||||
// Check that the item is gone
|
||||
$orderItems = $refreshedOrder->getOrderItems();
|
||||
$this->assertCount(0, $orderItems);
|
||||
|
||||
// Try to remove an item from an order that's not in 'new' or 'in_work' status
|
||||
$refreshedOrder->setStatus(Order::STATUS_ORDERED);
|
||||
$this->orderRepository->save($refreshedOrder);
|
||||
|
||||
$orderItem = new OrderItem($this->drinkType, 5, $refreshedOrder);
|
||||
$this->orderItemRepository->save($orderItem);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->service->removeOrderItem($refreshedOrder, $orderItem);
|
||||
}
|
||||
|
||||
public function testDeleteOrder(): void
|
||||
{
|
||||
// Create an order
|
||||
$order = new Order(Order::STATUS_NEW);
|
||||
$this->orderRepository->save($order);
|
||||
|
||||
// Get the ID
|
||||
$id = $order->getId();
|
||||
$this->assertNotNull($id);
|
||||
|
||||
// Check that it exists
|
||||
$this->assertInstanceOf(Order::class, $this->service->getOrderById($id));
|
||||
|
||||
// Delete it
|
||||
$this->service->deleteOrder($order);
|
||||
|
||||
// Check that it's gone
|
||||
$this->assertNull($this->service->getOrderById($id));
|
||||
|
||||
// Try to delete an order that's not in 'new' status
|
||||
$order = new Order(Order::STATUS_IN_WORK);
|
||||
$this->orderRepository->save($order);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->service->deleteOrder($order);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue