Skip to content

Commit 1d5208b

Browse files
Merge pull request #1730 from magento-engcom/2.2-develop-prs
[EngCom] Public Pull Requests - 2.2-develop - MAGETWO-83959: Issue: 3596. Resolve Notice with undefined index 'value' #12296 - MAGETWO-83957: #12083: Cannot import zero (0) value into custom attribute #12283 - MAGETWO-83868: 11941: Invoice for products that use qty decimal rounds down to whole number. #11997
2 parents 6f4ab5f + 17836e6 commit 1d5208b

File tree

12 files changed

+634
-19
lines changed

12 files changed

+634
-19
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ public function prepareAttributesWithDefaultValueForSave(array $rowData, $withDe
534534
public function clearEmptyData(array $rowData)
535535
{
536536
foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) {
537-
if (!$attrParams['is_static'] && empty($rowData[$attrCode])) {
537+
if (!$attrParams['is_static'] && !isset($rowData[$attrCode])) {
538538
unset($rowData[$attrCode]);
539539
}
540540
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Observer;
8+
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
13+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
14+
use Magento\Framework\Event\Observer;
15+
use Magento\Framework\Event\ObserverInterface;
16+
17+
/**
18+
* Add Stock items to product collection.
19+
*/
20+
class AddStockItemsObserver implements ObserverInterface
21+
{
22+
/**
23+
* @var StockItemCriteriaInterfaceFactory
24+
*/
25+
private $criteriaInterfaceFactory;
26+
27+
/**
28+
* @var StockItemRepositoryInterface
29+
*/
30+
private $stockItemRepository;
31+
32+
/**
33+
* @var StockConfigurationInterface
34+
*/
35+
private $stockConfiguration;
36+
37+
/**
38+
* AddStockItemsObserver constructor.
39+
*
40+
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
41+
* @param StockItemRepositoryInterface $stockItemRepository
42+
* @param StockConfigurationInterface $stockConfiguration
43+
*/
44+
public function __construct(
45+
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
46+
StockItemRepositoryInterface $stockItemRepository,
47+
StockConfigurationInterface $stockConfiguration
48+
) {
49+
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
50+
$this->stockItemRepository = $stockItemRepository;
51+
$this->stockConfiguration = $stockConfiguration;
52+
}
53+
54+
/**
55+
* Add stock items to products in collection.
56+
*
57+
* @param Observer $observer
58+
* @return void
59+
*/
60+
public function execute(Observer $observer)
61+
{
62+
/** @var Collection $productCollection */
63+
$productCollection = $observer->getData('collection');
64+
$productIds = array_keys($productCollection->getItems());
65+
$criteria = $this->criteriaInterfaceFactory->create();
66+
$criteria->setProductsFilter($productIds);
67+
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
68+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
69+
foreach ($stockItemCollection->getItems() as $item) {
70+
/** @var Product $product */
71+
$product = $productCollection->getItemById($item->getProductId());
72+
$productExtension = $product->getExtensionAttributes();
73+
$productExtension->setStockItem($item);
74+
$product->setExtensionAttributes($productExtension);
75+
}
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogInventory\Test\Unit\Observer;
8+
9+
use Magento\Catalog\Api\Data\ProductExtensionInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;
12+
use Magento\CatalogInventory\Api\Data\StockItemCollectionInterface;
13+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
14+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
15+
use Magento\CatalogInventory\Api\StockItemCriteriaInterface;
16+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
17+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
18+
use Magento\CatalogInventory\Observer\AddStockItemsObserver;
19+
use Magento\Framework\Event\Observer;
20+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
21+
use PHPUnit\Framework\TestCase;
22+
23+
class AddStockItemsObserverTest extends TestCase
24+
{
25+
/**
26+
* Test subject.
27+
*
28+
* @var AddStockItemsObserver
29+
*/
30+
private $subject;
31+
/**
32+
* @var StockItemCriteriaInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
33+
*/
34+
private $criteriaInterfaceFactoryMock;
35+
36+
/**
37+
* @var StockItemRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
38+
*/
39+
private $stockItemRepositoryMock;
40+
41+
/**
42+
* @var StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
43+
*/
44+
private $stockConfigurationMock;
45+
46+
/**
47+
* @inheritdoc
48+
*/
49+
protected function setUp()
50+
{
51+
$objectManager = new ObjectManager($this);
52+
$this->criteriaInterfaceFactoryMock = $this->getMockBuilder(StockItemCriteriaInterfaceFactory::class)
53+
->setMethods(['create'])
54+
->disableOriginalConstructor()
55+
->getMockForAbstractClass();
56+
$this->stockItemRepositoryMock = $this->getMockBuilder(StockItemRepositoryInterface::class)
57+
->setMethods(['getList'])
58+
->disableOriginalConstructor()
59+
->getMockForAbstractClass();
60+
$this->stockConfigurationMock = $this->getMockBuilder(StockConfigurationInterface::class)
61+
->setMethods(['getDefaultScopeId'])
62+
->disableOriginalConstructor()
63+
->getMockForAbstractClass();
64+
$this->subject = $objectManager->getObject(
65+
AddStockItemsObserver::class,
66+
[
67+
'criteriaInterfaceFactory' => $this->criteriaInterfaceFactoryMock,
68+
'stockItemRepository' => $this->stockItemRepositoryMock,
69+
'stockConfiguration' => $this->stockConfigurationMock
70+
]
71+
);
72+
}
73+
74+
/**
75+
* Test AddStockItemsObserver::execute() add stock item to product as extension attribute.
76+
*/
77+
public function testExecute()
78+
{
79+
$productId = 1;
80+
$defaultScopeId = 0;
81+
82+
$criteria = $this->getMockBuilder(StockItemCriteriaInterface::class)
83+
->setMethods(['setProductsFilter', 'setScopeFilter'])
84+
->disableOriginalConstructor()
85+
->getMockForAbstractClass();
86+
$criteria->expects(self::once())
87+
->method('setProductsFilter')
88+
->with(self::identicalTo([$productId]))
89+
->willReturn(true);
90+
$criteria->expects(self::once())
91+
->method('setScopeFilter')
92+
->with(self::identicalTo($defaultScopeId))
93+
->willReturn(true);
94+
95+
$this->criteriaInterfaceFactoryMock->expects(self::once())
96+
->method('create')
97+
->willReturn($criteria);
98+
$stockItemCollection = $this->getMockBuilder(StockItemCollectionInterface::class)
99+
->setMethods(['getItems'])
100+
->disableOriginalConstructor()
101+
->getMockForAbstractClass();
102+
$stockItem = $this->getMockBuilder(StockItemInterface::class)
103+
->setMethods(['getProductId'])
104+
->disableOriginalConstructor()
105+
->getMockForAbstractClass();
106+
$stockItem->expects(self::once())
107+
->method('getProductId')
108+
->willReturn($productId);
109+
110+
$stockItemCollection->expects(self::once())
111+
->method('getItems')
112+
->willReturn([$stockItem]);
113+
114+
$this->stockItemRepositoryMock->expects(self::once())
115+
->method('getList')
116+
->with(self::identicalTo($criteria))
117+
->willReturn($stockItemCollection);
118+
119+
$this->stockConfigurationMock->expects(self::once())
120+
->method('getDefaultScopeId')
121+
->willReturn($defaultScopeId);
122+
123+
$productExtension = $this->getMockBuilder(ProductExtensionInterface::class)
124+
->setMethods(['setStockItem'])
125+
->disableOriginalConstructor()
126+
->getMockForAbstractClass();
127+
$productExtension->expects(self::once())
128+
->method('setStockItem')
129+
->with(self::identicalTo($stockItem));
130+
131+
$product = $this->getMockBuilder(Product::class)
132+
->disableOriginalConstructor()
133+
->getMock();
134+
$product->expects(self::once())
135+
->method('getExtensionAttributes')
136+
->willReturn($productExtension);
137+
$product->expects(self::once())
138+
->method('setExtensionAttributes')
139+
->with(self::identicalTo($productExtension))
140+
->willReturnSelf();
141+
142+
/** @var ProductCollection|\PHPUnit_Framework_MockObject_MockObject $productCollection */
143+
$productCollection = $this->getMockBuilder(ProductCollection::class)
144+
->disableOriginalConstructor()
145+
->getMock();
146+
$productCollection->expects(self::once())
147+
->method('getItems')
148+
->willReturn([$productId => $product]);
149+
$productCollection->expects(self::once())
150+
->method('getItemById')
151+
->with(self::identicalTo($productId))
152+
->willReturn($product);
153+
154+
/** @var Observer|\PHPUnit_Framework_MockObject_MockObject $observer */
155+
$observer = $this->getMockBuilder(Observer::class)
156+
->disableOriginalConstructor()
157+
->getMock();
158+
$observer->expects(self::once())
159+
->method('getData')
160+
->with('collection')
161+
->willReturn($productCollection);
162+
163+
$this->subject->execute($observer);
164+
}
165+
}

app/code/Magento/CatalogInventory/etc/events.xml

+3
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,7 @@
4242
<event name="admin_system_config_changed_section_cataloginventory">
4343
<observer name="inventory" instance="Magento\CatalogInventory\Observer\UpdateItemsStockUponConfigChangeObserver"/>
4444
</event>
45+
<event name="sales_quote_item_collection_products_after_load">
46+
<observer name="add_stock_items" instance="Magento\CatalogInventory\Observer\AddStockItemsObserver"/>
47+
</event>
4548
</config>

app/code/Magento/Payment/Helper/Data.php

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ public function getPaymentMethodList($sorted = true, $asLabelValue = false, $wit
293293
foreach ($methods as $code => $title) {
294294
if (isset($groups[$code])) {
295295
$labelValues[$code]['label'] = $title;
296+
$labelValues[$code]['value'] = null;
296297
} elseif (isset($groupRelations[$code])) {
297298
unset($labelValues[$code]);
298299
$labelValues[$groupRelations[$code]]['value'][$code] = ['value' => $code, 'label' => $title];

0 commit comments

Comments
 (0)