diff --git a/src/Sylius/Bundle/ApiBundle/Command/SendOrderConfirmation.php b/src/Sylius/Bundle/ApiBundle/Command/SendOrderConfirmation.php new file mode 100644 index 00000000000..09ede58f595 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Command/SendOrderConfirmation.php @@ -0,0 +1,31 @@ +orderToken = $orderToken; + } + + public function orderToken(): string + { + return $this->orderToken; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Checkout/CompleteOrderHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Checkout/CompleteOrderHandler.php index 03dce9b4fbd..a081a2777a1 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/Checkout/CompleteOrderHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Checkout/CompleteOrderHandler.php @@ -14,12 +14,15 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler\Checkout; use SM\Factory\FactoryInterface; +use Sylius\Bundle\ApiBundle\Command\Cart\PickupCart; use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder; -use Sylius\Bundle\CoreBundle\Mailer\OrderEmailManagerInterface; +use Sylius\Bundle\ApiBundle\Event\OrderCompleted; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\OrderCheckoutTransitions; use Sylius\Component\Core\Repository\OrderRepositoryInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp; use Webmozart\Assert\Assert; /** @experimental */ @@ -31,17 +34,17 @@ final class CompleteOrderHandler implements MessageHandlerInterface /** @var FactoryInterface */ private $stateMachineFactory; - /** @var OrderEmailManagerInterface */ - private $emailManager; + /** @var MessageBusInterface */ + private $eventBus; public function __construct( OrderRepositoryInterface $orderRepository, FactoryInterface $stateMachineFactory, - OrderEmailManagerInterface $emailManager + MessageBusInterface $eventBus ) { $this->orderRepository = $orderRepository; $this->stateMachineFactory = $stateMachineFactory; - $this->emailManager = $emailManager; + $this->eventBus = $eventBus; } public function __invoke(CompleteOrder $completeOrder): OrderInterface @@ -66,7 +69,7 @@ public function __invoke(CompleteOrder $completeOrder): OrderInterface $stateMachine->apply(OrderCheckoutTransitions::TRANSITION_COMPLETE); - $this->emailManager->sendConfirmationEmail($cart); + $this->eventBus->dispatch(new OrderCompleted($cart->getTokenValue()), [new DispatchAfterCurrentBusStamp()]); return $cart; } diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/SendOrderConfirmationHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendOrderConfirmationHandler.php new file mode 100644 index 00000000000..65a076146fe --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendOrderConfirmationHandler.php @@ -0,0 +1,53 @@ +emailSender = $emailSender; + $this->orderRepository = $orderRepository; + } + + public function __invoke(SendOrderConfirmation $sendOrderConfirmation): void + { + /** @var OrderInterface $order */ + $order = $this->orderRepository->findOneByTokenValue($sendOrderConfirmation->orderToken()); + + $this->emailSender->send( + Emails::ORDER_CONFIRMATION_RESENT, + [$order->getCustomer()->getEmail()], + [ + 'order' => $order, + 'channel' => $order->getChannel(), + 'localeCode' => $order->getLocaleCode(), + ] + ); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Event/OrderCompleted.php b/src/Sylius/Bundle/ApiBundle/Event/OrderCompleted.php new file mode 100644 index 00000000000..b98b90bee12 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Event/OrderCompleted.php @@ -0,0 +1,30 @@ +orderToken = $orderToken; + } + + public function orderToken(): string + { + return $this->orderToken; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/EventHandler/OrderCompletedHandler.php b/src/Sylius/Bundle/ApiBundle/EventHandler/OrderCompletedHandler.php new file mode 100644 index 00000000000..4c49d342d08 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/EventHandler/OrderCompletedHandler.php @@ -0,0 +1,35 @@ +commandBus = $commandBus; + } + + public function __invoke(OrderCompleted $orderCompleted): void + { + $this->commandBus->dispatch(new SendOrderConfirmation($orderCompleted->orderToken())); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/app/config.yaml b/src/Sylius/Bundle/ApiBundle/Resources/config/app/config.yaml index e7f1d302593..66c2f3d715e 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/app/config.yaml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/app/config.yaml @@ -25,3 +25,7 @@ framework: middleware: - 'validation' - 'doctrine_transaction' + sylius_event.bus: + middleware: + - 'validation' + - 'doctrine_transaction' diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml index be17e44c66c..05585340f0f 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -78,8 +78,8 @@ - - + + @@ -101,5 +101,11 @@ + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml new file mode 100644 index 00000000000..27bcb3fb8fc --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Checkout/CompleteOrderHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Checkout/CompleteOrderHandlerSpec.php index 7fee82a94d7..2f5a483a356 100644 --- a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Checkout/CompleteOrderHandlerSpec.php +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Checkout/CompleteOrderHandlerSpec.php @@ -17,19 +17,22 @@ use SM\Factory\FactoryInterface; use SM\StateMachine\StateMachineInterface; use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder; -use Sylius\Bundle\CoreBundle\Mailer\OrderEmailManagerInterface; +use Sylius\Bundle\ApiBundle\Event\OrderCompleted; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\OrderCheckoutTransitions; use Sylius\Component\Core\Repository\OrderRepositoryInterface; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp; final class CompleteOrderHandlerSpec extends ObjectBehavior { function let( OrderRepositoryInterface $orderRepository, FactoryInterface $stateMachineFactory, - OrderEmailManagerInterface $emailManager + MessageBusInterface $eventBus ): void { - $this->beConstructedWith($orderRepository, $stateMachineFactory, $emailManager); + $this->beConstructedWith($orderRepository, $stateMachineFactory, $eventBus); } function it_handles_order_completion_without_notes( @@ -37,7 +40,7 @@ function it_handles_order_completion_without_notes( StateMachineInterface $stateMachine, OrderInterface $order, FactoryInterface $stateMachineFactory, - OrderEmailManagerInterface $emailManager + MessageBusInterface $eventBus ): void { $completeOrder = new CompleteOrder(); $completeOrder->setOrderTokenValue('ORDERTOKEN'); @@ -52,7 +55,13 @@ function it_handles_order_completion_without_notes( $stateMachine->apply('complete')->shouldBeCalled(); - $emailManager->sendConfirmationEmail($order)->shouldBeCalled(); + $orderCompleted = new OrderCompleted('COMPLETED_ORDER_TOKEN'); + + $eventBus + ->dispatch($orderCompleted, [new DispatchAfterCurrentBusStamp()]) + ->willReturn(new Envelope($orderCompleted)) + ->shouldBeCalled() + ; $this($completeOrder)->shouldReturn($order); } @@ -62,7 +71,7 @@ function it_handles_order_completion_with_notes( StateMachineInterface $stateMachine, OrderInterface $order, FactoryInterface $stateMachineFactory, - OrderEmailManagerInterface $emailManager + MessageBusInterface $eventBus ): void { $completeOrder = new CompleteOrder('ThankYou'); $completeOrder->setOrderTokenValue('ORDERTOKEN'); @@ -77,7 +86,13 @@ function it_handles_order_completion_with_notes( $stateMachine->apply('complete')->shouldBeCalled(); - $emailManager->sendConfirmationEmail($order)->shouldBeCalled(); + $orderCompleted = new OrderCompleted('COMPLETED_ORDER_TOKEN'); + + $eventBus + ->dispatch($orderCompleted, [new DispatchAfterCurrentBusStamp()]) + ->willReturn(new Envelope($orderCompleted)) + ->shouldBeCalled() + ; $this($completeOrder)->shouldReturn($order); } diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendOrderConfirmationHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendOrderConfirmationHandlerSpec.php new file mode 100644 index 00000000000..97e97ac7b9a --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendOrderConfirmationHandlerSpec.php @@ -0,0 +1,68 @@ +beConstructedWith($sender, $orderRepository); + } + + function it_is_a_message_handler(): void + { + $this->shouldImplement(MessageHandlerInterface::class); + } + + function it_sends_order_confirmation_message( + OrderInterface $order, + SendOrderConfirmation $sendOrderConfirmation, + SenderInterface $sender, + CustomerInterface $customer, + ChannelInterface $channel, + OrderRepositoryInterface $orderRepository + ): void { + $sendOrderConfirmation->orderToken()->willReturn('TOKEN'); + + $orderRepository->findOneByTokenValue('TOKEN')->willReturn($order); + + $order->getChannel()->willReturn($channel); + $order->getLocaleCode()->willReturn('pl_PL'); + + $order->getCustomer()->willReturn($customer); + $customer->getEmail()->willReturn('johnny.bravo@email.com'); + + $sender->send( + Emails::ORDER_CONFIRMATION_RESENT, + ['johnny.bravo@email.com'], + [ + 'order' => $order->getWrappedObject(), + 'channel' => $channel->getWrappedObject(), + 'localeCode' => 'pl_PL', + ] + )->shouldBeCalled(); + + $this(new SendOrderConfirmation('TOKEN')); + } +}