Skip to content

Commit a311785

Browse files
committed
ACP2E-1388:Bundle Products Not Combining Simple Product Prices When Set to Dynamic Pricing
fixed CR feedback
1 parent 0533ce1 commit a311785

File tree

2 files changed

+33
-46
lines changed

2 files changed

+33
-46
lines changed

app/code/Magento/Bundle/Model/Plugin/ProductPriceIndexModifier.php

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
namespace Magento\Bundle\Model\Plugin;
99

10+
use Magento\Bundle\Model\Link;
1011
use Magento\Bundle\Model\Product\Price;
1112
use Magento\Catalog\Api\Data\ProductInterface;
12-
use Magento\Catalog\Api\ProductRepositoryInterface;
1313
use Magento\Catalog\Model\Product\Type;
1414
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructure;
1515
use Magento\CatalogInventory\Api\StockConfigurationInterface;
@@ -38,11 +38,6 @@ class ProductPriceIndexModifier
3838
*/
3939
private MetadataPool $metadataPool;
4040

41-
/**
42-
* @var ProductRepositoryInterface
43-
*/
44-
private ProductRepositoryInterface $productRepository;
45-
4641
/**
4742
* @var string
4843
*/
@@ -52,22 +47,18 @@ class ProductPriceIndexModifier
5247
* @param StockConfigurationInterface $stockConfiguration
5348
* @param ResourceConnection $resourceConnection
5449
* @param MetadataPool $metadataPool
55-
* @param ProductRepositoryInterface|null $productRepository
5650
* @param string $connectionName
5751
*/
5852
public function __construct(
5953
StockConfigurationInterface $stockConfiguration,
6054
ResourceConnection $resourceConnection,
6155
MetadataPool $metadataPool,
62-
?ProductRepositoryInterface $productRepository = null,
6356
string $connectionName = 'indexer'
6457
) {
6558
$this->stockConfiguration = $stockConfiguration;
6659
$this->resourceConnection = $resourceConnection;
6760
$this->metadataPool = $metadataPool;
6861
$this->connectionName = $connectionName;
69-
$this->productRepository = $productRepository ?: \Magento\Framework\App\ObjectManager::getInstance()
70-
->get(ProductRepositoryInterface::class);
7162
}
7263

7364
/**
@@ -110,28 +101,45 @@ private function filterProductsFromDynamicPriceBundle(string $priceTableName, ar
110101
$linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
111102
$connection = $this->resourceConnection->getConnection($this->connectionName);
112103
$select = $connection->select();
113-
$select->from(['selection' => $this->resourceConnection->getTableName('catalog_product_bundle_selection')]);
114-
$select->columns(['product.entity_id AS bundle_id', 'selection.product_id AS child_product_id']);
104+
$select->from(['selection' => $this->resourceConnection->getTableName('catalog_product_bundle_selection')],
105+
[
106+
'product.entity_id AS bundle_id',
107+
'selection.product_id AS child_product_id',
108+
'pei.value AS bundle_price_type'
109+
]
110+
);
115111
$select->joinInner(
116112
['price' => $this->resourceConnection->getTableName($priceTableName)],
117-
implode(' AND ', ['price.entity_id = selection.product_id'])
113+
implode(' AND ', ['price.entity_id = selection.product_id']),
114+
null
118115
);
119116
$select->joinInner(
120117
['product' => $this->resourceConnection->getTableName('catalog_product_entity')],
121-
"product.$linkField = selection.parent_product_id"
118+
"product.$linkField = selection.parent_product_id",
119+
null
120+
);
121+
$select->joinInner(
122+
['pei' => $this->resourceConnection->getTableName('catalog_product_entity_int')],
123+
"product.$linkField = pei.$linkField",
124+
null
125+
);
126+
$select->joinInner(
127+
['ea' => $this->resourceConnection->getTableName('eav_attribute')],
128+
"pei.attribute_id = ea.attribute_id AND ea.attribute_code = '" . Link::KEY_PRICE_TYPE . "'",
129+
null
122130
);
123131
$select->where('selection.product_id IN (?)', $productIds);
124132
$select->where('product.type_id = ?', Type::TYPE_BUNDLE);
133+
$select->group('selection.product_id');
125134
$bundleProducts = $connection->fetchAll($select);
126135

127136
if (empty($bundleProducts)) {
128-
return [];
137+
return $productIds;
129138
}
130139

131140
$filteredProducts = [];
132-
foreach ($bundleProducts as $bundle) {
133-
$bundleProduct = $this->productRepository->getById($bundle['bundle_id']);
134-
if ($bundleProduct->getPriceType() != Price::PRICE_TYPE_DYNAMIC) {
141+
foreach($bundleProducts as $bundle) {
142+
if ($bundle['bundle_price_type'] !== Price::PRICE_TYPE_DYNAMIC) {
135143
$filteredProducts[] = $bundle['child_product_id'];
136144
}
137145
}

app/code/Magento/Bundle/Test/Unit/Model/Plugin/ProductPriceIndexModifierTest.php

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ class ProductPriceIndexModifierTest extends TestCase
5050
*/
5151
private IndexTableStructure $table;
5252

53-
/**
54-
* @var ProductRepositoryInterface|ProductRepositoryInterface&MockObject|MockObject
55-
*/
56-
private ProductRepositoryInterface $productRepository;
57-
5853
/**
5954
* @var ProductPriceIndexFilter|MockObject
6055
*/
@@ -67,12 +62,10 @@ protected function setUp(): void
6762
$this->subject = $this->createMock(ProductPriceIndexFilter::class);
6863
$this->resourceConnection = $this->createMock(ResourceConnection::class);
6964
$this->metadataPool = $this->createMock(MetadataPool::class);
70-
$this->productRepository = $this->createMock(ProductRepositoryInterface::class);
7165
$this->plugin = new ProductPriceIndexModifier(
7266
$this->stockConfiguration,
7367
$this->resourceConnection,
7468
$this->metadataPool,
75-
$this->productRepository,
7669
self::CONNECTION_NAME
7770
);
7871
}
@@ -101,10 +94,11 @@ public function testAroundModifyPriceFilteredEntities()
10194
$select = $this->createMock(Select::class);
10295
$select->expects($this->once())
10396
->method('from');
104-
$select->expects($this->exactly(2))
97+
$select->expects($this->exactly(4))
10598
->method('joinInner');
10699
$select->expects($this->exactly(2))
107100
->method('where');
101+
$select->expects($this->once())->method('group')->with('selection.product_id');
108102
$connection = $this->createMock(AdapterInterface::class);
109103
$connection->expects($this->once())
110104
->method('select')
@@ -115,42 +109,27 @@ public function testAroundModifyPriceFilteredEntities()
115109
->willReturn([
116110
[
117111
'bundle_id' => 1,
118-
'child_product_id' => 1
112+
'child_product_id' => 1,
113+
'bundle_price_type' => 0
119114
],
120115
[
121116
'bundle_id' => 1,
122-
'child_product_id' => 2
117+
'child_product_id' => 2,
118+
'bundle_price_type' => 1
123119
]
124120
]);
125121
$this->resourceConnection->expects($this->once())
126122
->method('getConnection')
127123
->with(self::CONNECTION_NAME)
128124
->willReturn($connection);
129125

130-
$bundleProduct1 = $this->getMockBuilder(ProductInterface::class)
131-
->disableOriginalConstructor()
132-
->addMethods(['getPriceType'])
133-
->getMockForAbstractClass();
134-
$bundleProduct1->expects($this->once())->method('getPriceType')
135-
->willReturn(1);
136-
$bundleProduct2 = $this->getMockBuilder(ProductInterface::class)
137-
->disableOriginalConstructor()
138-
->addMethods(['getPriceType'])
139-
->getMockForAbstractClass();
140-
$bundleProduct2->expects($this->once())->method('getPriceType')
141-
->willReturn(1);
142-
143-
$this->productRepository->expects($this->exactly(2))
144-
->method('getById')
145-
->willReturnOnConsecutiveCalls($bundleProduct1, $bundleProduct2);
146-
147126
$calledPriceTable = '';
148127
$calledEntities = [];
149128
$callable = function () use (&$calledPriceTable, &$calledEntities, $priceTableName, $entities) {
150129
$calledPriceTable = $priceTableName;
151130
$calledEntities = $entities;
152131
};
153-
$this->plugin->aroundModifyPrice($this->subject, $callable, $this->table, [1, 2]);
132+
$this->plugin->aroundModifyPrice($this->subject, $callable, $this->table, $entities);
154133
$this->assertSame($calledPriceTable, $priceTableName);
155134
$this->assertSame($calledEntities, $entities);
156135
}

0 commit comments

Comments
 (0)