diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml
index c9680034e1e21..3f15701216005 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addtocart.phtml
@@ -53,9 +53,7 @@
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
index ab46c78c6f6e7..4e2fbdc5dfa50 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js
@@ -11,13 +11,18 @@ define([], function () {
*/
return function (addressData) {
var identifier = Date.now();
+ var regionId = null;
+
+ if (addressData.region && addressData.region.region_id) {
+ regionId = addressData.region.region_id;
+ } else if (addressData.country_id && addressData.country_id == window.checkoutConfig.defaultCountryId) {
+ regionId = window.checkoutConfig.defaultRegionId;
+ }
return {
email: addressData.email,
countryId: (addressData.country_id) ? addressData.country_id : window.checkoutConfig.defaultCountryId,
- regionId: (addressData.region && addressData.region.region_id) ?
- addressData.region.region_id
- : window.checkoutConfig.defaultRegionId,
+ regionId: regionId,
regionCode: (addressData.region) ? addressData.region.region_code : null,
region: (addressData.region) ? addressData.region.region : null,
customerId: addressData.customer_id,
diff --git a/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php b/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php
new file mode 100644
index 0000000000000..49d9be6bcf8ff
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Product/Plugin/RemoveQuoteItems.php
@@ -0,0 +1,40 @@
+quoteItemsCleaner = $quoteItemsCleaner;
+ }
+
+ /**
+ * @param \Magento\Catalog\Model\ResourceModel\Product $subject
+ * @param \Closure $proceed
+ * @param \Magento\Catalog\Api\Data\ProductInterface $product
+ * @return mixed
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ * TODO: reimplement with after plugin
+ */
+ public function aroundDelete(
+ \Magento\Catalog\Model\ResourceModel\Product $subject,
+ \Closure $proceed,
+ \Magento\Catalog\Api\Data\ProductInterface $product
+ ) {
+ $result = $proceed($product);
+ $this->quoteItemsCleaner->execute($product);
+ return $result;
+ }
+}
diff --git a/app/code/Magento/Quote/Model/Product/QuoteItemsCleaner.php b/app/code/Magento/Quote/Model/Product/QuoteItemsCleaner.php
new file mode 100644
index 0000000000000..ec0e6809c48f7
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Product/QuoteItemsCleaner.php
@@ -0,0 +1,33 @@
+itemResource = $itemResource;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function execute(\Magento\Catalog\Api\Data\ProductInterface $product)
+ {
+ $this->itemResource->getConnection()->delete(
+ $this->itemResource->getMainTable(),
+ 'product_id = ' . $product->getId()
+ );
+ }
+}
diff --git a/app/code/Magento/Quote/Model/Product/QuoteItemsCleanerInterface.php b/app/code/Magento/Quote/Model/Product/QuoteItemsCleanerInterface.php
new file mode 100644
index 0000000000000..1691efab5e541
--- /dev/null
+++ b/app/code/Magento/Quote/Model/Product/QuoteItemsCleanerInterface.php
@@ -0,0 +1,17 @@
+getTable('quote_item'),
'item_id',
\Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
- )->addForeignKey(
- $installer->getFkName('quote_item', 'product_id', 'catalog_product_entity', 'entity_id'),
- 'product_id',
- $installer->getTable('catalog_product_entity'),
- 'entity_id',
- \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
)->addForeignKey(
$installer->getFkName('quote_item', 'quote_id', 'quote', 'entity_id'),
'quote_id',
diff --git a/app/code/Magento/Quote/Setup/Recurring.php b/app/code/Magento/Quote/Setup/Recurring.php
deleted file mode 100644
index 03fe30bf80272..0000000000000
--- a/app/code/Magento/Quote/Setup/Recurring.php
+++ /dev/null
@@ -1,73 +0,0 @@
-metadataPool = $metadataPool;
- $this->externalFKSetup = $externalFKSetup;
- }
-
- /**
- * {@inheritdoc}
- */
- public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
- {
- $installer = $setup;
- $installer->startSetup();
-
- $this->addExternalForeignKeys($installer);
-
- $installer->endSetup();
- }
-
- /**
- * Add external foreign keys
- *
- * @param SchemaSetupInterface $installer
- * @return void
- * @throws \Exception
- */
- protected function addExternalForeignKeys(SchemaSetupInterface $installer)
- {
- $metadata = $this->metadataPool->getMetadata(ProductInterface::class);
- $this->externalFKSetup->install(
- $installer,
- $metadata->getEntityTable(),
- $metadata->getIdentifierField(),
- 'quote_item',
- 'product_id'
- );
- }
-}
diff --git a/app/code/Magento/Quote/Setup/UpgradeSchema.php b/app/code/Magento/Quote/Setup/UpgradeSchema.php
index 602f93e0445f0..d2163035bdcbf 100644
--- a/app/code/Magento/Quote/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Quote/Setup/UpgradeSchema.php
@@ -41,7 +41,15 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
]
);
}
-
+ //drop foreign key for single DB case
+ if (version_compare($context->getVersion(), '2.0.3', '<')
+ && $setup->tableExists($setup->getTable('quote_item'))
+ ) {
+ $setup->getConnection()->dropForeignKey(
+ $setup->getTable('quote_item'),
+ $setup->getFkName('quote_item', 'product_id', 'catalog_product_entity', 'entity_id')
+ );
+ }
$setup->endSetup();
}
}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php
new file mode 100644
index 0000000000000..083722f3a1bb3
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Product/Plugin/RemoveQuoteItemsTest.php
@@ -0,0 +1,38 @@
+quoteItemsCleanerMock = $this->getMock(\Magento\Quote\Model\Product\QuoteItemsCleanerInterface::class);
+ $this->model = new \Magento\Quote\Model\Product\Plugin\RemoveQuoteItems($this->quoteItemsCleanerMock);
+ }
+
+ public function testAroundDelete()
+ {
+ $productResourceMock = $this->getMock(\Magento\Catalog\Model\ResourceModel\Product::class, [], [], '', false);
+ $productMock = $this->getMock(\Magento\Catalog\Api\Data\ProductInterface::class);
+ $closure = function () use ($productResourceMock) {
+ return $productResourceMock;
+ };
+
+ $this->quoteItemsCleanerMock->expects($this->once())->method('execute')->with($productMock);
+ $result = $this->model->aroundDelete($productResourceMock, $closure, $productMock);
+ $this->assertEquals($result, $productResourceMock);
+ }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Product/QuoteItemsCleanerTest.php b/app/code/Magento/Quote/Test/Unit/Model/Product/QuoteItemsCleanerTest.php
new file mode 100644
index 0000000000000..d6bb3e5ae31a8
--- /dev/null
+++ b/app/code/Magento/Quote/Test/Unit/Model/Product/QuoteItemsCleanerTest.php
@@ -0,0 +1,45 @@
+itemResourceMock = $this->getMock(
+ \Magento\Quote\Model\ResourceModel\Quote\Item::class,
+ [],
+ [],
+ '',
+ false
+ );
+ $this->model = new \Magento\Quote\Model\Product\QuoteItemsCleaner($this->itemResourceMock);
+ }
+
+ public function testExecute()
+ {
+ $tableName = 'table_name';
+ $productMock = $this->getMock(\Magento\Catalog\Api\Data\ProductInterface::class);
+ $productMock->expects($this->once())->method('getId')->willReturn(1);
+
+ $connectionMock = $this->getMock(\Magento\Framework\DB\Adapter\AdapterInterface::class);
+ $this->itemResourceMock->expects($this->once())->method('getConnection')->willReturn($connectionMock);
+ $this->itemResourceMock->expects($this->once())->method('getMainTable')->willReturn($tableName);
+
+ $connectionMock->expects($this->once())->method('delete')->with($tableName, 'product_id = 1');
+ $this->model->execute($productMock);
+ }
+}
diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml
index e3192f1c1d58e..384f5ca143b86 100644
--- a/app/code/Magento/Quote/etc/di.xml
+++ b/app/code/Magento/Quote/etc/di.xml
@@ -40,7 +40,6 @@
-
@@ -90,4 +89,8 @@
+
+
+
+
diff --git a/app/code/Magento/Quote/etc/module.xml b/app/code/Magento/Quote/etc/module.xml
index 8350b4c4f87ea..281cde9eeb9d1 100644
--- a/app/code/Magento/Quote/etc/module.xml
+++ b/app/code/Magento/Quote/etc/module.xml
@@ -6,6 +6,6 @@
*/
-->
-
+
diff --git a/app/code/Magento/Sales/Setup/UpgradeSchema.php b/app/code/Magento/Sales/Setup/UpgradeSchema.php
index 907d782e8deaf..34e7c29b6c6a0 100644
--- a/app/code/Magento/Sales/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Sales/Setup/UpgradeSchema.php
@@ -4,6 +4,8 @@
* See COPYING.txt for license details.
*/
namespace Magento\Sales\Setup;
+
+use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
@@ -14,6 +16,11 @@
*/
class UpgradeSchema implements UpgradeSchemaInterface
{
+ /**
+ * @var AdapterInterface
+ */
+ private $salesConnection;
+
/**
* {@inheritdoc}
*/
@@ -30,7 +37,8 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
'sales_bestsellers_aggregated_daily',
'product_id',
'catalog_product_entity',
- 'entity_id')
+ 'entity_id'
+ )
);
//sales_bestsellers_aggregated_monthly
$connection->dropForeignKey(
@@ -39,7 +47,8 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
'sales_bestsellers_aggregated_monthly',
'product_id',
'catalog_product_entity',
- 'entity_id')
+ 'entity_id'
+ )
);
//sales_bestsellers_aggregated_yearly
@@ -49,7 +58,8 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
'sales_bestsellers_aggregated_yearly',
'product_id',
'catalog_product_entity',
- 'entity_id')
+ 'entity_id'
+ )
);
$installer->endSetup();
@@ -66,7 +76,7 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
*/
private function addColumnBaseGrandTotal(SchemaSetupInterface $installer)
{
- $connection = $installer->getConnection();
+ $connection = $this->getSalesConnection();
$connection->addColumn(
$installer->getTable('sales_invoice_grid'),
'base_grand_total',
@@ -86,11 +96,29 @@ private function addColumnBaseGrandTotal(SchemaSetupInterface $installer)
*/
private function addIndexBaseGrandTotal(SchemaSetupInterface $installer)
{
- $connection = $installer->getConnection();
+ $connection = $this->getSalesConnection();
$connection->addIndex(
$installer->getTable('sales_invoice_grid'),
$installer->getIdxName('sales_invoice_grid', ['base_grand_total']),
['base_grand_total']
);
}
+
+ /**
+ * @return AdapterInterface
+ */
+ private function getSalesConnection()
+ {
+ if ($this->salesConnection === null) {
+ $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
+ /** @var ResourceConnection $resourceConnection */
+ $resourceConnection = $objectManager->get(ResourceConnection::class);
+ try {
+ $this->salesConnection = $resourceConnection->getConnectionByName('sales');
+ } catch (\DomainException $e) {
+ $this->salesConnection = $resourceConnection->getConnection();
+ }
+ }
+ return $this->salesConnection;
+ }
}
diff --git a/app/code/Magento/Tax/Model/TaxConfigProvider.php b/app/code/Magento/Tax/Model/TaxConfigProvider.php
index a56663a8d558a..95f371da1726a 100644
--- a/app/code/Magento/Tax/Model/TaxConfigProvider.php
+++ b/app/code/Magento/Tax/Model/TaxConfigProvider.php
@@ -55,6 +55,14 @@ public function __construct(
*/
public function getConfig()
{
+ $defaultRegionId = $this->scopeConfig->getValue(
+ \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION,
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+ );
+ // prevent wrong assignment on shipping rate estimation requests
+ if (0 == $defaultRegionId) {
+ $defaultRegionId = null;
+ }
return [
'isDisplayShippingPriceExclTax' => $this->isDisplayShippingPriceExclTax(),
'isDisplayShippingBothPrices' => $this->isDisplayShippingBothPrices(),
@@ -69,10 +77,7 @@ public function getConfig()
\Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
),
- 'defaultRegionId' => $this->scopeConfig->getValue(
- \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION,
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- ),
+ 'defaultRegionId' => $defaultRegionId,
'defaultPostcode' => $this->scopeConfig->getValue(
\Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_POSTCODE,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php
index 0cb720329c134..0ce7a40a5d1db 100644
--- a/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php
+++ b/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php
@@ -302,6 +302,35 @@ public function getConfigDataProvider()
Config::CONFIG_XML_PATH_DEFAULT_POSTCODE => '*',
],
],
+ 'zeroRegionToNull' => [
+ 'expectedResult' => [
+ 'isDisplayShippingPriceExclTax' => 1,
+ 'isDisplayShippingBothPrices' => 1,
+ 'reviewShippingDisplayMode' => 'excluding',
+ 'reviewItemPriceDisplayMode' => 'including',
+ 'reviewTotalsDisplayMode' => 'both',
+ 'includeTaxInGrandTotal' => 1,
+ 'isFullTaxSummaryDisplayed' => 1,
+ 'isZeroTaxDisplayed' => 1,
+ 'reloadOnBillingAddress' => false,
+ 'defaultCountryId' => 'US',
+ 'defaultRegionId' => null,
+ 'defaultPostcode' => '*',
+ ],
+ 'cartShippingBoth' => 0,
+ 'cartShippingExclTax' => 1,
+ 'cartBothPrices' => 0,
+ 'cartPriceExclTax' => 0,
+ 'cartSubTotalBoth' => 1,
+ 'cartSubTotalExclTax' => 0,
+ 'isQuoteVirtual' => false,
+ 'config' => [
+ Config::CONFIG_XML_PATH_BASED_ON => 'shipping',
+ Config::CONFIG_XML_PATH_DEFAULT_COUNTRY => 'US',
+ Config::CONFIG_XML_PATH_DEFAULT_REGION => 0,
+ Config::CONFIG_XML_PATH_DEFAULT_POSTCODE => '*',
+ ],
+ ],
];
}
}
diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php
index d3ea0ce15eb68..5a5b1d5c4dbde 100644
--- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php
+++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable.php
@@ -107,6 +107,13 @@
try {
$productToDelete = $productRepository->getById(1);
$productRepository->delete($productToDelete);
+
+ /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $itemResource */
+ $itemResource = Bootstrap::getObjectManager()->get(\Magento\Quote\Model\ResourceModel\Quote\Item::class);
+ $itemResource->getConnection()->delete(
+ $itemResource->getMainTable(),
+ 'product_id = ' . $productToDelete->getId()
+ );
} catch (\Exception $e) {
// Nothing to remove
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
index 6184dd7ee4355..78342c886de96 100755
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php
@@ -4225,4 +4225,5 @@
['Magento\Catalog\Test\Unit\Webapi\Product\Option\Type\File\ValidatorTest'],
['Magento\Framework\Search\Document', 'Magento\Framework\Api\Search\Document'],
['Magento\Framework\Search\DocumentField'],
+ ['Magento\Quote\Setup\Recurring'],
];