Skip to content

Commit fe64409

Browse files
ameysarzakdma
authored andcommitted
MAGETWO-63578: [Backport] - [GitHub #5547] Configurable product wrongly imported if sku is an integer - for 2.1
1 parent 0ccf4c8 commit fe64409

File tree

6 files changed

+218
-20
lines changed

6 files changed

+218
-20
lines changed

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ protected function _saveProductAttributes(array $attributesData)
12491249
$linkId = $this->_connection->fetchOne(
12501250
$this->_connection->select()
12511251
->from($this->getResource()->getTable('catalog_product_entity'))
1252-
->where('sku = ?', $sku)
1252+
->where('sku = ?', (string)$sku)
12531253
->columns($this->getProductEntityLinkField())
12541254
);
12551255

dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/ConfigurableTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@
77

88
use Magento\CatalogImportExport\Model\AbstractProductExportImportTestCase;
99

10+
/**
11+
* Configurable product import test.
12+
*/
1013
class ConfigurableTest extends AbstractProductExportImportTestCase
1114
{
15+
/**
16+
* @return array
17+
*/
1218
public function exportImportDataProvider()
1319
{
1420
return [
@@ -21,6 +27,15 @@ public function exportImportDataProvider()
2127
],
2228
['_cache_instance_products', '_cache_instance_configurable_attributes'],
2329
],
30+
'configurable-product-12345' => [
31+
[
32+
'Magento/ConfigurableProduct/_files/product_configurable_12345.php'
33+
],
34+
[
35+
'12345',
36+
],
37+
['_cache_instance_products', '_cache_instance_configurable_attributes'],
38+
],
2439
];
2540
}
2641

dev/tests/integration/testsuite/Magento/ConfigurableImportExport/Model/Import/Product/Type/ConfigurableTest.php

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@
66
namespace Magento\ConfigurableImportExport\Model\Import\Product\Type;
77

88
use Magento\Catalog\Api\ProductRepositoryInterface;
9-
use Magento\Framework\App\Bootstrap;
109
use Magento\Framework\App\Filesystem\DirectoryList;
1110
use Magento\ImportExport\Model\Import;
1211

1312
/**
13+
* Product type configurable import test.
14+
*
1415
* @magentoAppArea adminhtml
1516
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1617
*/
1718
class ConfigurableTest extends \PHPUnit_Framework_TestCase
1819
{
19-
/**
20-
* Configurable product test Name
21-
*/
22-
const TEST_PRODUCT_NAME = 'Configurable 1';
23-
2420
/**
2521
* Configurable product test Type
2622
*/
@@ -31,13 +27,6 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase
3127
*/
3228
protected $model;
3329

34-
/**
35-
* Configurable product options SKU list
36-
*
37-
* @var array
38-
*/
39-
protected $optionSkuList = ['Configurable 1-Option 1', 'Configurable 1-Option 2'];
40-
4130
/**
4231
* @var \Magento\Framework\ObjectManagerInterface
4332
*/
@@ -59,13 +48,35 @@ protected function setUp()
5948
}
6049

6150
/**
51+
* @return array
52+
*/
53+
public function configurableImportDataProvider()
54+
{
55+
return [
56+
'Configurable 1' => [
57+
__DIR__ . '/../../_files/import_configurable.csv',
58+
'Configurable 1',
59+
['Configurable 1-Option 1', 'Configurable 1-Option 2'],
60+
],
61+
'12345' => [
62+
__DIR__ . '/../../_files/import_configurable_12345.csv',
63+
'12345',
64+
['Configurable 1-Option 1', 'Configurable 1-Option 2'],
65+
],
66+
];
67+
}
68+
69+
/**
70+
* @param string $pathToFile Path to import file
71+
* @param string $productName Name/sku of configurable product
72+
* @param array $optionSkuList Name of variations for configurable product
6273
* @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php
6374
* @magentoAppArea adminhtml
75+
* @dataProvider configurableImportDataProvider
6476
*/
65-
public function testConfigurableImport()
77+
public function testConfigurableImport($pathToFile, $productName, $optionSkuList)
6678
{
6779
// import data from CSV file
68-
$pathToFile = __DIR__ . '/../../_files/import_configurable.csv';
6980
$filesystem = $this->objectManager->create(
7081
\Magento\Framework\Filesystem::class
7182
);
@@ -92,23 +103,23 @@ public function testConfigurableImport()
92103

93104
/** @var \Magento\Catalog\Model\ResourceModel\Product $resource */
94105
$resource = $this->objectManager->get(\Magento\Catalog\Model\ResourceModel\Product::class);
95-
$productId = $resource->getIdBySku(self::TEST_PRODUCT_NAME);
106+
$productId = $resource->getIdBySku($productName);
96107
$this->assertTrue(is_numeric($productId));
97108
/** @var \Magento\Catalog\Model\Product $product */
98109
$product = $this->objectManager->get(ProductRepositoryInterface::class)->getById($productId);
99110

100111
$this->assertFalse($product->isObjectNew());
101-
$this->assertEquals(self::TEST_PRODUCT_NAME, $product->getName());
112+
$this->assertEquals($productName, $product->getName());
102113
$this->assertEquals(self::TEST_PRODUCT_TYPE, $product->getTypeId());
103114

104115
$optionCollection = $product->getTypeInstance()->getConfigurableOptions($product);
105116
foreach ($optionCollection as $option) {
106117
foreach ($option as $optionData) {
107-
$this->assertContains($optionData['sku'], $this->optionSkuList);
118+
$this->assertContains($optionData['sku'], $optionSkuList);
108119
}
109120
}
110121

111-
$optionIdList = $resource->getProductsIdsBySkus($this->optionSkuList);
122+
$optionIdList = $resource->getProductsIdsBySkus($optionSkuList);
112123
foreach ($optionIdList as $optionId) {
113124
$this->assertArrayHasKey($optionId, $product->getExtensionAttributes()->getConfigurableProductLinks());
114125
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
sku,store_view_code,attribute_set_code,product_type,name,description,short_description,weight,product_online,tax_class_name,visibility,price,url_key,display_product_options_in,map_price,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,configurable_variations,configurable_variation_labels,associated_skus
2+
Configurable 1-Option 1,,Default,simple,Configurable 1-Option 1,,,,1,Taxable Goods,Not Visible Individually,10,configurable-1-option-1,Block after Info Column,,"attribute_with_option=Option Label,has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 1",99999,0,0,0,0,1,1,0,0,0,1,,1,1,0,0,1,0,0,0,1,,,
3+
Configurable 1-Option 2,,Default,simple,Configurable 1-Option 2,,,,1,Taxable Goods,Not Visible Individually,10,configurable-1-option-2,Block after Info Column,,"has_options=0,quantity_and_stock_status=In Stock,required_options=0,test_configurable=Option 2",99999,0,0,0,0,1,1,0,0,0,1,,1,1,0,0,1,0,0,0,1,,,
4+
12345,,Default,configurable,12345,,,,1,Taxable Goods,"Catalog, Search",10,12345,Block after Info Column,,"has_options=1,quantity_and_stock_status=In Stock,required_options=0",0,0,0,0,0,1,1,0,0,0,1,,1,0,0,0,1,0,0,0,1,"sku=Configurable 1-Option 1,test_configurable=Option 1|sku=Configurable 1-Option 2,test_configurable=Option 2",test_configurable=test_configurable,
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Catalog\Api\ProductRepositoryInterface;
8+
use Magento\Catalog\Model\Product;
9+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
10+
use Magento\Catalog\Model\Product\Type;
11+
use Magento\Catalog\Model\Product\Visibility;
12+
use Magento\Catalog\Setup\CategorySetup;
13+
use Magento\ConfigurableProduct\Helper\Product\Options\Factory;
14+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
15+
use Magento\Eav\Api\Data\AttributeOptionInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
18+
Bootstrap::getInstance()->reinitialize();
19+
20+
require __DIR__ . '/configurable_attribute.php';
21+
22+
/** @var ProductRepositoryInterface $productRepository */
23+
$productRepository = Bootstrap::getObjectManager()
24+
->create(ProductRepositoryInterface::class);
25+
26+
/** @var $installer CategorySetup */
27+
$installer = Bootstrap::getObjectManager()->create(CategorySetup::class);
28+
29+
/* Create simple products per each option value*/
30+
/** @var AttributeOptionInterface[] $options */
31+
$options = $attribute->getOptions();
32+
33+
$attributeValues = [];
34+
$attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default');
35+
$associatedProductIds = [];
36+
$productIds = [30, 40];
37+
array_shift($options); //remove the first option which is empty
38+
39+
foreach ($options as $option) {
40+
/** @var $product Product */
41+
$product = Bootstrap::getObjectManager()->create(Product::class);
42+
$productId = array_shift($productIds);
43+
$product->setTypeId(Type::TYPE_SIMPLE)
44+
->setId($productId)
45+
->setAttributeSetId($attributeSetId)
46+
->setWebsiteIds([1])
47+
->setName('Configurable Option' . $option->getLabel())
48+
->setSku('simple_' . $productId)
49+
->setPrice($productId)
50+
->setTestConfigurable($option->getValue())
51+
->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE)
52+
->setStatus(Status::STATUS_ENABLED)
53+
->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]);
54+
55+
$product = $productRepository->save($product);
56+
57+
/** @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */
58+
$stockItem = Bootstrap::getObjectManager()->create(\Magento\CatalogInventory\Model\Stock\Item::class);
59+
$stockItem->load($productId, 'product_id');
60+
61+
if (!$stockItem->getProductId()) {
62+
$stockItem->setProductId($productId);
63+
}
64+
$stockItem->setUseConfigManageStock(1);
65+
$stockItem->setQty(1000);
66+
$stockItem->setIsQtyDecimal(0);
67+
$stockItem->setIsInStock(1);
68+
$stockItem->save();
69+
70+
$attributeValues[] = [
71+
'label' => 'test',
72+
'attribute_id' => $attribute->getId(),
73+
'value_index' => $option->getValue(),
74+
];
75+
$associatedProductIds[] = $product->getId();
76+
}
77+
78+
/** @var $product Product */
79+
$product = Bootstrap::getObjectManager()->create(Product::class);
80+
81+
/** @var Factory $optionsFactory */
82+
$optionsFactory = Bootstrap::getObjectManager()->create(Factory::class);
83+
84+
$configurableAttributesData = [
85+
[
86+
'attribute_id' => $attribute->getId(),
87+
'code' => $attribute->getAttributeCode(),
88+
'label' => $attribute->getStoreLabel(),
89+
'position' => '0',
90+
'values' => $attributeValues,
91+
],
92+
];
93+
94+
$configurableOptions = $optionsFactory->create($configurableAttributesData);
95+
96+
$extensionConfigurableAttributes = $product->getExtensionAttributes();
97+
$extensionConfigurableAttributes->setConfigurableProductOptions($configurableOptions);
98+
$extensionConfigurableAttributes->setConfigurableProductLinks($associatedProductIds);
99+
100+
$product->setExtensionAttributes($extensionConfigurableAttributes);
101+
102+
// Remove any previously created product with the same id.
103+
/** @var \Magento\Framework\Registry $registry */
104+
$registry = Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class);
105+
$registry->unregister('isSecureArea');
106+
$registry->register('isSecureArea', true);
107+
try {
108+
$productToDelete = $productRepository->getById(11);
109+
$productRepository->delete($productToDelete);
110+
111+
/** @var \Magento\Quote\Model\ResourceModel\Quote\Item $itemResource */
112+
$itemResource = Bootstrap::getObjectManager()->get(\Magento\Quote\Model\ResourceModel\Quote\Item::class);
113+
$itemResource->getConnection()->delete(
114+
$itemResource->getMainTable(),
115+
'product_id = ' . $productToDelete->getId()
116+
);
117+
} catch (\Exception $e) {
118+
// Nothing to remove
119+
}
120+
$registry->unregister('isSecureArea');
121+
$registry->register('isSecureArea', false);
122+
123+
$product->setTypeId(Configurable::TYPE_CODE)
124+
->setId(11)
125+
->setAttributeSetId($attributeSetId)
126+
->setWebsiteIds([1])
127+
->setName('Configurable Product 12345')
128+
->setSku('12345')
129+
->setVisibility(Visibility::VISIBILITY_BOTH)
130+
->setStatus(Status::STATUS_ENABLED)
131+
->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]);
132+
133+
$productRepository->save($product);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
8+
9+
/** @var \Magento\Framework\Registry $registry */
10+
$registry = $objectManager->get(\Magento\Framework\Registry::class);
11+
12+
$registry->unregister('isSecureArea');
13+
$registry->register('isSecureArea', true);
14+
15+
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
16+
$productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
17+
18+
foreach (['simple_30', 'simple_40', '12345'] as $sku) {
19+
try {
20+
$product = $productRepository->get($sku, false, null, true);
21+
22+
$stockStatus = $objectManager->create(\Magento\CatalogInventory\Model\Stock\Status::class);
23+
$stockStatus->load($product->getEntityId(), 'product_id');
24+
$stockStatus->delete();
25+
26+
$productRepository->delete($product);
27+
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
28+
//Product already removed
29+
}
30+
}
31+
32+
require __DIR__ . '/configurable_attribute_rollback.php';
33+
34+
$registry->unregister('isSecureArea');
35+
$registry->register('isSecureArea', false);

0 commit comments

Comments
 (0)