diff --git a/composer.json b/composer.json index 3e9fa1a6..9a1f7903 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "spryker/mail": "^4.6.0", "spryker/mail-extension": "^1.0.0", "spryker/message-broker": "^1.2.1", - "spryker/oms-extension": "^1.3.0", + "spryker/oms-extension": "^1.4.0", "spryker/propel": "^3.28.0", "spryker/propel-orm": "^1.16.0", "spryker/sales": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^10.0.0 || ^11.0.0", diff --git a/src/Spryker/Shared/Oms/Transfer/oms.transfer.xml b/src/Spryker/Shared/Oms/Transfer/oms.transfer.xml index bc2d554d..6a6c69ac 100644 --- a/src/Spryker/Shared/Oms/Transfer/oms.transfer.xml +++ b/src/Spryker/Shared/Oms/Transfer/oms.transfer.xml @@ -281,4 +281,10 @@ + + + + + + diff --git a/src/Spryker/Zed/Oms/Business/Notifier/EventTriggeredNotifier.php b/src/Spryker/Zed/Oms/Business/Notifier/EventTriggeredNotifier.php new file mode 100644 index 00000000..bb457486 --- /dev/null +++ b/src/Spryker/Zed/Oms/Business/Notifier/EventTriggeredNotifier.php @@ -0,0 +1,56 @@ + + */ + protected array $omsEventTriggeredListenerPlugins; + + /** + * @param array<\Spryker\Zed\OmsExtension\Dependency\Plugin\OmsEventTriggeredListenerPluginInterface> $omsEventTriggeredListenerPlugins + */ + public function __construct(array $omsEventTriggeredListenerPlugins) + { + $this->omsEventTriggeredListenerPlugins = $omsEventTriggeredListenerPlugins; + } + + /** + * @param string $idEvent + * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems + * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $orderEntity + * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject $data + * + * @return void + */ + public function notifyOmsEventTriggeredListeners(string $idEvent, array $orderItems, SpySalesOrder $orderEntity, ReadOnlyArrayObject $data): void + { + $orderItemIds = array_map(function (SpySalesOrderItem $orderItem) { + return $orderItem->getIdSalesOrderItem(); + }, $orderItems); + + $omsEventTriggeredTransfer = (new OmsEventTriggeredTransfer()) + ->setIdEvent($idEvent) + ->setOrderItemIds($orderItemIds) + ->setIdSalesOrder($orderEntity->getIdSalesOrder()) + ->setEventData($data->getArrayCopy()); + + foreach ($this->omsEventTriggeredListenerPlugins as $omsEventTriggeredListener) { + if ($omsEventTriggeredListener->isApplicable($omsEventTriggeredTransfer)) { + $omsEventTriggeredListener->onEventTriggered($omsEventTriggeredTransfer); + } + } + } +} diff --git a/src/Spryker/Zed/Oms/Business/Notifier/EventTriggeredNotifierInterface.php b/src/Spryker/Zed/Oms/Business/Notifier/EventTriggeredNotifierInterface.php new file mode 100644 index 00000000..31b124e5 --- /dev/null +++ b/src/Spryker/Zed/Oms/Business/Notifier/EventTriggeredNotifierInterface.php @@ -0,0 +1,24 @@ + $orderItems + * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $orderEntity + * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject $data + * + * @return void + */ + public function notifyOmsEventTriggeredListeners(string $idEvent, array $orderItems, SpySalesOrder $orderEntity, ReadOnlyArrayObject $data); +} diff --git a/src/Spryker/Zed/Oms/Business/OmsBusinessFactory.php b/src/Spryker/Zed/Oms/Business/OmsBusinessFactory.php index e12693da..5cd04f6a 100644 --- a/src/Spryker/Zed/Oms/Business/OmsBusinessFactory.php +++ b/src/Spryker/Zed/Oms/Business/OmsBusinessFactory.php @@ -20,6 +20,8 @@ use Spryker\Zed\Oms\Business\Expander\StateHistoryExpanderInterface; use Spryker\Zed\Oms\Business\Lock\TriggerLocker; use Spryker\Zed\Oms\Business\Mail\MailHandler; +use Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifier; +use Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface; use Spryker\Zed\Oms\Business\OrderStateMachine\Builder; use Spryker\Zed\Oms\Business\OrderStateMachine\Finder; use Spryker\Zed\Oms\Business\OrderStateMachine\LockedOrderStateMachine; @@ -89,9 +91,18 @@ public function createOrderStateMachine(array $logContext = []) $this->getProvidedDependency(OmsDependencyProvider::COMMAND_PLUGINS), $this->createUtilReservation(), $this->getConfig(), + $this->createEventTriggeredNotifier(), ); } + /** + * @return \Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface + */ + public function createEventTriggeredNotifier(): EventTriggeredNotifierInterface + { + return new EventTriggeredNotifier($this->getOmsEventTriggeredListenerPlugins()); + } + /** * @param array $logContext * @@ -573,4 +584,12 @@ public function createOrderStatusChangedMessageSender(): OrderStatusChangedMessa { return new OrderStatusChangedMessageSender($this->getMessageBrokerFacade(), $this->getStoreFacade(), $this->getSalesFacade(), $this->getConfig(), $this->getQueryContainer()); } + + /** + * @return array<\Spryker\Zed\OmsExtension\Dependency\Plugin\OmsEventTriggeredListenerPluginInterface> + */ + public function getOmsEventTriggeredListenerPlugins(): array + { + return $this->getProvidedDependency(OmsDependencyProvider::PLUGINS_OMS_EVENT_TRIGGERED_LISTENER); + } } diff --git a/src/Spryker/Zed/Oms/Business/OmsFacadeInterface.php b/src/Spryker/Zed/Oms/Business/OmsFacadeInterface.php index 5342fba9..55390f77 100644 --- a/src/Spryker/Zed/Oms/Business/OmsFacadeInterface.php +++ b/src/Spryker/Zed/Oms/Business/OmsFacadeInterface.php @@ -86,6 +86,7 @@ public function isOrderFlaggedExcludeFromCustomer($idOrder); * - Calls condition plugins * - Sets timeouts for timeout events * - Triggers item reservation plugins + * - Notified listeners about event handling * - Unlocks state machine trigger * - Returns an array with data aggregated from the state machine plugins and an `OmsEventTriggerResponseTransfer` by the key `\Spryker\Zed\Oms\OmsConfig::OMS_EVENT_TRIGGER_RESPONSE`. * - If command plugins execution ends without issues `OmsEventTriggerResponse.isSuccessful = true`. @@ -113,6 +114,7 @@ public function triggerEventForOrderItems($eventId, array $orderItemIds, array $ * - Calls condition plugins * - Sets timeouts for timeout events * - Triggers item reservation plugins + * - Notified listeners about event handling * - Unlocks state machine trigger * - Returns an array with data aggregated from the state machine plugins and an `OmsEventTriggerResponseTransfer` by the key `\Spryker\Zed\Oms\OmsConfig::OMS_EVENT_TRIGGER_RESPONSE`. * - If command plugins execution ends without issues `OmsEventTriggerResponse.isSuccessful = true`. @@ -138,6 +140,7 @@ public function triggerEventForNewOrderItems(array $orderItemIds, array $data = * - Calls condition plugins * - Sets timeouts for timeout events * - Triggers item reservation plugins + * - Notified listeners about event handling * - Unlocks state machine trigger * - Returns an array with data aggregated from the state machine plugins and an `OmsEventTriggerResponseTransfer` by the key `\Spryker\Zed\Oms\OmsConfig::OMS_EVENT_TRIGGER_RESPONSE`. * - If command plugins execution ends without issues `OmsEventTriggerResponse.isSuccessful = true`. @@ -370,6 +373,7 @@ public function getStateDisplayName(SpySalesOrderItem $orderItem); * - Calls condition plugins * - Sets timeouts for timeout events * - Triggers item reservation plugins + * - Notified listeners about event handling * - Unlocks state machine trigger * - Returns an array with data aggregated from the state machine plugins and an `OmsEventTriggerResponseTransfer` by the key `\Spryker\Zed\Oms\OmsConfig::OMS_EVENT_TRIGGER_RESPONSE`. * - If command plugins execution ends without issues `OmsEventTriggerResponse.isSuccessful = true`. @@ -397,6 +401,7 @@ public function triggerEvent($eventId, ObjectCollection $orderItems, array $logC * - Calls condition plugins * - Sets timeouts for timeout events * - Triggers item reservation plugins + * - Notified listeners about event handling * - Unlocks state machine trigger * - Returns an array with data aggregated from the state machine plugins and an `OmsEventTriggerResponseTransfer` by the key `\Spryker\Zed\Oms\OmsConfig::OMS_EVENT_TRIGGER_RESPONSE`. * - If command plugins execution ends without issues `OmsEventTriggerResponse.isSuccessful = true`. @@ -423,6 +428,7 @@ public function triggerEventForNewItem(ObjectCollection $orderItems, array $logC * - Calls condition plugins * - Sets timeouts for timeout events * - Triggers item reservation plugins + * - Notified listeners about event handling * - Unlocks state machine trigger * - Returns an array with data aggregated from the state machine plugins and an `OmsEventTriggerResponseTransfer` by the key `\Spryker\Zed\Oms\OmsConfig::OMS_EVENT_TRIGGER_RESPONSE`. * - If command plugins execution ends without issues `OmsEventTriggerResponse.isSuccessful = true`. diff --git a/src/Spryker/Zed/Oms/Business/OrderStateMachine/OrderStateMachine.php b/src/Spryker/Zed/Oms/Business/OrderStateMachine/OrderStateMachine.php index 719ff441..4047f50b 100644 --- a/src/Spryker/Zed/Oms/Business/OrderStateMachine/OrderStateMachine.php +++ b/src/Spryker/Zed/Oms/Business/OrderStateMachine/OrderStateMachine.php @@ -18,6 +18,7 @@ use Orm\Zed\Oms\Persistence\SpyOmsOrderItemStateQuery; use Orm\Zed\Sales\Persistence\SpySalesOrderItem; use Spryker\Shared\ErrorHandler\ErrorLogger; +use Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface; use Spryker\Zed\Oms\Business\Process\ProcessInterface; use Spryker\Zed\Oms\Business\Process\StateInterface; use Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject; @@ -125,6 +126,11 @@ class OrderStateMachine implements OrderStateMachineInterface */ protected $omsConfig; + /** + * @var \Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface + */ + protected EventTriggeredNotifierInterface $eventTriggeredNotifier; + /** * @param \Spryker\Zed\Oms\Persistence\OmsQueryContainerInterface $queryContainer * @param \Spryker\Zed\Oms\Business\OrderStateMachine\BuilderInterface $builder @@ -135,6 +141,7 @@ class OrderStateMachine implements OrderStateMachineInterface * @param \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandCollectionInterface|array $commands * @param \Spryker\Zed\Oms\Business\Util\ReservationInterface $reservation * @param \Spryker\Zed\Oms\OmsConfig $omsConfig + * @param \Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface $eventTriggeredNotifier */ public function __construct( OmsQueryContainerInterface $queryContainer, @@ -145,7 +152,8 @@ public function __construct( $conditions, $commands, ReservationInterface $reservation, - OmsConfig $omsConfig + OmsConfig $omsConfig, + EventTriggeredNotifierInterface $eventTriggeredNotifier ) { $this->queryContainer = $queryContainer; $this->builder = $builder; @@ -156,6 +164,7 @@ public function __construct( $this->setCommands($commands); $this->reservation = $reservation; $this->omsConfig = $omsConfig; + $this->eventTriggeredNotifier = $eventTriggeredNotifier; } /** @@ -238,6 +247,15 @@ public function triggerEvent($eventId, array $orderItems, $data) } $sourceStateBuffer = $this->updateStateByEvent($eventId, $processedOrderItems, $sourceStateBuffer, $log); $this->saveOrderItems($processedOrderItems, $log, $processes, $sourceStateBuffer); + + $currentOrderItemEntity = current($processedOrderItems); + + if ($currentOrderItemEntity) { + $orderEntity = $currentOrderItemEntity->getOrder(); + + $this->eventTriggeredNotifier->notifyOmsEventTriggeredListeners($eventId, $processedOrderItems, $orderEntity, $data); + } + $allProcessedOrderItems = array_merge($allProcessedOrderItems, $processedOrderItems); } diff --git a/src/Spryker/Zed/Oms/OmsDependencyProvider.php b/src/Spryker/Zed/Oms/OmsDependencyProvider.php index 83cb93ce..428b13b5 100644 --- a/src/Spryker/Zed/Oms/OmsDependencyProvider.php +++ b/src/Spryker/Zed/Oms/OmsDependencyProvider.php @@ -97,6 +97,11 @@ class OmsDependencyProvider extends AbstractBundleDependencyProvider */ public const PLUGINS_TIMEOUT_PROCESSOR = 'PLUGINS_TIMEOUT_PROCESSOR'; + /** + * @var string + */ + public const PLUGINS_OMS_EVENT_TRIGGERED_LISTENER = 'PLUGINS_OMS_EVENT_TRIGGERED_LISTENER'; + /** * @var string */ @@ -165,6 +170,7 @@ public function provideBusinessLayerDependencies(Container $container) $container = $this->addOmsReservationWriterStrategyPlugins($container); $container = $this->addReservationPostSaveTerminationAwareStrategyPlugins($container); $container = $this->addTimeoutProcessorPlugins($container); + $container = $this->addOmsEventTriggeredListenerPlugins($container); $container = $this->addMessageBrokerFacade($container); return $container; @@ -603,6 +609,28 @@ protected function getTimeoutProcessorPlugins(): array return []; } + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + protected function addOmsEventTriggeredListenerPlugins(Container $container): Container + { + $container->set(static::PLUGINS_OMS_EVENT_TRIGGERED_LISTENER, function () { + return $this->getOmsEventTriggeredListenerPlugins(); + }); + + return $container; + } + + /** + * @return array<\Spryker\Zed\OmsExtension\Dependency\Plugin\OmsEventTriggeredListenerPluginInterface> + */ + protected function getOmsEventTriggeredListenerPlugins(): array + { + return []; + } + /** * @param \Spryker\Zed\Kernel\Container $container * diff --git a/tests/SprykerTest/Zed/Oms/Business/OmsFacadeTest.php b/tests/SprykerTest/Zed/Oms/Business/OmsFacadeTest.php index 834bab64..4eb2bf4e 100644 --- a/tests/SprykerTest/Zed/Oms/Business/OmsFacadeTest.php +++ b/tests/SprykerTest/Zed/Oms/Business/OmsFacadeTest.php @@ -130,6 +130,33 @@ public function testIsOrderFlaggedExcludeFromCustomerShouldReturnTrueWhenAllStat $this->assertTrue($isOrderExcluded); } + /** + * @group new + * + * @return void + */ + public function testEventTriggeredListenersAreNotifiedWhenEventIsTriggered(): void + { + $testStateMachineProcessName = 'Test01'; + + $omsEventTriggeredListener = $this->tester->setupEventTriggeredListenerPluginDependency(); + + $omsFacade = $this->createOmsFacadeWithTestStateMachine([$testStateMachineProcessName]); + + $saveOrderTransfer = $this->tester->haveOrder([ + 'unitPrice' => 100, + 'sumPrice' => 100, + ], $testStateMachineProcessName); + + $idSalesOrder = $saveOrderTransfer->getIdSalesOrder(); + + $salesOrderEntity = SpySalesOrderQuery::create()->filterByIdSalesOrder($idSalesOrder)->findOne(); + + $omsFacade->triggerEvent('authorize', $salesOrderEntity->getItems(), []); + + $this->assertTrue($omsEventTriggeredListener->wasTriggered); + } + /** * @return void */ diff --git a/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/OrderStateMachineTest.php b/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/OrderStateMachineTest.php index a041c187..37c90565 100644 --- a/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/OrderStateMachineTest.php +++ b/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/OrderStateMachineTest.php @@ -16,6 +16,7 @@ use Orm\Zed\Sales\Persistence\SpySalesOrder as ChildSpySalesOrder; use Orm\Zed\Sales\Persistence\SpySalesOrderItem; use ReflectionClass; +use Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifier; use Spryker\Zed\Oms\Business\OmsBusinessFactory; use Spryker\Zed\Oms\Business\OrderStateMachine\BuilderInterface; use Spryker\Zed\Oms\Business\OrderStateMachine\OrderStateMachine; @@ -82,6 +83,7 @@ public function testInstantiationConditionsArrayShouldConvertedToCollection(): v [], $this->getReservationMock(), new OmsConfig(), + new EventTriggeredNotifier([]), ); $reflection = new ReflectionClass(OrderStateMachine::class); $reflectionProperty = $reflection->getProperty('conditions'); @@ -110,6 +112,7 @@ public function testInstantiationWithConditionCollection(): void [], $this->getReservationMock(), new OmsConfig(), + new EventTriggeredNotifier([]), ); $reflection = new ReflectionClass(OrderStateMachine::class); $reflectionProperty = $reflection->getProperty('conditions'); @@ -135,6 +138,7 @@ public function testInstantiationCommandsArrayShouldConvertedToCollection(): voi [static::COMMAND_NAME => $this->getCommandMock()], $this->getReservationMock(), new OmsConfig(), + new EventTriggeredNotifier([]), ); $reflection = new ReflectionClass(OrderStateMachine::class); $reflectionProperty = $reflection->getProperty('commands'); @@ -163,6 +167,7 @@ public function testInstantiationWithCommandCollection(): void $commandCollection, $this->getReservationMock(), new OmsConfig(), + new EventTriggeredNotifier([]), ); $reflection = new ReflectionClass(OrderStateMachine::class); $reflectionProperty = $reflection->getProperty('commands'); @@ -273,6 +278,7 @@ protected function getOrderStatemachineMockForConditionsWithCriteriaTest(array $ [], $omsBusinessFactory->createUtilReservation(), $omsConfigMock, + $omsBusinessFactory->createEventTriggeredNotifier(), ]) ->onlyMethods($methods); diff --git a/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/TimeoutTest.php b/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/TimeoutTest.php index 952f6edd..38437575 100644 --- a/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/TimeoutTest.php +++ b/tests/SprykerTest/Zed/Oms/Business/OrderStateMachine/TimeoutTest.php @@ -314,6 +314,7 @@ protected function createOrderStateMachineMock(array $methods): OrderStateMachin $omsBusinessFactory->getProvidedDependency(OmsDependencyProvider::COMMAND_PLUGINS), $omsBusinessFactory->createUtilReservation(), $omsConfigMock, + $omsBusinessFactory->createEventTriggeredNotifier(), ]) ->onlyMethods($methods) ->getMock(); diff --git a/tests/SprykerTest/Zed/Oms/_support/OmsBusinessTester.php b/tests/SprykerTest/Zed/Oms/_support/OmsBusinessTester.php index 3c30c928..905632fa 100644 --- a/tests/SprykerTest/Zed/Oms/_support/OmsBusinessTester.php +++ b/tests/SprykerTest/Zed/Oms/_support/OmsBusinessTester.php @@ -15,6 +15,7 @@ use Generated\Shared\DataBuilder\ItemMetadataBuilder; use Generated\Shared\DataBuilder\QuoteBuilder; use Generated\Shared\Transfer\CustomerTransfer; +use Generated\Shared\Transfer\OmsEventTriggeredTransfer; use Generated\Shared\Transfer\OrderTransfer; use Generated\Shared\Transfer\QuoteTransfer; use Generated\Shared\Transfer\StoreTransfer; @@ -35,6 +36,7 @@ use Spryker\Zed\Oms\Dependency\Facade\OmsToSalesInterface; use Spryker\Zed\Oms\OmsConfig; use Spryker\Zed\Oms\Persistence\OmsQueryContainer; +use Spryker\Zed\OmsExtension\Dependency\Plugin\OmsEventTriggeredListenerPluginInterface; use Spryker\Zed\SalesPayment\SalesPaymentDependencyProvider; use Spryker\Zed\Store\Communication\Plugin\MessageBroker\CurrentStoreReferenceMessageAttributeProviderPlugin; use Spryker\Zed\Store\Communication\Plugin\MessageBroker\StoreReferenceMessageValidatorPlugin; @@ -406,4 +408,41 @@ public function setupMessageBroker(): void $this->setDependency(MessageBrokerDependencyProvider::PLUGINS_EXTERNAL_VALIDATOR, [new StoreReferenceMessageValidatorPlugin()]); } + + /** + * @return \Spryker\Zed\OmsExtension\Dependency\Plugin\OmsEventTriggeredListenerPluginInterface + */ + public function setupEventTriggeredListenerPluginDependency(): OmsEventTriggeredListenerPluginInterface + { + $omsEventTriggeredListener = new class implements OmsEventTriggeredListenerPluginInterface { + /** + * @var bool + */ + public $wasTriggered; + + /** + * @param \Generated\Shared\Transfer\OmsEventTriggeredTransfer $omsEventTriggeredTransfer + * + * @return void + */ + public function onEventTriggered(OmsEventTriggeredTransfer $omsEventTriggeredTransfer): void + { + $this->wasTriggered = true; + } + + /** + * @param \Generated\Shared\Transfer\OmsEventTriggeredTransfer $omsEventTriggeredTransfer + * + * @return bool + */ + public function isApplicable(OmsEventTriggeredTransfer $omsEventTriggeredTransfer): bool + { + return true; + } + }; + + $this->setDependency('PLUGINS_OMS_EVENT_TRIGGERED_LISTENER', [$omsEventTriggeredListener]); + + return $omsEventTriggeredListener; + } }