QuoteManagement.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Quote\Model;
  7. use Magento\Authorization\Model\UserContextInterface;
  8. use Magento\Framework\App\ObjectManager;
  9. use Magento\Framework\Event\ManagerInterface as EventManager;
  10. use Magento\Framework\Exception\CouldNotSaveException;
  11. use Magento\Framework\Exception\LocalizedException;
  12. use Magento\Framework\Exception\StateException;
  13. use Magento\Quote\Api\Data\PaymentInterface;
  14. use Magento\Quote\Model\Quote\Address\ToOrder as ToOrderConverter;
  15. use Magento\Quote\Model\Quote\Address\ToOrderAddress as ToOrderAddressConverter;
  16. use Magento\Quote\Model\Quote as QuoteEntity;
  17. use Magento\Quote\Model\Quote\Item\ToOrderItem as ToOrderItemConverter;
  18. use Magento\Quote\Model\Quote\Payment\ToOrderPayment as ToOrderPaymentConverter;
  19. use Magento\Sales\Api\Data\OrderInterfaceFactory as OrderFactory;
  20. use Magento\Sales\Api\OrderManagementInterface as OrderManagement;
  21. use Magento\Store\Model\StoreManagerInterface;
  22. /**
  23. * Class QuoteManagement
  24. *
  25. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  26. * @SuppressWarnings(PHPMD.TooManyFields)
  27. */
  28. class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface
  29. {
  30. /**
  31. * @var EventManager
  32. */
  33. protected $eventManager;
  34. /**
  35. * @var QuoteValidator
  36. */
  37. protected $quoteValidator;
  38. /**
  39. * @var OrderFactory
  40. */
  41. protected $orderFactory;
  42. /**
  43. * @var OrderManagement
  44. */
  45. protected $orderManagement;
  46. /**
  47. * @var CustomerManagement
  48. */
  49. protected $customerManagement;
  50. /**
  51. * @var ToOrderConverter
  52. */
  53. protected $quoteAddressToOrder;
  54. /**
  55. * @var ToOrderAddressConverter
  56. */
  57. protected $quoteAddressToOrderAddress;
  58. /**
  59. * @var ToOrderItemConverter
  60. */
  61. protected $quoteItemToOrderItem;
  62. /**
  63. * @var ToOrderPaymentConverter
  64. */
  65. protected $quotePaymentToOrderPayment;
  66. /**
  67. * @var UserContextInterface
  68. */
  69. protected $userContext;
  70. /**
  71. * @var \Magento\Quote\Api\CartRepositoryInterface
  72. */
  73. protected $quoteRepository;
  74. /**
  75. * @var \Magento\Customer\Api\CustomerRepositoryInterface
  76. */
  77. protected $customerRepository;
  78. /**
  79. * @var \Magento\Customer\Model\CustomerFactory
  80. */
  81. protected $customerModelFactory;
  82. /**
  83. * @var \Magento\Quote\Model\Quote\AddressFactory
  84. */
  85. protected $quoteAddressFactory;
  86. /**
  87. * @var \Magento\Framework\Api\DataObjectHelper
  88. */
  89. protected $dataObjectHelper;
  90. /**
  91. * @var StoreManagerInterface
  92. */
  93. protected $storeManager;
  94. /**
  95. * @var \Magento\Checkout\Model\Session
  96. */
  97. protected $checkoutSession;
  98. /**
  99. * @var \Magento\Customer\Model\Session
  100. */
  101. protected $customerSession;
  102. /**
  103. * @var \Magento\Customer\Api\AccountManagementInterface
  104. */
  105. protected $accountManagement;
  106. /**
  107. * @var QuoteFactory
  108. */
  109. protected $quoteFactory;
  110. /**
  111. * @var \Magento\Quote\Model\QuoteIdMaskFactory
  112. */
  113. private $quoteIdMaskFactory;
  114. /**
  115. * @var \Magento\Customer\Api\AddressRepositoryInterface
  116. */
  117. private $addressRepository;
  118. /**
  119. * @var array
  120. */
  121. private $addressesToSync = [];
  122. /**
  123. * @param EventManager $eventManager
  124. * @param QuoteValidator $quoteValidator
  125. * @param OrderFactory $orderFactory
  126. * @param OrderManagement $orderManagement
  127. * @param CustomerManagement $customerManagement
  128. * @param ToOrderConverter $quoteAddressToOrder
  129. * @param ToOrderAddressConverter $quoteAddressToOrderAddress
  130. * @param ToOrderItemConverter $quoteItemToOrderItem
  131. * @param ToOrderPaymentConverter $quotePaymentToOrderPayment
  132. * @param UserContextInterface $userContext
  133. * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
  134. * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository
  135. * @param \Magento\Customer\Model\CustomerFactory $customerModelFactory
  136. * @param \Magento\Quote\Model\Quote\AddressFactory $quoteAddressFactory
  137. * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
  138. * @param StoreManagerInterface $storeManager
  139. * @param \Magento\Checkout\Model\Session $checkoutSession
  140. * @param \Magento\Customer\Model\Session $customerSession
  141. * @param \Magento\Customer\Api\AccountManagementInterface $accountManagement
  142. * @param QuoteFactory $quoteFactory
  143. * @param \Magento\Quote\Model\QuoteIdMaskFactory|null $quoteIdMaskFactory
  144. * @param \Magento\Customer\Api\AddressRepositoryInterface|null $addressRepository
  145. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  146. */
  147. public function __construct(
  148. EventManager $eventManager,
  149. QuoteValidator $quoteValidator,
  150. OrderFactory $orderFactory,
  151. OrderManagement $orderManagement,
  152. CustomerManagement $customerManagement,
  153. ToOrderConverter $quoteAddressToOrder,
  154. ToOrderAddressConverter $quoteAddressToOrderAddress,
  155. ToOrderItemConverter $quoteItemToOrderItem,
  156. ToOrderPaymentConverter $quotePaymentToOrderPayment,
  157. UserContextInterface $userContext,
  158. \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
  159. \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
  160. \Magento\Customer\Model\CustomerFactory $customerModelFactory,
  161. \Magento\Quote\Model\Quote\AddressFactory $quoteAddressFactory,
  162. \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
  163. StoreManagerInterface $storeManager,
  164. \Magento\Checkout\Model\Session $checkoutSession,
  165. \Magento\Customer\Model\Session $customerSession,
  166. \Magento\Customer\Api\AccountManagementInterface $accountManagement,
  167. \Magento\Quote\Model\QuoteFactory $quoteFactory,
  168. \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory = null,
  169. \Magento\Customer\Api\AddressRepositoryInterface $addressRepository = null
  170. ) {
  171. $this->eventManager = $eventManager;
  172. $this->quoteValidator = $quoteValidator;
  173. $this->orderFactory = $orderFactory;
  174. $this->orderManagement = $orderManagement;
  175. $this->customerManagement = $customerManagement;
  176. $this->quoteAddressToOrder = $quoteAddressToOrder;
  177. $this->quoteAddressToOrderAddress = $quoteAddressToOrderAddress;
  178. $this->quoteItemToOrderItem = $quoteItemToOrderItem;
  179. $this->quotePaymentToOrderPayment = $quotePaymentToOrderPayment;
  180. $this->userContext = $userContext;
  181. $this->quoteRepository = $quoteRepository;
  182. $this->customerRepository = $customerRepository;
  183. $this->customerModelFactory = $customerModelFactory;
  184. $this->quoteAddressFactory = $quoteAddressFactory;
  185. $this->dataObjectHelper = $dataObjectHelper;
  186. $this->storeManager = $storeManager;
  187. $this->checkoutSession = $checkoutSession;
  188. $this->accountManagement = $accountManagement;
  189. $this->customerSession = $customerSession;
  190. $this->quoteFactory = $quoteFactory;
  191. $this->quoteIdMaskFactory = $quoteIdMaskFactory ?: ObjectManager::getInstance()
  192. ->get(\Magento\Quote\Model\QuoteIdMaskFactory::class);
  193. $this->addressRepository = $addressRepository ?: ObjectManager::getInstance()
  194. ->get(\Magento\Customer\Api\AddressRepositoryInterface::class);
  195. }
  196. /**
  197. * @inheritdoc
  198. */
  199. public function createEmptyCart()
  200. {
  201. $storeId = $this->storeManager->getStore()->getStoreId();
  202. $quote = $this->createAnonymousCart($storeId);
  203. $quote->setBillingAddress($this->quoteAddressFactory->create());
  204. $quote->setShippingAddress($this->quoteAddressFactory->create());
  205. try {
  206. $quote->getShippingAddress()->setCollectShippingRates(true);
  207. $this->quoteRepository->save($quote);
  208. } catch (\Exception $e) {
  209. throw new CouldNotSaveException(__("The quote can't be created."));
  210. }
  211. return $quote->getId();
  212. }
  213. /**
  214. * @inheritdoc
  215. */
  216. public function createEmptyCartForCustomer($customerId)
  217. {
  218. $storeId = $this->storeManager->getStore()->getStoreId();
  219. $quote = $this->createCustomerCart($customerId, $storeId);
  220. try {
  221. $this->quoteRepository->save($quote);
  222. } catch (\Exception $e) {
  223. throw new CouldNotSaveException(__("The quote can't be created."));
  224. }
  225. return (int)$quote->getId();
  226. }
  227. /**
  228. * @inheritdoc
  229. */
  230. public function assignCustomer($cartId, $customerId, $storeId)
  231. {
  232. $quote = $this->quoteRepository->getActive($cartId);
  233. $customer = $this->customerRepository->getById($customerId);
  234. $customerModel = $this->customerModelFactory->create();
  235. if (!in_array($storeId, $customerModel->load($customerId)->getSharedStoreIds())) {
  236. throw new StateException(
  237. __("The customer can't be assigned to the cart. The cart belongs to a different store.")
  238. );
  239. }
  240. if ($quote->getCustomerId()) {
  241. throw new StateException(
  242. __("The customer can't be assigned to the cart because the cart isn't anonymous.")
  243. );
  244. }
  245. try {
  246. $this->quoteRepository->getForCustomer($customerId);
  247. throw new StateException(
  248. __("The customer can't be assigned to the cart because the customer already has an active cart.")
  249. );
  250. } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
  251. }
  252. $quote->setCustomer($customer);
  253. $quote->setCustomerIsGuest(0);
  254. /** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
  255. $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'quote_id');
  256. if ($quoteIdMask->getId()) {
  257. $quoteIdMask->delete();
  258. }
  259. $this->quoteRepository->save($quote);
  260. return true;
  261. }
  262. /**
  263. * Creates an anonymous cart.
  264. *
  265. * @param int $storeId
  266. * @return \Magento\Quote\Model\Quote Cart object.
  267. */
  268. protected function createAnonymousCart($storeId)
  269. {
  270. /** @var \Magento\Quote\Model\Quote $quote */
  271. $quote = $this->quoteFactory->create();
  272. $quote->setStoreId($storeId);
  273. return $quote;
  274. }
  275. /**
  276. * Creates a cart for the currently logged-in customer.
  277. *
  278. * @param int $customerId
  279. * @param int $storeId
  280. * @return \Magento\Quote\Model\Quote Cart object.
  281. * @throws CouldNotSaveException The cart could not be created.
  282. */
  283. protected function createCustomerCart($customerId, $storeId)
  284. {
  285. try {
  286. $quote = $this->quoteRepository->getActiveForCustomer($customerId);
  287. } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
  288. $customer = $this->customerRepository->getById($customerId);
  289. /** @var \Magento\Quote\Model\Quote $quote */
  290. $quote = $this->quoteFactory->create();
  291. $quote->setStoreId($storeId);
  292. $quote->setCustomer($customer);
  293. $quote->setCustomerIsGuest(0);
  294. }
  295. return $quote;
  296. }
  297. /**
  298. * @inheritdoc
  299. */
  300. public function placeOrder($cartId, PaymentInterface $paymentMethod = null)
  301. {
  302. $quote = $this->quoteRepository->getActive($cartId);
  303. if ($paymentMethod) {
  304. $paymentMethod->setChecks([
  305. \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT,
  306. \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY,
  307. \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY,
  308. \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX,
  309. \Magento\Payment\Model\Method\AbstractMethod::CHECK_ZERO_TOTAL,
  310. ]);
  311. $quote->getPayment()->setQuote($quote);
  312. $data = $paymentMethod->getData();
  313. $quote->getPayment()->importData($data);
  314. } else {
  315. $quote->collectTotals();
  316. }
  317. if ($quote->getCheckoutMethod() === self::METHOD_GUEST) {
  318. $quote->setCustomerId(null);
  319. $quote->setCustomerEmail($quote->getBillingAddress()->getEmail());
  320. $quote->setCustomerIsGuest(true);
  321. $quote->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID);
  322. }
  323. $this->eventManager->dispatch('checkout_submit_before', ['quote' => $quote]);
  324. $order = $this->submit($quote);
  325. if (null == $order) {
  326. throw new LocalizedException(
  327. __('A server error stopped your order from being placed. Please try to place your order again.')
  328. );
  329. }
  330. $this->checkoutSession->setLastQuoteId($quote->getId());
  331. $this->checkoutSession->setLastSuccessQuoteId($quote->getId());
  332. $this->checkoutSession->setLastOrderId($order->getId());
  333. $this->checkoutSession->setLastRealOrderId($order->getIncrementId());
  334. $this->checkoutSession->setLastOrderStatus($order->getStatus());
  335. $this->eventManager->dispatch('checkout_submit_all_after', ['order' => $order, 'quote' => $quote]);
  336. return $order->getId();
  337. }
  338. /**
  339. * @inheritdoc
  340. */
  341. public function getCartForCustomer($customerId)
  342. {
  343. return $this->quoteRepository->getActiveForCustomer($customerId);
  344. }
  345. /**
  346. * Submit quote
  347. *
  348. * @param Quote $quote
  349. * @param array $orderData
  350. * @return \Magento\Framework\Model\AbstractExtensibleModel|\Magento\Sales\Api\Data\OrderInterface|object|null
  351. * @throws \Exception
  352. * @throws \Magento\Framework\Exception\LocalizedException
  353. */
  354. public function submit(QuoteEntity $quote, $orderData = [])
  355. {
  356. if (!$quote->getAllVisibleItems()) {
  357. $quote->setIsActive(false);
  358. return null;
  359. }
  360. return $this->submitQuote($quote, $orderData);
  361. }
  362. /**
  363. * Convert quote items to order items for quote
  364. *
  365. * @param Quote $quote
  366. * @return array
  367. */
  368. protected function resolveItems(QuoteEntity $quote)
  369. {
  370. $orderItems = [];
  371. foreach ($quote->getAllItems() as $quoteItem) {
  372. $itemId = $quoteItem->getId();
  373. if (!empty($orderItems[$itemId])) {
  374. continue;
  375. }
  376. $parentItemId = $quoteItem->getParentItemId();
  377. /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $parentItem */
  378. if ($parentItemId && !isset($orderItems[$parentItemId])) {
  379. $orderItems[$parentItemId] = $this->quoteItemToOrderItem->convert(
  380. $quoteItem->getParentItem(),
  381. ['parent_item' => null]
  382. );
  383. }
  384. $parentItem = isset($orderItems[$parentItemId]) ? $orderItems[$parentItemId] : null;
  385. $orderItems[$itemId] = $this->quoteItemToOrderItem->convert($quoteItem, ['parent_item' => $parentItem]);
  386. }
  387. return array_values($orderItems);
  388. }
  389. /**
  390. * Submit quote
  391. *
  392. * @param Quote $quote
  393. * @param array $orderData
  394. * @return \Magento\Framework\Model\AbstractExtensibleModel|\Magento\Sales\Api\Data\OrderInterface|object
  395. * @throws \Exception
  396. * @throws \Magento\Framework\Exception\LocalizedException
  397. */
  398. protected function submitQuote(QuoteEntity $quote, $orderData = [])
  399. {
  400. $order = $this->orderFactory->create();
  401. $this->quoteValidator->validateBeforeSubmit($quote);
  402. if (!$quote->getCustomerIsGuest()) {
  403. if ($quote->getCustomerId()) {
  404. $this->_prepareCustomerQuote($quote);
  405. $this->customerManagement->validateAddresses($quote);
  406. }
  407. $this->customerManagement->populateCustomerInfo($quote);
  408. }
  409. $addresses = [];
  410. $quote->reserveOrderId();
  411. if ($quote->isVirtual()) {
  412. $this->dataObjectHelper->mergeDataObjects(
  413. \Magento\Sales\Api\Data\OrderInterface::class,
  414. $order,
  415. $this->quoteAddressToOrder->convert($quote->getBillingAddress(), $orderData)
  416. );
  417. } else {
  418. $this->dataObjectHelper->mergeDataObjects(
  419. \Magento\Sales\Api\Data\OrderInterface::class,
  420. $order,
  421. $this->quoteAddressToOrder->convert($quote->getShippingAddress(), $orderData)
  422. );
  423. $shippingAddress = $this->quoteAddressToOrderAddress->convert(
  424. $quote->getShippingAddress(),
  425. [
  426. 'address_type' => 'shipping',
  427. 'email' => $quote->getCustomerEmail()
  428. ]
  429. );
  430. $shippingAddress->setData('quote_address_id', $quote->getShippingAddress()->getId());
  431. $addresses[] = $shippingAddress;
  432. $order->setShippingAddress($shippingAddress);
  433. $order->setShippingMethod($quote->getShippingAddress()->getShippingMethod());
  434. }
  435. $billingAddress = $this->quoteAddressToOrderAddress->convert(
  436. $quote->getBillingAddress(),
  437. [
  438. 'address_type' => 'billing',
  439. 'email' => $quote->getCustomerEmail()
  440. ]
  441. );
  442. $billingAddress->setData('quote_address_id', $quote->getBillingAddress()->getId());
  443. $addresses[] = $billingAddress;
  444. $order->setBillingAddress($billingAddress);
  445. $order->setAddresses($addresses);
  446. $order->setPayment($this->quotePaymentToOrderPayment->convert($quote->getPayment()));
  447. $order->setItems($this->resolveItems($quote));
  448. if ($quote->getCustomer()) {
  449. $order->setCustomerId($quote->getCustomer()->getId());
  450. }
  451. $order->setQuoteId($quote->getId());
  452. $order->setCustomerEmail($quote->getCustomerEmail());
  453. $order->setCustomerFirstname($quote->getCustomerFirstname());
  454. $order->setCustomerMiddlename($quote->getCustomerMiddlename());
  455. $order->setCustomerLastname($quote->getCustomerLastname());
  456. $this->eventManager->dispatch(
  457. 'sales_model_service_quote_submit_before',
  458. [
  459. 'order' => $order,
  460. 'quote' => $quote
  461. ]
  462. );
  463. try {
  464. $order = $this->orderManagement->place($order);
  465. $quote->setIsActive(false);
  466. $this->eventManager->dispatch(
  467. 'sales_model_service_quote_submit_success',
  468. [
  469. 'order' => $order,
  470. 'quote' => $quote
  471. ]
  472. );
  473. $this->quoteRepository->save($quote);
  474. } catch (\Exception $e) {
  475. if (!empty($this->addressesToSync)) {
  476. foreach ($this->addressesToSync as $addressId) {
  477. $this->addressRepository->deleteById($addressId);
  478. }
  479. }
  480. $this->eventManager->dispatch(
  481. 'sales_model_service_quote_submit_failure',
  482. [
  483. 'order' => $order,
  484. 'quote' => $quote,
  485. 'exception' => $e
  486. ]
  487. );
  488. throw $e;
  489. }
  490. return $order;
  491. }
  492. /**
  493. * Prepare quote for customer order submit
  494. *
  495. * @param Quote $quote
  496. * @return void
  497. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  498. * @SuppressWarnings(PHPMD.NPathComplexity)
  499. */
  500. protected function _prepareCustomerQuote($quote)
  501. {
  502. /** @var Quote $quote */
  503. $billing = $quote->getBillingAddress();
  504. $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress();
  505. $customer = $this->customerRepository->getById($quote->getCustomerId());
  506. $hasDefaultBilling = (bool)$customer->getDefaultBilling();
  507. $hasDefaultShipping = (bool)$customer->getDefaultShipping();
  508. if ($shipping && !$shipping->getSameAsBilling()
  509. && (!$shipping->getCustomerId() || $shipping->getSaveInAddressBook())
  510. ) {
  511. $shippingAddress = $shipping->exportCustomerAddress();
  512. if (!$hasDefaultShipping) {
  513. //Make provided address as default shipping address
  514. $shippingAddress->setIsDefaultShipping(true);
  515. $hasDefaultShipping = true;
  516. if (!$hasDefaultBilling && !$billing->getSaveInAddressBook()) {
  517. $shippingAddress->setIsDefaultBilling(true);
  518. $hasDefaultBilling = true;
  519. }
  520. }
  521. //save here new customer address
  522. $shippingAddress->setCustomerId($quote->getCustomerId());
  523. $this->addressRepository->save($shippingAddress);
  524. $quote->addCustomerAddress($shippingAddress);
  525. $shipping->setCustomerAddressData($shippingAddress);
  526. $this->addressesToSync[] = $shippingAddress->getId();
  527. $shipping->setCustomerAddressId($shippingAddress->getId());
  528. }
  529. if (!$billing->getCustomerId() || $billing->getSaveInAddressBook()) {
  530. $billingAddress = $billing->exportCustomerAddress();
  531. if (!$hasDefaultBilling) {
  532. //Make provided address as default shipping address
  533. if (!$hasDefaultShipping) {
  534. //Make provided address as default shipping address
  535. $billingAddress->setIsDefaultShipping(true);
  536. }
  537. $billingAddress->setIsDefaultBilling(true);
  538. }
  539. $billingAddress->setCustomerId($quote->getCustomerId());
  540. $this->addressRepository->save($billingAddress);
  541. $quote->addCustomerAddress($billingAddress);
  542. $billing->setCustomerAddressData($billingAddress);
  543. $this->addressesToSync[] = $billingAddress->getId();
  544. $billing->setCustomerAddressId($billingAddress->getId());
  545. }
  546. if ($shipping && !$shipping->getCustomerId() && !$hasDefaultBilling) {
  547. $shipping->setIsDefaultBilling(true);
  548. }
  549. }
  550. }