Skip to content

Commit 184b840

Browse files
ENGCOM-6151: Merge guest quote to customer quote 24808 #24862
- Merge Pull Request #24862 from ivan-koliadynskyy/magento2:merge-guest-quote-to-customer-quote-24808 - Merged commits: 1. 2a6dc66 2. dc460c8 3. 9f77a81 4. 6ff21a6 5. d0e2ced 6. b6f0bb3 7. fe12c41 8. e5095fb 9. daede85 10. 08fb9ae 11. 8b08a51
2 parents ba8602a + 8b08a51 commit 184b840

File tree

5 files changed

+126
-58
lines changed

5 files changed

+126
-58
lines changed

app/code/Magento/Quote/Api/CartManagementInterface.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public function getCartForCustomer($customerId);
5252
* @param int $customerId The customer ID.
5353
* @param int $storeId
5454
* @return boolean
55+
* @throws \Magento\Framework\Exception\LocalizedException
56+
* @throws \Magento\Framework\Exception\StateException
57+
* @throws \Magento\Framework\Exception\NoSuchEntityException
5558
*/
5659
public function assignCustomer($cartId, $customerId, $storeId);
5760

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,22 +298,28 @@ public function assignCustomer($cartId, $customerId, $storeId)
298298
);
299299
}
300300
try {
301-
$this->quoteRepository->getForCustomer($customerId);
302-
throw new StateException(
303-
__("The customer can't be assigned to the cart because the customer already has an active cart.")
304-
);
301+
$customerActiveQuote = $this->quoteRepository->getForCustomer($customerId);
302+
303+
$quote->merge($customerActiveQuote);
304+
$customerActiveQuote->setIsActive(0);
305+
$this->quoteRepository->save($customerActiveQuote);
306+
305307
// phpcs:ignore Magento2.CodeAnalysis.EmptyBlock
306308
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
307309
}
308310

309311
$quote->setCustomer($customer);
310312
$quote->setCustomerIsGuest(0);
313+
$quote->setIsActive(1);
314+
311315
/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
312316
$quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'quote_id');
313317
if ($quoteIdMask->getId()) {
314318
$quoteIdMask->delete();
315319
}
320+
316321
$this->quoteRepository->save($quote);
322+
317323
return true;
318324
}
319325

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

Lines changed: 94 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77

88
namespace Magento\Quote\Test\Unit\Model;
99

10+
use Magento\Customer\Api\Data\CustomerInterface;
11+
use Magento\Customer\Model\Customer;
1012
use Magento\Framework\App\RequestInterface;
11-
use Magento\Framework\Exception\NoSuchEntityException;
1213

1314
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
1415
use Magento\Quote\Model\CustomerManagement;
16+
use Magento\Quote\Model\Quote;
1517
use Magento\Quote\Model\QuoteIdMaskFactory;
1618
use Magento\Sales\Api\Data\OrderAddressInterface;
1719

@@ -199,7 +201,7 @@ protected function setUp()
199201
);
200202

201203
$this->quoteMock = $this->createPartialMock(
202-
\Magento\Quote\Model\Quote::class,
204+
Quote::class,
203205
[
204206
'assignCustomer',
205207
'collectTotals',
@@ -275,7 +277,7 @@ public function testCreateEmptyCartAnonymous()
275277
$storeId = 345;
276278
$quoteId = 2311;
277279

278-
$quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class);
280+
$quoteMock = $this->createMock(Quote::class);
279281
$quoteAddress = $this->createPartialMock(
280282
\Magento\Quote\Model\Quote\Address::class,
281283
['setCollectShippingRates']
@@ -306,14 +308,14 @@ public function testCreateEmptyCartForCustomer()
306308
$quoteId = 2311;
307309
$userId = 567;
308310

309-
$quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class);
311+
$quoteMock = $this->createMock(Quote::class);
310312

311313
$this->quoteRepositoryMock
312314
->expects($this->once())
313315
->method('getActiveForCustomer')
314316
->with($userId)
315-
->willThrowException(new NoSuchEntityException());
316-
$customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
317+
->willThrowException(new \Magento\Framework\Exception\NoSuchEntityException());
318+
$customer = $this->getMockBuilder(CustomerInterface::class)
317319
->setMethods(['getDefaultBilling'])->disableOriginalConstructor()->getMockForAbstractClass();
318320
$quoteAddress = $this->createPartialMock(
319321
\Magento\Quote\Model\Quote\Address::class,
@@ -342,14 +344,14 @@ public function testCreateEmptyCartForCustomerReturnExistsQuote()
342344
$storeId = 345;
343345
$userId = 567;
344346

345-
$quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class);
347+
$quoteMock = $this->createMock(Quote::class);
346348

347349
$this->quoteRepositoryMock
348350
->expects($this->once())
349351
->method('getActiveForCustomer')
350352
->with($userId)->willReturn($quoteMock);
351353

352-
$customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
354+
$customer = $this->getMockBuilder(CustomerInterface::class)
353355
->setMethods(['getDefaultBilling'])->disableOriginalConstructor()->getMockForAbstractClass();
354356
$quoteAddress = $this->createPartialMock(
355357
\Magento\Quote\Model\Quote\Address::class,
@@ -379,8 +381,8 @@ public function testAssignCustomerFromAnotherStore()
379381
$customerId = 455;
380382
$storeId = 5;
381383

382-
$quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class);
383-
$customerMock = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class);
384+
$quoteMock = $this->createMock(Quote::class);
385+
$customerMock = $this->createMock(CustomerInterface::class);
384386

385387
$this->quoteRepositoryMock
386388
->expects($this->once())
@@ -395,7 +397,7 @@ public function testAssignCustomerFromAnotherStore()
395397
->willReturn($customerMock);
396398

397399
$customerModelMock = $this->createPartialMock(
398-
\Magento\Customer\Model\Customer::class,
400+
Customer::class,
399401
['load', 'getSharedStoreIds']
400402
);
401403
$this->customerFactoryMock->expects($this->once())->method('create')->willReturn($customerModelMock);
@@ -424,10 +426,10 @@ public function testAssignCustomerToNonanonymousCart()
424426
$storeId = 5;
425427

426428
$quoteMock = $this->createPartialMock(
427-
\Magento\Quote\Model\Quote::class,
429+
Quote::class,
428430
['getCustomerId', 'setCustomer', 'setCustomerIsGuest']
429431
);
430-
$customerMock = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class);
432+
$customerMock = $this->createMock(CustomerInterface::class);
431433

432434
$this->quoteRepositoryMock
433435
->expects($this->once())
@@ -442,7 +444,7 @@ public function testAssignCustomerToNonanonymousCart()
442444
->willReturn($customerMock);
443445

444446
$customerModelMock = $this->createPartialMock(
445-
\Magento\Customer\Model\Customer::class,
447+
Customer::class,
446448
['load', 'getSharedStoreIds']
447449
);
448450
$this->customerFactoryMock->expects($this->once())->method('create')->willReturn($customerModelMock);
@@ -463,7 +465,7 @@ public function testAssignCustomerToNonanonymousCart()
463465
}
464466

465467
/**
466-
* @expectedException \Magento\Framework\Exception\StateException
468+
* @expectedException \Magento\Framework\Exception\NoSuchEntityException
467469
*/
468470
public function testAssignCustomerNoSuchCustomer()
469471
{
@@ -472,10 +474,51 @@ public function testAssignCustomerNoSuchCustomer()
472474
$storeId = 5;
473475

474476
$quoteMock = $this->createPartialMock(
475-
\Magento\Quote\Model\Quote::class,
477+
Quote::class,
476478
['getCustomerId', 'setCustomer', 'setCustomerIsGuest']
477479
);
478-
$customerMock = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class);
480+
481+
$this->quoteRepositoryMock
482+
->expects($this->once())
483+
->method('getActive')
484+
->with($cartId)
485+
->willReturn($quoteMock);
486+
487+
$this->customerRepositoryMock
488+
->expects($this->once())
489+
->method('getById')
490+
->with($customerId)
491+
->willThrowException(new \Magento\Framework\Exception\NoSuchEntityException());
492+
493+
$this->expectExceptionMessage(
494+
"No such entity."
495+
);
496+
497+
$this->model->assignCustomer($cartId, $customerId, $storeId);
498+
}
499+
500+
public function testAssignCustomerWithActiveCart()
501+
{
502+
$cartId = 220;
503+
$customerId = 455;
504+
$storeId = 5;
505+
506+
$this->getPropertyValue($this->model, 'quoteIdMaskFactory')
507+
->expects($this->once())
508+
->method('create')
509+
->willReturn($this->quoteIdMock);
510+
511+
$quoteMock = $this->createPartialMock(
512+
Quote::class,
513+
['getCustomerId', 'setCustomer', 'setCustomerIsGuest', 'setIsActive', 'getIsActive', 'merge']
514+
);
515+
516+
$activeQuoteMock = $this->createPartialMock(
517+
Quote::class,
518+
['getCustomerId', 'setCustomer', 'setCustomerIsGuest', 'setIsActive', 'getIsActive', 'merge']
519+
);
520+
521+
$customerMock = $this->createMock(CustomerInterface::class);
479522

480523
$this->quoteRepositoryMock
481524
->expects($this->once())
@@ -490,7 +533,7 @@ public function testAssignCustomerNoSuchCustomer()
490533
->willReturn($customerMock);
491534

492535
$customerModelMock = $this->createPartialMock(
493-
\Magento\Customer\Model\Customer::class,
536+
Customer::class,
494537
['load', 'getSharedStoreIds']
495538
);
496539
$this->customerFactoryMock->expects($this->once())->method('create')->willReturn($customerModelMock);
@@ -506,17 +549,26 @@ public function testAssignCustomerNoSuchCustomer()
506549
->willReturn([$storeId, 'some store value']);
507550

508551
$quoteMock->expects($this->once())->method('getCustomerId')->willReturn(null);
509-
510552
$this->quoteRepositoryMock
511553
->expects($this->once())
512554
->method('getForCustomer')
513-
->with($customerId);
555+
->with($customerId)
556+
->willReturn($activeQuoteMock);
514557

515-
$this->model->assignCustomer($cartId, $customerId, $storeId);
558+
$quoteMock->expects($this->once())->method('merge')->with($activeQuoteMock)->willReturnSelf();
559+
$activeQuoteMock->expects($this->once())->method('setIsActive')->with(0);
560+
$this->quoteRepositoryMock->expects($this->atLeastOnce())->method('save')->with($activeQuoteMock);
516561

517-
$this->expectExceptionMessage(
518-
"The customer can't be assigned to the cart because the customer already has an active cart."
519-
);
562+
$quoteMock->expects($this->once())->method('setCustomer')->with($customerMock);
563+
$quoteMock->expects($this->once())->method('setCustomerIsGuest')->with(0);
564+
$quoteMock->expects($this->once())->method('setIsActive')->with(1);
565+
566+
$this->quoteIdMock->expects($this->once())->method('load')->with($cartId, 'quote_id')->willReturnSelf();
567+
$this->quoteIdMock->expects($this->once())->method('getId')->willReturn(10);
568+
$this->quoteIdMock->expects($this->once())->method('delete');
569+
$this->quoteRepositoryMock->expects($this->atLeastOnce())->method('save')->with($quoteMock);
570+
571+
$this->model->assignCustomer($cartId, $customerId, $storeId);
520572
}
521573

522574
public function testAssignCustomer()
@@ -529,15 +581,13 @@ public function testAssignCustomer()
529581
->expects($this->once())
530582
->method('create')
531583
->willReturn($this->quoteIdMock);
532-
$this->quoteIdMock->expects($this->once())->method('load')->with($cartId, 'quote_id')->willReturnSelf();
533-
$this->quoteIdMock->expects($this->once())->method('getId')->willReturn(10);
534-
$this->quoteIdMock->expects($this->once())->method('delete');
584+
535585
$quoteMock = $this->createPartialMock(
536-
\Magento\Quote\Model\Quote::class,
537-
['getCustomerId', 'setCustomer', 'setCustomerIsGuest']
586+
Quote::class,
587+
['getCustomerId', 'setCustomer', 'setCustomerIsGuest', 'setIsActive', 'getIsActive', 'merge']
538588
);
539-
$customerMock = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class);
540589

590+
$customerMock = $this->createMock(CustomerInterface::class);
541591
$this->quoteRepositoryMock
542592
->expects($this->once())
543593
->method('getActive')
@@ -551,10 +601,12 @@ public function testAssignCustomer()
551601
->willReturn($customerMock);
552602

553603
$customerModelMock = $this->createPartialMock(
554-
\Magento\Customer\Model\Customer::class,
604+
Customer::class,
555605
['load', 'getSharedStoreIds']
556606
);
607+
557608
$this->customerFactoryMock->expects($this->once())->method('create')->willReturn($customerModelMock);
609+
558610
$customerModelMock
559611
->expects($this->once())
560612
->method('load')
@@ -572,11 +624,17 @@ public function testAssignCustomer()
572624
->expects($this->once())
573625
->method('getForCustomer')
574626
->with($customerId)
575-
->willThrowException(new NoSuchEntityException());
627+
->willThrowException(new \Magento\Framework\Exception\NoSuchEntityException());
628+
629+
$quoteMock->expects($this->never())->method('merge');
576630

577631
$quoteMock->expects($this->once())->method('setCustomer')->with($customerMock);
578632
$quoteMock->expects($this->once())->method('setCustomerIsGuest')->with(0);
633+
$quoteMock->expects($this->once())->method('setIsActive')->with(1);
579634

635+
$this->quoteIdMock->expects($this->once())->method('load')->with($cartId, 'quote_id')->willReturnSelf();
636+
$this->quoteIdMock->expects($this->once())->method('getId')->willReturn(10);
637+
$this->quoteIdMock->expects($this->once())->method('delete');
580638
$this->quoteRepositoryMock->expects($this->once())->method('save')->with($quoteMock);
581639

582640
$this->model->assignCustomer($cartId, $customerId, $storeId);
@@ -881,7 +939,7 @@ protected function getQuote(
881939
\Magento\Quote\Model\Quote\Address $shippingAddress = null
882940
) {
883941
$quote = $this->createPartialMock(
884-
\Magento\Quote\Model\Quote::class,
942+
Quote::class,
885943
[
886944
'setIsActive',
887945
'getCustomerEmail',
@@ -928,7 +986,7 @@ protected function getQuote(
928986
->willReturn($payment);
929987

930988
$customer = $this->createPartialMock(
931-
\Magento\Customer\Model\Customer::class,
989+
Customer::class,
932990
['getDefaultBilling', 'getId']
933991
);
934992
$quote->expects($this->any())->method('getCustomerId')->willReturn($customerId);
@@ -1016,12 +1074,12 @@ protected function prepareOrderFactory(
10161074
}
10171075

10181076
/**
1019-
* @throws NoSuchEntityException
1077+
* @throws \Magento\Framework\Exception\NoSuchEntityException
10201078
*/
10211079
public function testGetCartForCustomer()
10221080
{
10231081
$customerId = 100;
1024-
$cartMock = $this->createMock(\Magento\Quote\Model\Quote::class);
1082+
$cartMock = $this->createMock(Quote::class);
10251083
$this->quoteRepositoryMock->expects($this->once())
10261084
->method('getActiveForCustomer')
10271085
->with($customerId)

dev/tests/api-functional/testsuite/Magento/Quote/Api/CartManagementTest.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,21 +310,20 @@ public function testAssignCustomerThrowsExceptionIfCartIsAssignedToDifferentStor
310310
}
311311

312312
/**
313-
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
313+
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php
314314
* @magentoApiDataFixture Magento/Sales/_files/quote.php
315-
* @expectedException \Exception
316315
*/
317-
public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart()
316+
public function testAssignCustomerCartMerged()
318317
{
319318
/** @var $customer \Magento\Customer\Model\Customer */
320319
$customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class)->load(1);
321320
// Customer has a quote with reserved order ID test_order_1 (see fixture)
322321
/** @var $customerQuote \Magento\Quote\Model\Quote */
323322
$customerQuote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)
324-
->load('test_order_1', 'reserved_order_id');
325-
$customerQuote->setIsActive(1)->save();
323+
->load('test_order_item_with_items', 'reserved_order_id');
326324
/** @var $quote \Magento\Quote\Model\Quote */
327325
$quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
326+
$expectedQuoteItemsQty = $customerQuote->getItemsQty() + $quote->getItemsQty();
328327

329328
$cartId = $quote->getId();
330329
$customerId = $customer->getId();
@@ -346,11 +345,13 @@ public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart(
346345
'customerId' => $customerId,
347346
'storeId' => 1,
348347
];
349-
$this->_webApiCall($serviceInfo, $requestData);
348+
$this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
350349

351-
$this->expectExceptionMessage(
352-
"The customer can't be assigned to the cart because the customer already has an active cart."
353-
);
350+
$mergedQuote = $this->objectManager
351+
->create(\Magento\Quote\Model\Quote::class)
352+
->load('test01', 'reserved_order_id');
353+
354+
$this->assertEquals($expectedQuoteItemsQty, $mergedQuote->getItemsQty());
354355
}
355356

356357
/**

0 commit comments

Comments
 (0)