src/Stock/Service/StockService.php line 161

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace App\Stock\Service;
  3. use App\Framework\Exception\ValidationException;
  4. use App\Order\Event\OrderItemsUpdatedEvent;
  5. use App\Product\Entity\Product;
  6. use App\Product\Service\ProductService;
  7. use App\Stock\Entity\StockItem;
  8. use App\Stock\Entity\StockMovement;
  9. use App\Stock\Event\StockChangedEvent;
  10. use App\Stock\Message\ProductOutOfStockEvent;
  11. use App\Stock\Repository\StockItemRepository;
  12. use App\Stock\Repository\StockMovementRepository;
  13. use Doctrine\ORM\ORMException;
  14. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\Messenger\MessageBusInterface;
  17. use Symfony\Component\PropertyAccess\PropertyAccess;
  18. use Symfony\Component\Validator\Validator\ValidatorInterface;
  19. class StockService implements EventSubscriberInterface
  20. {
  21.     private StockItemRepository $repository;
  22.     private StockMovementRepository $stockMovementRepository;
  23.     private EventDispatcherInterface $dispatcher;
  24.     private ValidatorInterface $validator;
  25.     private ProductService $productService;
  26.     private MessageBusInterface $eventBus;
  27.     public function __construct(
  28.         StockItemRepository $repository,
  29.         StockMovementRepository $stockMovementRepository,
  30.         ProductService $productService,
  31.         EventDispatcherInterface $dispatcher,
  32.         ValidatorInterface $validator,
  33.         MessageBusInterface $eventBus
  34.     ) {
  35.         $this->repository $repository;
  36.         $this->stockMovementRepository $stockMovementRepository;
  37.         $this->dispatcher $dispatcher;
  38.         $this->productService $productService;
  39.         $this->validator $validator;
  40.         $this->eventBus $eventBus;
  41.     }
  42.     /**
  43.      * @return array The event names to listen to
  44.      */
  45.     public static function getSubscribedEvents(): array
  46.     {
  47.         return [
  48.             OrderItemsUpdatedEvent::class => 'onOrderItemsUpdated',
  49.             StockChangedEvent::class => 'onStockChanged',
  50.         ];
  51.     }
  52.     /**
  53.      * @throws ORMException
  54.      */
  55.     public function addStock(StockItem $stockItemint $amountstring $comment ''): void
  56.     {
  57.         // Update stock
  58.         $prevStock $stockItem->getCurrentStock();
  59.         $stockItem->setCurrentStock($prevStock $amount);
  60.         // Flush
  61.         $this->repository->flush();
  62.         // Dispatch event
  63.         $this->dispatcher->dispatch(new StockChangedEvent($stockItem$prevStock$prevStock $amount$comment));
  64.     }
  65.     /**
  66.      * @throws ORMException
  67.      */
  68.     public function removeStock(StockItem $stockItemint $amountstring $comment): void
  69.     {
  70.         // Update the stock of the base product
  71.         $prevStock $stockItem->getCurrentStock();
  72.         $stockItem->setCurrentStock($prevStock $amount);
  73.         // Flush
  74.         $this->repository->flush();
  75.         // Dispatch event
  76.         $this->dispatcher->dispatch(new StockChangedEvent($stockItem$prevStock$prevStock $amount$comment));
  77.     }
  78.     /**
  79.      * @return StockItem[]
  80.      */
  81.     public function getStockList(): array
  82.     {
  83.         return $this->repository->findAllSorted();
  84.     }
  85.     public function getStockByProduct(Product $product): ?StockItem
  86.     {
  87.         return $this->repository->findByProductId($product->getId());
  88.     }
  89.     /**
  90.      * @return StockMovement[]
  91.      */
  92.     public function getStockMovementsByProductLastTwelveMonths(Product $product): array {
  93.         return $this->stockMovementRepository->findByProductIdLastTwelveMonths($product->getId());
  94.     }
  95.     public function createFromFields(array $fields): StockItem
  96.     {
  97.         $stockItem = new StockItem();
  98.         $fields array_intersect_key(
  99.             $fields,
  100.             array_flip(['product''minimumStockLevel''stopSellingStockLevel''perishable'])
  101.         );
  102.         $accessor PropertyAccess::createPropertyAccessor();
  103.         foreach ($fields as $key => $value) {
  104.             $accessor->setValue($stockItem$key$value);
  105.         }
  106.         $errors $this->validator->validate($stockItem);
  107.         if (count($errors) > 0) {
  108.             throw new ValidationException($errors);
  109.         }
  110.         $this->repository->add($stockItemtrue);
  111.         return $stockItem;
  112.     }
  113.     public function updateFields(StockItem $stockItem, array $fields): void
  114.     {
  115.         $fields array_intersect_key(
  116.             $fields,
  117.             array_flip(['minimumStockLevel''stopSellingStockLevel''perishable'])
  118.         );
  119.         // Update each modified field
  120.         $accessor PropertyAccess::createPropertyAccessor();
  121.         foreach ($fields as $key => $value) {
  122.             $accessor->setValue($stockItem$key$value);
  123.         }
  124.         $errors $this->validator->validate($stockItem);
  125.         if (count($errors) > 0) {
  126.             throw new ValidationException($errors);
  127.         }
  128.         // flush
  129.         $this->repository->flush();
  130.     }
  131.     public function onOrderItemsUpdated(OrderItemsUpdatedEvent $event): void
  132.     {
  133.         $comment 'Modificación Pedido ' $event->getOrder()->getId();
  134.         $items $event->getVariations();
  135.         foreach ($items as $key => $item) {
  136.             $product $item['product'];
  137.             $variation $item['variation'];
  138.             $stockItem $this->getStockByProduct($product);
  139.             if ($stockItem !== null) {
  140.                 if ($variation 0) {
  141.                     $this->removeStock($stockItem$variation$comment);
  142.                 } else {
  143.                     $this->addStock($stockItem$variation$comment);
  144.                 }
  145.             }
  146.         }
  147.     }
  148.     /**
  149.      * @throws ORMException
  150.      */
  151.     public function onStockChanged(StockChangedEvent $event): void
  152.     {
  153.         // Register the stock movement
  154.         $movement = new StockMovement();
  155.         $movement->setStockItem($event->getStockItem());
  156.         $movement->setBalance($event->getNewStock());
  157.         $movement->setComment($event->getComment());
  158.         $movement->setQuantity($event->getNewStock() - $event->getPreviousStock());
  159.         $this->stockMovementRepository->add($movementtrue);
  160.         // Disable public sale of product if stock goes below a certain level
  161.         $stockItem $event->getStockItem();
  162.         if ($event->getNewStock() < $stockItem->getStopSellingStockLevel()) {
  163.             $this->productService->stopSellingProduct($stockItem->getProduct());
  164.             $this->eventBus->dispatch(new ProductOutOfStockEvent($stockItem->getProduct()->getId()));
  165.         }
  166.     }
  167. }