1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Copyright © 2016-present Spryker Systems GmbH. All rights reserved. |
||
5 | * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. |
||
6 | */ |
||
7 | |||
8 | namespace Spryker\Zed\Oms\Business\OrderStateMachine; |
||
9 | |||
10 | use DateTime; |
||
11 | use Exception; |
||
12 | use Generated\Shared\Transfer\MessageTransfer; |
||
13 | use Generated\Shared\Transfer\OmsCheckConditionsQueryCriteriaTransfer; |
||
14 | use Generated\Shared\Transfer\OmsEventTriggerResponseTransfer; |
||
15 | use Generated\Shared\Transfer\ReservationRequestTransfer; |
||
16 | use LogicException; |
||
17 | use Orm\Zed\Oms\Persistence\SpyOmsOrderItemState; |
||
18 | use Orm\Zed\Oms\Persistence\SpyOmsOrderItemStateQuery; |
||
19 | use Orm\Zed\Sales\Persistence\SpySalesOrderItem; |
||
20 | use Spryker\Shared\ErrorHandler\ErrorLogger; |
||
21 | use Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface; |
||
22 | use Spryker\Zed\Oms\Business\Process\ProcessInterface; |
||
23 | use Spryker\Zed\Oms\Business\Process\StateInterface; |
||
24 | use Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject; |
||
25 | use Spryker\Zed\Oms\Business\Util\ReservationInterface; |
||
26 | use Spryker\Zed\Oms\Business\Util\TransitionLogInterface; |
||
27 | use Spryker\Zed\Oms\Communication\Plugin\Oms\Command\CommandCollection; |
||
28 | use Spryker\Zed\Oms\Communication\Plugin\Oms\Command\CommandCollectionInterface; |
||
29 | use Spryker\Zed\Oms\Communication\Plugin\Oms\Condition\ConditionCollection; |
||
30 | use Spryker\Zed\Oms\Dependency\Plugin\Command\CommandByItemInterface; |
||
31 | use Spryker\Zed\Oms\Dependency\Plugin\Command\CommandByOrderInterface; |
||
32 | use Spryker\Zed\Oms\Dependency\Plugin\Command\CommandInterface; |
||
33 | use Spryker\Zed\Oms\Dependency\Plugin\Condition\ConditionCollectionInterface; |
||
34 | use Spryker\Zed\Oms\OmsConfig; |
||
35 | use Spryker\Zed\Oms\Persistence\OmsQueryContainerInterface; |
||
36 | use Spryker\Zed\PropelOrm\Business\Transaction\DatabaseTransactionHandlerTrait; |
||
37 | |||
38 | class OrderStateMachine implements OrderStateMachineInterface |
||
39 | { |
||
40 | use DatabaseTransactionHandlerTrait; |
||
0 ignored issues
–
show
|
|||
41 | |||
42 | /** |
||
43 | * @var string |
||
44 | */ |
||
45 | public const BY_ITEM = 'byItem'; |
||
46 | |||
47 | /** |
||
48 | * @var string |
||
49 | */ |
||
50 | public const BY_ORDER = 'byOrder'; |
||
51 | |||
52 | /** |
||
53 | * @var int |
||
54 | */ |
||
55 | public const MAX_EVENT_REPEATS = 10; |
||
56 | |||
57 | /** |
||
58 | * @deprecated Not in use anymore, will be removed in the next major. |
||
59 | * |
||
60 | * @var int |
||
61 | */ |
||
62 | public const MAX_ON_ENTER = 50; |
||
63 | |||
64 | /** |
||
65 | * @var array |
||
66 | */ |
||
67 | protected $eventCounter = []; |
||
68 | |||
69 | /** |
||
70 | * @var array |
||
71 | */ |
||
72 | protected $returnData = []; |
||
73 | |||
74 | /** |
||
75 | * @var array |
||
76 | */ |
||
77 | protected $processBuffer = []; |
||
78 | |||
79 | /** |
||
80 | * @var array |
||
81 | */ |
||
82 | protected $states = []; |
||
83 | |||
84 | /** |
||
85 | * @var \Spryker\Zed\Oms\Persistence\OmsQueryContainerInterface |
||
86 | */ |
||
87 | protected $queryContainer; |
||
88 | |||
89 | /** |
||
90 | * @var \Spryker\Zed\Oms\Business\OrderStateMachine\TimeoutInterface |
||
91 | */ |
||
92 | protected $timeout; |
||
93 | |||
94 | /** |
||
95 | * @var \Spryker\Zed\Oms\Business\OrderStateMachine\BuilderInterface |
||
96 | */ |
||
97 | protected $builder; |
||
98 | |||
99 | /** |
||
100 | * @var \Spryker\Zed\Oms\Business\Util\TransitionLogInterface |
||
101 | */ |
||
102 | protected $transitionLog; |
||
103 | |||
104 | /** |
||
105 | * @var \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject |
||
106 | */ |
||
107 | protected $activeProcesses; |
||
108 | |||
109 | /** |
||
110 | * @var \Spryker\Zed\Oms\Dependency\Plugin\Condition\ConditionCollectionInterface |
||
111 | */ |
||
112 | protected $conditions; |
||
113 | |||
114 | /** |
||
115 | * @var \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandCollectionInterface |
||
116 | */ |
||
117 | protected $commands; |
||
118 | |||
119 | /** |
||
120 | * @var \Spryker\Zed\Oms\Business\Util\ReservationInterface |
||
121 | */ |
||
122 | protected $reservation; |
||
123 | |||
124 | /** |
||
125 | * @var \Spryker\Zed\Oms\OmsConfig |
||
126 | */ |
||
127 | protected $omsConfig; |
||
128 | |||
129 | /** |
||
130 | * @var \Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface |
||
131 | */ |
||
132 | protected EventTriggeredNotifierInterface $eventTriggeredNotifier; |
||
133 | |||
134 | /** |
||
135 | * @param \Spryker\Zed\Oms\Persistence\OmsQueryContainerInterface $queryContainer |
||
136 | * @param \Spryker\Zed\Oms\Business\OrderStateMachine\BuilderInterface $builder |
||
137 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $transitionLog |
||
138 | * @param \Spryker\Zed\Oms\Business\OrderStateMachine\TimeoutInterface $timeout |
||
139 | * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject $activeProcesses |
||
140 | * @param \Spryker\Zed\Oms\Dependency\Plugin\Condition\ConditionCollectionInterface|array $conditions |
||
141 | * @param \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandCollectionInterface|array $commands |
||
142 | * @param \Spryker\Zed\Oms\Business\Util\ReservationInterface $reservation |
||
143 | * @param \Spryker\Zed\Oms\OmsConfig $omsConfig |
||
144 | * @param \Spryker\Zed\Oms\Business\Notifier\EventTriggeredNotifierInterface $eventTriggeredNotifier |
||
145 | */ |
||
146 | public function __construct( |
||
147 | OmsQueryContainerInterface $queryContainer, |
||
148 | BuilderInterface $builder, |
||
149 | TransitionLogInterface $transitionLog, |
||
150 | TimeoutInterface $timeout, |
||
151 | ReadOnlyArrayObject $activeProcesses, |
||
152 | $conditions, |
||
153 | $commands, |
||
154 | ReservationInterface $reservation, |
||
155 | OmsConfig $omsConfig, |
||
156 | EventTriggeredNotifierInterface $eventTriggeredNotifier |
||
157 | ) { |
||
158 | $this->queryContainer = $queryContainer; |
||
159 | $this->builder = $builder; |
||
160 | $this->transitionLog = $transitionLog; |
||
161 | $this->timeout = $timeout; |
||
162 | $this->activeProcesses = $activeProcesses; |
||
163 | $this->setConditions($conditions); |
||
164 | $this->setCommands($commands); |
||
165 | $this->reservation = $reservation; |
||
166 | $this->omsConfig = $omsConfig; |
||
167 | $this->eventTriggeredNotifier = $eventTriggeredNotifier; |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Converts array to collection for BC |
||
172 | * |
||
173 | * @param \Spryker\Zed\Oms\Dependency\Plugin\Condition\ConditionCollectionInterface|array $conditions |
||
174 | * |
||
175 | * @return void |
||
176 | */ |
||
177 | protected function setConditions($conditions) |
||
178 | { |
||
179 | if ($conditions instanceof ConditionCollectionInterface) { |
||
180 | $this->conditions = $conditions; |
||
181 | |||
182 | return; |
||
183 | } |
||
184 | |||
185 | $conditionCollection = new ConditionCollection(); |
||
186 | foreach ($conditions as $name => $condition) { |
||
187 | $conditionCollection->add($condition, $name); |
||
188 | } |
||
189 | |||
190 | $this->conditions = $conditionCollection; |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Converts array to collection for BC |
||
195 | * |
||
196 | * @param \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandCollectionInterface|array $commands |
||
197 | * |
||
198 | * @return void |
||
199 | */ |
||
200 | protected function setCommands($commands) |
||
201 | { |
||
202 | if ($commands instanceof CommandCollectionInterface) { |
||
203 | $this->commands = $commands; |
||
204 | |||
205 | return; |
||
206 | } |
||
207 | |||
208 | $commandCollection = new CommandCollection(); |
||
209 | foreach ($commands as $name => $command) { |
||
210 | $commandCollection->add($command, $name); |
||
211 | } |
||
212 | |||
213 | $this->commands = $commandCollection; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * @param string $eventId |
||
218 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
219 | * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject|array $data |
||
220 | * |
||
221 | * @return array |
||
222 | */ |
||
223 | public function triggerEvent($eventId, array $orderItems, $data) |
||
224 | { |
||
225 | $data = $this->makeDataReadOnly($data); |
||
226 | |||
227 | $processes = $this->getProcesses($orderItems); |
||
228 | |||
229 | $orderItems = $this->filterAffectedOrderItems($eventId, $orderItems, $processes); |
||
230 | |||
231 | $log = $this->initTransitionLog($orderItems); |
||
232 | |||
233 | $orderGroup = $this->groupByOrderAndState($eventId, $orderItems, $processes); |
||
234 | $sourceStateBuffer = []; |
||
235 | |||
236 | $allProcessedOrderItems = []; |
||
237 | foreach ($orderGroup as $orderGroupKey => $groupedOrderItems) { |
||
238 | if (!$this->checkOrderGroupForEventRepetitions($eventId, $orderGroupKey)) { |
||
239 | continue; |
||
240 | } |
||
241 | |||
242 | $this->logSourceState($groupedOrderItems, $log); |
||
243 | |||
244 | $processedOrderItems = $this->runCommand($eventId, $groupedOrderItems, $processes, $data, $log); |
||
245 | if ($processedOrderItems === null) { |
||
246 | continue; |
||
247 | } |
||
248 | $sourceStateBuffer = $this->updateStateByEvent($eventId, $processedOrderItems, $sourceStateBuffer, $log); |
||
249 | $this->saveOrderItems($processedOrderItems, $log, $processes, $sourceStateBuffer); |
||
250 | |||
251 | $currentOrderItemEntity = current($processedOrderItems); |
||
252 | |||
253 | if ($currentOrderItemEntity) { |
||
254 | $orderEntity = $currentOrderItemEntity->getOrder(); |
||
255 | |||
256 | $this->eventTriggeredNotifier->notifyOmsEventTriggeredListeners($eventId, $processedOrderItems, $orderEntity, $data); |
||
257 | } |
||
258 | |||
259 | $allProcessedOrderItems = array_merge($allProcessedOrderItems, $processedOrderItems); |
||
260 | } |
||
261 | |||
262 | $orderItemsWithOnEnterEvent = $this->filterItemsWithOnEnterEvent($allProcessedOrderItems, $processes, $sourceStateBuffer); |
||
263 | |||
264 | $log->saveAll(); |
||
265 | |||
266 | $this->triggerOnEnterEvents($orderItemsWithOnEnterEvent, $data); |
||
267 | |||
268 | return $this->returnData; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * @param string $eventId |
||
273 | * @param array $orderItemIds |
||
274 | * @param array<string, mixed> $data |
||
275 | * |
||
276 | * @return array |
||
277 | */ |
||
278 | public function triggerEventForOrderItems($eventId, array $orderItemIds, $data) |
||
279 | { |
||
280 | $orderItems = $this->queryContainer |
||
281 | ->querySalesOrderItems($orderItemIds) |
||
282 | ->find() |
||
283 | ->getData(); |
||
284 | |||
285 | return $this->triggerEvent($eventId, $orderItems, $data); |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * @param string $eventId |
||
290 | * @param int $orderItemId |
||
291 | * @param array<string, mixed> $data |
||
292 | * |
||
293 | * @return array|null |
||
294 | */ |
||
295 | public function triggerEventForOneOrderItem($eventId, $orderItemId, $data) |
||
296 | { |
||
297 | $orderItems = $this->queryContainer |
||
298 | ->querySalesOrderItems([$orderItemId]) |
||
299 | ->find() |
||
300 | ->getData(); |
||
301 | |||
302 | return $this->triggerEvent($eventId, $orderItems, $data); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
307 | * @param array<string, mixed> $data |
||
308 | * |
||
309 | * @return array |
||
310 | */ |
||
311 | public function triggerEventForNewItem(array $orderItems, $data) |
||
312 | { |
||
313 | $data = $this->makeDataReadOnly($data); |
||
314 | $sourceStateBuffer = []; |
||
315 | $processes = $this->getProcesses($orderItems); |
||
316 | |||
317 | $orderItemsWithOnEnterEvent = $this->filterItemsWithOnEnterEvent($orderItems, $processes, $sourceStateBuffer); |
||
318 | $this->triggerOnEnterEvents($orderItemsWithOnEnterEvent, $data); |
||
319 | |||
320 | $orderItemsWithTimeoutEvent = $this->filterItemsWithTimeoutEvent($orderItems, $processes); |
||
321 | $this->saveTimeoutEvents($orderItemsWithTimeoutEvent); |
||
322 | |||
323 | return $this->returnData; |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * @param array<int> $orderItemIds |
||
328 | * @param array<string, mixed> $data |
||
329 | * |
||
330 | * @return array |
||
331 | */ |
||
332 | public function triggerEventForNewOrderItems(array $orderItemIds, $data) |
||
333 | { |
||
334 | $orderItems = $this->queryContainer |
||
335 | ->querySalesOrderItems($orderItemIds) |
||
336 | ->find() |
||
337 | ->getData(); |
||
338 | |||
339 | return $this->triggerEventForNewItem($orderItems, $data); |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * @param array $logContext |
||
344 | * @param \Generated\Shared\Transfer\OmsCheckConditionsQueryCriteriaTransfer|null $omsCheckConditionsQueryCriteriaTransfer |
||
345 | * |
||
346 | * @return int |
||
347 | */ |
||
348 | public function checkConditions(array $logContext = [], ?OmsCheckConditionsQueryCriteriaTransfer $omsCheckConditionsQueryCriteriaTransfer = null) |
||
349 | { |
||
350 | $affectedOrderItems = 0; |
||
351 | foreach ($this->activeProcesses as $processName) { |
||
352 | $process = $this->builder->createProcess($processName); |
||
353 | $orderStateMachine = clone $this; |
||
354 | $affectedOrderItems += $orderStateMachine->checkConditionsForProcess($process, $omsCheckConditionsQueryCriteriaTransfer); |
||
355 | } |
||
356 | |||
357 | return $affectedOrderItems; |
||
358 | } |
||
359 | |||
360 | /** |
||
361 | * @param \Spryker\Zed\Oms\Business\Process\ProcessInterface $process |
||
362 | * @param \Generated\Shared\Transfer\OmsCheckConditionsQueryCriteriaTransfer|null $omsCheckConditionsQueryCriteriaTransfer |
||
363 | * |
||
364 | * @return int |
||
365 | */ |
||
366 | protected function checkConditionsForProcess(ProcessInterface $process, ?OmsCheckConditionsQueryCriteriaTransfer $omsCheckConditionsQueryCriteriaTransfer) |
||
367 | { |
||
368 | $transitions = $process->getAllTransitionsWithoutEvent(); |
||
369 | |||
370 | $stateToTransitionsMap = $this->createStateToTransitionMap($transitions); |
||
371 | |||
372 | $orderItems = $this->getOrderItemsByState(array_keys($stateToTransitionsMap), $process, $omsCheckConditionsQueryCriteriaTransfer); |
||
373 | |||
374 | $countAffectedItems = count($orderItems); |
||
375 | |||
376 | if (count($orderItems) === 0) { |
||
377 | return 0; |
||
378 | } |
||
379 | |||
380 | $log = $this->initTransitionLog($orderItems); |
||
381 | |||
382 | $sourceStateBuffer = $this->updateStateByTransition($stateToTransitionsMap, $orderItems, [], $log); |
||
383 | |||
384 | $processes = [$process->getName() => $process]; |
||
385 | |||
386 | $this->saveOrderItems($orderItems, $log, $processes, $sourceStateBuffer); |
||
387 | |||
388 | $orderItemsWithOnEnterEvent = $this->filterItemsWithOnEnterEvent($orderItems, $processes, $sourceStateBuffer); |
||
389 | |||
390 | $data = $this->makeDataReadOnly([]); |
||
391 | |||
392 | $this->triggerOnEnterEvents($orderItemsWithOnEnterEvent, $data); |
||
393 | |||
394 | return $countAffectedItems; |
||
395 | } |
||
396 | |||
397 | /** |
||
398 | * @param array<\Spryker\Zed\Oms\Business\Process\TransitionInterface> $transitions |
||
399 | * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem $orderItem |
||
400 | * @param \Spryker\Zed\Oms\Business\Process\StateInterface $sourceState |
||
401 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
402 | * |
||
403 | * @throws \Exception |
||
404 | * |
||
405 | * @return \Spryker\Zed\Oms\Business\Process\StateInterface |
||
406 | */ |
||
407 | protected function checkCondition(array $transitions, $orderItem, StateInterface $sourceState, TransitionLogInterface $log) |
||
408 | { |
||
409 | $possibleTransitions = []; |
||
410 | |||
411 | foreach ($transitions as $transition) { |
||
412 | if ($transition->hasCondition()) { |
||
413 | $conditionString = $transition->getCondition(); |
||
414 | $conditionModel = $this->getCondition($conditionString); |
||
415 | |||
416 | try { |
||
417 | $conditionCheck = $conditionModel->check($orderItem); |
||
418 | } catch (Exception $e) { |
||
419 | $log->setIsError(true); |
||
420 | $log->setErrorMessage(get_class($e) . ' - ' . $e->getMessage()); |
||
421 | $log->saveAll(); |
||
422 | |||
423 | throw $e; |
||
424 | } |
||
425 | |||
426 | if ($conditionCheck === true) { |
||
427 | array_unshift($possibleTransitions, $transition); |
||
428 | } |
||
429 | |||
430 | $log->addCondition($orderItem, $conditionModel); |
||
431 | } else { |
||
432 | array_push($possibleTransitions, $transition); |
||
433 | } |
||
434 | } |
||
435 | |||
436 | if (count($possibleTransitions) > 0) { |
||
437 | /** @var \Spryker\Zed\Oms\Business\Process\TransitionInterface $selectedTransition */ |
||
438 | $selectedTransition = array_shift($possibleTransitions); |
||
439 | $targetState = $selectedTransition->getTarget(); |
||
440 | } else { |
||
441 | $targetState = $sourceState; |
||
442 | } |
||
443 | |||
444 | return $targetState; |
||
445 | } |
||
446 | |||
447 | /** |
||
448 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
449 | * |
||
450 | * @return array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> |
||
451 | */ |
||
452 | protected function getProcesses(array $orderItems) |
||
453 | { |
||
454 | $processes = []; |
||
455 | foreach ($orderItems as $orderItem) { |
||
456 | $processName = $orderItem->getProcess()->getName(); |
||
457 | if (array_key_exists($processName, $processes) === false) { |
||
458 | $processes[$processName] = $this->builder->createProcess($processName); |
||
459 | } |
||
460 | } |
||
461 | |||
462 | return $processes; |
||
463 | } |
||
464 | |||
465 | /** |
||
466 | * Filters out all items that are not affected by the current event |
||
467 | * |
||
468 | * @param string $eventId |
||
469 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
470 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
471 | * |
||
472 | * @return array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> |
||
473 | */ |
||
474 | protected function filterAffectedOrderItems($eventId, array $orderItems, $processes) |
||
475 | { |
||
476 | $orderItemsFiltered = []; |
||
477 | foreach ($orderItems as $orderItem) { |
||
478 | $stateName = $orderItem->getState()->getName(); |
||
479 | $processName = $orderItem->getProcess()->getName(); |
||
480 | $process = $processes[$processName]; |
||
481 | |||
482 | $state = $process->getStateFromAllProcesses($stateName); |
||
483 | |||
484 | if ($state->hasEvent($eventId)) { |
||
485 | $orderItemsFiltered[] = $orderItem; |
||
486 | } |
||
487 | } |
||
488 | |||
489 | return $orderItemsFiltered; |
||
490 | } |
||
491 | |||
492 | /** |
||
493 | * @param string $eventId |
||
494 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
495 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
496 | * |
||
497 | * @return array |
||
498 | */ |
||
499 | protected function groupByOrderAndState($eventId, array $orderItems, $processes) |
||
500 | { |
||
501 | $orderEventGroup = []; |
||
502 | foreach ($orderItems as $orderItem) { |
||
503 | $stateId = $orderItem->getState()->getName(); |
||
504 | $processId = $orderItem->getProcess()->getName(); |
||
505 | $process = $processes[$processId]; |
||
506 | $orderId = $orderItem->getOrder()->getIdSalesOrder(); |
||
507 | |||
508 | $state = $process->getStateFromAllProcesses($stateId); |
||
509 | |||
510 | if ($state->hasEvent($eventId)) { |
||
511 | $key = $orderId . '-' . $stateId; |
||
512 | if (!isset($orderEventGroup[$key])) { |
||
513 | $orderEventGroup[$key] = []; |
||
514 | } |
||
515 | $orderEventGroup[$key][] = $orderItem; |
||
516 | } |
||
517 | } |
||
518 | |||
519 | return $orderEventGroup; |
||
520 | } |
||
521 | |||
522 | /** |
||
523 | * @param \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandInterface $command |
||
524 | * |
||
525 | * @throws \LogicException |
||
526 | * |
||
527 | * @return string |
||
528 | */ |
||
529 | protected function getCommandType(CommandInterface $command) |
||
530 | { |
||
531 | if ($command instanceof CommandByOrderInterface) { |
||
532 | return static::BY_ORDER; |
||
533 | } |
||
534 | if ($command instanceof CommandByItemInterface) { |
||
535 | return static::BY_ITEM; |
||
536 | } |
||
537 | |||
538 | throw new LogicException('Unknown type of command: ' . get_class($command)); |
||
539 | } |
||
540 | |||
541 | /** |
||
542 | * Specification: |
||
543 | * - Performs commands on items |
||
544 | * - All passing items should have the same event available |
||
545 | * - For CommandByOrderInterface the command will be taken from the first order item |
||
546 | * |
||
547 | * @param string $eventId |
||
548 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
549 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
550 | * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject $data |
||
551 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
552 | * |
||
553 | * @throws \LogicException |
||
554 | * |
||
555 | * @return array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem>|null |
||
556 | */ |
||
557 | protected function runCommand($eventId, array $orderItems, array $processes, ReadOnlyArrayObject $data, TransitionLogInterface $log) |
||
558 | { |
||
559 | $processedOrderItems = []; |
||
560 | |||
561 | /** @var \Orm\Zed\Sales\Persistence\SpySalesOrderItem $currentOrderItemEntity */ |
||
562 | $currentOrderItemEntity = current($orderItems); |
||
563 | $orderEntity = $currentOrderItemEntity->getOrder(); |
||
564 | |||
565 | foreach ($orderItems as $orderItemEntity) { |
||
566 | $stateId = $orderItemEntity->getState()->getName(); |
||
567 | $processId = $orderItemEntity->getProcess()->getName(); |
||
568 | $process = $processes[$processId]; |
||
569 | $state = $process->getStateFromAllProcesses($stateId); |
||
570 | $event = $state->getEvent($eventId); |
||
571 | |||
572 | $log->setEvent($event); |
||
573 | |||
574 | if (!$event->hasCommand()) { |
||
575 | $processedOrderItems[] = $orderItemEntity; |
||
576 | |||
577 | continue; |
||
578 | } |
||
579 | |||
580 | /** @var \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandByOrderInterface|\Spryker\Zed\Oms\Dependency\Plugin\Command\CommandByItemInterface|\Spryker\Zed\Oms\Dependency\Plugin\Command\CommandInterface $command */ |
||
581 | $command = $this->getCommand($event->getCommand()); |
||
582 | $type = $this->getCommandType($command); |
||
583 | |||
584 | $log->addCommand($orderItemEntity, $command); |
||
585 | |||
586 | $omsEventTriggerResponseTransfer = (new OmsEventTriggerResponseTransfer())->setIsSuccessful(true); |
||
587 | $this->returnData[OmsConfig::OMS_EVENT_TRIGGER_RESPONSE] = $omsEventTriggerResponseTransfer; |
||
588 | |||
589 | try { |
||
590 | if ($command instanceof CommandByOrderInterface) { |
||
591 | $returnData = $command->run($orderItems, $orderEntity, $data); |
||
592 | if (is_array($returnData)) { |
||
593 | $this->returnData = array_merge($this->returnData, $returnData); |
||
594 | } |
||
595 | |||
596 | return $orderItems; |
||
597 | } |
||
598 | |||
599 | if ($command instanceof CommandByItemInterface) { |
||
600 | $returnData = $command->run($orderItemEntity, $data); |
||
601 | $this->returnData = array_merge($this->returnData, $returnData); |
||
602 | $processedOrderItems[] = $orderItemEntity; |
||
603 | } else { |
||
604 | throw new LogicException('Unknown type of command: ' . get_class($command)); |
||
605 | } |
||
606 | } catch (Exception $e) { |
||
607 | $log->setIsError(true); |
||
608 | $log->setErrorMessage(get_class($e) . ' - ' . $e->getMessage()); |
||
609 | $log->saveAll(); |
||
610 | |||
611 | ErrorLogger::getInstance()->log($e); |
||
612 | |||
613 | $errorMessage = $e->getMessage() ?: 'Currently not executable.'; |
||
614 | $omsEventTriggerResponseTransfer |
||
615 | ->setIsSuccessful(false) |
||
616 | ->addMessage( |
||
617 | (new MessageTransfer())->setValue($errorMessage), |
||
618 | ); |
||
619 | $this->returnData[OmsConfig::OMS_EVENT_TRIGGER_RESPONSE] = $omsEventTriggerResponseTransfer; |
||
620 | |||
621 | if ($type === static::BY_ORDER) { |
||
622 | return null; // intercept the processing of a grouped order items for the current order state |
||
623 | } |
||
624 | } |
||
625 | } |
||
626 | |||
627 | return $processedOrderItems; |
||
628 | } |
||
629 | |||
630 | /** |
||
631 | * @param string $eventId |
||
632 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
633 | * @param array $sourceStateBuffer |
||
634 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
635 | * |
||
636 | * @return array |
||
637 | */ |
||
638 | protected function updateStateByEvent($eventId, array $orderItems, array $sourceStateBuffer, TransitionLogInterface $log) |
||
639 | { |
||
640 | $targetStateMap = []; |
||
641 | foreach ($orderItems as $i => $orderItem) { |
||
642 | $stateId = $orderItem->getState()->getName(); |
||
643 | $sourceStateBuffer[$orderItem->getIdSalesOrderItem()] = $stateId; |
||
644 | |||
645 | $process = $this->builder->createProcess($orderItem->getProcess()->getName()); |
||
646 | $sourceState = $process->getStateFromAllProcesses($stateId); |
||
647 | |||
648 | $log->addSourceState($orderItem, $sourceState->getName()); |
||
649 | |||
650 | $targetState = $sourceState; |
||
651 | if ($eventId && $sourceState->hasEvent($eventId)) { |
||
652 | $transitions = $sourceState->getEvent($eventId)->getTransitionsBySource($sourceState); |
||
653 | $targetState = $this->checkCondition($transitions, $orderItem, $sourceState, $log); |
||
654 | $log->addTargetState($orderItem, $targetState->getName()); |
||
655 | } |
||
656 | |||
657 | $targetStateMap[$i] = $targetState->getName(); |
||
658 | } |
||
659 | |||
660 | foreach ($orderItems as $i => $orderItem) { |
||
661 | $this->setState($orderItems[$i], $targetStateMap[$i]); |
||
662 | } |
||
663 | |||
664 | return $sourceStateBuffer; |
||
665 | } |
||
666 | |||
667 | /** |
||
668 | * @param array $stateToTransitionsMap |
||
669 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
670 | * @param array $sourceStateBuffer |
||
671 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
672 | * |
||
673 | * @return array |
||
674 | */ |
||
675 | protected function updateStateByTransition($stateToTransitionsMap, array $orderItems, array $sourceStateBuffer, TransitionLogInterface $log) |
||
676 | { |
||
677 | $targetStateMap = []; |
||
678 | foreach ($orderItems as $i => $orderItem) { |
||
679 | $stateId = $orderItem->getState()->getName(); |
||
680 | $sourceStateBuffer[$orderItem->getIdSalesOrderItem()] = $stateId; |
||
681 | $process = $this->builder->createProcess($orderItem->getProcess()->getName()); |
||
682 | $sourceState = $process->getStateFromAllProcesses($stateId); |
||
683 | |||
684 | $log->addSourceState($orderItem, $sourceState->getName()); |
||
685 | |||
686 | $transitions = $stateToTransitionsMap[$orderItem->getState()->getName()]; |
||
687 | |||
688 | $targetState = $sourceState; |
||
689 | if (count($transitions) > 0) { |
||
690 | $targetState = $this->checkCondition($transitions, $orderItem, $sourceState, $log); |
||
691 | } |
||
692 | |||
693 | $log->addTargetState($orderItem, $targetState->getName()); |
||
694 | |||
695 | $targetStateMap[$i] = $targetState->getName(); |
||
696 | } |
||
697 | |||
698 | foreach ($orderItems as $i => $orderItem) { |
||
699 | $this->setState($orderItems[$i], $targetStateMap[$i]); |
||
700 | } |
||
701 | |||
702 | return $sourceStateBuffer; |
||
703 | } |
||
704 | |||
705 | /** |
||
706 | * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem $orderItem |
||
707 | * @param string $stateName |
||
708 | * |
||
709 | * @return void |
||
710 | */ |
||
711 | protected function setState($orderItem, $stateName) |
||
712 | { |
||
713 | if (isset($this->states[$stateName])) { |
||
714 | $state = $this->states[$stateName]; |
||
715 | } else { |
||
716 | $state = SpyOmsOrderItemStateQuery::create()->findOneByName($stateName); |
||
717 | if ($state === null) { |
||
718 | $state = new SpyOmsOrderItemState(); |
||
719 | $state->setName($stateName); |
||
720 | $state->save(); |
||
721 | } |
||
722 | $this->states[$stateName] = $state; |
||
723 | } |
||
724 | $orderItem->setState($state); |
||
725 | $orderItem->setLastStateChange(new DateTime()); |
||
726 | } |
||
727 | |||
728 | /** |
||
729 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
730 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
731 | * @param array $sourceStateBuffer |
||
732 | * |
||
733 | * @throws \LogicException |
||
734 | * |
||
735 | * @return array<array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem>> |
||
736 | */ |
||
737 | protected function filterItemsWithOnEnterEvent(array $orderItems, array $processes, array $sourceStateBuffer) |
||
738 | { |
||
739 | $orderItemsWithOnEnterEvent = []; |
||
740 | foreach ($orderItems as $orderItem) { |
||
741 | $stateId = $orderItem->getState()->getName(); |
||
742 | $processId = $orderItem->getProcess()->getName(); |
||
743 | |||
744 | if (!isset($processes[$processId])) { |
||
745 | throw new LogicException("Unknown process $processId"); |
||
746 | } |
||
747 | |||
748 | $process = $processes[$processId]; |
||
749 | $targetState = $process->getStateFromAllProcesses($stateId); |
||
750 | |||
751 | if (isset($sourceStateBuffer[$orderItem->getIdSalesOrderItem()])) { |
||
752 | $sourceState = $sourceStateBuffer[$orderItem->getIdSalesOrderItem()]; |
||
753 | } else { |
||
754 | $sourceState = $process->getStateFromAllProcesses($orderItem->getState()->getName()); |
||
755 | } |
||
756 | |||
757 | if ($sourceState === $targetState && $targetState->isReserved()) { |
||
758 | $reservationRequestTransfer = (new ReservationRequestTransfer()) |
||
759 | ->fromArray($orderItem->toArray(), true); |
||
760 | $this->reservation->updateReservation($reservationRequestTransfer); |
||
761 | } |
||
762 | |||
763 | if ( |
||
764 | $sourceState !== $targetState->getName() |
||
765 | && $targetState->hasOnEnterEvent() |
||
766 | ) { |
||
767 | $event = $targetState->getOnEnterEvent(); |
||
768 | if (array_key_exists($event->getName(), $orderItemsWithOnEnterEvent) === false) { |
||
769 | $orderItemsWithOnEnterEvent[$event->getName()] = []; |
||
770 | } |
||
771 | $orderItemsWithOnEnterEvent[$event->getName()][] = $orderItem; |
||
772 | } |
||
773 | } |
||
774 | |||
775 | return $orderItemsWithOnEnterEvent; |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject|array $data |
||
780 | * |
||
781 | * @return \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject |
||
782 | */ |
||
783 | protected function makeDataReadOnly($data) |
||
784 | { |
||
785 | if (is_array($data)) { |
||
786 | $data = new ReadOnlyArrayObject($data); |
||
787 | } |
||
788 | |||
789 | return $data; |
||
790 | } |
||
791 | |||
792 | /** |
||
793 | * To protect against loops, every event can only be used several times per order group. |
||
794 | * |
||
795 | * @param string $eventId |
||
796 | * @param string $orderGroupKey |
||
797 | * |
||
798 | * @return bool |
||
799 | */ |
||
800 | protected function checkOrderGroupForEventRepetitions(string $eventId, string $orderGroupKey): bool |
||
801 | { |
||
802 | if (!isset($this->eventCounter[$eventId][$orderGroupKey])) { |
||
803 | $this->eventCounter[$eventId][$orderGroupKey] = 0; |
||
804 | } |
||
805 | |||
806 | $this->eventCounter[$eventId][$orderGroupKey]++; |
||
807 | |||
808 | return $this->eventCounter[$eventId][$orderGroupKey] < static::MAX_EVENT_REPEATS; |
||
809 | } |
||
810 | |||
811 | /** |
||
812 | * @param array<array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem>> $orderItemsWithOnEnterEvent |
||
813 | * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject $data |
||
814 | * |
||
815 | * @return void |
||
816 | */ |
||
817 | protected function triggerOnEnterEvents(array $orderItemsWithOnEnterEvent, ReadOnlyArrayObject $data) |
||
818 | { |
||
819 | if (count($orderItemsWithOnEnterEvent) > 0) { |
||
820 | foreach ($orderItemsWithOnEnterEvent as $eventId => $orderItems) { |
||
821 | $this->triggerEvent($eventId, $orderItems, $data); |
||
822 | } |
||
823 | } |
||
824 | } |
||
825 | |||
826 | /** |
||
827 | * @param array<\Spryker\Zed\Oms\Business\Process\TransitionInterface> $transitions |
||
828 | * |
||
829 | * @return array |
||
830 | */ |
||
831 | protected function createStateToTransitionMap(array $transitions) |
||
832 | { |
||
833 | $stateToTransitionsMap = []; |
||
834 | foreach ($transitions as $transition) { |
||
835 | $sourceId = $transition->getSource()->getName(); |
||
836 | if (array_key_exists($sourceId, $stateToTransitionsMap) === false) { |
||
837 | $stateToTransitionsMap[$sourceId] = []; |
||
838 | } |
||
839 | $stateToTransitionsMap[$sourceId][] = $transition; |
||
840 | } |
||
841 | |||
842 | return $stateToTransitionsMap; |
||
843 | } |
||
844 | |||
845 | /** |
||
846 | * @param array $states |
||
847 | * @param \Spryker\Zed\Oms\Business\Process\ProcessInterface $process |
||
848 | * @param \Generated\Shared\Transfer\OmsCheckConditionsQueryCriteriaTransfer|null $omsCheckConditionsQueryCriteriaTransfer |
||
849 | * |
||
850 | * @return array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> |
||
851 | */ |
||
852 | protected function getOrderItemsByState( |
||
853 | array $states, |
||
854 | ProcessInterface $process, |
||
855 | ?OmsCheckConditionsQueryCriteriaTransfer $omsCheckConditionsQueryCriteriaTransfer |
||
856 | ) { |
||
857 | $omsCheckConditionsQueryCriteriaTransfer = $this->prepareOmsCheckConditionsQueryCriteriaTransfer($omsCheckConditionsQueryCriteriaTransfer); |
||
858 | |||
859 | $storeName = $omsCheckConditionsQueryCriteriaTransfer->getStoreName(); |
||
860 | $limit = $omsCheckConditionsQueryCriteriaTransfer->getLimit(); |
||
861 | |||
862 | if ($storeName === null && $limit === null) { |
||
863 | return $this->queryContainer |
||
864 | ->querySalesOrderItemsByState($states, $process->getName()) |
||
865 | ->find() |
||
866 | ->getData(); |
||
867 | } |
||
868 | |||
869 | $omsProcessEntity = $this->queryContainer->queryProcess($process->getName())->findOne(); |
||
870 | /** @var \Propel\Runtime\Collection\ObjectCollection $omsOrderItemEntityCollection */ |
||
871 | $omsOrderItemEntityCollection = $this->queryContainer->querySalesOrderItemStatesByName($states)->find(); |
||
872 | |||
873 | if ($omsProcessEntity === null || $omsOrderItemEntityCollection->count() === 0) { |
||
874 | return []; |
||
875 | } |
||
876 | |||
877 | return $this->queryContainer |
||
878 | ->querySalesOrderItemsByProcessIdStateIdsAndQueryCriteria( |
||
879 | $omsProcessEntity->getIdOmsOrderProcess(), |
||
880 | $omsOrderItemEntityCollection->getPrimaryKeys(), |
||
881 | $omsCheckConditionsQueryCriteriaTransfer, |
||
882 | ) |
||
883 | ->find() |
||
884 | ->getData(); |
||
885 | } |
||
886 | |||
887 | /** |
||
888 | * @param \Generated\Shared\Transfer\OmsCheckConditionsQueryCriteriaTransfer|null $omsCheckConditionsQueryCriteriaTransfer |
||
889 | * |
||
890 | * @return \Generated\Shared\Transfer\OmsCheckConditionsQueryCriteriaTransfer |
||
891 | */ |
||
892 | protected function prepareOmsCheckConditionsQueryCriteriaTransfer( |
||
893 | ?OmsCheckConditionsQueryCriteriaTransfer $omsCheckConditionsQueryCriteriaTransfer = null |
||
894 | ): OmsCheckConditionsQueryCriteriaTransfer { |
||
895 | if ($omsCheckConditionsQueryCriteriaTransfer === null) { |
||
896 | $omsCheckConditionsQueryCriteriaTransfer = new OmsCheckConditionsQueryCriteriaTransfer(); |
||
897 | } |
||
898 | |||
899 | if ($omsCheckConditionsQueryCriteriaTransfer->getLimit() === null) { |
||
900 | $omsCheckConditionsQueryCriteriaTransfer->setLimit($this->omsConfig->getCheckConditionsQueryLimit()); |
||
901 | } |
||
902 | |||
903 | return $omsCheckConditionsQueryCriteriaTransfer; |
||
904 | } |
||
905 | |||
906 | /** |
||
907 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
908 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
909 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
910 | * @param array $sourceStateBuffer |
||
911 | * |
||
912 | * @return void |
||
913 | */ |
||
914 | protected function saveOrderItems(array $orderItems, TransitionLogInterface $log, array $processes, array $sourceStateBuffer) |
||
915 | { |
||
916 | $currentTime = new DateTime('now'); |
||
917 | $timeoutModel = clone $this->timeout; |
||
918 | |||
919 | foreach ($orderItems as $orderItem) { |
||
920 | $this->handleDatabaseTransaction(function () use ($orderItem, $processes, $sourceStateBuffer, $timeoutModel, $log, $currentTime) { |
||
921 | $this->executeSaveOrderItemTransaction( |
||
922 | $orderItem, |
||
923 | $processes, |
||
924 | $sourceStateBuffer, |
||
925 | $timeoutModel, |
||
926 | $log, |
||
927 | $currentTime, |
||
928 | ); |
||
929 | }); |
||
930 | } |
||
931 | } |
||
932 | |||
933 | /** |
||
934 | * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem $orderItem |
||
935 | * @param array $processes |
||
936 | * @param array $sourceStateBuffer |
||
937 | * @param \Spryker\Zed\Oms\Business\OrderStateMachine\TimeoutInterface $timeoutModel |
||
938 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
939 | * @param \DateTime $currentTime |
||
940 | * |
||
941 | * @return void |
||
942 | */ |
||
943 | protected function executeSaveOrderItemTransaction( |
||
944 | SpySalesOrderItem $orderItem, |
||
945 | array $processes, |
||
946 | array $sourceStateBuffer, |
||
947 | TimeoutInterface $timeoutModel, |
||
948 | TransitionLogInterface $log, |
||
949 | DateTime $currentTime |
||
950 | ) { |
||
951 | $process = $processes[$orderItem->getProcess()->getName()]; |
||
952 | |||
953 | $sourceState = $sourceStateBuffer[$orderItem->getIdSalesOrderItem()]; |
||
954 | $targetState = $orderItem->getState()->getName(); |
||
955 | |||
956 | if ($sourceState !== $targetState) { |
||
957 | $timeoutModel->dropOldTimeout($process, $sourceState, $orderItem); |
||
958 | $timeoutModel->setNewTimeout($process, $orderItem, $currentTime); |
||
959 | } |
||
960 | |||
961 | $orderItem->save(); |
||
962 | $this->updateOmsReservation($process, $sourceState, $targetState, $orderItem); |
||
963 | $log->save($orderItem); |
||
964 | } |
||
965 | |||
966 | /** |
||
967 | * @param string $command |
||
968 | * |
||
969 | * @return \Spryker\Zed\Oms\Dependency\Plugin\Command\CommandInterface |
||
970 | */ |
||
971 | protected function getCommand($command) |
||
972 | { |
||
973 | return $this->commands->get($command); |
||
974 | } |
||
975 | |||
976 | /** |
||
977 | * @param string $condition |
||
978 | * |
||
979 | * @return \Spryker\Zed\Oms\Dependency\Plugin\Condition\ConditionInterface |
||
980 | */ |
||
981 | protected function getCondition($condition) |
||
982 | { |
||
983 | return $this->conditions->get($condition); |
||
984 | } |
||
985 | |||
986 | /** |
||
987 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
988 | * |
||
989 | * @return \Spryker\Zed\Oms\Business\Util\TransitionLogInterface |
||
990 | */ |
||
991 | protected function initTransitionLog(array $orderItems) |
||
992 | { |
||
993 | $log = clone $this->transitionLog; |
||
994 | |||
995 | $log->init($orderItems); |
||
996 | |||
997 | return $log; |
||
998 | } |
||
999 | |||
1000 | /** |
||
1001 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
1002 | * @param \Spryker\Zed\Oms\Business\Util\TransitionLogInterface $log |
||
1003 | * |
||
1004 | * @return void |
||
1005 | */ |
||
1006 | protected function logSourceState($orderItems, TransitionLogInterface $log) |
||
1007 | { |
||
1008 | foreach ($orderItems as $orderItem) { |
||
1009 | $stateName = $orderItem->getState()->getName(); |
||
1010 | $log->addSourceState($orderItem, $stateName); |
||
1011 | } |
||
1012 | } |
||
1013 | |||
1014 | /** |
||
1015 | * @deprecated Use {@link updateOmsReservation()} instead. |
||
1016 | * |
||
1017 | * @param \Spryker\Zed\Oms\Business\Process\ProcessInterface $process |
||
1018 | * @param string $sourceStateId |
||
1019 | * @param string $targetStateId |
||
1020 | * @param string $sku |
||
1021 | * |
||
1022 | * @return void |
||
1023 | */ |
||
1024 | protected function updateReservation(ProcessInterface $process, $sourceStateId, $targetStateId, $sku) |
||
1025 | { |
||
1026 | $sourceStateIsReserved = $process->getStateFromAllProcesses($sourceStateId)->isReserved(); |
||
1027 | $targetStateIsReserved = $process->getStateFromAllProcesses($targetStateId)->isReserved(); |
||
1028 | |||
1029 | if ($sourceStateIsReserved !== $targetStateIsReserved) { |
||
1030 | $this->reservation->updateReservationQuantity($sku); |
||
1031 | } |
||
1032 | } |
||
1033 | |||
1034 | /** |
||
1035 | * @param \Spryker\Zed\Oms\Business\Process\ProcessInterface $process |
||
1036 | * @param string $sourceState |
||
1037 | * @param string $targetState |
||
1038 | * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem $salesOrderItem |
||
1039 | * |
||
1040 | * @return void |
||
1041 | */ |
||
1042 | protected function updateOmsReservation( |
||
1043 | ProcessInterface $process, |
||
1044 | string $sourceState, |
||
1045 | string $targetState, |
||
1046 | SpySalesOrderItem $salesOrderItem |
||
1047 | ): void { |
||
1048 | $sourceStateIsReserved = $process->getStateFromAllProcesses($sourceState)->isReserved(); |
||
1049 | $targetStateIsReserved = $process->getStateFromAllProcesses($targetState)->isReserved(); |
||
1050 | |||
1051 | if ($sourceStateIsReserved !== $targetStateIsReserved) { |
||
1052 | $reservationRequestTransfer = (new ReservationRequestTransfer()) |
||
1053 | ->fromArray($salesOrderItem->toArray(), true); |
||
1054 | $this->reservation->updateReservation($reservationRequestTransfer); |
||
1055 | } |
||
1056 | } |
||
1057 | |||
1058 | /** |
||
1059 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
1060 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
1061 | * |
||
1062 | * @throws \LogicException |
||
1063 | * |
||
1064 | * @return array |
||
1065 | */ |
||
1066 | protected function filterItemsWithTimeoutEvent(array $orderItems, array $processes) |
||
1067 | { |
||
1068 | $orderItemsWithTimeoutEvent = []; |
||
1069 | foreach ($orderItems as $orderItem) { |
||
1070 | $stateId = $orderItem->getState()->getName(); |
||
1071 | $processId = $orderItem->getProcess()->getName(); |
||
1072 | |||
1073 | if (!isset($processes[$processId])) { |
||
1074 | throw new LogicException("Unknown process $processId"); |
||
1075 | } |
||
1076 | |||
1077 | $process = $processes[$processId]; |
||
1078 | $targetState = $process->getStateFromAllProcesses($stateId); |
||
1079 | |||
1080 | if ($targetState->hasTimeoutEvent()) { |
||
1081 | $events = $targetState->getTimeoutEvents(); |
||
1082 | foreach ($events as $event) { |
||
1083 | $orderItemKey = sprintf('%s_%s', $orderItem->getIdSalesOrderItem(), $orderItem->getFkOmsOrderItemState()); |
||
1084 | if (!isset($orderItemsWithTimeoutEvent[$event->getName()][$orderItemKey])) { |
||
1085 | $orderItemsWithTimeoutEvent[$event->getName()][$orderItemKey] = $orderItem; |
||
1086 | } |
||
1087 | } |
||
1088 | } |
||
1089 | } |
||
1090 | |||
1091 | return $orderItemsWithTimeoutEvent; |
||
1092 | } |
||
1093 | |||
1094 | /** |
||
1095 | * @param array $orderItemsWithTimeoutEvent |
||
1096 | * |
||
1097 | * @return void |
||
1098 | */ |
||
1099 | protected function saveTimeoutEvents(array $orderItemsWithTimeoutEvent) |
||
1100 | { |
||
1101 | foreach ($orderItemsWithTimeoutEvent as $eventId => $orderItems) { |
||
1102 | $this->saveTimeoutEvent($eventId, $orderItems); |
||
1103 | } |
||
1104 | } |
||
1105 | |||
1106 | /** |
||
1107 | * @param string $eventId |
||
1108 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
1109 | * |
||
1110 | * @return void |
||
1111 | */ |
||
1112 | protected function saveTimeoutEvent($eventId, array $orderItems) |
||
1113 | { |
||
1114 | $processes = $this->getProcesses($orderItems); |
||
1115 | $orderItems = $this->filterAffectedOrderItems($eventId, $orderItems, $processes); |
||
1116 | $sourceStateBuffer = $this->getStateByEvent($orderItems); |
||
1117 | $orderGroup = $this->groupByOrderAndState($eventId, $orderItems, $processes); |
||
1118 | |||
1119 | foreach ($orderGroup as $orderGroupKey => $groupedOrderItems) { |
||
1120 | if (!$this->checkOrderGroupForEventRepetitions($eventId, $orderGroupKey)) { |
||
1121 | return; |
||
1122 | } |
||
1123 | |||
1124 | $this->saveOrderItemsTimeout($groupedOrderItems, $processes, $sourceStateBuffer); |
||
1125 | } |
||
1126 | } |
||
1127 | |||
1128 | /** |
||
1129 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
1130 | * |
||
1131 | * @return array |
||
1132 | */ |
||
1133 | protected function getStateByEvent(array $orderItems) |
||
1134 | { |
||
1135 | $sourceStateBuffer = []; |
||
1136 | foreach ($orderItems as $orderItem) { |
||
1137 | $stateId = $orderItem->getState()->getName(); |
||
1138 | $sourceStateBuffer[$orderItem->getIdSalesOrderItem()] = $stateId; |
||
1139 | } |
||
1140 | |||
1141 | return $sourceStateBuffer; |
||
1142 | } |
||
1143 | |||
1144 | /** |
||
1145 | * @param array<\Orm\Zed\Sales\Persistence\SpySalesOrderItem> $orderItems |
||
1146 | * @param array<\Spryker\Zed\Oms\Business\Process\ProcessInterface> $processes |
||
1147 | * @param array $sourceStateBuffer |
||
1148 | * |
||
1149 | * @return void |
||
1150 | */ |
||
1151 | protected function saveOrderItemsTimeout(array $orderItems, array $processes, array $sourceStateBuffer) |
||
1152 | { |
||
1153 | $currentTime = new DateTime('now'); |
||
1154 | |||
1155 | $this->timeout->dropOldTimeouts($orderItems, $processes, $sourceStateBuffer); |
||
1156 | $this->timeout->setNewTimeouts($orderItems, $currentTime, $processes); |
||
1157 | } |
||
1158 | } |
||
1159 |
This trait has been deprecated. The supplier of the trait has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.