1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
/**
* Refer to LICENSE.txt distributed with the Temando Shipping module for notice of license
*/
namespace Temando\Shipping\Plugin\Sales;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\OrderRepositoryInterface as SalesOrderRepositoryInterface;
use Psr\Log\LoggerInterface;
use Temando\Shipping\Api\Data\Order\OrderReferenceInterface;
use Temando\Shipping\Api\Data\Order\OrderReferenceInterfaceFactory;
use Temando\Shipping\Model\Checkout\Submit\OrderDataInitializer;
use Temando\Shipping\Model\ResourceModel\Repository\OrderRepositoryInterface;
use Temando\Shipping\Model\Shipping\Carrier;
use Temando\Shipping\Webservice\Processor\OrderOperationProcessorPool;
/**
* OrderRepositoryPlugin
*
* @package Temando\Shipping\Plugin
* @author Christoph Aßmann <christoph.assmann@netresearch.de>
* @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @link https://www.temando.com/
*/
class OrderRepositoryPlugin
{
/**
* @var OrderReferenceInterfaceFactory
*/
private $orderReferenceFactory;
/**
* @var OrderDataInitializer
*/
private $orderDataInitializer;
/**
* @var OrderRepositoryInterface
*/
private $orderRepository;
/**
* @var OrderOperationProcessorPool
*/
private $processorPool;
/**
* @var LoggerInterface
*/
private $logger;
/**
* OrderRepositoryPlugin constructor.
* @param OrderReferenceInterfaceFactory $orderReferenceFactory
* @param OrderDataInitializer $orderDataInitializer
* @param OrderRepositoryInterface $orderRepository
* @param OrderOperationProcessorPool $processorPool
* @param LoggerInterface $logger
*/
public function __construct(
OrderReferenceInterfaceFactory $orderReferenceFactory,
OrderDataInitializer $orderDataInitializer,
OrderRepositoryInterface $orderRepository,
OrderOperationProcessorPool $processorPool,
LoggerInterface $logger
) {
$this->orderReferenceFactory = $orderReferenceFactory;
$this->orderDataInitializer = $orderDataInitializer;
$this->orderRepository = $orderRepository;
$this->processorPool = $processorPool;
$this->logger = $logger;
}
/**
* Manifest order at Temando platform.
*
* Observers don't work:
* - `sales_order_save_commit_after` is no longer triggered in guest checkout
* - `sales_order_save_after` does not have related entities (addresses) persisted yet
*
* Other promising events like `sales_order_place_after`, `checkout_submit_all_after`,
* `sales_model_service_quote_submit_success` are
* - triggered before the order was saved or
* - not triggered at all in multi address checkout or some payment providers'
* custom checkout implementations (paypal express, sagepay, …).
*
* @param SalesOrderRepositoryInterface $subject
* @param OrderInterface|\Magento\Sales\Model\Order $salesOrder
* @return OrderInterface
*/
public function afterSave(SalesOrderRepositoryInterface $subject, OrderInterface $salesOrder)
{
if (!$salesOrder->getData('shipping_method')) {
// virtual or corrupt order
return $salesOrder;
}
$shippingMethod = $salesOrder->getShippingMethod(true);
$carrierCode = $shippingMethod->getData('carrier_code');
if ($carrierCode !== Carrier::CODE) {
// not interested in other carriers
return $salesOrder;
}
try {
$orderReference = $this->orderRepository->getReferenceByOrderId($salesOrder->getId());
} catch (NoSuchEntityException $exception) {
$orderReference = $this->orderReferenceFactory->create(['data' => [
OrderReferenceInterface::ORDER_ID => $salesOrder->getId(),
]]);
}
if ($orderReference->getExtOrderId()) {
// Do not send orders to Temando platform that were saved already.
return $salesOrder;
}
try {
// create request data from local (sales) order entity
$order = $this->orderDataInitializer->getOrder($salesOrder);
// save order at Temando platform as well as local reference to it.
$saveResult = $this->orderRepository->save($order);
$this->processorPool->processSaveResponse($salesOrder, $order, $saveResult);
} catch (LocalizedException $exception) {
// nothing we can do here, just don't interrupt order process
$this->logger->critical($exception->getLogMessage(), ['exception' => $exception]);
}
return $salesOrder;
}
}