Skip to content

Commit 0764c2d

Browse files
committed
Merge remote-tracking branch 'mainline/2.3-develop' into MC-18403
2 parents f9c4705 + 62b8f8a commit 0764c2d

File tree

27 files changed

+443
-859
lines changed

27 files changed

+443
-859
lines changed

app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/StockDataFilter.php

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
use Magento\CatalogInventory\Api\StockConfigurationInterface;
99
use Magento\Framework\App\Config\ScopeConfigInterface;
10-
use Magento\CatalogInventory\Model\Stock;
1110

1211
/**
1312
* Class StockDataFilter
@@ -61,8 +60,8 @@ public function filter(array $stockData)
6160
$stockData['qty'] = self::MAX_QTY_VALUE;
6261
}
6362

64-
if (isset($stockData['min_qty'])) {
65-
$stockData['min_qty'] = $this->purifyMinQty($stockData['min_qty'], $stockData['backorders']);
63+
if (isset($stockData['min_qty']) && (int)$stockData['min_qty'] < 0) {
64+
$stockData['min_qty'] = 0;
6665
}
6766

6867
if (!isset($stockData['is_decimal_divided']) || $stockData['is_qty_decimal'] == 0) {
@@ -71,27 +70,4 @@ public function filter(array $stockData)
7170

7271
return $stockData;
7372
}
74-
75-
/**
76-
* Purifies min_qty.
77-
*
78-
* @param int $minQty
79-
* @param int $backOrders
80-
* @return float
81-
*/
82-
private function purifyMinQty(int $minQty, int $backOrders): float
83-
{
84-
/**
85-
* As described in the documentation if the Backorders Option is disabled
86-
* it is recommended to set the Out Of Stock Threshold to a positive number.
87-
* That's why to clarify the logic to the end user the code below prevent him to set a negative number so such
88-
* a number will turn to zero.
89-
* @see https://docs.magento.com/m2/ce/user_guide/catalog/inventory-backorders.html
90-
*/
91-
if ($backOrders === Stock::BACKORDERS_NO && $minQty < 0) {
92-
$minQty = 0;
93-
}
94-
95-
return (float)$minQty;
96-
}
9773
}

app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Source.php

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use Magento\Catalog\Model\Product\Attribute\Source\Status as ProductStatus;
99
use Magento\Catalog\Api\Data\ProductInterface;
1010
use Magento\Catalog\Api\Data\ProductAttributeInterface;
11+
use Magento\Framework\DB\Select;
12+
use Magento\Framework\DB\Sql\UnionExpression;
1113

1214
/**
1315
* Catalog Product Eav Select and Multiply Select Attributes Indexer resource model
@@ -199,13 +201,52 @@ protected function _prepareSelectIndex($entityIds = null, $attributeId = null)
199201
'dd.attribute_id',
200202
's.store_id',
201203
'value' => new \Zend_Db_Expr('COALESCE(ds.value, dd.value)'),
202-
'cpe.entity_id',
204+
'cpe.entity_id AS source_id',
203205
]
204206
);
205207

206208
if ($entityIds !== null) {
207209
$ids = implode(',', array_map('intval', $entityIds));
210+
$selectWithoutDefaultStore = $connection->select()->from(
211+
['wd' => $this->getTable('catalog_product_entity_int')],
212+
[
213+
'cpe.entity_id',
214+
'attribute_id',
215+
'store_id',
216+
'value',
217+
'cpe.entity_id',
218+
]
219+
)->joinLeft(
220+
['cpe' => $this->getTable('catalog_product_entity')],
221+
"cpe.{$productIdField} = wd.{$productIdField}",
222+
[]
223+
)->joinLeft(
224+
['d2d' => $this->getTable('catalog_product_entity_int')],
225+
sprintf(
226+
"d2d.store_id = 0 AND d2d.{$productIdField} = wd.{$productIdField} AND d2d.attribute_id = %s",
227+
$this->_eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'status')->getId()
228+
),
229+
[]
230+
)->joinLeft(
231+
['d2s' => $this->getTable('catalog_product_entity_int')],
232+
"d2s.store_id != 0 AND d2s.attribute_id = d2d.attribute_id AND " .
233+
"d2s.{$productIdField} = d2d.{$productIdField}",
234+
[]
235+
)
236+
->where((new \Zend_Db_Expr('COALESCE(d2s.value, d2d.value)')) . ' = ' . ProductStatus::STATUS_ENABLED)
237+
->where("wd.attribute_id IN({$attrIdsFlat})")
238+
->where('wd.value IS NOT NULL')
239+
->where('wd.store_id != 0')
240+
->where("cpe.entity_id IN({$ids})");
208241
$select->where("cpe.entity_id IN({$ids})");
242+
$selects = new UnionExpression(
243+
[$select, $selectWithoutDefaultStore],
244+
Select::SQL_UNION,
245+
'( %s )'
246+
);
247+
248+
$select = $connection->select();
249+
$select->from(['u' => $selects]);
209250
}
210251

211252
/**
@@ -342,7 +383,7 @@ private function getMultiSelectAttributeWithSourceModels($attrIds)
342383
ProductAttributeInterface::ENTITY_TYPE_CODE,
343384
$criteria
344385
)->getItems();
345-
386+
346387
$options = [];
347388
foreach ($attributes as $attribute) {
348389
$sourceModelOptions = $attribute->getOptions();

app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
<createData entity="SimpleProductInStockQuantityZero" stepKey="createProduct"/>
2424

2525
<!-- Configure Magento to show out of stock products and to allow backorders -->
26+
<magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockEnable.path}} {{CatalogInventoryOptionsShowOutOfStockEnable.value}}" stepKey="setConfigShowOutOfStockTrue"/>
2627
<magentoCLI command="config:set {{CatalogInventoryItemOptionsBackordersEnable.path}} {{CatalogInventoryItemOptionsBackordersEnable.value}}" stepKey="setConfigAllowBackordersTrue"/>
2728
</before>
2829

2930
<after>
3031
<!-- Set Magento back to default configuration -->
32+
<magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockDisable.path}} {{CatalogInventoryOptionsShowOutOfStockDisable.value}}" stepKey="setConfigShowOutOfStockFalse"/>
3133
<magentoCLI command="config:set {{CatalogInventoryItemOptionsBackordersDisable.path}} {{CatalogInventoryItemOptionsBackordersDisable.value}}" stepKey="setConfigAllowBackordersFalse"/>
3234
<deleteData createDataKey="createProduct" stepKey="deleteProduct"/>
3335
</after>

app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/StockDataFilterTest.php

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@
66
namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Initialization;
77

88
use Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter;
9-
use Magento\CatalogInventory\Model\Stock;
10-
use Magento\Framework\App\Config\ScopeConfigInterface;
11-
use Magento\CatalogInventory\Model\Configuration;
12-
use PHPUnit\Framework\TestCase;
139

1410
/**
15-
* StockDataFilter test.
11+
* Class StockDataFilterTest
1612
*/
17-
class StockDataFilterTest extends TestCase
13+
class StockDataFilterTest extends \PHPUnit\Framework\TestCase
1814
{
1915
/**
2016
* @var \PHPUnit_Framework_MockObject_MockObject
@@ -31,43 +27,35 @@ class StockDataFilterTest extends TestCase
3127
*/
3228
protected $stockDataFilter;
3329

34-
/**
35-
* @var \PHPUnit_Framework_MockObject_MockObject
36-
*/
30+
/** @var \PHPUnit_Framework_MockObject_MockObject */
3731
protected $stockConfiguration;
3832

39-
/**
40-
* @inheritdoc
41-
*/
4233
protected function setUp()
4334
{
44-
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
35+
$this->scopeConfigMock = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class);
4536

46-
$this->scopeConfigMock->method('getValue')
47-
->will($this->returnValue(1));
37+
$this->scopeConfigMock->expects($this->any())->method('getValue')->will($this->returnValue(1));
4838

4939
$this->stockConfiguration = $this->createPartialMock(
50-
Configuration::class,
40+
\Magento\CatalogInventory\Model\Configuration::class,
5141
['getManageStock']
5242
);
5343

5444
$this->stockDataFilter = new StockDataFilter($this->scopeConfigMock, $this->stockConfiguration);
5545
}
5646

5747
/**
58-
* Tests filter method.
59-
*
6048
* @param array $inputStockData
6149
* @param array $outputStockData
62-
* @return void
6350
*
6451
* @covers \Magento\Catalog\Controller\Adminhtml\Product\Initialization\StockDataFilter::filter
6552
* @dataProvider filterDataProvider
6653
*/
6754
public function testFilter(array $inputStockData, array $outputStockData)
6855
{
6956
if (isset($inputStockData['use_config_manage_stock']) && $inputStockData['use_config_manage_stock'] === 1) {
70-
$this->stockConfiguration->method('getManageStock')
57+
$this->stockConfiguration->expects($this->once())
58+
->method('getManageStock')
7159
->will($this->returnValue($outputStockData['manage_stock']));
7260
}
7361

@@ -105,13 +93,8 @@ public function filterDataProvider()
10593
],
10694
],
10795
'case4' => [
108-
'inputStockData' => ['min_qty' => -1, 'backorders' => Stock::BACKORDERS_NO],
109-
'outputStockData' => [
110-
'min_qty' => 0,
111-
'is_decimal_divided' => 0,
112-
'use_config_manage_stock' => 0,
113-
'backorders' => Stock::BACKORDERS_NO,
114-
],
96+
'inputStockData' => ['min_qty' => -1],
97+
'outputStockData' => ['min_qty' => 0, 'is_decimal_divided' => 0, 'use_config_manage_stock' => 0],
11598
],
11699
'case5' => [
117100
'inputStockData' => ['is_qty_decimal' => 0],
@@ -120,25 +103,7 @@ public function filterDataProvider()
120103
'is_decimal_divided' => 0,
121104
'use_config_manage_stock' => 0,
122105
],
123-
],
124-
'case6' => [
125-
'inputStockData' => ['min_qty' => -1, 'backorders' => Stock::BACKORDERS_YES_NONOTIFY],
126-
'outputStockData' => [
127-
'min_qty' => -1,
128-
'is_decimal_divided' => 0,
129-
'use_config_manage_stock' => 0,
130-
'backorders' => Stock::BACKORDERS_YES_NONOTIFY,
131-
],
132-
],
133-
'case7' => [
134-
'inputStockData' => ['min_qty' => -1, 'backorders' => Stock::BACKORDERS_YES_NOTIFY],
135-
'outputStockData' => [
136-
'min_qty' => -1,
137-
'is_decimal_divided' => 0,
138-
'use_config_manage_stock' => 0,
139-
'backorders' => Stock::BACKORDERS_YES_NOTIFY,
140-
],
141-
],
106+
]
142107
];
143108
}
144109
}

app/code/Magento/CatalogInventory/Model/ResourceModel/Stock/Item.php

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use Magento\Framework\DB\Select;
1515
use Magento\Framework\App\ObjectManager;
1616
use Magento\Framework\Stdlib\DateTime\DateTime;
17-
use Zend_Db_Expr;
1817

1918
/**
2019
* Stock item resource model
@@ -184,12 +183,16 @@ public function updateSetOutOfStock(int $websiteId)
184183
'is_in_stock = ' . Stock::STOCK_IN_STOCK,
185184
'(use_config_manage_stock = 1 AND 1 = ' . $this->stockConfiguration->getManageStock() . ')'
186185
. ' OR (use_config_manage_stock = 0 AND manage_stock = 1)',
187-
'(' . $this->getBackordersExpr() .' = 0 AND qty <= ' . $this->getMinQtyExpr() . ')'
188-
. ' OR (' . $this->getBackordersExpr() .' != 0 AND '
189-
. $this->getMinQtyExpr() . ' != 0 AND qty <= ' . $this->getMinQtyExpr() . ')',
186+
'(use_config_min_qty = 1 AND qty <= ' . $this->stockConfiguration->getMinQty() . ')'
187+
. ' OR (use_config_min_qty = 0 AND qty <= min_qty)',
190188
'product_id IN (' . $select->assemble() . ')',
191189
];
192-
190+
$backordersWhere = '(use_config_backorders = 0 AND backorders = ' . Stock::BACKORDERS_NO . ')';
191+
if (Stock::BACKORDERS_NO == $this->stockConfiguration->getBackorders()) {
192+
$where[] = $backordersWhere . ' OR use_config_backorders = 1';
193+
} else {
194+
$where[] = $backordersWhere;
195+
}
193196
$connection->update($this->getMainTable(), $values, $where);
194197

195198
$this->stockIndexerProcessor->markIndexerAsInvalid();
@@ -212,8 +215,8 @@ public function updateSetInStock(int $websiteId)
212215
$where = [
213216
'website_id = ' . $websiteId,
214217
'stock_status_changed_auto = 1',
215-
'(qty > ' . $this->getMinQtyExpr() . ')'
216-
. ' OR (' . $this->getBackordersExpr() . ' != 0 AND ' . $this->getMinQtyExpr() . ' = 0)', // If infinite
218+
'(use_config_min_qty = 1 AND qty > ' . $this->stockConfiguration->getMinQty() . ')'
219+
. ' OR (use_config_min_qty = 0 AND qty > min_qty)',
217220
'product_id IN (' . $select->assemble() . ')',
218221
];
219222
$manageStockWhere = '(use_config_manage_stock = 0 AND manage_stock = 1)';
@@ -301,12 +304,12 @@ public function getBackordersExpr(string $tableAlias = ''): \Zend_Db_Expr
301304
}
302305

303306
/**
304-
* Get Minimum Sale Quantity Expression.
307+
* Get Minimum Sale Quantity Expression
305308
*
306309
* @param string $tableAlias
307-
* @return Zend_Db_Expr
310+
* @return \Zend_Db_Expr
308311
*/
309-
public function getMinSaleQtyExpr(string $tableAlias = ''): Zend_Db_Expr
312+
public function getMinSaleQtyExpr(string $tableAlias = ''): \Zend_Db_Expr
310313
{
311314
if ($tableAlias) {
312315
$tableAlias .= '.';
@@ -320,26 +323,6 @@ public function getMinSaleQtyExpr(string $tableAlias = ''): Zend_Db_Expr
320323
return $itemMinSaleQty;
321324
}
322325

323-
/**
324-
* Get Min Qty Expression
325-
*
326-
* @param string $tableAlias
327-
* @return Zend_Db_Expr
328-
*/
329-
public function getMinQtyExpr(string $tableAlias = ''): Zend_Db_Expr
330-
{
331-
if ($tableAlias) {
332-
$tableAlias .= '.';
333-
}
334-
$itemBackorders = $this->getConnection()->getCheckSql(
335-
$tableAlias . 'use_config_min_qty = 1',
336-
$this->stockConfiguration->getMinQty(),
337-
$tableAlias . 'min_qty'
338-
);
339-
340-
return $itemBackorders;
341-
}
342-
343326
/**
344327
* Build select for products with types from config
345328
*

app/code/Magento/CatalogInventory/Model/StockStateProvider.php

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,31 +72,14 @@ public function __construct(
7272
*/
7373
public function verifyStock(StockItemInterface $stockItem)
7474
{
75-
// Manage stock, but qty is null
7675
if ($stockItem->getQty() === null && $stockItem->getManageStock()) {
7776
return false;
7877
}
79-
80-
// Backorders are not allowed and qty reached min qty
8178
if ($stockItem->getBackorders() == StockItemInterface::BACKORDERS_NO
8279
&& $stockItem->getQty() <= $stockItem->getMinQty()
8380
) {
8481
return false;
8582
}
86-
87-
$backordersAllowed = [Stock::BACKORDERS_YES_NONOTIFY, Stock::BACKORDERS_YES_NOTIFY];
88-
if (in_array($stockItem->getBackorders(), $backordersAllowed)) {
89-
// Infinite - let it be In stock
90-
if ($stockItem->getMinQty() == 0) {
91-
return true;
92-
}
93-
94-
// qty reached min qty - let it stand Out Of Stock
95-
if ($stockItem->getQty() <= $stockItem->getMinQty()) {
96-
return false;
97-
}
98-
}
99-
10083
return true;
10184
}
10285

@@ -262,17 +245,15 @@ public function checkQty(StockItemInterface $stockItem, $qty)
262245
if (!$stockItem->getManageStock()) {
263246
return true;
264247
}
265-
266-
$backordersAllowed = [Stock::BACKORDERS_YES_NONOTIFY, Stock::BACKORDERS_YES_NOTIFY];
267-
// Infinite check
268-
if ($stockItem->getMinQty() == 0 && in_array($stockItem->getBackorders(), $backordersAllowed)) {
269-
return true;
270-
}
271-
272248
if ($stockItem->getQty() - $stockItem->getMinQty() - $qty < 0) {
273-
return false;
249+
switch ($stockItem->getBackorders()) {
250+
case \Magento\CatalogInventory\Model\Stock::BACKORDERS_YES_NONOTIFY:
251+
case \Magento\CatalogInventory\Model\Stock::BACKORDERS_YES_NOTIFY:
252+
break;
253+
default:
254+
return false;
255+
}
274256
}
275-
276257
return true;
277258
}
278259

0 commit comments

Comments
 (0)