vendor/boldr/shop-bundle/src/EventSubscriber/InvoiceEventSubscriber.php line 98

Open in your IDE?
  1. <?php
  2. namespace Boldr\Shop\ShopBundle\EventSubscriber;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. use Boldr\Shop\ShopBundle\Event\{ PaymentStatusUpdatedEventInvoiceProFormaUpdatedEventInvoiceStatusUpdatedEventPaymentCreatedEventInvoiceCreatedEvent };
  6. use Boldr\Shop\ShopBundle\Entity\{ PaymentInvoice };
  7. use Boldr\Shop\ShopBundle\OrderFlow\{ OrderFlowManagerInterfaceOrderStateChangeProcessor };
  8. use Boldr\Shop\ShopBundle\Invoice\InvoiceNumberGeneratorInterface;
  9. use Boldr\Shop\ShopBundle\EmailFactory;
  10. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  11. use Symfony\Component\Mailer\MailerInterface;
  12. use DateTimeImmutable;
  13. class InvoiceEventSubscriber implements EventSubscriberInterface
  14. {
  15.     private OrderFlowManagerInterface $orderFlowManager;
  16.     private InvoiceNumberGeneratorInterface $invoiceNumberGenerator;
  17.     private EventDispatcherInterface $eventDispatcher;
  18.     private EntityManagerInterface $em;
  19.     private OrderStateChangeProcessor $orderStateChangeProcessor;
  20.     private EmailFactory $emailFactory;
  21.     private MailerInterface $mailer;
  22.     public function __construct(
  23.         OrderFlowManagerInterface $orderFlowManager,
  24.         InvoiceNumberGeneratorInterface $invoiceNumberGenerator,
  25.         EventDispatcherInterface $eventDispatcher,
  26.         OrderStateChangeProcessor $orderStateChangeProcessor,
  27.         EntityManagerInterface $em,
  28.         EmailFactory $emailFactory,
  29.         MailerInterface $mailer
  30.     )
  31.     {
  32.         $this->orderFlowManager $orderFlowManager;
  33.         $this->invoiceNumberGenerator $invoiceNumberGenerator;
  34.         $this->eventDispatcher $eventDispatcher;
  35.         $this->orderStateChangeProcessor $orderStateChangeProcessor;
  36.         $this->em $em;
  37.         $this->emailFactory $emailFactory;
  38.         $this->mailer $mailer;
  39.     }
  40.     public static function getSubscribedEvents()
  41.     {
  42.         return [
  43.             PaymentCreatedEvent::class => [
  44.                 ['onPaymentCreated'10]
  45.             ],
  46.             PaymentStatusUpdatedEvent::class => [
  47.                 ['onPaymentStatusUpdated'10]
  48.             ],
  49.             InvoiceCreatedEvent::class => [
  50.                 ['onInvoiceCreated'10]
  51.             ],
  52.             InvoiceProFormaUpdatedEvent::class => [
  53.                 ['onInvoiceProFormaUpdated'10]
  54.             ],
  55.             InvoiceStatusUpdatedEvent::class => [
  56.                 ['onInvoiceStatusUpdated'10]
  57.             ]
  58.         ];
  59.     }
  60.     private function updateInvoiceStatus(Invoice $invoice$newStatus)
  61.     {
  62.         if ($invoice->getStatus() !== $newStatus)
  63.         {
  64.             $event = new InvoiceStatusUpdatedEvent($invoice$invoice->getStatus(), $newStatus);
  65.             $invoice->setStatus($newStatus);
  66.             $this->em->flush();
  67.             $this->eventDispatcher->dispatch($event);
  68.         }
  69.     }
  70.     private function handleInvoiceChange(Invoice $invoice)
  71.     {
  72.         // Generate invoice number if invoice is finished and agreed
  73.         if ($invoice->getNumber() === null)
  74.         {
  75.             if ($invoice->isCreditInvoice() || $this->orderFlowManager->canGenerateInvoiceNumber($invoice))
  76.             {
  77.                 $date = new DateTimeImmutable;
  78.                 $number $invoice->isProForma() ? null $this->invoiceNumberGenerator->generateInvoiceNumber($invoice->getCustomer(), $date);
  79.                 $invoice->finalize($number$date);
  80.             }
  81.         }
  82.         // Mark as paid if no amount left outstanding
  83.         $newStatus abs($invoice->getAmountOutstanding()) < 0.000001 Invoice::STATUS_PAID : ($invoice->isDraft() ? Invoice::STATUS_DRAFT Invoice::STATUS_UNPAID);
  84.         $this->updateInvoiceStatus($invoice$newStatus);
  85.         $this->em->flush();
  86.     }
  87.     public function onInvoiceProFormaUpdated(InvoiceProFormaUpdatedEvent $event)
  88.     {
  89.         $invoice $event->getInvoice();
  90.         $this->handleInvoiceChange($invoice);
  91.     }
  92.     public function onPaymentCreated(PaymentCreatedEvent $event)
  93.     {
  94.         $invoice $event->getPayment()->getInvoice();
  95.         $this->handleInvoiceChange($invoice);
  96.     }
  97.     public function onPaymentStatusUpdated(PaymentStatusUpdatedEvent $event)
  98.     {
  99.         $payment $event->getPayment();
  100.         if ($event->getNewStatus() === Payment::STATUS_FAILED)
  101.         {
  102.             $invoice $payment->getInvoice();
  103.             if ($invoice->getStatus() !== Invoice::STATUS_PAID)
  104.             {
  105.                 $retryUrl null;
  106.                 try
  107.                 {
  108.                     $email $this->emailFactory->createPaymentFailedEmail($event->getPayment(), $retryUrl);
  109.                     $this->mailer->send($email);
  110.                 }
  111.                 catch (\Exception $ex)
  112.                 {
  113.                     // fail silently
  114.                 }
  115.             }
  116.         }
  117.         else
  118.         {
  119.             $invoice $event->getPayment()->getInvoice();
  120.             $this->handleInvoiceChange($invoice);
  121.         }
  122.     }
  123.     public function onInvoiceCreated(InvoiceCreatedEvent $event)
  124.     {
  125.         $invoice $event->getInvoice();
  126.         $this->handleInvoiceChange($invoice);
  127.     }
  128.     public function onInvoiceStatusUpdated(InvoiceStatusUpdatedEvent $event)
  129.     {
  130.         $invoice $event->getInvoice();
  131.         $orders = [];
  132.         foreach ($invoice->getItems() as $invoiceItem)
  133.         {
  134.             $orders[] = $invoiceItem->getOrder();
  135.         }
  136.         $doneOrders = [];
  137.         foreach ($orders as $order)
  138.         {
  139.             if (!in_array($order$doneOrders))
  140.             {
  141.                 $doneOrders[] = $order;
  142.                 $nextStates $this->orderFlowManager->getNextStates($order);
  143.                 foreach ($nextStates as $nextState)
  144.                 {
  145.                     $changeStateSteps $this->orderFlowManager->getChangeStateSteps($order$nextState);
  146.                     if ($changeStateSteps->getAutomatic())
  147.                     {
  148.                         $doComplete true;
  149.                         foreach ($changeStateSteps->getSteps() as $step)
  150.                         {
  151.                             if (!$step->isCompleted($order))
  152.                             {
  153.                                 $doComplete false;
  154.                                 break;
  155.                             }
  156.                         }
  157.                         if ($doComplete)
  158.                         {
  159.                             $this->orderStateChangeProcessor->changeState($order$nextState);
  160.                             break;
  161.                         }
  162.                     }
  163.                 }
  164.             }
  165.         }
  166.         $this->em->flush();
  167.     }
  168. }