From ab1324ecc1d5e2990acfd4f14c7b77765d343a9e Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun Date: Fri, 13 Jul 2018 15:12:21 +0300 Subject: [PATCH 1/3] Fix the issue with "Shipping address is not set" exception #16555 --- app/code/Magento/Multishipping/Controller/Checkout.php | 1 + .../Magento/Quote/Model/ShippingMethodManagement.php | 4 +--- .../Test/Unit/Model/ShippingMethodManagementTest.php | 10 ++-------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Multishipping/Controller/Checkout.php b/app/code/Magento/Multishipping/Controller/Checkout.php index 1870736a0efd9..161021768ce19 100644 --- a/app/code/Magento/Multishipping/Controller/Checkout.php +++ b/app/code/Magento/Multishipping/Controller/Checkout.php @@ -84,6 +84,7 @@ protected function _getCheckoutSession() * * @param RequestInterface $request * @return \Magento\Framework\App\ResponseInterface + * @throws \Magento\Framework\Exception\NotFoundException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagement.php b/app/code/Magento/Quote/Model/ShippingMethodManagement.php index ade2649d0b1b0..ac609e7f435ea 100644 --- a/app/code/Magento/Quote/Model/ShippingMethodManagement.php +++ b/app/code/Magento/Quote/Model/ShippingMethodManagement.php @@ -171,9 +171,7 @@ public function set($cartId, $carrierCode, $methodCode) * @param string $methodCode The shipping method code. * @return void * @throws InputException The shipping method is not valid for an empty cart. - * @throws CouldNotSaveException The shipping method could not be saved. * @throws NoSuchEntityException CThe Cart includes virtual product(s) only, so a shipping address is not used. - * @throws StateException The billing or shipping address is missing. Set the address and try again. */ public function apply($cartId, $carrierCode, $methodCode) { @@ -191,7 +189,7 @@ public function apply($cartId, $carrierCode, $methodCode) } $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { - throw new StateException(__('The shipping address is missing. Set the address and try again.')); + return; } $shippingAddress->setShippingMethod($carrierCode . '_' . $methodCode); } diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php index 198f1c54a42b4..6042ab25eef7f 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php @@ -344,10 +344,6 @@ public function testSetMethodWithVirtualProduct() $this->model->set($cartId, $carrierCode, $methodCode); } - /** - * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage The shipping address is missing. Set the address and try again. - */ public function testSetMethodWithoutShippingAddress() { $cartId = 12; @@ -361,6 +357,7 @@ public function testSetMethodWithoutShippingAddress() $this->quote->expects($this->once())->method('isVirtual')->will($this->returnValue(false)); $this->quote->expects($this->once()) ->method('getShippingAddress')->will($this->returnValue($this->shippingAddress)); + $this->quote->expects($this->once())->method('collectTotals')->willReturnSelf(); $this->shippingAddress->expects($this->once())->method('getCountryId')->will($this->returnValue(null)); $this->model->set($cartId, $carrierCode, $methodCode); @@ -402,10 +399,6 @@ public function testSetMethodWithCouldNotSaveException() $this->model->set($cartId, $carrierCode, $methodCode); } - /** - * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage The shipping address is missing. Set the address and try again. - */ public function testSetMethodWithoutAddress() { $cartId = 12; @@ -420,6 +413,7 @@ public function testSetMethodWithoutAddress() $this->quote->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddress); + $this->quote->expects($this->once())->method('collectTotals')->willReturnSelf(); $this->shippingAddress->expects($this->once())->method('getCountryId'); $this->model->set($cartId, $carrierCode, $methodCode); From 9868428966220ddc23fe04f3af985eab2d66ff59 Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun Date: Sun, 12 Aug 2018 10:16:19 +0300 Subject: [PATCH 2/3] Fix the issue with "Shipping address is not set" exception, Fix the integrity constraint violation error when trying to access Shopping Cart --- .../Multishipping/Controller/Checkout.php | 11 ++++++++++- app/code/Magento/Multishipping/Helper/Url.php | 10 ++++++++++ .../Quote/Model/ShippingMethodManagement.php | 18 ++++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Multishipping/Controller/Checkout.php b/app/code/Magento/Multishipping/Controller/Checkout.php index 161021768ce19..92417c7cb3a18 100644 --- a/app/code/Magento/Multishipping/Controller/Checkout.php +++ b/app/code/Magento/Multishipping/Controller/Checkout.php @@ -8,6 +8,7 @@ use Magento\Customer\Api\AccountManagementInterface; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Framework\App\RequestInterface; +use Magento\Framework\Exception\StateException; /** * Multishipping checkout controller @@ -153,7 +154,15 @@ public function dispatch(RequestInterface $request) return parent::dispatch($request); } - $quote = $this->_getCheckout()->getQuote(); + try { + $checkout = $this->_getCheckout(); + } catch (StateException $e) { + $this->getResponse()->setRedirect($this->_getHelper()->getMSNewShippingUrl()); + $this->_actionFlag->set('', self::FLAG_NO_DISPATCH, true); + return parent::dispatch($request); + } + + $quote = $checkout->getQuote(); if (!$quote->hasItems() || $quote->getHasError() || $quote->isVirtual()) { $this->getResponse()->setRedirect($this->_getHelper()->getCartUrl()); $this->_actionFlag->set('', self::FLAG_NO_DISPATCH, true); diff --git a/app/code/Magento/Multishipping/Helper/Url.php b/app/code/Magento/Multishipping/Helper/Url.php index e293e3d4d7121..eaefa8fe8bee3 100644 --- a/app/code/Magento/Multishipping/Helper/Url.php +++ b/app/code/Magento/Multishipping/Helper/Url.php @@ -63,6 +63,16 @@ public function getMSShippingAddressSavedUrl() return $this->_getUrl('multishipping/checkout_address/shippingSaved'); } + /** + * Retrieve register url + * + * @return string + */ + public function getMSNewShippingUrl() + { + return $this->_getUrl('multishipping/checkout_address/newShipping'); + } + /** * Retrieve register url * diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagement.php b/app/code/Magento/Quote/Model/ShippingMethodManagement.php index ac609e7f435ea..f62866539c6cc 100644 --- a/app/code/Magento/Quote/Model/ShippingMethodManagement.php +++ b/app/code/Magento/Quote/Model/ShippingMethodManagement.php @@ -16,6 +16,7 @@ use Magento\Quote\Api\Data\AddressInterface; use Magento\Quote\Api\Data\EstimateAddressInterface; use Magento\Quote\Api\ShipmentEstimationInterface; +use Magento\Quote\Model\ResourceModel\Quote\Address as QuoteAddressResource; /** * Shipping method read service @@ -63,6 +64,11 @@ class ShippingMethodManagement implements */ private $addressFactory; + /** + * @var QuoteAddressResource + */ + private $quoteAddressResource; + /** * Constructor * @@ -71,13 +77,15 @@ class ShippingMethodManagement implements * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository * @param Quote\TotalsCollector $totalsCollector * @param AddressInterfaceFactory|null $addressFactory + * @param QuoteAddressResource|null $quoteAddressResource */ public function __construct( \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, Cart\ShippingMethodConverter $converter, \Magento\Customer\Api\AddressRepositoryInterface $addressRepository, \Magento\Quote\Model\Quote\TotalsCollector $totalsCollector, - AddressInterfaceFactory $addressFactory = null + AddressInterfaceFactory $addressFactory = null, + QuoteAddressResource $quoteAddressResource = null ) { $this->quoteRepository = $quoteRepository; $this->converter = $converter; @@ -85,6 +93,8 @@ public function __construct( $this->totalsCollector = $totalsCollector; $this->addressFactory = $addressFactory ?: ObjectManager::getInstance() ->get(AddressInterfaceFactory::class); + $this->quoteAddressResource = $quoteAddressResource ?: ObjectManager::getInstance() + ->get(QuoteAddressResource::class); } /** @@ -172,6 +182,8 @@ public function set($cartId, $carrierCode, $methodCode) * @return void * @throws InputException The shipping method is not valid for an empty cart. * @throws NoSuchEntityException CThe Cart includes virtual product(s) only, so a shipping address is not used. + * @throws StateException The billing or shipping address is not set. + * @throws \Exception */ public function apply($cartId, $carrierCode, $methodCode) { @@ -189,7 +201,9 @@ public function apply($cartId, $carrierCode, $methodCode) } $shippingAddress = $quote->getShippingAddress(); if (!$shippingAddress->getCountryId()) { - return; + // Remove empty quote address + $this->quoteAddressResource->delete($shippingAddress); + throw new StateException(__('The shipping address is missing. Set the address and try again.')); } $shippingAddress->setShippingMethod($carrierCode . '_' . $methodCode); } From 2c546c4d67d1b8434405874f80c02eb898c3dced Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun Date: Sun, 12 Aug 2018 10:44:14 +0300 Subject: [PATCH 3/3] Update PHPUnit tests --- .../Model/ShippingMethodManagementTest.php | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php index 6042ab25eef7f..34d7707d31666 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php @@ -15,7 +15,9 @@ use Magento\Quote\Model\Quote\Address\Rate; use Magento\Quote\Model\Quote\TotalsCollector; use Magento\Quote\Model\QuoteRepository; +use Magento\Quote\Model\ResourceModel\Quote\Address as QuoteAddressResource; use Magento\Quote\Model\ShippingMethodManagement; +use Magento\Store\Model\Store; use PHPUnit_Framework_MockObject_MockObject as MockObject; /** @@ -83,6 +85,16 @@ class ShippingMethodManagementTest extends \PHPUnit\Framework\TestCase */ private $totalsCollector; + /** + * @var Store|MockObject + */ + private $storeMock; + + /** + * @var QuoteAddressResource|MockObject + */ + private $quoteAddressResource; + protected function setUp() { $this->objectManager = new ObjectManager($this); @@ -98,7 +110,8 @@ protected function setUp() $className = \Magento\Framework\Reflection\DataObjectProcessor::class; $this->dataProcessor = $this->createMock($className); - $this->storeMock = $this->createMock(\Magento\Store\Model\Store::class); + $this->quoteAddressResource = $this->createMock(QuoteAddressResource::class); + $this->storeMock = $this->createMock(Store::class); $this->quote = $this->getMockBuilder(Quote::class) ->disableOriginalConstructor() ->setMethods([ @@ -150,6 +163,7 @@ protected function setUp() 'converter' => $this->converter, 'totalsCollector' => $this->totalsCollector, 'addressRepository' => $this->addressRepository, + 'quoteAddressResource' => $this->quoteAddressResource, ] ); @@ -344,6 +358,10 @@ public function testSetMethodWithVirtualProduct() $this->model->set($cartId, $carrierCode, $methodCode); } + /** + * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. + */ public function testSetMethodWithoutShippingAddress() { $cartId = 12; @@ -357,8 +375,8 @@ public function testSetMethodWithoutShippingAddress() $this->quote->expects($this->once())->method('isVirtual')->will($this->returnValue(false)); $this->quote->expects($this->once()) ->method('getShippingAddress')->will($this->returnValue($this->shippingAddress)); - $this->quote->expects($this->once())->method('collectTotals')->willReturnSelf(); $this->shippingAddress->expects($this->once())->method('getCountryId')->will($this->returnValue(null)); + $this->quoteAddressResource->expects($this->once())->method('delete')->with($this->shippingAddress); $this->model->set($cartId, $carrierCode, $methodCode); } @@ -399,6 +417,10 @@ public function testSetMethodWithCouldNotSaveException() $this->model->set($cartId, $carrierCode, $methodCode); } + /** + * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage The shipping address is missing. Set the address and try again. + */ public function testSetMethodWithoutAddress() { $cartId = 12; @@ -413,8 +435,8 @@ public function testSetMethodWithoutAddress() $this->quote->expects($this->once()) ->method('getShippingAddress') ->willReturn($this->shippingAddress); - $this->quote->expects($this->once())->method('collectTotals')->willReturnSelf(); $this->shippingAddress->expects($this->once())->method('getCountryId'); + $this->quoteAddressResource->expects($this->once())->method('delete')->with($this->shippingAddress); $this->model->set($cartId, $carrierCode, $methodCode); }