Skip to content

Commit

Permalink
Merge pull request #81 from magmodules/release/2.2.0
Browse files Browse the repository at this point in the history
Release/2.2.0
  • Loading branch information
Marvin-Magmodules authored Oct 21, 2024
2 parents fa62c7a + 8a3018e commit 763979a
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 99 deletions.
184 changes: 105 additions & 79 deletions Service/ProductData/AttributeCollector/Data/Stock.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Module\Manager as ModuleManager;
use Magento\Store\Api\WebsiteRepositoryInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magmodules\Sooqr\Api\Log\RepositoryInterface as LogRepository;

/**
* Service class for stock data
Expand All @@ -35,39 +38,51 @@ class Stock
* @var ModuleManager
*/
private $moduleManager;
/**
* @var StoreManagerInterface
*/
private $storeManager;
/**
* @var WebsiteRepositoryInterface
*/
private $websiteRepository;
/**
* @var LogRepository
*/
private $logRepository;
/**
* @var string
*/
private $linkField;

/**
* Stock constructor.
* @param ResourceConnection $resource
* @param ModuleManager $moduleManager
* @param MetadataPool $metadataPool
* @throws Exception
*/
public function __construct(
ResourceConnection $resource,
ModuleManager $moduleManager,
StoreManagerInterface $storeManager,
WebsiteRepositoryInterface $websiteRepository,
LogRepository $logRepository,
MetadataPool $metadataPool
) {
$this->resource = $resource;
$this->moduleManager = $moduleManager;
$this->storeManager = $storeManager;
$this->websiteRepository = $websiteRepository;
$this->logRepository = $logRepository;
$this->linkField = $metadataPool->getMetadata(ProductInterface::class)->getLinkField();
}

/**
* Get stock data
*
* @param array $productIds
* @param int $storeId
* @return array[]
*/
public function execute(array $productIds = []): array
public function execute(array $productIds = [], int $storeId = 0): array
{
$this->setData('entity_ids', $productIds);
return ($this->isMsiEnabled())
? $this->getMsiStock()
? $this->getMsiStock($storeId)
: $this->getNoMsiStock();
}

Expand Down Expand Up @@ -116,29 +131,26 @@ private function isMsiEnabled(): bool
*
* @return array[]
*/
private function getMsiStock(): array
private function getMsiStock(int $storeId): array
{
$channels = $this->getChannels();
$stockData = $this->collectMsi($channels);
$result = $this->getNoMsiStock(true);
$stockId = $this->getStockId($storeId);
$stockData = $this->collectMsi($stockId);
$reservations = $this->collectMsiReservations($stockId);
$result = $this->getNoMsiStock();

foreach ($stockData as $value) {
foreach ($channels as $channel) {
if (!array_key_exists($value['product_id'], $result)) {
continue;
}
if (!array_key_exists($value['product_id'], $result)) {
continue;
}

$qty = $value[sprintf('quantity_%s', (int)$channel)];
$reserved = max($result[$value['product_id']]['reserved'], 0);
$salableQty = $qty - $reserved;
$quantity = (int)($value['quantity'] ?? 0);
$reservations = max($reservations[$value['product_id']] ?? 0, 0);

$result[$value['product_id']]['msi'][$channel] = [
'qty' => (int)($value[sprintf('quantity_%s', (int)$channel)] ?? 0),
'is_salable' => $value[sprintf('is_salable_%s', (int)$channel)] ?? 0,
'availability' => $value[sprintf('is_salable_%s', (int)$channel)] ?? 0,
'salable_qty' => $salableQty ?: 0
];
}
$result[$value['product_id']]['qty'] = $quantity;
$result[$value['product_id']]['is_salable'] = $value['is_salable'] ?? 0;
$result[$value['product_id']]['availability'] = $value['is_salable'] ?? 0;
$result[$value['product_id']]['is_in_stock'] = $value['is_salable'] ?? 0;
$result[$value['product_id']]['salable_qty'] = $quantity - $reservations;
}

return $result;
Expand All @@ -147,52 +159,78 @@ private function getMsiStock(): array
/**
* Get MSI stock channels
*
* @return array[]
* @param int $storeId
* @return int
*/
private function getChannels(): array
private function getStockId(int $storeId): int
{
$select = $this->resource->getConnection()->select()
->from(
$this->resource->getTableName('inventory_stock_sales_channel'),
['stock_id']
)
->where(
'type = ?',
'website'
);
return array_unique($this->resource->getConnection()->fetchCol($select));
try {
$store = $this->storeManager->getStore($storeId);
$website = $this->websiteRepository->getById($store->getWebsiteId());
$select = $this->resource->getConnection()->select()
->from(
$this->resource->getTableName('inventory_stock_sales_channel'),
['stock_id']
)
->where(
'type = ?',
'website'
)->where(
'code = ?',
$website->getCode()
)->limit(1);
return (int)$this->resource->getConnection()->fetchOne($select);
} catch (\Exception $exception) {
$this->logRepository->addErrorLog('MSI getStockId', $exception->getMessage());
return 1;
}
}

/**
* Collect MSI stock data
*
* @param array[] $channels
* @param int $stockId
* @return array[]
*/
private function collectMsi(array $channels): array
private function collectMsi(int $stockId): array
{
$stockView = sprintf('inventory_stock_%s', (int)$stockId);
$select = $this->resource->getConnection()->select()
->from(
['cpe' => $this->resource->getTableName('catalog_product_entity')],
['product_id' => 'entity_id', $this->linkField]
)->where(
'cpe.entity_id IN (?)',
$this->entityIds
)->joinLeft(
['inv_stock' => $this->resource->getTableName($stockView)],
"cpe.sku = inv_stock.sku",
['inv_stock.quantity', 'inv_stock.is_salable']
);

foreach ($channels as $channel) {
$table = sprintf('inventory_stock_%s', (int)$channel);
$select->joinLeft(
[$table => $this->resource->getTableName($table)],
"cpe.sku = {$table}.sku",
[
sprintf('quantity_%s', (int)$channel) => "{$table}.quantity",
sprintf('is_salable_%s', (int)$channel) => "{$table}.is_salable"
]
return $this->resource->getConnection()->fetchAll($select);
}

/**
* @param int $stockId
* @return array
*/
private function collectMsiReservations(int $stockId): array
{
$select = $this->resource->getConnection()->select()
->from(
['cpe' => $this->resource->getTableName('catalog_product_entity')],
['product_id' => 'entity_id']
)->where(
'cpe.entity_id IN (?)',
$this->entityIds
)->joinLeft(
['inv_res' => $this->resource->getTableName('inventory_reservation')],
"inv_res.sku = cpe.sku AND inv_res.stock_id = {$stockId}",
['reserved' => 'SUM(COALESCE(inv_res.quantity, 0))']
);
}

return $this->resource->getConnection()->fetchAll($select);
return $this->resource->getConnection()->fetchPairs($select);
}

/**
Expand All @@ -209,10 +247,9 @@ private function collectMsi(array $channels): array
* min_sale_qty
* ]
*
* @param bool $addMsi
* @return array[]
*/
private function getNoMsiStock(bool $addMsi = false): array
private function getNoMsiStock(): array
{
$result = [];
$select = $this->resource->getConnection()
Expand All @@ -235,36 +272,25 @@ private function getNoMsiStock(bool $addMsi = false): array
['css' => $this->resource->getTableName('cataloginventory_stock_status')],
'css.product_id = catalog_product_entity.entity_id',
['stock_status']
)->where(
'cataloginventory_stock_item.product_id IN (?)',
$this->entityIds
)->group(
'product_id'
);
if ($addMsi) {
$select->joinLeft(
['inventory_reservation' => $this->resource->getTableName('inventory_reservation')],
'inventory_reservation.sku = catalog_product_entity.sku',
['reserved' => 'SUM(COALESCE(inventory_reservation.quantity, 0))']
);
}
$select->where('cataloginventory_stock_item.product_id IN (?)', $this->entityIds);
$select->group('product_id');
$values = $this->resource->getConnection()->fetchAll($select);

foreach ($values as $value) {
$result[$value['product_id']] =
[
'qty' => (int)$value['qty'],
'is_in_stock' => (int)$value['stock_status'],
'availability' => (int)$value['stock_status'],
'manage_stock' => (int)$value['manage_stock'],
'qty_increments' => (int)$value['qty_increments'],
'min_sale_qty' => (int)$value['min_sale_qty']
];
if ($addMsi) {
$reserved = (int)$value['reserved'] * -1;
$result[$value['product_id']] += [
'reserved' => $reserved,
'salable_qty' => (int)($value['qty'] - $reserved)
];
}
$result[$value['product_id']] = [
'qty' => (int)$value['qty'],
'is_in_stock' => (int)$value['stock_status'],
'availability' => (int)$value['stock_status'],
'manage_stock' => (int)$value['manage_stock'],
'qty_increments' => (int)$value['qty_increments'],
'min_sale_qty' => (int)$value['min_sale_qty']
];
}

return $result;
}

Expand Down
2 changes: 1 addition & 1 deletion Service/ProductData/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public function execute(array $entityIds, array $attributeMap, array $extraParam
}

if ($extraParameters['stock']['inventory']) {
$result = $this->stock->execute($productIds);
$result = $this->stock->execute($productIds, $storeId);
$inventoryFields = array_merge(
$extraParameters['stock']['inventory_fields'],
['qty', 'msi', 'salable_qty', 'reserved', 'is_in_stock']
Expand Down
35 changes: 29 additions & 6 deletions Service/ProductData/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public function execute(array $filter, int $storeId = 0): array
*/
private function filterVisibility(array $filter, int $storeId = 0): array
{

if ($filter['filter_by_visibility']) {
$visibility = is_array($filter['visibility'])
? $filter['visibility']
Expand All @@ -102,7 +103,9 @@ private function filterVisibility(array $filter, int $storeId = 0): array
}

$connection = $this->resourceConnection->getConnection();
$select = $connection->select()->distinct()->from(

// Get all EntityIds from base store bases on visibility filter
$selectBase = $connection->select()->distinct()->from(
['catalog_product_entity_int' => $this->resourceConnection->getTableName('catalog_product_entity_int')],
[$this->entityId]
)->joinLeft(
Expand All @@ -116,13 +119,33 @@ private function filterVisibility(array $filter, int $storeId = 0): array
'attribute_code = ?',
'visibility'
)->where(
'store_id IN (?)',
[0, $storeId]
)->order(
'store_id ASC'
'store_id = ?',
0
);

return $connection->fetchCol($select);
// Check for EntityIds that needs to be removed as visibility is set differently on store-view
$selectStore = $connection->select()->distinct()->from(
['catalog_product_entity_int' => $this->resourceConnection->getTableName('catalog_product_entity_int')],
[$this->entityId]
)->joinLeft(
['eav_attribute' => $this->resourceConnection->getTableName('eav_attribute')],
'eav_attribute.attribute_id = catalog_product_entity_int.attribute_id',
[]
)->where(
'value NOT IN (?)',
$visibility
)->where(
'attribute_code = ?',
'visibility'
)->where(
'store_id = ?',
$storeId
);

return array_diff(
$connection->fetchCol($selectBase),
$connection->fetchCol($selectStore)
);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "magmodules/magento2-sooqr",
"description": "Sooqr integration for Magento 2",
"type": "magento2-module",
"version": "2.1.8",
"version": "2.2.0",
"license": [
"OSL-3.0",
"AFL-3.0"
Expand Down
2 changes: 1 addition & 1 deletion etc/adminhtml/menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
<menu>
<add id="Magmodules_Sooqr::general"
title="Sooqr"
title="Spotler"
module="Magmodules_Sooqr"
sortOrder="100"
resource="Magmodules_Sooqr::feed"
Expand Down
2 changes: 1 addition & 1 deletion etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<tab id="sooqr" translate="label" sortOrder="300" class="sooqr-plugin">
<label>Sooqr</label>
<label>Spotler</label>
</tab>
<include path="Magmodules_Sooqr::system/general.xml"/>
<include path="Magmodules_Sooqr::system/data.xml"/>
Expand Down
2 changes: 1 addition & 1 deletion etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<sooqr_general>
<general>
<enable>1</enable>
<version>v2.1.8</version>
<version>v2.2.0</version>
</general>
<credentials>
<environment>production</environment>
Expand Down
Loading

0 comments on commit 763979a

Please sign in to comment.