Skip to content

Commit 763979a

Browse files
Merge pull request #81 from magmodules/release/2.2.0
Release/2.2.0
2 parents fa62c7a + 8a3018e commit 763979a

File tree

9 files changed

+149
-99
lines changed

9 files changed

+149
-99
lines changed

Service/ProductData/AttributeCollector/Data/Stock.php

Lines changed: 105 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
use Magento\Framework\App\ResourceConnection;
1313
use Magento\Framework\EntityManager\MetadataPool;
1414
use Magento\Framework\Module\Manager as ModuleManager;
15+
use Magento\Store\Api\WebsiteRepositoryInterface;
16+
use Magento\Store\Model\StoreManagerInterface;
17+
use Magmodules\Sooqr\Api\Log\RepositoryInterface as LogRepository;
1518

1619
/**
1720
* Service class for stock data
@@ -35,39 +38,51 @@ class Stock
3538
* @var ModuleManager
3639
*/
3740
private $moduleManager;
41+
/**
42+
* @var StoreManagerInterface
43+
*/
44+
private $storeManager;
45+
/**
46+
* @var WebsiteRepositoryInterface
47+
*/
48+
private $websiteRepository;
49+
/**
50+
* @var LogRepository
51+
*/
52+
private $logRepository;
3853
/**
3954
* @var string
4055
*/
4156
private $linkField;
4257

43-
/**
44-
* Stock constructor.
45-
* @param ResourceConnection $resource
46-
* @param ModuleManager $moduleManager
47-
* @param MetadataPool $metadataPool
48-
* @throws Exception
49-
*/
5058
public function __construct(
5159
ResourceConnection $resource,
5260
ModuleManager $moduleManager,
61+
StoreManagerInterface $storeManager,
62+
WebsiteRepositoryInterface $websiteRepository,
63+
LogRepository $logRepository,
5364
MetadataPool $metadataPool
5465
) {
5566
$this->resource = $resource;
5667
$this->moduleManager = $moduleManager;
68+
$this->storeManager = $storeManager;
69+
$this->websiteRepository = $websiteRepository;
70+
$this->logRepository = $logRepository;
5771
$this->linkField = $metadataPool->getMetadata(ProductInterface::class)->getLinkField();
5872
}
5973

6074
/**
6175
* Get stock data
6276
*
6377
* @param array $productIds
78+
* @param int $storeId
6479
* @return array[]
6580
*/
66-
public function execute(array $productIds = []): array
81+
public function execute(array $productIds = [], int $storeId = 0): array
6782
{
6883
$this->setData('entity_ids', $productIds);
6984
return ($this->isMsiEnabled())
70-
? $this->getMsiStock()
85+
? $this->getMsiStock($storeId)
7186
: $this->getNoMsiStock();
7287
}
7388

@@ -116,29 +131,26 @@ private function isMsiEnabled(): bool
116131
*
117132
* @return array[]
118133
*/
119-
private function getMsiStock(): array
134+
private function getMsiStock(int $storeId): array
120135
{
121-
$channels = $this->getChannels();
122-
$stockData = $this->collectMsi($channels);
123-
$result = $this->getNoMsiStock(true);
136+
$stockId = $this->getStockId($storeId);
137+
$stockData = $this->collectMsi($stockId);
138+
$reservations = $this->collectMsiReservations($stockId);
139+
$result = $this->getNoMsiStock();
124140

125141
foreach ($stockData as $value) {
126-
foreach ($channels as $channel) {
127-
if (!array_key_exists($value['product_id'], $result)) {
128-
continue;
129-
}
142+
if (!array_key_exists($value['product_id'], $result)) {
143+
continue;
144+
}
130145

131-
$qty = $value[sprintf('quantity_%s', (int)$channel)];
132-
$reserved = max($result[$value['product_id']]['reserved'], 0);
133-
$salableQty = $qty - $reserved;
146+
$quantity = (int)($value['quantity'] ?? 0);
147+
$reservations = max($reservations[$value['product_id']] ?? 0, 0);
134148

135-
$result[$value['product_id']]['msi'][$channel] = [
136-
'qty' => (int)($value[sprintf('quantity_%s', (int)$channel)] ?? 0),
137-
'is_salable' => $value[sprintf('is_salable_%s', (int)$channel)] ?? 0,
138-
'availability' => $value[sprintf('is_salable_%s', (int)$channel)] ?? 0,
139-
'salable_qty' => $salableQty ?: 0
140-
];
141-
}
149+
$result[$value['product_id']]['qty'] = $quantity;
150+
$result[$value['product_id']]['is_salable'] = $value['is_salable'] ?? 0;
151+
$result[$value['product_id']]['availability'] = $value['is_salable'] ?? 0;
152+
$result[$value['product_id']]['is_in_stock'] = $value['is_salable'] ?? 0;
153+
$result[$value['product_id']]['salable_qty'] = $quantity - $reservations;
142154
}
143155

144156
return $result;
@@ -147,52 +159,78 @@ private function getMsiStock(): array
147159
/**
148160
* Get MSI stock channels
149161
*
150-
* @return array[]
162+
* @param int $storeId
163+
* @return int
151164
*/
152-
private function getChannels(): array
165+
private function getStockId(int $storeId): int
153166
{
154-
$select = $this->resource->getConnection()->select()
155-
->from(
156-
$this->resource->getTableName('inventory_stock_sales_channel'),
157-
['stock_id']
158-
)
159-
->where(
160-
'type = ?',
161-
'website'
162-
);
163-
return array_unique($this->resource->getConnection()->fetchCol($select));
167+
try {
168+
$store = $this->storeManager->getStore($storeId);
169+
$website = $this->websiteRepository->getById($store->getWebsiteId());
170+
$select = $this->resource->getConnection()->select()
171+
->from(
172+
$this->resource->getTableName('inventory_stock_sales_channel'),
173+
['stock_id']
174+
)
175+
->where(
176+
'type = ?',
177+
'website'
178+
)->where(
179+
'code = ?',
180+
$website->getCode()
181+
)->limit(1);
182+
return (int)$this->resource->getConnection()->fetchOne($select);
183+
} catch (\Exception $exception) {
184+
$this->logRepository->addErrorLog('MSI getStockId', $exception->getMessage());
185+
return 1;
186+
}
164187
}
165188

166189
/**
167190
* Collect MSI stock data
168191
*
169-
* @param array[] $channels
192+
* @param int $stockId
170193
* @return array[]
171194
*/
172-
private function collectMsi(array $channels): array
195+
private function collectMsi(int $stockId): array
173196
{
197+
$stockView = sprintf('inventory_stock_%s', (int)$stockId);
174198
$select = $this->resource->getConnection()->select()
175199
->from(
176200
['cpe' => $this->resource->getTableName('catalog_product_entity')],
177201
['product_id' => 'entity_id', $this->linkField]
178202
)->where(
179203
'cpe.entity_id IN (?)',
180204
$this->entityIds
205+
)->joinLeft(
206+
['inv_stock' => $this->resource->getTableName($stockView)],
207+
"cpe.sku = inv_stock.sku",
208+
['inv_stock.quantity', 'inv_stock.is_salable']
181209
);
182210

183-
foreach ($channels as $channel) {
184-
$table = sprintf('inventory_stock_%s', (int)$channel);
185-
$select->joinLeft(
186-
[$table => $this->resource->getTableName($table)],
187-
"cpe.sku = {$table}.sku",
188-
[
189-
sprintf('quantity_%s', (int)$channel) => "{$table}.quantity",
190-
sprintf('is_salable_%s', (int)$channel) => "{$table}.is_salable"
191-
]
211+
return $this->resource->getConnection()->fetchAll($select);
212+
}
213+
214+
/**
215+
* @param int $stockId
216+
* @return array
217+
*/
218+
private function collectMsiReservations(int $stockId): array
219+
{
220+
$select = $this->resource->getConnection()->select()
221+
->from(
222+
['cpe' => $this->resource->getTableName('catalog_product_entity')],
223+
['product_id' => 'entity_id']
224+
)->where(
225+
'cpe.entity_id IN (?)',
226+
$this->entityIds
227+
)->joinLeft(
228+
['inv_res' => $this->resource->getTableName('inventory_reservation')],
229+
"inv_res.sku = cpe.sku AND inv_res.stock_id = {$stockId}",
230+
['reserved' => 'SUM(COALESCE(inv_res.quantity, 0))']
192231
);
193-
}
194232

195-
return $this->resource->getConnection()->fetchAll($select);
233+
return $this->resource->getConnection()->fetchPairs($select);
196234
}
197235

198236
/**
@@ -209,10 +247,9 @@ private function collectMsi(array $channels): array
209247
* min_sale_qty
210248
* ]
211249
*
212-
* @param bool $addMsi
213250
* @return array[]
214251
*/
215-
private function getNoMsiStock(bool $addMsi = false): array
252+
private function getNoMsiStock(): array
216253
{
217254
$result = [];
218255
$select = $this->resource->getConnection()
@@ -235,36 +272,25 @@ private function getNoMsiStock(bool $addMsi = false): array
235272
['css' => $this->resource->getTableName('cataloginventory_stock_status')],
236273
'css.product_id = catalog_product_entity.entity_id',
237274
['stock_status']
275+
)->where(
276+
'cataloginventory_stock_item.product_id IN (?)',
277+
$this->entityIds
278+
)->group(
279+
'product_id'
238280
);
239-
if ($addMsi) {
240-
$select->joinLeft(
241-
['inventory_reservation' => $this->resource->getTableName('inventory_reservation')],
242-
'inventory_reservation.sku = catalog_product_entity.sku',
243-
['reserved' => 'SUM(COALESCE(inventory_reservation.quantity, 0))']
244-
);
245-
}
246-
$select->where('cataloginventory_stock_item.product_id IN (?)', $this->entityIds);
247-
$select->group('product_id');
248281
$values = $this->resource->getConnection()->fetchAll($select);
249282

250283
foreach ($values as $value) {
251-
$result[$value['product_id']] =
252-
[
253-
'qty' => (int)$value['qty'],
254-
'is_in_stock' => (int)$value['stock_status'],
255-
'availability' => (int)$value['stock_status'],
256-
'manage_stock' => (int)$value['manage_stock'],
257-
'qty_increments' => (int)$value['qty_increments'],
258-
'min_sale_qty' => (int)$value['min_sale_qty']
259-
];
260-
if ($addMsi) {
261-
$reserved = (int)$value['reserved'] * -1;
262-
$result[$value['product_id']] += [
263-
'reserved' => $reserved,
264-
'salable_qty' => (int)($value['qty'] - $reserved)
265-
];
266-
}
284+
$result[$value['product_id']] = [
285+
'qty' => (int)$value['qty'],
286+
'is_in_stock' => (int)$value['stock_status'],
287+
'availability' => (int)$value['stock_status'],
288+
'manage_stock' => (int)$value['manage_stock'],
289+
'qty_increments' => (int)$value['qty_increments'],
290+
'min_sale_qty' => (int)$value['min_sale_qty']
291+
];
267292
}
293+
268294
return $result;
269295
}
270296

Service/ProductData/Data.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public function execute(array $entityIds, array $attributeMap, array $extraParam
145145
}
146146

147147
if ($extraParameters['stock']['inventory']) {
148-
$result = $this->stock->execute($productIds);
148+
$result = $this->stock->execute($productIds, $storeId);
149149
$inventoryFields = array_merge(
150150
$extraParameters['stock']['inventory_fields'],
151151
['qty', 'msi', 'salable_qty', 'reserved', 'is_in_stock']

Service/ProductData/Filter.php

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public function execute(array $filter, int $storeId = 0): array
8888
*/
8989
private function filterVisibility(array $filter, int $storeId = 0): array
9090
{
91+
9192
if ($filter['filter_by_visibility']) {
9293
$visibility = is_array($filter['visibility'])
9394
? $filter['visibility']
@@ -102,7 +103,9 @@ private function filterVisibility(array $filter, int $storeId = 0): array
102103
}
103104

104105
$connection = $this->resourceConnection->getConnection();
105-
$select = $connection->select()->distinct()->from(
106+
107+
// Get all EntityIds from base store bases on visibility filter
108+
$selectBase = $connection->select()->distinct()->from(
106109
['catalog_product_entity_int' => $this->resourceConnection->getTableName('catalog_product_entity_int')],
107110
[$this->entityId]
108111
)->joinLeft(
@@ -116,13 +119,33 @@ private function filterVisibility(array $filter, int $storeId = 0): array
116119
'attribute_code = ?',
117120
'visibility'
118121
)->where(
119-
'store_id IN (?)',
120-
[0, $storeId]
121-
)->order(
122-
'store_id ASC'
122+
'store_id = ?',
123+
0
123124
);
124125

125-
return $connection->fetchCol($select);
126+
// Check for EntityIds that needs to be removed as visibility is set differently on store-view
127+
$selectStore = $connection->select()->distinct()->from(
128+
['catalog_product_entity_int' => $this->resourceConnection->getTableName('catalog_product_entity_int')],
129+
[$this->entityId]
130+
)->joinLeft(
131+
['eav_attribute' => $this->resourceConnection->getTableName('eav_attribute')],
132+
'eav_attribute.attribute_id = catalog_product_entity_int.attribute_id',
133+
[]
134+
)->where(
135+
'value NOT IN (?)',
136+
$visibility
137+
)->where(
138+
'attribute_code = ?',
139+
'visibility'
140+
)->where(
141+
'store_id = ?',
142+
$storeId
143+
);
144+
145+
return array_diff(
146+
$connection->fetchCol($selectBase),
147+
$connection->fetchCol($selectStore)
148+
);
126149
}
127150

128151
/**

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "magmodules/magento2-sooqr",
33
"description": "Sooqr integration for Magento 2",
44
"type": "magento2-module",
5-
"version": "2.1.8",
5+
"version": "2.2.0",
66
"license": [
77
"OSL-3.0",
88
"AFL-3.0"

etc/adminhtml/menu.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
88
<menu>
99
<add id="Magmodules_Sooqr::general"
10-
title="Sooqr"
10+
title="Spotler"
1111
module="Magmodules_Sooqr"
1212
sortOrder="100"
1313
resource="Magmodules_Sooqr::feed"

etc/adminhtml/system.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
1010
<system>
1111
<tab id="sooqr" translate="label" sortOrder="300" class="sooqr-plugin">
12-
<label>Sooqr</label>
12+
<label>Spotler</label>
1313
</tab>
1414
<include path="Magmodules_Sooqr::system/general.xml"/>
1515
<include path="Magmodules_Sooqr::system/data.xml"/>

etc/config.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<sooqr_general>
1212
<general>
1313
<enable>1</enable>
14-
<version>v2.1.8</version>
14+
<version>v2.2.0</version>
1515
</general>
1616
<credentials>
1717
<environment>production</environment>

0 commit comments

Comments
 (0)