PlacedOrderFixture.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <?php
  2. /**
  3. * Refer to LICENSE.txt distributed with the Temando Shipping module for notice of license
  4. */
  5. namespace Temando\Shipping\Test\Integration\Fixture;
  6. use Magento\Catalog\Api\ProductRepositoryInterface;
  7. use Magento\Catalog\Model\ProductRepository;
  8. use Magento\Framework\Api\SearchCriteriaBuilder;
  9. use Magento\Sales\Model\Order\Address as OrderAddress;
  10. use Magento\Sales\Model\OrderRepository;
  11. use Magento\Quote\Model\Quote\Address as QuoteAddress;
  12. use Magento\Quote\Model\QuoteRepository;
  13. use Magento\TestFramework\Helper\Bootstrap;
  14. use Temando\Shipping\Api\Data\Order\OrderReferenceInterface;
  15. use Temando\Shipping\Model\Order\OrderReference;
  16. use Temando\Shipping\Model\ResourceModel\Order\OrderRepository as OrderReferenceRepository;
  17. /**
  18. * PlacedOrderFixture
  19. *
  20. * @package Temando\Shipping\Test
  21. * @author Christoph Aßmann <christoph.assmann@netresearch.de>
  22. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  23. * @link http://www.temando.com/
  24. */
  25. final class PlacedOrderFixture
  26. {
  27. /**
  28. * @var string
  29. */
  30. private static $orderIncrementId = '0000000303';
  31. /**
  32. * @var string
  33. */
  34. private static $externalOrderId = '00000000-3000-0003-0000-000000000000';
  35. /**
  36. * @var string[]
  37. */
  38. private $customerData = [
  39. 'email' => 'foo@example.org',
  40. 'firstname' => 'Foo',
  41. 'lastname' => 'Example',
  42. 'company' => 'Temando',
  43. 'street' => '550 Montgomery St.',
  44. 'city' => 'California',
  45. 'postcode' => '94111',
  46. 'country' => 'US',
  47. 'phone' => '911',
  48. ];
  49. /**
  50. * @var string[]
  51. */
  52. private $productData = [
  53. 'FX-24-MB03' => [
  54. 'name' => 'Crown Summit Fixture Backpack',
  55. 'qty' => 1,
  56. 'unit_price' => 38,
  57. ],
  58. 'FX-24-WG03' => [
  59. 'name' => 'Clamber Fixture Watch',
  60. 'qty' => 2,
  61. 'unit_price' => 54,
  62. ],
  63. ];
  64. /**
  65. * @param string $addressType
  66. * @return OrderAddress
  67. */
  68. private function getOrderAddress($addressType)
  69. {
  70. $address = Bootstrap::getObjectManager()->create(OrderAddress::class, ['data' => [
  71. 'address_type' => $addressType,
  72. 'email' => $this->customerData['email'],
  73. 'firstname' => $this->customerData['firstname'],
  74. 'lastname' => $this->customerData['lastname'],
  75. 'company' => $this->customerData['company'],
  76. 'street' => $this->customerData['street'],
  77. 'city' => $this->customerData['city'],
  78. 'postcode' => $this->customerData['postcode'],
  79. 'country_id' => $this->customerData['country'],
  80. 'telephone' => $this->customerData['phone'],
  81. ]]);
  82. return $address;
  83. }
  84. /**
  85. * @param string $addressType
  86. * @return QuoteAddress
  87. */
  88. private function getQuoteAddress($addressType)
  89. {
  90. $address = Bootstrap::getObjectManager()->create(QuoteAddress::class, ['data' => [
  91. 'address_type' => $addressType,
  92. 'email' => $this->customerData['email'],
  93. 'firstname' => $this->customerData['firstname'],
  94. 'lastname' => $this->customerData['lastname'],
  95. 'company' => $this->customerData['company'],
  96. 'street' => $this->customerData['street'],
  97. 'city' => $this->customerData['city'],
  98. 'postcode' => $this->customerData['postcode'],
  99. 'country_id' => $this->customerData['country'],
  100. 'telephone' => $this->customerData['phone'],
  101. ]]);
  102. return $address;
  103. }
  104. /**
  105. * @param string $orderIncrementId
  106. * @param string $quoteId
  107. * @param string $storeId
  108. * @param string $currency
  109. * @return \Magento\Sales\Model\Order
  110. */
  111. private function getOrder($orderIncrementId, $quoteId, $storeId = '1', $currency = 'USD')
  112. {
  113. $orderDate = date('Y-m-d H:i:s');
  114. $shippingMethod = 'temando_standard';
  115. $shippingCost = 7.95;
  116. $subTotal = 0;
  117. /** @var \Magento\Sales\Model\Order $order */
  118. $order = Bootstrap::getObjectManager()->create(\Magento\Sales\Model\Order::class, ['data' => [
  119. 'increment_id' => $orderIncrementId,
  120. 'quote_id' => $quoteId,
  121. 'store_id' => $storeId,
  122. 'created_at' => $orderDate,
  123. 'updated_at' => $orderDate,
  124. 'shipping_method' => $shippingMethod,
  125. 'shipping_amount' => $shippingCost,
  126. 'base_shipping_amount' => $shippingCost,
  127. 'base_currency_code' => $currency,
  128. 'store_currency_code' => $currency,
  129. 'customer_email' => $this->customerData['email'],
  130. 'customer_firstname' => $this->customerData['firstname'],
  131. 'customer_lastname' => $this->customerData['lastname'],
  132. ]]);
  133. foreach ($this->productData as $sku => $productData) {
  134. $orderItemQty = $productData['qty'];
  135. $orderItemUnitPrice = $productData['unit_price'];
  136. $orderItem = Bootstrap::getObjectManager()->create(\Magento\Sales\Model\Order\Item::class, ['data' => [
  137. 'created_at' => $orderDate,
  138. 'store_id' => $storeId,
  139. 'is_virtual' => false,
  140. 'sku' => $sku,
  141. 'name' => $productData['name'],
  142. 'product_id' => $productData['entity_id'],
  143. 'qty' => $orderItemQty,
  144. 'price' => $orderItemUnitPrice,
  145. 'base_price' => $orderItemUnitPrice,
  146. 'row_total' => $orderItemQty * $orderItemUnitPrice,
  147. 'base_row_total' => $orderItemQty * $orderItemUnitPrice,
  148. 'product_type' => 'simple',
  149. 'price_incl_tax' => $orderItemUnitPrice,
  150. 'base_price_incl_tax' => $orderItemUnitPrice,
  151. 'row_total_incl_tax' => $orderItemQty * $orderItemUnitPrice,
  152. 'base_row_total_incl_tax' => $orderItemQty * $orderItemUnitPrice,
  153. 'qty_ordered' => $productData['qty'],
  154. 'qty_shipped' => 0,
  155. 'qty_refunded' => 0,
  156. 'qty_canceled' => 0,
  157. ]]);
  158. $order->addItem($orderItem);
  159. $subTotal += ($orderItemQty * $orderItemUnitPrice);
  160. }
  161. $order->setTotalItemCount(count($order->getItems()));
  162. $order->setSubtotal($subTotal);
  163. $order->setBaseSubtotal($subTotal);
  164. $order->setGrandTotal($subTotal + $shippingCost);
  165. $order->setBaseGrandTotal($subTotal + $shippingCost);
  166. return $order;
  167. }
  168. /**
  169. * @param string $orderIncrementId
  170. * @param string $storeId
  171. * @param string $currency
  172. * @return \Magento\Quote\Model\Quote
  173. */
  174. private function getQuote($orderIncrementId, $storeId = '1', $currency = 'USD')
  175. {
  176. $quoteDate = date('Y-m-d H:i:s');
  177. $shippingCost = 7.95;
  178. $subTotal = 0;
  179. /** @var \Magento\Quote\Model\Quote $quote */
  180. $quote = Bootstrap::getObjectManager()->create(\Magento\Quote\Model\Quote::class, ['data' => [
  181. 'store_id' => $storeId,
  182. 'created_at' => $quoteDate,
  183. 'updated_at' => $quoteDate,
  184. 'base_currency_code' => $currency,
  185. 'store_currency_code' => $currency,
  186. 'customer_email' => $this->customerData['email'],
  187. 'customer_firstname' => $this->customerData['firstname'],
  188. 'customer_lastname' => $this->customerData['lastname'],
  189. 'reserved_order_id' => $orderIncrementId,
  190. 'is_active' => '0', // already converted to order
  191. ]]);
  192. foreach ($this->productData as $sku => $productData) {
  193. $quoteItemQty = $productData['qty'];
  194. $quoteItemUnitPrice = $productData['unit_price'];
  195. $quoteItem = Bootstrap::getObjectManager()->create(\Magento\Quote\Model\Quote\Item::class, ['data' => [
  196. 'created_at' => $quoteDate,
  197. 'store_id' => $storeId,
  198. 'is_virtual' => false,
  199. 'sku' => $sku,
  200. 'name' => $productData['name'],
  201. 'qty' => $quoteItemQty,
  202. 'price' => $quoteItemUnitPrice,
  203. 'base_price' => $quoteItemUnitPrice,
  204. 'row_total' => $quoteItemQty * $quoteItemUnitPrice,
  205. 'base_row_total' => $quoteItemQty * $quoteItemUnitPrice,
  206. 'product_type' => 'simple',
  207. 'price_incl_tax' => $quoteItemUnitPrice,
  208. 'base_price_incl_tax' => $quoteItemUnitPrice,
  209. 'row_total_incl_tax' => $quoteItemQty * $quoteItemUnitPrice,
  210. 'base_row_total_incl_tax' => $quoteItemQty * $quoteItemUnitPrice,
  211. 'product_id' => $productData['entity_id'],
  212. ]]);
  213. $quote->addItem($quoteItem);
  214. $subTotal += ($quoteItemQty * $quoteItemUnitPrice);
  215. }
  216. $quote->setItemsCount(count($quote->getItems()));
  217. $quote->setSubtotal($subTotal);
  218. $quote->setBaseSubtotal($subTotal);
  219. $quote->setGrandTotal($subTotal + $shippingCost);
  220. $quote->setBaseGrandTotal($subTotal + $shippingCost);
  221. return $quote;
  222. }
  223. // ---------- GETTERS FOR ASSERTIONS / LOADING FIXTURE ENTITIES --------- //
  224. /**
  225. * @return string
  226. */
  227. public static function getOrderIncrementId()
  228. {
  229. return self::$orderIncrementId;
  230. }
  231. /**
  232. * @return string
  233. */
  234. public static function getExternalOrderId()
  235. {
  236. return self::$externalOrderId;
  237. }
  238. // ------------------------- PUBLIC ENTRYPOINTS ------------------------- //
  239. /**
  240. * @return \Magento\Sales\Api\Data\OrderInterface|\Magento\Sales\Model\Order
  241. */
  242. public function createQuoteAndOrder()
  243. {
  244. $orderIncrementId = $this->getOrderIncrementId();
  245. // save products
  246. /** @var ProductRepositoryInterface $productRepository */
  247. $productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
  248. foreach ($this->productData as $sku => &$productData) {
  249. $product = Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class, ['data' => [
  250. 'attribute_set_id' => '4',
  251. 'type_id' => 'simple',
  252. 'sku' => $sku,
  253. 'name' => $productData['name'],
  254. 'price' => $productData['unit_price'],
  255. ]]);
  256. $product = $productRepository->save($product);
  257. $productData['entity_id'] = $product->getId();
  258. }
  259. // save quote
  260. $cartRepository = Bootstrap::getObjectManager()->get(QuoteRepository::class);
  261. $quote = $this->getQuote($orderIncrementId);
  262. $quoteBillingAddress = $this->getQuoteAddress(QuoteAddress::ADDRESS_TYPE_BILLING);
  263. $quoteShippingAddress = $this->getQuoteAddress(QuoteAddress::ADDRESS_TYPE_SHIPPING);
  264. $quote->setBillingAddress($quoteBillingAddress);
  265. $quote->setShippingAddress($quoteShippingAddress);
  266. $cartRepository->save($quote);
  267. // save order
  268. /** @var OrderRepository $orderRepository */
  269. $orderRepository = Bootstrap::getObjectManager()->get(OrderRepository::class);
  270. $order = $this->getOrder($orderIncrementId, $quote->getId());
  271. $orderBillingAddress = $this->getOrderAddress(OrderAddress::TYPE_BILLING);
  272. $orderShippingAddress = $this->getOrderAddress(OrderAddress::TYPE_SHIPPING);
  273. $payment = Bootstrap::getObjectManager()->create(\Magento\Sales\Model\Order\Payment::class, ['data' => [
  274. 'method' => 'checkmo',
  275. ]]);
  276. $order->setBillingAddress($orderBillingAddress);
  277. $order->setShippingAddress($orderShippingAddress);
  278. $order->setPayment($payment);
  279. return $orderRepository->save($order);
  280. }
  281. public function createOrderReference()
  282. {
  283. $order = $this->createQuoteAndOrder();
  284. // save external order reference
  285. /** @var OrderReferenceRepository $orderReferenceRepository */
  286. $orderReferenceRepository = Bootstrap::getObjectManager()->get(OrderReferenceRepository::class);
  287. $orderReference = Bootstrap::getObjectManager()->create(OrderReference::class, ['data' => [
  288. OrderReferenceInterface::ORDER_ID => $order->getId(),
  289. OrderReferenceInterface::EXT_ORDER_ID => self::$externalOrderId,
  290. ]]);
  291. $orderReferenceRepository->saveReference($orderReference);
  292. }
  293. public function rollbackQuoteAndOrder()
  294. {
  295. $orderIncrementId = $this->getOrderIncrementId();
  296. /** @var OrderRepository $orderRepository */
  297. $orderRepository = Bootstrap::getObjectManager()->get(OrderRepository::class);
  298. /** @var QuoteRepository $cartRepository */
  299. $cartRepository = Bootstrap::getObjectManager()->get(QuoteRepository::class);
  300. /** @var ProductRepository $productRepository */
  301. $productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
  302. /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
  303. $searchCriteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class);
  304. $searchCriteriaBuilder->addFilter('increment_id', $orderIncrementId);
  305. $searchCriteriaBuilder->setPageSize(1);
  306. $searchResult = $orderRepository->getList($searchCriteriaBuilder->create());
  307. foreach ($searchResult as $order) {
  308. $orderRepository->delete($order);
  309. }
  310. /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
  311. $searchCriteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class);
  312. $searchCriteriaBuilder->addFilter('reserved_order_id', $orderIncrementId);
  313. $searchCriteriaBuilder->setPageSize(1);
  314. $searchResult = $cartRepository->getList($searchCriteriaBuilder->create());
  315. foreach ($searchResult->getItems() as $quote) {
  316. $cartRepository->delete($quote);
  317. }
  318. $skus = array_keys($this->productData);
  319. /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
  320. $searchCriteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class);
  321. $searchCriteriaBuilder->addFilter('sku', $skus, 'in');
  322. $searchResult = $productRepository->getList($searchCriteriaBuilder->create());
  323. foreach ($searchResult->getItems() as $product) {
  324. $productRepository->delete($product);
  325. }
  326. $productRepository->cleanCache();
  327. }
  328. // ------------------------- STATIC ENTRYPOINTS ------------------------- //
  329. /**
  330. * Create fixtures:
  331. * - products
  332. * - quote with quote items
  333. * - order with order items
  334. */
  335. public static function createQuoteAndOrderFixture()
  336. {
  337. /** @var PlacedOrderFixture $self */
  338. $self = Bootstrap::getObjectManager()->create(static::class);
  339. $self->createQuoteAndOrder();
  340. }
  341. /**
  342. * Create fixtures:
  343. * - products
  344. * - quote with quote items
  345. * - order with order items
  346. * - temando external order reference
  347. */
  348. public static function createOrderReferenceFixture()
  349. {
  350. /** @var PlacedOrderFixture $self */
  351. $self = Bootstrap::getObjectManager()->create(static::class);
  352. $self->createOrderReference();
  353. }
  354. /**
  355. * Rollback fixtures:
  356. * - order
  357. * - quote
  358. * - products
  359. */
  360. public static function createQuoteAndOrderFixtureRollback()
  361. {
  362. /** @var PlacedOrderFixture $self */
  363. $self = Bootstrap::getObjectManager()->create(static::class);
  364. $self->rollbackQuoteAndOrder();
  365. }
  366. /**
  367. * Rollback fixtures:
  368. * - order
  369. * - quote
  370. * - products
  371. */
  372. public static function createOrderReferenceFixtureRollback()
  373. {
  374. /** @var PlacedOrderFixture $self */
  375. $self = Bootstrap::getObjectManager()->create(static::class);
  376. $self->rollbackQuoteAndOrder();
  377. }
  378. }