OrderRepository.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <?php
  2. /**
  3. * Refer to LICENSE.txt distributed with the Temando Shipping module for notice of license
  4. */
  5. namespace Temando\Shipping\Model\ResourceModel\Order;
  6. use Magento\Framework\Exception\CouldNotSaveException;
  7. use Magento\Framework\Exception\NoSuchEntityException;
  8. use Temando\Shipping\Api\Data\Order\OrderReferenceInterface;
  9. use Temando\Shipping\Api\Data\Order\OrderReferenceInterfaceFactory;
  10. use Temando\Shipping\Model\OrderInterface;
  11. use Temando\Shipping\Model\ResourceModel\Repository\OrderRepositoryInterface;
  12. use Temando\Shipping\Rest\Adapter\OrderApiInterface;
  13. use Temando\Shipping\Rest\EntityMapper\OrderRequestTypeBuilder;
  14. use Temando\Shipping\Rest\EntityMapper\OrderResponseMapper;
  15. use Temando\Shipping\Rest\Exception\AdapterException;
  16. use Temando\Shipping\Rest\Request\OrderRequestFactory;
  17. use Temando\Shipping\Rest\Request\Type\OrderRequestTypeInterface;
  18. use Temando\Shipping\Webservice\Response\Type\OrderResponseType;
  19. /**
  20. * Temando Order Repository
  21. *
  22. * @package Temando\Shipping\Model
  23. * @author Christoph Aßmann <christoph.assmann@netresearch.de>
  24. * @author Sebastian Ertner <sebastian.ertner@netresearch.de>
  25. * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  26. * @link https://www.temando.com/
  27. */
  28. class OrderRepository implements OrderRepositoryInterface
  29. {
  30. /**
  31. * @var OrderApiInterface
  32. */
  33. private $apiAdapter;
  34. /**
  35. * @var OrderRequestFactory
  36. */
  37. private $requestFactory;
  38. /**
  39. * @var OrderRequestTypeBuilder
  40. */
  41. private $requestBuilder;
  42. /**
  43. * @var OrderResponseMapper
  44. */
  45. private $orderResponseMapper;
  46. /**
  47. * @var OrderReference
  48. */
  49. private $resource;
  50. /**
  51. * @var OrderReferenceInterfaceFactory
  52. */
  53. private $orderReferenceFactory;
  54. /**
  55. * OrderRepository constructor.
  56. * @param OrderApiInterface $apiAdapter
  57. * @param OrderRequestFactory $requestFactory
  58. * @param OrderRequestTypeBuilder $requestBuilder
  59. * @param OrderResponseMapper $orderResponseMapper
  60. * @param OrderReference $resource
  61. * @param OrderReferenceInterfaceFactory $orderReferenceFactory
  62. */
  63. public function __construct(
  64. OrderApiInterface $apiAdapter,
  65. OrderRequestFactory $requestFactory,
  66. OrderRequestTypeBuilder $requestBuilder,
  67. OrderResponseMapper $orderResponseMapper,
  68. OrderReference $resource,
  69. OrderReferenceInterfaceFactory $orderReferenceFactory
  70. ) {
  71. $this->apiAdapter = $apiAdapter;
  72. $this->requestFactory = $requestFactory;
  73. $this->requestBuilder = $requestBuilder;
  74. $this->orderResponseMapper = $orderResponseMapper;
  75. $this->resource = $resource;
  76. $this->orderReferenceFactory = $orderReferenceFactory;
  77. }
  78. /**
  79. * @param int $entityId
  80. * @return OrderReferenceInterface
  81. * @throws NoSuchEntityException
  82. */
  83. private function getReferenceById($entityId)
  84. {
  85. /** @var \Temando\Shipping\Model\Order\OrderReference $orderReference */
  86. $orderReference = $this->orderReferenceFactory->create();
  87. $this->resource->load($orderReference, $entityId);
  88. if (!$orderReference->getId()) {
  89. throw new NoSuchEntityException(__('Order with id "%1" does not exist.', $entityId));
  90. }
  91. return $orderReference;
  92. }
  93. /**
  94. * Create a regular order at the platform.
  95. *
  96. * @param OrderRequestTypeInterface $orderType
  97. * @return OrderResponseType
  98. * @throws CouldNotSaveException
  99. */
  100. private function create(OrderRequestTypeInterface $orderType)
  101. {
  102. $orderRequest = $this->requestFactory->create([
  103. 'order' => $orderType,
  104. 'action' => OrderApiInterface::ACTION_CREATE,
  105. ]);
  106. try {
  107. $createdOrder = $this->apiAdapter->createOrder($orderRequest);
  108. } catch (AdapterException $e) {
  109. throw new CouldNotSaveException(__('Unable to save order.'), $e);
  110. }
  111. return $this->orderResponseMapper->map($createdOrder);
  112. }
  113. /**
  114. * Create a regular order at the platform and allocate pickup fulfillments.
  115. *
  116. * @param OrderRequestTypeInterface $orderType
  117. * @return OrderResponseType
  118. * @throws CouldNotSaveException
  119. */
  120. private function allocatePickup(OrderRequestTypeInterface $orderType)
  121. {
  122. $orderRequest = $this->requestFactory->create([
  123. 'order' => $orderType,
  124. 'action' => OrderApiInterface::ACTION_ALLOCATE_PICKUP,
  125. ]);
  126. try {
  127. $createdOrder = $this->apiAdapter->createOrder($orderRequest);
  128. } catch (AdapterException $e) {
  129. throw new CouldNotSaveException(__('Unable to save order.'), $e);
  130. }
  131. return $this->orderResponseMapper->map($createdOrder);
  132. }
  133. /**
  134. * Create a regular order at the platform and allocate shipments.
  135. *
  136. * @param OrderRequestTypeInterface $orderType
  137. * @return OrderResponseType
  138. * @throws CouldNotSaveException
  139. */
  140. private function allocateShipment(OrderRequestTypeInterface $orderType)
  141. {
  142. $orderRequest = $this->requestFactory->create([
  143. 'order' => $orderType,
  144. 'action' => OrderApiInterface::ACTION_ALLOCATE_SHIPMENT,
  145. ]);
  146. try {
  147. $allocatedOrder = $this->apiAdapter->createOrder($orderRequest);
  148. } catch (AdapterException $e) {
  149. throw new CouldNotSaveException(__('Unable to allocate shipments.'), $e);
  150. }
  151. return $this->orderResponseMapper->map($allocatedOrder);
  152. }
  153. /**
  154. * Update a previously created order at the platform.
  155. *
  156. * @param OrderRequestTypeInterface $orderType
  157. * @return OrderResponseType
  158. * @throws CouldNotSaveException
  159. */
  160. private function update(OrderRequestTypeInterface $orderType)
  161. {
  162. $orderRequest = $this->requestFactory->create([
  163. 'order' => $orderType,
  164. 'action' => OrderApiInterface::ACTION_UPDATE,
  165. ]);
  166. try {
  167. $updatedOrder = $this->apiAdapter->updateOrder($orderRequest);
  168. } catch (AdapterException $e) {
  169. throw new CouldNotSaveException(__('Unable to save order.'), $e);
  170. }
  171. return $this->orderResponseMapper->map($updatedOrder);
  172. }
  173. /**
  174. * @param OrderInterface $order
  175. * @return OrderResponseType
  176. * @throws CouldNotSaveException
  177. */
  178. public function save(OrderInterface $order)
  179. {
  180. // build order request type
  181. $orderType = $this->requestBuilder->build($order);
  182. // may be replaced by config setting in the future.
  183. $isOrderAllocationEnabled = true;
  184. $isPaymentPending = ($order->getStatus() === OrderInterface::STATUS_AWAITING_PAYMENT);
  185. $isUpdate = $order->getOrderId() && $order->getSourceId();
  186. $pickup = $order->getPickupLocation();
  187. $isPickupOrder = !empty($pickup) && !empty($pickup->getPickupLocationId());
  188. if ($isUpdate) {
  189. $orderResponse = $this->update($orderType);
  190. } elseif ($isPickupOrder) {
  191. $orderResponse = $this->allocatePickup($orderType);
  192. } elseif ($isOrderAllocationEnabled && !$isPaymentPending) {
  193. $orderResponse = $this->allocateShipment($orderType);
  194. } else {
  195. $orderResponse = $this->create($orderType);
  196. }
  197. if ($order->getSourceId() && !$order->getOrderId()) {
  198. // persist order reference if
  199. // - local order entity exists
  200. // - remote order entity does not yet exist
  201. $orderReference = $this->orderReferenceFactory->create(['data' => [
  202. OrderReferenceInterface::EXT_ORDER_ID => $orderResponse->getOrderId(),
  203. OrderReferenceInterface::ORDER_ID => $order->getSourceId(),
  204. ]]);
  205. $this->saveReference($orderReference);
  206. }
  207. return $orderResponse;
  208. }
  209. /**
  210. * @param OrderReferenceInterface $orderReference
  211. * @return OrderReferenceInterface
  212. * @throws CouldNotSaveException
  213. */
  214. public function saveReference(OrderReferenceInterface $orderReference)
  215. {
  216. try {
  217. /** @var \Temando\Shipping\Model\Order\OrderReference $orderReference */
  218. $this->resource->save($orderReference);
  219. } catch (\Exception $exception) {
  220. throw new CouldNotSaveException(__('Unable to save order reference.'), $exception);
  221. }
  222. return $orderReference;
  223. }
  224. /**
  225. * @param string $orderId Temando Order ID
  226. * @return OrderReferenceInterface
  227. * @throws NoSuchEntityException
  228. */
  229. public function getReferenceByExtOrderId($orderId)
  230. {
  231. $entityId = $this->resource->getIdByExtOrderId($orderId);
  232. if (!$entityId) {
  233. throw new NoSuchEntityException(__('Order reference to "%1" does not exist.', $orderId));
  234. }
  235. return $this->getReferenceById($entityId);
  236. }
  237. /**
  238. * @param int $orderId
  239. * @return OrderReferenceInterface
  240. * @throws NoSuchEntityException
  241. */
  242. public function getReferenceByOrderId($orderId)
  243. {
  244. $entityId = $this->resource->getIdByOrderId($orderId);
  245. if (!$entityId) {
  246. $msg = 'Order reference for order "%1" does not exist.';
  247. throw new NoSuchEntityException(__($msg, $orderId));
  248. }
  249. return $this->getReferenceById($entityId);
  250. }
  251. }