@@ -32,30 +32,12 @@ class Price
3232 'bundle_price_type '
3333 ];
3434
35- /**
36- * @var CatalogPrice
37- */
38- private $ commonPriceModel ;
39- /**
40- * @var RuleFactory
41- */
42- private $ resourceRuleFactory ;
43- /**
44- * @var CatalogHelper
45- */
46- private $ catalogHelper ;
47- /**
48- * @var StoreManagerInterface
49- */
50- private $ storeManager ;
51- /**
52- * @var TimezoneInterface
53- */
54- private $ localeDate ;
55- /**
56- * @var CollectionFactory
57- */
58- private $ collectionFactory ;
35+ private CatalogPrice $ commonPriceModel ;
36+ private RuleFactory $ resourceRuleFactory ;
37+ private CatalogHelper $ catalogHelper ;
38+ private StoreManagerInterface $ storeManager ;
39+ private TimezoneInterface $ localeDate ;
40+ private CollectionFactory $ collectionFactory ;
5941
6042 private $ price = null ;
6143 private $ finalPrice = null ;
@@ -66,6 +48,7 @@ class Price
6648 private $ maxPrice = null ;
6749 private $ totalPrice = null ;
6850 private $ websiteId = null ;
51+ private $ currecy = null ;
6952 private $ taxClasses = [];
7053 private $ bundlePriceType = null ;
7154 private $ groupedPriceType = null ;
@@ -102,45 +85,76 @@ public function execute(
10285 int $ storeId = 0
10386 ): array {
10487 $ store = $ this ->getStore ((int )$ storeId );
88+ $ this ->currecy = $ store ->getDefaultCurrencyCode ();
10589 $ this ->websiteId = $ store ->getWebsiteId ();
10690 $ this ->taxClasses = [];
10791
108- $ this ->setData ('products ' , $ this ->getProductData ($ productIds ));
92+ $ this ->setData ('products ' , $ this ->getProductData ($ productIds, $ storeId ));
10993 $ this ->setData ('grouped_price_type ' , $ groupedPriceType );
11094 $ this ->setData ('bundle_price_type ' , $ bundlePriceType );
95+ $ rate = $ store ->getBaseCurrency ()->getRate ($ this ->currecy );
11196
11297 foreach ($ this ->products as $ product ) {
11398 $ this ->setPrices ($ product , $ this ->groupedPriceType , $ this ->bundlePriceType );
114-
115- if (array_key_exists ((int )$ product ->getTaxClassId (), $ this ->taxClasses )) {
116- $ percent = $ this ->taxClasses [(int )$ product ->getTaxClassId ()];
117- } else {
118- $ priceInclTax = $ this ->processPrice ($ product , (float )$ this ->price , $ store );
119- $ percent = $ this ->price == 0 ? 1 : round ($ priceInclTax / $ this ->price , 2 );
120- if ($ percent !== 1 ) {
121- $ this ->taxClasses [(int )$ product ->getTaxClassId ()] = $ percent ;
122- }
123- }
99+ $ percent = $ this ->getPercentage ($ product , $ store );
124100
125101 $ result [$ product ->getId ()] = [
126- 'price ' => $ percent * $ this ->price ,
127- 'price_ex ' => $ this ->price ,
128- 'final_price ' => $ this ->finalPrice ? $ percent * $ this ->finalPrice : null ,
129- 'final_price_ex ' => $ this ->finalPrice ,
130- 'sales_price ' => $ this ->salesPrice ? $ percent * $ this ->salesPrice : null ,
131- 'min_price ' => $ this ->minPrice ? $ percent * $ this ->minPrice : null ,
132- 'max_price ' => $ this ->maxPrice ? $ percent * $ this ->maxPrice : null ,
133- 'special_price ' => $ this ->specialPrice ? $ percent * $ this ->specialPrice : null ,
134- 'total_price ' => $ this ->totalPrice ? $ percent * $ this ->totalPrice : null ,
102+ 'price ' => $ this -> round ( $ percent * $ this ->price ) ,
103+ 'price_ex ' => $ this ->round ( $ this -> price * $ rate ) ,
104+ 'final_price ' => $ this ->round ( $ this -> finalPrice ? $ percent * $ this ->finalPrice : null ) ,
105+ 'final_price_ex ' => $ this ->round ( $ this -> finalPrice * $ rate ) ,
106+ 'sales_price ' => $ this ->round ( $ this -> salesPrice ? $ percent * $ this ->salesPrice : null ) ,
107+ 'min_price ' => $ this ->round ( $ this -> minPrice ? $ percent * $ this ->minPrice : null ) ,
108+ 'max_price ' => $ this ->round ( $ this -> maxPrice ? $ percent * $ this ->maxPrice : null ) ,
109+ 'special_price ' => $ this ->round ( $ this -> specialPrice ? $ percent * $ this ->specialPrice : null ) ,
110+ 'total_price ' => $ this ->round ( $ this -> totalPrice ? $ percent * $ this ->totalPrice : null ) ,
135111 'sales_date_range ' => $ this ->getSpecialPriceDateRang ($ product ),
136112 'discount_perc ' => $ this ->getDiscountPercentage (),
137- 'tax ' => abs (1 - $ percent ) * 100
113+ 'tax ' => abs (1 - ($ percent /$ rate )) * 100 ,
114+ 'currency ' => $ this ->currecy
138115 ];
139116 }
140117
141118 return $ result ?? [];
142119 }
143120
121+ /**
122+ * Calculate price multiplier including tax adjustments and currency rate differences.
123+ *
124+ * Returns a float multiplier based on the processed price (incl. tax) and original price,
125+ * potentially adjusted for base-to-store currency conversion.
126+ *
127+ * @param Product $product The product for which to calculate the price multiplier.
128+ * @param StoreInterface|null $store The store context used to resolve tax and currency.
129+ * @return float The price multiplier relative to base price.
130+ */
131+ private function getPercentage (Product $ product , ?StoreInterface $ store ): float
132+ {
133+ $ taxClassId = (int )$ product ->getTaxClassId ();
134+
135+ if (isset ($ this ->taxClasses [$ taxClassId ])) {
136+ return $ this ->taxClasses [$ taxClassId ];
137+ }
138+
139+ if ($ this ->price == 0.0 ) {
140+ $ percent = 1.0 ;
141+ } else {
142+ $ processed = $ this ->processPrice ($ product , (float )$ this ->price , $ store );
143+ $ percent = round ($ processed / $ this ->price , 2 );
144+ }
145+
146+ // Adjust for currency difference
147+ if ($ store ->getBaseCurrencyCode () !== $ this ->currecy ) {
148+ $ rate = $ store ->getBaseCurrency ()->getRate ($ this ->currecy );
149+ if ($ rate > 0 ) {
150+ $ percent *= $ rate ;
151+ }
152+ }
153+
154+ $ this ->taxClasses [$ taxClassId ] = $ percent ;
155+ return $ percent ;
156+ }
157+
144158 /**
145159 * @param int $storeId
146160 * @return StoreInterface|null
@@ -178,14 +192,18 @@ public function setData($type, $data)
178192
179193 /**
180194 * @param array $productIds
195+ * @param int $storeId
181196 * @return Collection|AbstractDb
182197 */
183- private function getProductData (array $ productIds = [])
198+ private function getProductData (array $ productIds = [], int $ storeId = 0 )
184199 {
185200 $ products = $ this ->collectionFactory ->create ()
186201 ->addFieldToSelect (['price ' , 'special_price ' , 'tax_class_id ' , 'special_from_date ' , 'special_to_date ' ])
187- ->addFieldToFilter ('entity_id ' , ['in ' => $ productIds ]);
202+ ->addFieldToFilter ('entity_id ' , ['in ' => $ productIds ])
203+ ->addStoreFilter ($ storeId )
204+ ->setStoreId ($ storeId );
188205
206+ // Join the price attributes
189207 $ products ->getSelect ()->joinLeft (
190208 ['price_index ' => $ products ->getTable ('catalog_product_index_price ' )],
191209 join (
@@ -256,6 +274,11 @@ private function setPrices(Product $product, ?string $groupedPriceType, ?string
256274 }
257275 }
258276
277+ private function round ($ price )
278+ {
279+ return round ((float )$ price , 2 );
280+ }
281+
259282 /**
260283 * @param Product $product
261284 */
@@ -412,7 +435,6 @@ private function getRulePrice(Product $product): float
412435 */
413436 private function processPrice (Product $ product , float $ price , ?StoreInterface $ store ): float
414437 {
415-
416438 return (float )$ this ->catalogHelper ->getTaxPrice (
417439 $ product ,
418440 $ price ,
0 commit comments