Skip to content

Commit 3d9bbe9

Browse files
Merge branch 'MAGETWO-97317' of https://github.com/magento-epam/magento2ce into MAGETWO-97317
2 parents 0740f7c + 39735a7 commit 3d9bbe9

File tree

10 files changed

+490
-35
lines changed

10 files changed

+490
-35
lines changed

app/code/Magento/Quote/Model/QuoteManagement.php

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Quote\Model;
89

@@ -249,6 +250,8 @@ public function createEmptyCartForCustomer($customerId)
249250
$storeId = $this->storeManager->getStore()->getStoreId();
250251
$quote = $this->createCustomerCart($customerId, $storeId);
251252

253+
$this->_prepareCustomerQuote($quote);
254+
252255
try {
253256
$this->quoteRepository->save($quote);
254257
} catch (\Exception $e) {
@@ -281,6 +284,7 @@ public function assignCustomer($cartId, $customerId, $storeId)
281284
throw new StateException(
282285
__("The customer can't be assigned to the cart because the customer already has an active cart.")
283286
);
287+
// phpcs:ignore Magento2.CodeAnalysis.EmptyBlock
284288
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
285289
}
286290

@@ -539,7 +543,7 @@ protected function submitQuote(QuoteEntity $quote, $orderData = [])
539543
}
540544

541545
/**
542-
* Prepare quote for customer order submit
546+
* Prepare address for customer quote.
543547
*
544548
* @param Quote $quote
545549
* @return void
@@ -559,41 +563,59 @@ protected function _prepareCustomerQuote($quote)
559563
if ($shipping && !$shipping->getSameAsBilling()
560564
&& (!$shipping->getCustomerId() || $shipping->getSaveInAddressBook())
561565
) {
562-
$shippingAddress = $shipping->exportCustomerAddress();
563-
if (!$hasDefaultShipping) {
564-
//Make provided address as default shipping address
565-
$shippingAddress->setIsDefaultShipping(true);
566-
$hasDefaultShipping = true;
567-
if (!$hasDefaultBilling && !$billing->getSaveInAddressBook()) {
568-
$shippingAddress->setIsDefaultBilling(true);
569-
$hasDefaultBilling = true;
566+
if ($shipping->getQuoteId()) {
567+
$shippingAddress = $shipping->exportCustomerAddress();
568+
} else {
569+
$defaultShipping = $this->customerRepository->getById($customer->getId())->getDefaultShipping();
570+
if ($defaultShipping) {
571+
$shippingAddress = $this->addressRepository->getById($defaultShipping);
572+
}
573+
}
574+
if (isset($shippingAddress)) {
575+
if (!$hasDefaultShipping) {
576+
//Make provided address as default shipping address
577+
$shippingAddress->setIsDefaultShipping(true);
578+
$hasDefaultShipping = true;
579+
if (!$hasDefaultBilling && !$billing->getSaveInAddressBook()) {
580+
$shippingAddress->setIsDefaultBilling(true);
581+
$hasDefaultBilling = true;
582+
}
570583
}
584+
//save here new customer address
585+
$shippingAddress->setCustomerId($quote->getCustomerId());
586+
$this->addressRepository->save($shippingAddress);
587+
$quote->addCustomerAddress($shippingAddress);
588+
$shipping->setCustomerAddressData($shippingAddress);
589+
$this->addressesToSync[] = $shippingAddress->getId();
590+
$shipping->setCustomerAddressId($shippingAddress->getId());
571591
}
572-
//save here new customer address
573-
$shippingAddress->setCustomerId($quote->getCustomerId());
574-
$this->addressRepository->save($shippingAddress);
575-
$quote->addCustomerAddress($shippingAddress);
576-
$shipping->setCustomerAddressData($shippingAddress);
577-
$this->addressesToSync[] = $shippingAddress->getId();
578-
$shipping->setCustomerAddressId($shippingAddress->getId());
579592
}
580593

581594
if (!$billing->getCustomerId() || $billing->getSaveInAddressBook()) {
582-
$billingAddress = $billing->exportCustomerAddress();
583-
if (!$hasDefaultBilling) {
584-
//Make provided address as default shipping address
585-
if (!$hasDefaultShipping) {
595+
if ($billing->getQuoteId()) {
596+
$billingAddress = $billing->exportCustomerAddress();
597+
} else {
598+
$defaultBilling = $this->customerRepository->getById($customer->getId())->getDefaultBilling();
599+
if ($defaultBilling) {
600+
$billingAddress = $this->addressRepository->getById($defaultBilling);
601+
}
602+
}
603+
if (isset($billingAddress)) {
604+
if (!$hasDefaultBilling) {
586605
//Make provided address as default shipping address
587-
$billingAddress->setIsDefaultShipping(true);
606+
if (!$hasDefaultShipping) {
607+
//Make provided address as default shipping address
608+
$billingAddress->setIsDefaultShipping(true);
609+
}
610+
$billingAddress->setIsDefaultBilling(true);
588611
}
589-
$billingAddress->setIsDefaultBilling(true);
612+
$billingAddress->setCustomerId($quote->getCustomerId());
613+
$this->addressRepository->save($billingAddress);
614+
$quote->addCustomerAddress($billingAddress);
615+
$billing->setCustomerAddressData($billingAddress);
616+
$this->addressesToSync[] = $billingAddress->getId();
617+
$billing->setCustomerAddressId($billingAddress->getId());
590618
}
591-
$billingAddress->setCustomerId($quote->getCustomerId());
592-
$this->addressRepository->save($billingAddress);
593-
$quote->addCustomerAddress($billingAddress);
594-
$billing->setCustomerAddressData($billingAddress);
595-
$this->addressesToSync[] = $billingAddress->getId();
596-
$billing->setCustomerAddressId($billingAddress->getId());
597619
}
598620
if ($shipping && !$shipping->getCustomerId() && !$hasDefaultBilling) {
599621
$shipping->setIsDefaultBilling(true);
@@ -627,12 +649,13 @@ private function rollbackAddresses(
627649
'exception' => $e,
628650
]
629651
);
652+
// phpcs:ignore Magento2.Exceptions.ThrowCatch
630653
} catch (\Exception $consecutiveException) {
631654
$message = sprintf(
632655
"An exception occurred on 'sales_model_service_quote_submit_failure' event: %s",
633656
$consecutiveException->getMessage()
634657
);
635-
658+
// phpcs:ignore Magento2.Exceptions.DirectThrow
636659
throw new \Exception($message, 0, $e);
637660
}
638661
}

app/code/Magento/Quote/Model/QuoteRepository/SaveHandler.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Quote\Model\QuoteRepository;
79

810
use Magento\Quote\Api\Data\CartInterface;
911
use Magento\Customer\Api\AddressRepositoryInterface;
1012
use Magento\Framework\App\ObjectManager;
1113
use Magento\Framework\Exception\NoSuchEntityException;
1214
use Magento\Framework\Exception\InputException;
15+
use Magento\Quote\Api\Data\AddressInterfaceFactory;
1316

17+
/**
18+
* Handler for saving quote.
19+
*/
1420
class SaveHandler
1521
{
1622
/**
@@ -38,26 +44,35 @@ class SaveHandler
3844
*/
3945
private $addressRepository;
4046

47+
/**
48+
* @var AddressInterfaceFactory
49+
*/
50+
private $quoteAddressFactory;
51+
4152
/**
4253
* @param \Magento\Quote\Model\ResourceModel\Quote $quoteResource
4354
* @param \Magento\Quote\Model\Quote\Item\CartItemPersister $cartItemPersister
4455
* @param \Magento\Quote\Model\Quote\Address\BillingAddressPersister $billingAddressPersister
4556
* @param \Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister $shippingAssignmentPersister
4657
* @param AddressRepositoryInterface $addressRepository
58+
* @param AddressInterfaceFactory|null $addressFactory
4759
*/
4860
public function __construct(
4961
\Magento\Quote\Model\ResourceModel\Quote $quoteResource,
5062
\Magento\Quote\Model\Quote\Item\CartItemPersister $cartItemPersister,
5163
\Magento\Quote\Model\Quote\Address\BillingAddressPersister $billingAddressPersister,
5264
\Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister $shippingAssignmentPersister,
53-
AddressRepositoryInterface $addressRepository = null
65+
AddressRepositoryInterface $addressRepository = null,
66+
AddressInterfaceFactory $addressFactory = null
5467
) {
5568
$this->quoteResourceModel = $quoteResource;
5669
$this->cartItemPersister = $cartItemPersister;
5770
$this->billingAddressPersister = $billingAddressPersister;
5871
$this->shippingAssignmentPersister = $shippingAssignmentPersister;
5972
$this->addressRepository = $addressRepository
6073
?: ObjectManager::getInstance()->get(AddressRepositoryInterface::class);
74+
$this->quoteAddressFactory = $addressFactory ?:ObjectManager::getInstance()
75+
->get(AddressInterfaceFactory::class);
6176
}
6277

6378
/**
@@ -80,6 +95,9 @@ public function save(CartInterface $quote)
8095
/** @var \Magento\Quote\Model\Quote\Item $item */
8196
if (!$item->isDeleted()) {
8297
$quote->setLastAddedItem($this->cartItemPersister->save($quote, $item));
98+
} elseif (count($items) === 1) {
99+
$quote->setBillingAddress($this->quoteAddressFactory->create());
100+
$quote->setShippingAddress($this->quoteAddressFactory->create());
83101
}
84102
}
85103
}

app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Quote\Test\Unit\Model;
89

@@ -284,13 +285,23 @@ public function testCreateEmptyCartForCustomer()
284285
->method('getActiveForCustomer')
285286
->with($userId)
286287
->willThrowException(new NoSuchEntityException());
288+
$customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
289+
->setMethods(['getDefaultBilling'])->disableOriginalConstructor()->getMockForAbstractClass();
290+
$quoteAddress = $this->createPartialMock(
291+
\Magento\Quote\Model\Quote\Address::class,
292+
['getCustomerId']
293+
);
294+
$quoteAddress->expects($this->atLeastOnce())->method('getCustomerId')->willReturn(567);
295+
$quoteMock->expects($this->atLeastOnce())->method('getBillingAddress')->willReturn($quoteAddress);
287296

288297
$this->quoteFactoryMock->expects($this->once())->method('create')->willReturn($quoteMock);
289298
$quoteMock->expects($this->any())->method('setStoreId')->with($storeId);
290299
$quoteMock->expects($this->any())->method('setCustomerIsGuest')->with(0);
291300

292301
$this->quoteRepositoryMock->expects($this->once())->method('save')->with($quoteMock);
293302
$quoteMock->expects($this->once())->method('getId')->willReturn($quoteId);
303+
$this->customerRepositoryMock->expects($this->atLeastOnce())->method('getById')->willReturn($customer);
304+
$customer->expects($this->atLeastOnce())->method('getDefaultBilling')->willReturn(0);
294305

295306
$this->storeManagerMock->expects($this->once())->method('getStore')->willReturnSelf();
296307
$this->storeManagerMock->expects($this->once())->method('getStoreId')->willReturn($storeId);
@@ -310,6 +321,17 @@ public function testCreateEmptyCartForCustomerReturnExistsQuote()
310321
->method('getActiveForCustomer')
311322
->with($userId)->willReturn($quoteMock);
312323

324+
$customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
325+
->setMethods(['getDefaultBilling'])->disableOriginalConstructor()->getMockForAbstractClass();
326+
$quoteAddress = $this->createPartialMock(
327+
\Magento\Quote\Model\Quote\Address::class,
328+
['getCustomerId']
329+
);
330+
$quoteAddress->expects($this->atLeastOnce())->method('getCustomerId')->willReturn(567);
331+
$quoteMock->expects($this->atLeastOnce())->method('getBillingAddress')->willReturn($quoteAddress);
332+
$this->customerRepositoryMock->expects($this->atLeastOnce())->method('getById')->willReturn($customer);
333+
$customer->expects($this->atLeastOnce())->method('getDefaultBilling')->willReturn(0);
334+
313335
$this->quoteFactoryMock->expects($this->never())->method('create')->willReturn($quoteMock);
314336
$this->quoteRepositoryMock->expects($this->once())->method('save')->with($quoteMock);
315337

@@ -541,7 +563,10 @@ public function testSubmit()
541563
$quoteId = 1;
542564
$quoteItem = $this->createMock(\Magento\Quote\Model\Quote\Item::class);
543565
$billingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class);
544-
$shippingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class);
566+
$shippingAddress = $this->createPartialMock(
567+
\Magento\Quote\Model\Quote\Address::class,
568+
['getQuoteId', 'getShippingMethod', 'getId']
569+
);
545570
$payment = $this->createMock(\Magento\Quote\Model\Quote\Payment::class);
546571
$baseOrder = $this->createMock(\Magento\Sales\Api\Data\OrderInterface::class);
547572
$convertedBilling = $this->createPartialMockForAbstractClass(OrderAddressInterface::class, ['setData']);
@@ -842,6 +867,7 @@ protected function getQuote(
842867
$quote->expects($this->any())
843868
->method('getShippingAddress')
844869
->willReturn($shippingAddress);
870+
$shippingAddress->expects($this->any())->method('getQuoteId')->willReturn($id);
845871
}
846872
$quote->expects($this->any())
847873
->method('getBillingAddress')
@@ -991,7 +1017,10 @@ public function testSubmitForCustomer()
9911017
$quoteId = 1;
9921018
$quoteItem = $this->createMock(\Magento\Quote\Model\Quote\Item::class);
9931019
$billingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class);
994-
$shippingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class);
1020+
$shippingAddress = $this->createPartialMock(
1021+
\Magento\Quote\Model\Quote\Address::class,
1022+
['getQuoteId', 'getShippingMethod', 'getId', 'exportCustomerAddress']
1023+
);
9951024
$payment = $this->createMock(\Magento\Quote\Model\Quote\Payment::class);
9961025
$baseOrder = $this->createMock(\Magento\Sales\Api\Data\OrderInterface::class);
9971026
$convertedBilling = $this->createPartialMockForAbstractClass(OrderAddressInterface::class, ['setData']);
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Quote\Api;
9+
10+
use Magento\TestFramework\TestCase\WebapiAbstract;
11+
12+
/**
13+
* Class for payment info in quote for registered customer.
14+
*/
15+
class CartAddingItemsTest extends WebapiAbstract
16+
{
17+
/**
18+
* @var \Magento\TestFramework\ObjectManager
19+
*/
20+
protected $objectManager;
21+
22+
protected function setUp()
23+
{
24+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
25+
}
26+
27+
/**
28+
* Test price for cart after adding product to.
29+
*
30+
* @magentoApiDataFixture Magento/Catalog/_files/product_without_options_with_stock_data.php
31+
* @magentoApiDataFixture Magento/Customer/_files/customer_one_address.php
32+
* @return void
33+
*/
34+
public function testPriceForCreatingQuoteFromEmptyCart()
35+
{
36+
$this->_markTestAsRestOnly();
37+
38+
// Get customer ID token
39+
/** @var \Magento\Integration\Api\CustomerTokenServiceInterface $customerTokenService */
40+
$customerTokenService = $this->objectManager->create(
41+
\Magento\Integration\Api\CustomerTokenServiceInterface::class
42+
);
43+
$token = $customerTokenService->createCustomerAccessToken(
44+
'customer_one_address@test.com',
45+
'password'
46+
);
47+
48+
// Creating empty cart for registered customer.
49+
$serviceInfo = [
50+
'rest' => [
51+
'resourcePath' => '/V1/carts/mine',
52+
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
53+
'token' => $token
54+
]
55+
];
56+
57+
$quoteId = $this->_webApiCall($serviceInfo, ['customerId' => 999]); // customerId 999 will get overridden
58+
$this->assertGreaterThan(0, $quoteId);
59+
60+
// Adding item to the cart
61+
$serviceInfoForAddingProduct = [
62+
'rest' => [
63+
'resourcePath' => '/V1/carts/mine/items',
64+
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
65+
'token' => $token
66+
]
67+
];
68+
$requestData = [
69+
'cartItem' => [
70+
'quote_id' => $quoteId,
71+
'sku' => 'simple',
72+
'qty' => 1
73+
]
74+
];
75+
$item = $this->_webApiCall($serviceInfoForAddingProduct, $requestData);
76+
$this->assertNotEmpty($item);
77+
$this->assertEquals(10, $item['price']);
78+
79+
// Get payment information
80+
$serviceInfoForGettingPaymentInfo = [
81+
'rest' => [
82+
'resourcePath' => '/V1/carts/mine/payment-information',
83+
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
84+
'token' => $token
85+
]
86+
];
87+
$paymentInfo = $this->_webApiCall($serviceInfoForGettingPaymentInfo);
88+
$this->assertEquals($paymentInfo['totals']['grand_total'], 10);
89+
90+
/** @var \Magento\Quote\Model\Quote $quote */
91+
$quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class);
92+
$quote->load($quoteId);
93+
$quote->delete();
94+
}
95+
}

0 commit comments

Comments
 (0)