6 declare(strict_types=1);
31 private $connectionName;
36 private $joinAttributeProcessor;
41 private $moduleManager;
46 private $eventManager;
53 private $dimensionToFieldMapper = [
54 WebsiteDimensionProvider::DIMENSION_NAME =>
'pw.website_id',
55 CustomerGroupDimensionProvider::DIMENSION_NAME =>
'cg.customer_group_id',
66 private $metadataPool;
78 \
Magento\Framework\Module\Manager $moduleManager,
79 \
Magento\Framework\Event\ManagerInterface $eventManager,
81 $connectionName =
'indexer' 84 $this->connectionName = $connectionName;
85 $this->joinAttributeProcessor = $joinAttributeProcessor;
87 $this->eventManager = $eventManager;
88 $this->metadataPool = $metadataPool;
101 public function getQuery(array $dimensions,
string $productType, array $entityIds = []):
Select 103 $connection = $this->getConnection();
104 $metadata = $this->metadataPool->getMetadata(\
Magento\Catalog\Api\Data\ProductInterface::class);
105 $linkField = $metadata->getLinkField();
107 $select = $connection->select()->from(
108 [
'e' => $this->getTable(
'catalog_product_entity')],
111 [
'cg' => $this->getTable(
'customer_group')],
112 array_key_exists(CustomerGroupDimensionProvider::DIMENSION_NAME, $dimensions)
115 $this->dimensionToFieldMapper[CustomerGroupDimensionProvider::DIMENSION_NAME],
116 $dimensions[CustomerGroupDimensionProvider::DIMENSION_NAME]->getValue()
118 [
'customer_group_id']
120 [
'pw' => $this->getTable(
'catalog_product_website')],
121 'pw.product_id = e.entity_id',
124 [
'cwd' => $this->getTable(
'catalog_product_index_website')],
125 'pw.website_id = cwd.website_id',
129 [
'tp' => $this->getTable(
'catalog_product_index_tier_price')],
130 'tp.entity_id = e.entity_id AND' .
131 ' tp.customer_group_id = cg.customer_group_id AND tp.website_id = pw.website_id',
135 [
'tier_price_1' => $this->getTable(
'catalog_product_entity_tier_price')],
136 'tier_price_1.' . $linkField .
' = e.' . $linkField .
' AND tier_price_1.all_groups = 0' .
137 ' AND tier_price_1.customer_group_id = cg.customer_group_id AND tier_price_1.qty = 1' .
138 ' AND tier_price_1.website_id = 0',
143 [
'tier_price_2' => $this->getTable(
'catalog_product_entity_tier_price')],
144 'tier_price_2.' . $linkField .
' = e.' . $linkField .
' AND tier_price_2.all_groups = 0 ' .
145 'AND tier_price_2.customer_group_id = cg.customer_group_id AND tier_price_2.qty = 1' .
146 ' AND tier_price_2.website_id = pw.website_id',
150 [
'tier_price_3' => $this->getTable(
'catalog_product_entity_tier_price')],
151 'tier_price_3.' . $linkField .
' = e.' . $linkField .
' AND tier_price_3.all_groups = 1 ' .
152 'AND tier_price_3.customer_group_id = 0 AND tier_price_3.qty = 1 AND tier_price_3.website_id = 0',
156 [
'tier_price_4' => $this->getTable(
'catalog_product_entity_tier_price')],
157 'tier_price_4.' . $linkField .
' = e.' . $linkField .
' AND tier_price_4.all_groups = 1' .
158 ' AND tier_price_4.customer_group_id = 0 AND tier_price_4.qty = 1' .
159 ' AND tier_price_4.website_id = pw.website_id',
163 foreach ($dimensions as $dimension) {
164 if (!isset($this->dimensionToFieldMapper[$dimension->getName()])) {
165 throw new \LogicException(
166 'Provided dimension is not valid for Price indexer: ' . $dimension->getName()
169 $select->where($this->dimensionToFieldMapper[$dimension->getName()] .
' = ?', $dimension->getValue());
172 if ($this->moduleManager->isEnabled(
'Magento_Tax')) {
173 $taxClassId = $this->joinAttributeProcessor->process(
$select,
'tax_class_id');
175 $taxClassId = new \Zend_Db_Expr(0);
177 $select->columns([
'tax_class_id' => $taxClassId]);
181 $price = $this->joinAttributeProcessor->process(
$select,
'price');
182 $specialPrice = $this->joinAttributeProcessor->process(
$select,
'special_price');
183 $specialFrom = $this->joinAttributeProcessor->process(
$select,
'special_from_date');
184 $specialTo = $this->joinAttributeProcessor->process(
$select,
'special_to_date');
185 $currentDate =
'cwd.website_date';
187 $maxUnsignedBigint =
'~0';
188 $specialFromDate = $connection->getDatePartSql($specialFrom);
189 $specialToDate = $connection->getDatePartSql($specialTo);
190 $specialFromExpr =
"{$specialFrom} IS NULL OR {$specialFromDate} <= {$currentDate}";
191 $specialToExpr =
"{$specialTo} IS NULL OR {$specialToDate} >= {$currentDate}";
192 $specialPriceExpr = $connection->getCheckSql(
193 "{$specialPrice} IS NOT NULL AND ({$specialFromExpr}) AND ({$specialToExpr})",
197 $tierPrice = $this->getTotalTierPriceExpression(
$price);
198 $tierPriceExpr = $connection->getIfNullSql($tierPrice, $maxUnsignedBigint);
199 $finalPrice = $connection->getLeastSql([
208 'price' => $connection->getIfNullSql(
$price, 0),
210 'final_price' => $connection->getIfNullSql($finalPrice, 0),
211 'min_price' => $connection->getIfNullSql($finalPrice, 0),
212 'max_price' => $connection->getIfNullSql($finalPrice, 0),
213 'tier_price' => $tierPrice,
217 $select->where(
"e.type_id = ?", $productType);
219 if ($entityIds !==
null) {
220 if (count($entityIds) > 1) {
221 $select->where(sprintf(
'e.entity_id BETWEEN %s AND %s', min($entityIds), max($entityIds)));
223 $select->where(
'e.entity_id = ?', $entityIds);
230 $this->eventManager->dispatch(
231 'prepare_catalog_product_index_select',
249 private function getTotalTierPriceExpression(\
Zend_Db_Expr $priceExpression)
251 $maxUnsignedBigint =
'~0';
253 return $this->getConnection()->getCheckSql(
257 'tier_price_1.value_id is NULL',
258 'tier_price_2.value_id is NULL',
259 'tier_price_3.value_id is NULL',
260 'tier_price_4.value_id is NULL' 264 $this->getConnection()->getLeastSql([
265 $this->getConnection()->getIfNullSql(
266 $this->getTierPriceExpressionForTable(
'tier_price_1', $priceExpression),
269 $this->getConnection()->getIfNullSql(
270 $this->getTierPriceExpressionForTable(
'tier_price_2', $priceExpression),
273 $this->getConnection()->getIfNullSql(
274 $this->getTierPriceExpressionForTable(
'tier_price_3', $priceExpression),
277 $this->getConnection()->getIfNullSql(
278 $this->getTierPriceExpressionForTable(
'tier_price_4', $priceExpression),
294 return $this->getConnection()->getCheckSql(
295 sprintf(
'%s.value = 0', $tableAlias),
297 'ROUND(%s * (1 - ROUND(%s.percentage_value * cwd.rate, 4) / 100), 4)',
301 sprintf(
'ROUND(%s.value * cwd.rate, 4)', $tableAlias)
313 if ($this->connection ===
null) {
314 $this->connection = $this->resource->getConnection($this->connectionName);
317 return $this->connection;
__construct(\Magento\Framework\App\ResourceConnection $resource, JoinAttributeProcessor $joinAttributeProcessor, \Magento\Framework\Module\Manager $moduleManager, \Magento\Framework\Event\ManagerInterface $eventManager, \Magento\Framework\EntityManager\MetadataPool $metadataPool, $connectionName='indexer')
getQuery(array $dimensions, string $productType, array $entityIds=[])