88namespace Magento \BundleImportExport \Model \Import \Product \Type ;
99
1010use Magento \Bundle \Model \Product \Price as BundlePrice ;
11+ use Magento \Catalog \Helper \Data as CatalogData ;
1112use Magento \Catalog \Model \Product \Type \AbstractType ;
1213use Magento \Catalog \Model \ResourceModel \Product \Attribute \CollectionFactory as AttributeCollectionFactory ;
1314use 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 *
0 commit comments