src/EventSubscriber/Inventory/ShipmentStockMovementSubscriber.php line 31

  1. <?php
  2. namespace App\EventSubscriber\Inventory;
  3. use App\Doctrine\Type\Inventory\MovementType;
  4. use App\Entity\Expediting\Package;
  5. use App\Entity\Inventory\PackageStockEntry;
  6. use App\Entity\Inventory\PackageStockExit;
  7. use App\Entity\Inventory\Warehouse;
  8. use App\Event\Inventory\ShipmentStockEntryEvent;
  9. use App\Event\Inventory\ShipmentStockEventInterface;
  10. use App\Event\Inventory\ShipmentStockExitEvent;
  11. use Doctrine\ORM\EntityManagerInterface;
  12. use DomainException;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. readonly class ShipmentStockMovementSubscriber implements EventSubscriberInterface
  15. {
  16.     public function __construct(
  17.         private EntityManagerInterface $entityManager,
  18.     ) {}
  19.     public static function getSubscribedEvents(): array
  20.     {
  21.         return [
  22.             ShipmentStockEntryEvent::IDENTIFIER => ['handleEntry'0],
  23.             ShipmentStockExitEvent::IDENTIFIER => ['handleExit'0],
  24.         ];
  25.     }
  26.     public function handleEntry(ShipmentStockEventInterface $event): void
  27.     {
  28.         $this->processMovements($eventMovementType::ENTRY);
  29.     }
  30.     public function handleExit(ShipmentStockEventInterface $event): void
  31.     {
  32.         $this->processMovements($eventMovementType::EXIT);
  33.     }
  34.     private function processMovements(ShipmentStockEventInterface $eventMovementType $movementType): void
  35.     {
  36.         $shippingSegment $event->getShippingSegment();
  37.         $warehouse MovementType::ENTRY === $movementType
  38.             $shippingSegment->getPlaceOfDischarge()
  39.             : $shippingSegment->getPlaceOfLoading();
  40.         foreach ($shippingSegment->getShippingPlan()->getPackages() as $package) {
  41.             $entity MovementType::ENTRY === $movementType
  42.                 ? new PackageStockEntry()
  43.                 : new PackageStockExit();
  44.             $entity
  45.                 ->setPackage($package)
  46.                 ->setWarehouse($warehouse)
  47.                 ->setShippingSegment($shippingSegment)
  48.                 ->setCompletedAt($event->getCompletedOn());
  49.              // Before persisting, we need to correctly associate all Exits with the corresponding Entries
  50.             if (MovementType::EXIT === $movementType) {
  51.                 $stockEntry $this->getPackageStockEntry($package$warehouse);
  52.                 $entity->setStockEntry($stockEntry);
  53.             }
  54.             $this->entityManager->persist($entity);
  55.         }
  56.         $this->entityManager->flush();
  57.     }
  58.     private function getPackageStockEntry(Package $packageWarehouse $warehouse): PackageStockEntry
  59.     {
  60.         foreach ($package->getMovements() as $movement) {
  61.             if (
  62.                 $movement instanceof PackageStockEntry &&
  63.                 $movement->getWarehouse() === $warehouse
  64.             ) {
  65.                 if ($movement->getStockExit() instanceof PackageStockExit) {
  66.                     throw new DomainException('Last stock entry is already associated with a stock exit.');
  67.                 }
  68.                 return $movement;
  69.             }
  70.         }
  71.         throw new DomainException('No stock entry found for stock exit.');
  72.     }
  73. }