@@ -75,6 +75,11 @@ abstract class AbstractAction
75
75
*/
76
76
private $ productResource ;
77
77
78
+ /**
79
+ * @var \Magento\Indexer\Model\ResourceModel\FrontendResource
80
+ */
81
+ private $ indexerFrontendResource ;
82
+
78
83
/**
79
84
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
80
85
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -84,6 +89,7 @@ abstract class AbstractAction
84
89
* @param \Magento\Catalog\Model\Product\Type $catalogProductType
85
90
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\Factory $indexerPriceFactory
86
91
* @param \Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice $defaultIndexerResource
92
+ * @param \Magento\Indexer\Model\ResourceModel\FrontendResource|null $indexerFrontendResource
87
93
*/
88
94
public function __construct (
89
95
\Magento \Framework \App \Config \ScopeConfigInterface $ config ,
@@ -93,7 +99,8 @@ public function __construct(
93
99
\Magento \Framework \Stdlib \DateTime $ dateTime ,
94
100
\Magento \Catalog \Model \Product \Type $ catalogProductType ,
95
101
\Magento \Catalog \Model \ResourceModel \Product \Indexer \Price \Factory $ indexerPriceFactory ,
96
- \Magento \Catalog \Model \ResourceModel \Product \Indexer \Price \DefaultPrice $ defaultIndexerResource
102
+ \Magento \Catalog \Model \ResourceModel \Product \Indexer \Price \DefaultPrice $ defaultIndexerResource ,
103
+ \Magento \Indexer \Model \ResourceModel \FrontendResource $ indexerFrontendResource = null
97
104
) {
98
105
$ this ->_config = $ config ;
99
106
$ this ->_storeManager = $ storeManager ;
@@ -104,6 +111,10 @@ public function __construct(
104
111
$ this ->_indexerPriceFactory = $ indexerPriceFactory ;
105
112
$ this ->_defaultIndexerResource = $ defaultIndexerResource ;
106
113
$ this ->_connection = $ this ->_defaultIndexerResource ->getConnection ();
114
+ $ this ->indexerFrontendResource = $ indexerFrontendResource ?: \Magento \Framework \App \ObjectManager::getInstance ()
115
+ ->get (
116
+ \Magento \Catalog \Model \ResourceModel \Product \Indexer \Price \FrontendResource::class
117
+ );
107
118
}
108
119
109
120
/**
@@ -124,7 +135,7 @@ protected function _syncData(array $processIds = [])
124
135
{
125
136
// delete invalid rows
126
137
$ select = $ this ->_connection ->select ()->from (
127
- ['index_price ' => $ this ->_defaultIndexerResource -> getTable ( ' catalog_product_index_price ' )],
138
+ ['index_price ' => $ this ->getIndexTargetTable ( )],
128
139
null
129
140
)->joinLeft (
130
141
['ip_tmp ' => $ this ->_defaultIndexerResource ->getIdxTable ()],
@@ -141,7 +152,7 @@ protected function _syncData(array $processIds = [])
141
152
142
153
$ this ->_insertFromTable (
143
154
$ this ->_defaultIndexerResource ->getIdxTable (),
144
- $ this ->_defaultIndexerResource -> getTable ( ' catalog_product_index_price ' )
155
+ $ this ->getIndexTargetTable ( )
145
156
);
146
157
return $ this ;
147
158
}
@@ -217,61 +228,90 @@ protected function _prepareTierPriceIndex($entityIds = null)
217
228
{
218
229
$ table = $ this ->_defaultIndexerResource ->getTable ('catalog_product_index_tier_price ' );
219
230
$ this ->_emptyTable ($ table );
220
-
221
- $ tierPriceExpression = $ this ->_connection ->getCheckSql (
222
- 'tp.value = 0 ' ,
223
- 'product_price.value * (1 - tp.percentage_value / 100) ' ,
224
- 'tp.value '
225
- );
226
- $ websiteExpression = $ this ->_connection ->getCheckSql (
227
- 'tp.website_id = 0 ' ,
228
- 'ROUND( ' . $ tierPriceExpression . ' * cwd.rate, 4) ' ,
229
- $ tierPriceExpression
230
- );
231
+ if (empty ($ entityIds )) {
232
+ return $ this ;
233
+ }
231
234
$ linkField = $ this ->getProductIdFieldName ();
232
235
$ priceAttribute = $ this ->getProductResource ()->getAttribute ('price ' );
233
-
234
- $ select = $ this ->_connection ->select ()->from (
236
+ $ baseColumns = [
237
+ 'cpe.entity_id ' ,
238
+ 'tp.customer_group_id ' ,
239
+ 'tp.website_id '
240
+ ];
241
+ if ($ linkField !== 'entity_id ' ) {
242
+ $ baseColumns [] = 'cpe. ' . $ linkField ;
243
+ };
244
+ $ subSelect = $ this ->_connection ->select ()->from (
235
245
['cpe ' => $ this ->_defaultIndexerResource ->getTable ('catalog_product_entity ' )],
236
- ['cpe.entity_id ' ]
237
- )->join (
246
+ array_merge_recursive (
247
+ $ baseColumns ,
248
+ [
249
+ 'min(tp.value) AS value ' ,
250
+ 'min(tp.percentage_value) AS percentage_value '
251
+ ]
252
+ )
253
+ )->joinInner (
238
254
['tp ' => $ this ->_defaultIndexerResource ->getTable (['catalog_product_entity ' , 'tier_price ' ])],
239
255
'tp. ' . $ linkField . ' = cpe. ' . $ linkField ,
240
256
[]
241
- )->join (
242
- ['cg ' => $ this ->_defaultIndexerResource ->getTable ('customer_group ' )],
243
- 'tp.all_groups = 1 OR (tp.all_groups = 0 AND tp.customer_group_id = cg.customer_group_id) ' ,
244
- ['customer_group_id ' ]
245
- )->join (
246
- ['cw ' => $ this ->_defaultIndexerResource ->getTable ('store_website ' )],
247
- 'tp.website_id = 0 OR tp.website_id = cw.website_id ' ,
248
- ['website_id ' ]
249
- )->join (
250
- ['cwd ' => $ this ->_defaultIndexerResource ->getTable ('catalog_product_index_website ' )],
251
- 'cw.website_id = cwd.website_id ' ,
252
- []
253
- )->join (
254
- ['product_price ' => $ priceAttribute ->getBackend ()->getTable ()],
255
- 'tp. ' . $ linkField . ' = product_price. ' . $ linkField ,
256
- []
257
- )->where (
258
- 'cw.website_id != 0 '
259
- )->where (
260
- 'product_price.attribute_id = ? ' ,
261
- $ priceAttribute ->getAttributeId ()
262
- )->columns (
263
- new \Zend_Db_Expr ("MIN( {$ websiteExpression }) " )
264
- )->group (
265
- ['cpe.entity_id ' , 'cg.customer_group_id ' , 'cw.website_id ' ]
266
- );
257
+ )->where ("cpe.entity_id IN(?) " , $ entityIds )
258
+ ->where ("tp.website_id != 0 " )
259
+ ->group (['cpe.entity_id ' , 'tp.customer_group_id ' , 'tp.website_id ' ]);
260
+
261
+ $ subSelect2 = $ this ->_connection ->select ()
262
+ ->from (
263
+ ['cpe ' => $ this ->_defaultIndexerResource ->getTable ('catalog_product_entity ' )],
264
+ array_merge_recursive (
265
+ $ baseColumns ,
266
+ [
267
+ 'MIN(ROUND(tp.value * cwd.rate, 4)) AS value ' ,
268
+ 'MIN(ROUND(tp.percentage_value * cwd.rate, 4)) AS percentage_value '
269
+
270
+ ]
271
+ )
272
+ )
273
+ ->joinInner (
274
+ ['tp ' => $ this ->_defaultIndexerResource ->getTable (['catalog_product_entity ' , 'tier_price ' ])],
275
+ 'tp. ' . $ linkField . ' = cpe. ' . $ linkField ,
276
+ []
277
+ )->join (
278
+ ['cw ' => $ this ->_defaultIndexerResource ->getTable ('store_website ' )],
279
+ true ,
280
+ []
281
+ )
282
+ ->joinInner (
283
+ ['cwd ' => $ this ->_defaultIndexerResource ->getTable ('catalog_product_index_website ' )],
284
+ 'cw.website_id = cwd.website_id ' ,
285
+ []
286
+ )
287
+ ->where ("cpe.entity_id IN(?) " , $ entityIds )
288
+ ->where ("tp.website_id = 0 " )
289
+ ->group (
290
+ ['cpe.entity_id ' , 'tp.customer_group_id ' , 'tp.website_id ' ]
291
+ );
267
292
268
- if (!empty ($ entityIds )) {
269
- $ select ->where ("cpe.entity_id IN(?) " , $ entityIds );
270
- }
293
+ $ unionSelect = $ this ->_connection ->select ()
294
+ ->union ([$ subSelect , $ subSelect2 ], \Magento \Framework \DB \Select::SQL_UNION_ALL );
295
+ $ select = $ this ->_connection ->select ()
296
+ ->from (
297
+ ['b ' => new \Zend_Db_Expr (sprintf ('(%s) ' , $ unionSelect ->assemble ()))],
298
+ [
299
+ 'b.entity_id ' ,
300
+ 'b.customer_group_id ' ,
301
+ 'b.website_id ' ,
302
+ 'MIN(IF(b.value = 0, product_price.value * (1 - b.percentage_value / 100), b.value)) '
303
+ ]
304
+ )
305
+ ->joinInner (
306
+ ['product_price ' => $ priceAttribute ->getBackend ()->getTable ()],
307
+ 'b. ' . $ linkField . ' = product_price. ' . $ linkField ,
308
+ []
309
+ )
310
+ ->group (['b.entity_id ' , 'b.customer_group_id ' , 'b.website_id ' ]);
311
+
312
+ $ query = $ select ->insertFromSelect ($ table , [], false );
271
313
272
- $ query = $ select ->insertFromSelect ($ table );
273
314
$ this ->_connection ->query ($ query );
274
-
275
315
return $ this ;
276
316
}
277
317
@@ -460,7 +500,7 @@ protected function _copyRelationIndexData($parentIds, $excludeIds = null)
460
500
461
501
if ($ children ) {
462
502
$ select = $ this ->_connection ->select ()->from (
463
- $ this ->_defaultIndexerResource -> getTable ( ' catalog_product_index_price ' )
503
+ $ this ->getIndexTargetTable ( )
464
504
)->where (
465
505
'entity_id IN(?) ' ,
466
506
$ children
@@ -472,6 +512,18 @@ protected function _copyRelationIndexData($parentIds, $excludeIds = null)
472
512
return $ this ;
473
513
}
474
514
515
+ /**
516
+ * Retrieve index table that will be used for write operations.
517
+ *
518
+ * This method is used during both partial and full reindex to identify the the table.
519
+ *
520
+ * @return string
521
+ */
522
+ protected function getIndexTargetTable ()
523
+ {
524
+ return $ this ->indexerFrontendResource ->getMainTable ();
525
+ }
526
+
475
527
/**
476
528
* @return string
477
529
*/
0 commit comments