Skip to content

Commit 13bd726

Browse files
committed
Merge remote-tracking branch 'origin/ACP2E-4243' into PR_2025_10_21_muntianu
2 parents 2f8cfc9 + f2607a4 commit 13bd726

File tree

8 files changed

+886
-223
lines changed

8 files changed

+886
-223
lines changed

app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php

Lines changed: 196 additions & 55 deletions
Large diffs are not rendered by default.

app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\BundleImportExport\Model\Import\Product\Type;
99

1010
use Magento\Bundle\Model\Product\Price as BundlePrice;
11+
use Magento\Catalog\Helper\Data as CatalogData;
1112
use Magento\Catalog\Model\Product\Type\AbstractType;
1213
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory as AttributeCollectionFactory;
1314
use Magento\CatalogImportExport\Model\Import\Product;
@@ -143,6 +144,16 @@ class Bundle extends CatalogImportExportAbstractType implements
143144
*/
144145
private $storeCodeToId = [];
145146

147+
/**
148+
* @var array
149+
*/
150+
private array $websiteCodeToId = [];
151+
152+
/**
153+
* @var CatalogData
154+
*/
155+
private $catalogData;
156+
146157
/**
147158
* @param AttributeSetCollectionFactory $attrSetColFac
148159
* @param AttributeCollectionFactory $prodAttrColFac
@@ -151,6 +162,7 @@ class Bundle extends CatalogImportExportAbstractType implements
151162
* @param MetadataPool|null $metadataPool
152163
* @param Bundle\RelationsDataSaver|null $relationsDataSaver
153164
* @param StoreManagerInterface|null $storeManager
165+
* @param CatalogData|null $catalogData
154166
*/
155167
public function __construct(
156168
AttributeSetCollectionFactory $attrSetColFac,
@@ -159,14 +171,16 @@ public function __construct(
159171
array $params,
160172
?MetadataPool $metadataPool = null,
161173
?Bundle\RelationsDataSaver $relationsDataSaver = null,
162-
?StoreManagerInterface $storeManager = null
174+
?StoreManagerInterface $storeManager = null,
175+
?CatalogData $catalogData = null
163176
) {
164177
parent::__construct($attrSetColFac, $prodAttrColFac, $resource, $params, $metadataPool);
165178

166179
$this->relationsDataSaver = $relationsDataSaver
167180
?: ObjectManager::getInstance()->get(Bundle\RelationsDataSaver::class);
168181
$this->storeManager = $storeManager
169182
?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
183+
$this->catalogData = $catalogData ?? ObjectManager::getInstance()->get(CatalogData::class);
170184
}
171185

172186
/**
@@ -661,6 +675,7 @@ protected function populateInsertOptionValues(array $optionIds): array
661675
protected function insertSelections()
662676
{
663677
$selections = [];
678+
$optionIds = [];
664679

665680
foreach ($this->_cachedOptions as $productId => $options) {
666681
foreach ($options as $option) {
@@ -669,6 +684,7 @@ protected function insertSelections()
669684
if (isset($selection['position'])) {
670685
$index = $selection['position'];
671686
}
687+
$optionIds[$option['option_id']] = $option['option_id'];
672688
if ($tmpArray = $this->populateSelectionTemplate(
673689
$selection,
674690
$option['option_id'],
@@ -684,9 +700,118 @@ protected function insertSelections()
684700

685701
$this->relationsDataSaver->saveSelections($selections);
686702

703+
if (!empty($optionIds) && !$this->catalogData->isPriceGlobal()) {
704+
$this->saveSelectionsPrices($optionIds);
705+
}
706+
687707
return $this;
688708
}
689709

710+
/**
711+
* Insert selections prices for websites.
712+
*
713+
* @param array $optionIds
714+
* @return void
715+
*/
716+
private function saveSelectionsPrices(array $optionIds): void
717+
{
718+
$selectionPrices = $this->getSelectionsPrices();
719+
if (empty($selectionPrices)) {
720+
return;
721+
}
722+
$select = $this->connection->select()
723+
->from($this->_resource->getTableName('catalog_product_bundle_selection'))
724+
->where('option_id IN (?)', array_keys($optionIds));
725+
$existingSelections = $this->connection->fetchAll($select);
726+
$selectionPricesToInsert = [];
727+
foreach ($existingSelections as $selection) {
728+
$prices = $selectionPrices[$selection['parent_product_id']][$selection['option_id']]
729+
[$selection['product_id']] ?? [];
730+
foreach ($prices as $websiteId => $data) {
731+
$selectionPricesToInsert[] = [
732+
'selection_id' => $selection['selection_id'],
733+
'parent_product_id' => $selection['parent_product_id'],
734+
'website_id' => $websiteId,
735+
'selection_price_type' => $data['selection_price_type']
736+
?? $selection['selection_price_type'],
737+
'selection_price_value' => $data['selection_price_value'],
738+
];
739+
}
740+
}
741+
if (!empty($selectionPricesToInsert)) {
742+
$this->relationsDataSaver->saveSelectionPrices($selectionPricesToInsert);
743+
}
744+
}
745+
746+
/**
747+
* Returns selections prices by parentProductId, optionId, productId, and websiteId.
748+
*
749+
* @return array
750+
*/
751+
private function getSelectionsPrices(): array
752+
{
753+
$selectionPrices = [];
754+
foreach ($this->_cachedOptions as $parentProductId => $options) {
755+
foreach ($options as $option) {
756+
foreach ($option['selections'] as $selection) {
757+
$productId = $this->_cachedSkuToProducts[$selection['sku']] ?? null;
758+
if (!$productId) {
759+
continue;
760+
}
761+
$selectionPrices[$parentProductId][$option['option_id']][$productId] =
762+
$this->getSelectionPrices($selection);
763+
}
764+
}
765+
}
766+
767+
return $selectionPrices;
768+
}
769+
770+
/**
771+
* Returns selection prices by websiteId.
772+
*
773+
* @param array $selection
774+
* @return array
775+
*/
776+
private function getSelectionPrices(array $selection): array
777+
{
778+
$prices = [];
779+
foreach ($selection as $key => $value) {
780+
$value = trim($value);
781+
if (is_numeric($value) && str_starts_with($key, 'price_website_')) {
782+
$websiteCode = str_replace('price_website_', '', $key);
783+
$websiteId = $this->getWebsiteIdByCode($websiteCode);
784+
$priceType = $selection['price_type_website_' . $websiteCode] ?? $selection['price_type'] ?? null;
785+
$prices[$websiteId] = [
786+
'selection_price_value' => (float) $value,
787+
'selection_price_type' => match ($priceType) {
788+
self::VALUE_FIXED => self::SELECTION_PRICE_TYPE_FIXED,
789+
default => self::SELECTION_PRICE_TYPE_PERCENT,
790+
}
791+
];
792+
}
793+
}
794+
return $prices;
795+
}
796+
797+
/**
798+
* Get website id by website code.
799+
*
800+
* @param string $websiteCode
801+
* @return int
802+
*/
803+
private function getWebsiteIdByCode(string $websiteCode): int
804+
{
805+
if (!isset($this->websiteCodeToId[$websiteCode])) {
806+
$this->websiteCodeToId = [];
807+
foreach ($this->storeManager->getWebsites() as $website) {
808+
$this->websiteCodeToId[$website->getCode()] = (int)$website->getId();
809+
}
810+
}
811+
812+
return $this->websiteCodeToId[$websiteCode] ?? Store::DEFAULT_STORE_ID;
813+
}
814+
690815
/**
691816
* Insert parent/child product relations
692817
*

app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle/RelationsDataSaver.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,23 @@ public function saveSelections(array $selections)
105105
}
106106
}
107107

108+
/**
109+
* Saves bundle selection prices per website
110+
*
111+
* @param array $values
112+
* @return void
113+
*/
114+
public function saveSelectionPrices(array $values): void
115+
{
116+
if (!empty($values)) {
117+
$this->resource->getConnection()->insertOnDuplicate(
118+
$this->resource->getTableName('catalog_product_bundle_selection_price'),
119+
$values,
120+
['selection_price_type', 'selection_price_value']
121+
);
122+
}
123+
}
124+
108125
/**
109126
* Saves given parent/child relations.
110127
*

0 commit comments

Comments
 (0)