Skip to content

Commit 8103c56

Browse files
author
Valeriy Nayda
authored
Merge pull request #76 from magento-engcom/msi-out-of-stock
MSI magento-engcom/magento#65:
2 parents a77be45 + 4704c06 commit 8103c56

File tree

18 files changed

+215
-177
lines changed

18 files changed

+215
-177
lines changed

app/code/Magento/Inventory/Indexer/StockItem/GetAssignedStockIds.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public function execute(array $sourceIds): array
4242
);
4343

4444
if (count($sourceIds)) {
45-
$select->where(StockSourceLink::SOURCE_ID . ' = ?', $sourceIds);
45+
$select->where(StockSourceLink::SOURCE_ID . ' IN (?)', $sourceIds);
4646
}
4747
$select->group(StockSourceLink::STOCK_ID);
4848
return $connection->fetchCol($select);

app/code/Magento/Inventory/Indexer/StockItem/IndexDataProvider.php

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
namespace Magento\Inventory\Indexer\StockItem;
77

88
use Magento\Framework\App\ResourceConnection;
9+
use Magento\Inventory\Model\ResourceModel\Source as SourceResourceModel;
910
use Magento\Inventory\Model\ResourceModel\SourceItem as SourceItemResourceModel;
1011
use Magento\Inventory\Model\ResourceModel\StockSourceLink as StockSourceLinkResourceModel;
12+
use Magento\Inventory\Model\Source;
1113
use Magento\Inventory\Model\StockSourceLink;
14+
use Magento\InventoryApi\Api\Data\SourceInterface;
1215
use Magento\InventoryApi\Api\Data\SourceItemInterface;
1316

1417
/**
@@ -37,31 +40,42 @@ public function __construct(ResourceConnection $resourceConnection)
3740
public function getData(int $stockId, array $sourceIds = []): \ArrayIterator
3841
{
3942
$connection = $this->resourceConnection->getConnection();
43+
$sourceTable = $connection->getTableName(SourceResourceModel::TABLE_NAME_SOURCE);
4044
$sourceItemTable = $connection->getTableName(SourceItemResourceModel::TABLE_NAME_SOURCE_ITEM);
4145
$sourceStockLinkTable = $connection->getTableName(StockSourceLinkResourceModel::TABLE_NAME_STOCK_SOURCE_LINK);
4246

47+
// find all enabled sources
48+
$select = $connection->select()
49+
->from($sourceTable, [SourceInterface::SOURCE_ID])
50+
->where(SourceInterface::ENABLED . ' = ?', 1);
51+
if (count($sourceIds)) {
52+
$select->where(Source::SOURCE_ID . ' IN (?)', $sourceIds);
53+
}
54+
$sourceIds = $connection->fetchCol($select);
55+
56+
if (0 === count($sourceIds)) {
57+
return new \ArrayIterator([]);
58+
}
59+
4360
$select = $connection
4461
->select()
4562
->from(
4663
['source_item' => $sourceItemTable],
4764
[
4865
SourceItemInterface::SKU,
49-
'SUM(' . SourceItemInterface::QUANTITY . ') as ' . SourceItemInterface::QUANTITY,
50-
SourceItemInterface::STATUS,
66+
SourceItemInterface::QUANTITY => 'SUM(' . SourceItemInterface::QUANTITY . ')',
5167
]
5268
)
5369
->joinLeft(
5470
['stock_source_link' => $sourceStockLinkTable],
5571
'source_item.' . SourceItemInterface::SOURCE_ID . ' = stock_source_link.' . StockSourceLink::SOURCE_ID,
5672
[]
5773
)
58-
->where('stock_source_link.' . StockSourceLink::STOCK_ID . ' = ?', $stockId);
59-
60-
if (count($sourceIds)) {
61-
$select->where('stock_source_link.' . StockSourceLink::SOURCE_ID . ' = ?', $sourceIds);
62-
}
74+
->where('source_item.' . SourceItemInterface::STATUS . ' = ?', SourceItemInterface::STATUS_IN_STOCK)
75+
->where('stock_source_link.' . StockSourceLink::STOCK_ID . ' = ?', $stockId)
76+
->where('stock_source_link.' . StockSourceLink::SOURCE_ID . ' IN (?)', $sourceIds)
77+
->group([SourceItemInterface::SKU]);
6378

64-
$select->group([SourceItemInterface::SKU, SourceItemInterface::STATUS]);
6579
return new \ArrayIterator($connection->fetchAll($select));
6680
}
6781
}

app/code/Magento/Inventory/Indexer/StockItem/IndexHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function saveIndex(IndexName $indexName, \Traversable $documents)
6161
{
6262
$tableName = $this->indexNameResolver->resolveName($indexName);
6363

64-
$columns = [IndexStructure::SKU, IndexStructure::QUANTITY, IndexStructure::STATUS];
64+
$columns = [IndexStructure::SKU, IndexStructure::QUANTITY];
6565
foreach ($this->batch->getItems($documents, $this->batchSize) as $batchDocuments) {
6666
$this->resourceConnection
6767
->getConnection()

app/code/Magento/Inventory/Indexer/StockItem/IndexStructure.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class IndexStructure implements IndexStructureInterface
2121
*/
2222
const SKU = 'sku';
2323
const QUANTITY = 'quantity';
24-
const STATUS = 'status';
2524
/**#@-*/
2625

2726
/**
@@ -84,15 +83,6 @@ public function create(IndexName $indexName, string $connectionName = ResourceCo
8483
Table::OPTION_SCALE => 4,
8584
],
8685
'Quantity'
87-
)->addColumn(
88-
self::STATUS,
89-
Table::TYPE_SMALLINT,
90-
null,
91-
[
92-
Table::OPTION_NULLABLE => true,
93-
Table::OPTION_UNSIGNED => true,
94-
],
95-
'Status'
9686
);
9787
$connection->createTable($table);
9888
}

app/code/Magento/Inventory/Test/Integration/Indexer/StockItemTest.php renamed to app/code/Magento/Inventory/Test/Integration/Indexer/IndexationTest.php

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,31 @@
1717
/**
1818
* Preconditions:
1919
*
20-
* SourceItems:
21-
* SKU-1 - Source-1 - 5qty
22-
* SKU-1 - Source-2 - 3qty
23-
* SKU-2 - Source-3 - 5qty
20+
* Products to Sources links:
21+
* SKU-1 - EU-source-1(id:1) - 5.5qty
22+
* SKU-1 - EU-source-2(id:2) - 3qty
23+
* SKU-1 - EU-source-3(id:3) - 10qty (out of stock)
24+
* SKU-1 - EU-source-4(id:4) - 10qty (disabled source)
2425
*
25-
* Sources to Stock links:
26-
* Source-1 - Stock-1
27-
* Source-2 - Stock-1
28-
* Source-3 - Stock-2
26+
* SKU-2 - US-source-1(id:3) - 5qty
27+
*
28+
* Sources to Stocks links:
29+
* EU-source-1(id:1) - EU-stock(id:1)
30+
* EU-source-2(id:2) - EU-stock(id:1)
31+
* EU-source-3(id:3) - EU-stock(id:1)
32+
* EU-source-disabled(id:4) - EU-stock(id:1)
33+
*
34+
* US-source-1(id:5) - US-stock(id:2)
35+
*
36+
* EU-source-1(id:1) - Global-stock(id:3)
37+
* EU-source-2(id:2) - Global-stock(id:3)
38+
* EU-source-3(id:3) - Global-stock(id:3)
39+
* EU-source-disabled(id:4) - Global-stock(id:3)
40+
* US-source-1(id:5) - Global-stock(id:3)
2941
*
3042
* TODO: fixture via composer
3143
*/
32-
class StockItemTest extends TestCase
44+
class IndexationTest extends TestCase
3345
{
3446
/**
3547
* @var IndexerInterface
@@ -55,7 +67,7 @@ public function tearDown()
5567
/** @var IndexStructureInterface $indexStructure */
5668
$indexStructure = Bootstrap::getObjectManager()->get(IndexStructureInterface::class);
5769

58-
foreach ([1, 2] as $stockId) {
70+
foreach ([1, 2, 3] as $stockId) {
5971
$indexName = $indexNameBuilder
6072
->setIndexId(StockItemIndexerInterface::INDEXER_ID)
6173
->addDimension('stock_', $stockId)
@@ -74,13 +86,11 @@ public function tearDown()
7486
*/
7587
public function testReindexRow()
7688
{
77-
self::assertEquals(0, $this->indexerChecker->execute(1, 'SKU-1'));
78-
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-2'));
79-
8089
$this->indexer->reindexRow(1);
8190

82-
self::assertEquals(8, $this->indexerChecker->execute(1, 'SKU-1'));
83-
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-2'));
91+
self::assertEquals(8.5, $this->indexerChecker->execute(1, 'SKU-1'));
92+
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-1'));
93+
self::assertEquals(8.5, $this->indexerChecker->execute(3, 'SKU-1'));
8494
}
8595

8696
/**
@@ -92,13 +102,15 @@ public function testReindexRow()
92102
*/
93103
public function testReindexList()
94104
{
95-
self::assertEquals(0, $this->indexerChecker->execute(1, 'SKU-1'));
96-
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-2'));
105+
$this->indexer->reindexList([1, 5]);
97106

98-
$this->indexer->reindexList([1]);
107+
self::assertEquals(8.5, $this->indexerChecker->execute(1, 'SKU-1'));
108+
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-1'));
109+
self::assertEquals(8.5, $this->indexerChecker->execute(3, 'SKU-1'));
99110

100-
self::assertEquals(8, $this->indexerChecker->execute(1, 'SKU-1'));
101-
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-2'));
111+
self::assertEquals(0, $this->indexerChecker->execute(1, 'SKU-2'));
112+
self::assertEquals(5, $this->indexerChecker->execute(2, 'SKU-2'));
113+
self::assertEquals(5, $this->indexerChecker->execute(3, 'SKU-2'));
102114
}
103115

104116
/**
@@ -110,12 +122,14 @@ public function testReindexList()
110122
*/
111123
public function testReindexAll()
112124
{
113-
self::assertEquals(0, $this->indexerChecker->execute(1, 'SKU-1'));
114-
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-2'));
115-
116125
$this->indexer->reindexAll();
117126

118-
self::assertEquals(8, $this->indexerChecker->execute(1, 'SKU-1'));
127+
self::assertEquals(8.5, $this->indexerChecker->execute(1, 'SKU-1'));
128+
self::assertEquals(0, $this->indexerChecker->execute(2, 'SKU-1'));
129+
self::assertEquals(8.5, $this->indexerChecker->execute(3, 'SKU-1'));
130+
131+
self::assertEquals(0, $this->indexerChecker->execute(1, 'SKU-2'));
119132
self::assertEquals(5, $this->indexerChecker->execute(2, 'SKU-2'));
133+
self::assertEquals(5, $this->indexerChecker->execute(3, 'SKU-2'));
120134
}
121135
}

app/code/Magento/Inventory/etc/di.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
<preference for="Magento\Inventory\Model\Source\Command\GetInterface" type="Magento\Inventory\Model\Source\Command\Get"/>
1616
<preference for="Magento\Inventory\Model\Source\Command\GetListInterface" type="Magento\Inventory\Model\Source\Command\GetList"/>
1717
<preference for="Magento\Inventory\Model\Source\Command\SaveInterface" type="Magento\Inventory\Model\Source\Command\Save"/>
18-
<!-- TODO: describe bug -->
19-
<preference for="Magento\Inventory\Model\Source\Validator\SourceValidatorInterface" type="Magento\Inventory\Model\Source\Validator\ValidatorChain"/>
2018
<type name="Magento\Inventory\Model\Source\Validator\ValidatorChain">
2119
<arguments>
2220
<argument name="validators" xsi:type="array">
@@ -47,7 +45,6 @@
4745
<preference for="Magento\Inventory\Model\Stock\Command\GetInterface" type="Magento\Inventory\Model\Stock\Command\Get"/>
4846
<preference for="Magento\Inventory\Model\Stock\Command\GetListInterface" type="Magento\Inventory\Model\Stock\Command\GetList"/>
4947
<preference for="Magento\Inventory\Model\Stock\Command\SaveInterface" type="Magento\Inventory\Model\Stock\Command\Save"/>
50-
<preference for="Magento\Inventory\Model\Stock\Validator\StockValidatorInterface" type="Magento\Inventory\Model\Stock\Validator\ValidatorChain"/>
5148
<type name="Magento\Inventory\Model\Stock\Validator\ValidatorChain">
5249
<arguments>
5350
<argument name="validators" xsi:type="array">
@@ -93,7 +90,7 @@
9390
</argument>
9491
</arguments>
9592
</type>
96-
<type name="Magento\Inventory\Model\Stock\Command\Save">
93+
<type name="Magento\Inventory\Model\Reservation\ReservationBuilder">
9794
<arguments>
9895
<argument name="reservationValidator" xsi:type="object">Magento\Inventory\Model\Reservation\Validator\ValidatorChain</argument>
9996
</arguments>

app/code/Magento/InventoryApi/Test/Api/SourceRepository/GetListTest.php

Lines changed: 46 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\InventoryApi\Test\Api\SourceRepository;
78

9+
use Magento\Framework\Api\SearchCriteria;
810
use Magento\Framework\Api\SortOrder;
911
use Magento\Framework\Webapi\Rest\Request;
1012
use Magento\InventoryApi\Api\Data\SourceInterface;
@@ -22,13 +24,50 @@ class GetListTest extends WebapiAbstract
2224

2325
/**
2426
* @magentoApiDataFixture ../../../../app/code/Magento/InventoryApi/Test/_files/sources.php
25-
* @param array $searchCriteria
26-
* @param array $expectedItemsData
27-
* @dataProvider dataProviderGetList
2827
*/
29-
public function testGetList(array $searchCriteria, array $expectedItemsData)
28+
public function testGetList()
3029
{
31-
$requestData = ['searchCriteria' => $searchCriteria];
30+
$requestData = [
31+
'searchCriteria' => [
32+
SearchCriteria::FILTER_GROUPS => [
33+
[
34+
'filters' => [
35+
[
36+
'field' => SourceInterface::ENABLED,
37+
'value' => 1,
38+
'condition_type' => 'eq',
39+
],
40+
],
41+
],
42+
],
43+
SearchCriteria::SORT_ORDERS => [
44+
[
45+
'field' => SourceInterface::PRIORITY,
46+
'direction' => SortOrder::SORT_DESC,
47+
],
48+
[
49+
'field' => SourceInterface::NAME,
50+
'direction' => SortOrder::SORT_DESC,
51+
],
52+
],
53+
SearchCriteria::CURRENT_PAGE => 2,
54+
SearchCriteria::PAGE_SIZE => 2,
55+
],
56+
];
57+
$expectedTotalCount = 4;
58+
$expectedItemsData = [
59+
[
60+
SourceInterface::ENABLED => true,
61+
SourceInterface::PRIORITY => 100,
62+
SourceInterface::NAME => 'US-source-1',
63+
],
64+
[
65+
SourceInterface::ENABLED => true,
66+
SourceInterface::PRIORITY => 100,
67+
SourceInterface::NAME => 'EU-source-1',
68+
],
69+
];
70+
3271
$serviceInfo = [
3372
'rest' => [
3473
'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData),
@@ -43,75 +82,8 @@ public function testGetList(array $searchCriteria, array $expectedItemsData)
4382
? $this->_webApiCall($serviceInfo)
4483
: $this->_webApiCall($serviceInfo, $requestData);
4584

46-
self::assertEquals(count($expectedItemsData), $response['total_count']);
47-
AssertArrayContains::assert($searchCriteria, $response['search_criteria']);
85+
AssertArrayContains::assert($requestData['searchCriteria'], $response['search_criteria']);
86+
self::assertEquals($expectedTotalCount, $response['total_count']);
4887
AssertArrayContains::assert($expectedItemsData, $response['items']);
4988
}
50-
51-
/**
52-
* @return array
53-
*/
54-
public function dataProviderGetList()
55-
{
56-
return [
57-
'filtering_by_field' => [
58-
[
59-
'filter_groups' => [
60-
[
61-
'filters' => [
62-
[
63-
'field' => SourceInterface::ENABLED,
64-
'value' => 0,
65-
'condition_type' => 'eq',
66-
],
67-
],
68-
],
69-
],
70-
'sort_orders' => [
71-
[
72-
'field' => SourceInterface::PRIORITY,
73-
'direction' => SortOrder::SORT_DESC,
74-
],
75-
],
76-
],
77-
[
78-
[
79-
SourceInterface::NAME => 'source-name-3',
80-
],
81-
[
82-
SourceInterface::NAME => 'source-name-4',
83-
],
84-
],
85-
],
86-
'ordering_by_field' => [
87-
[
88-
'filter_groups' => [], // It is need for soap mode
89-
'sort_orders' => [
90-
[
91-
'field' => SourceInterface::PRIORITY,
92-
'direction' => SortOrder::SORT_DESC,
93-
],
94-
[
95-
'field' => SourceInterface::NAME,
96-
'direction' => SortOrder::SORT_DESC,
97-
],
98-
],
99-
],
100-
[
101-
[
102-
SourceInterface::NAME => 'source-name-1',
103-
],
104-
[
105-
SourceInterface::NAME => 'source-name-3',
106-
],
107-
[
108-
SourceInterface::NAME => 'source-name-2',
109-
],
110-
[
111-
SourceInterface::NAME => 'source-name-4',
112-
],
113-
],
114-
],
115-
];
116-
}
11789
}

0 commit comments

Comments
 (0)