src/EventSubscriber/Finance/Quotation/QuotationStatusSubscriber.php line 34

  1. <?php
  2. namespace App\EventSubscriber\Finance\Quotation;
  3. use App\Doctrine\Type\Expediting\ShippingPlanStatus;
  4. use App\Doctrine\Type\Expediting\ShippingSegmentStatus;
  5. use App\Doctrine\Type\Finance\PayableStatus;
  6. use App\Doctrine\Type\Scheduler\TaskStatus;
  7. use App\Entity\Finance\Quotation;
  8. use App\Entity\Scheduler\Task;
  9. use App\Event\Finance\QuotationStatusUpdateEvent;
  10. use App\EventSubscriber\TasksCancelerTrait;
  11. use App\Repository\Scheduler\TaskRepository;
  12. use DateTime;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. readonly class QuotationStatusSubscriber implements EventSubscriberInterface
  16. {
  17.     use TasksCancelerTrait;
  18.     public function __construct(
  19.         private EntityManagerInterface $entityManager,
  20.         private TaskRepository         $taskRepository,
  21.     ) {}
  22.     public static function getSubscribedEvents(): array
  23.     {
  24.         return [
  25.             QuotationStatusUpdateEvent::IDENTIFIER => ['process'0],
  26.         ];
  27.     }
  28.     public function process(QuotationStatusUpdateEvent $event): void
  29.     {
  30.         $quotation $event->getQuotation();
  31.         if (PayableStatus::ACCEPTED === $quotation->getStatus()) {
  32.             $this->updateShippingPlan($quotationstatusShippingPlanStatus::APPROVED);
  33.             $this->closeReviewTask($quotation);
  34.             $this->closeWorkAwardTask($quotation);
  35.             $this->closeRemainingQuotations($quotation);
  36.             $this->scheduleApprovalIssuance($quotation);
  37.         } elseif (PayableStatus::DECLINED === $quotation->getStatus()) {
  38.             $this->updateShippingPlan($quotation);
  39.             $this->closeReviewTask($quotation);
  40.             $this->cancelApprovalIssuance($quotation);
  41.         } else {
  42.             $this->updateShippingPlan($quotation);
  43.             $this->cancelApprovalIssuance($quotation);
  44.             $this->resetWorkAwardTask($quotation);
  45.             $this->resetQuotationReviewTask($quotation);
  46.             $this->rescheduleRemainingQuotations($quotation);
  47.         }
  48.         $this->entityManager->flush();
  49.     }
  50.     private function updateShippingPlan(Quotation $quotation, ?ShippingPlanStatus $status ShippingPlanStatus::DRAFTED): void
  51.     {
  52.         $shippingPlan $quotation->getShippingPlan()
  53.             ->setStatus($status);
  54.         $this->entityManager->persist($shippingPlan);
  55.         $segmentsStatus = ($status === ShippingPlanStatus::DRAFTED)
  56.             ? ShippingSegmentStatus::PLANNED
  57.             ShippingSegmentStatus::APPROVED;
  58.         foreach ($shippingPlan->getShippingSegments() as $segment) {
  59.             $segment->setStatus($segmentsStatus);
  60.             $this->entityManager->persist($segment);
  61.         }
  62.     }
  63.     private function closeReviewTask(Quotation $quotation): void
  64.     {
  65.         $task $this->taskRepository->getQuotationReviewTask($quotationcreateIfNulltrue);
  66.         $task->setStatus(TaskStatus::COMPLETED);
  67.         $task->setCompletedOn(new DateTime());
  68.         $this->entityManager->persist($task);
  69.     }
  70.     private function closeWorkAwardTask(Quotation $quotation): void
  71.     {
  72.         $task $this->taskRepository->getWorkAwardTask($quotation->getShippingPlan(), createIfNulltrue);
  73.         $task->setStatus(TaskStatus::COMPLETED);
  74.         $task->setCompletedOn(new DateTime());
  75.         $this->entityManager->persist($task);
  76.     }
  77.     private function closeRemainingQuotations(Quotation $currentQuotation): void
  78.     {
  79.         $quotations $currentQuotation->getShippingPlan()->getQuotations();
  80.         foreach ($quotations as $quotation) {
  81.             if ($currentQuotation->getId() !== $quotation->getId() && PayableStatus::AMENDED !== $quotation->getStatus()) {
  82.                 $this->declineQuotation($quotation);
  83.             }
  84.         }
  85.     }
  86.     private function declineQuotation(Quotation $quotation): void
  87.     {
  88.         // First, Update quotation status
  89.         $quotation->setStatus(PayableStatus::QUOTED);
  90.         $this->entityManager->persist($quotation);
  91.         // Then, cancel pending attached tasks
  92.         $pickupQuotationRequestTask $this->taskRepository->getPickupQuotationRequestTask($quotation);
  93.         $pickupQuotationFillingTask $this->taskRepository->getPickupQuotationFillingTask($quotation);
  94.         $quotationReviewTask $this->taskRepository->getQuotationReviewTask($quotation);
  95.         $this->cancelTasks([$pickupQuotationRequestTask$pickupQuotationFillingTask$quotationReviewTask]);
  96.     }
  97.     private function scheduleApprovalIssuance(Quotation $quotation): void
  98.     {
  99.         $quotationApprovalIssuanceTask $this->taskRepository->getQuotationApprovalIssuanceTask($quotationcreateIfNulltrue);
  100.         $this->entityManager->persist($quotationApprovalIssuanceTask);
  101.     }
  102.     private function rescheduleRemainingQuotations(Quotation $currentQuotation): void
  103.     {
  104.         $quotations $currentQuotation->getShippingPlan()->getQuotations();
  105.         foreach ($quotations as $quotation) {
  106.             if ($quotation->getId() !== $currentQuotation->getId()) {
  107.                 $this->rescheduleQuotations($quotation);
  108.             }
  109.         }
  110.     }
  111.     private function cancelApprovalIssuance(Quotation $quotation): void
  112.     {
  113.         $quotationApprovalIssuanceTask $this->taskRepository->getQuotationApprovalIssuanceTask($quotation);
  114.         $this->cancelTasks([$quotationApprovalIssuanceTask]);
  115.     }
  116.     private function rescheduleQuotations(Quotation $quotation): void
  117.     {
  118.         // Only process quotations that were automatically declined by the system
  119.         if (PayableStatus::QUOTED !== $quotation->getStatus()) {
  120.             return;
  121.         }
  122.         // Only reschedule tasks that were canceled, cancel pending attached tasks
  123.         $pickupQuotationRequestTask $this->taskRepository->getPickupQuotationRequestTask($quotation);
  124.         if (!$pickupQuotationRequestTask instanceof Task) {
  125.             $pickupQuotationRequestTask $this->taskRepository->getPickupQuotationRequestTask($quotationcreateIfNulltrue);
  126.             $this->entityManager->persist($pickupQuotationRequestTask);
  127.         }
  128.         $pickupQuotationFillingTask $this->taskRepository->getPickupQuotationFillingTask($quotation);
  129.         if (!$pickupQuotationFillingTask instanceof Task) {
  130.             $pickupQuotationFillingTask $this->taskRepository->getPickupQuotationRequestTask($quotationcreateIfNulltrue);
  131.             $this->entityManager->persist($pickupQuotationFillingTask);
  132.         }
  133.         $quotationReviewTask $this->taskRepository->getQuotationReviewTask($quotation);
  134.         if (!$quotationReviewTask instanceof Task) {
  135.             $quotationReviewTask $this->taskRepository->getPickupQuotationRequestTask($quotationcreateIfNulltrue);
  136.             $this->entityManager->persist($quotationReviewTask);
  137.         }
  138.     }
  139.     private function resetWorkAwardTask(Quotation $quotation): void
  140.     {
  141.         $workOrder $quotation->getShippingPlan()->getWorkOrder();
  142.         if (null === $workOrder) {
  143.             return;
  144.         }
  145.         $task $this->taskRepository->getWorkAwardTask($quotation->getShippingPlan(), createIfNulltrue);
  146.         $task->setStatus(TaskStatus::PLANNED);
  147.         $task->setCompletedOn(null);
  148.         $this->entityManager->persist($task);
  149.     }
  150.     private function resetQuotationReviewTask(Quotation $quotation): void
  151.     {
  152.         $task $this->taskRepository->getQuotationReviewTask($quotationcreateIfNulltrue);
  153.         $task->setStatus(TaskStatus::PLANNED);
  154.         $task->setCompletedOn(null);
  155.         $this->entityManager->persist($task);
  156.     }
  157. }