1+ import camelCase from 'lodash/camelCase'
2+
13function isSpecialPriceActive ( fromDate , toDate ) {
24 if ( ! fromDate && ! toDate ) {
35 return true
@@ -20,84 +22,96 @@ function isSpecialPriceActive (fromDate, toDate) {
2022 }
2123}
2224
25+ /**
26+ * change object keys to camelCase
27+ */
28+ function toCamelCase ( obj = { } ) {
29+ return Object . keys ( obj ) . reduce ( ( accObj , currKey ) => {
30+ accObj [ camelCase ( currKey ) ] = obj [ currKey ]
31+ return accObj
32+ } , { } )
33+ }
34+
35+ /**
36+ * Create price object with base price and tax
37+ * @param price - product price which is used to extract tax value
38+ * @param rateFactor - tax % in decimal
39+ * @param isPriceInclTax - determines if price already include tax
40+ */
41+ function createSinglePrice ( price = 0 , rateFactor = 0 , isPriceInclTax ) {
42+ const _price = isPriceInclTax ? price / ( 1 + rateFactor ) : price
43+ const tax = _price * rateFactor
44+
45+ return { price : _price , tax }
46+ }
47+
48+ /**
49+ * assign price and tax to product with proper keys
50+ * @param AssignPriceParams
51+ */
52+ function assignPrice ( { product, target, price = 0 , tax = 0 , deprecatedPriceFieldsSupport = true } ) {
53+ let priceUpdate = {
54+ [ target ] : price ,
55+ [ `${ target } _tax` ] : tax ,
56+ [ `${ target } _incl_tax` ] : price + tax
57+ }
58+
59+ if ( deprecatedPriceFieldsSupport ) {
60+ /** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
61+ priceUpdate = Object . assign ( priceUpdate , toCamelCase ( priceUpdate ) )
62+ /** END */
63+ }
64+
65+ Object . assign ( product , priceUpdate )
66+ }
67+
2368export function updateProductPrices ( { product, rate, sourcePriceInclTax = false , deprecatedPriceFieldsSupport = false , finalPriceInclTax = true } ) {
2469 const rate_factor = parseFloat ( rate . rate ) / 100
25- if ( finalPriceInclTax ) {
26- product . final_price_incl_tax = parseFloat ( product . final_price ) // final price does include tax
27- product . final_price = product . final_price_incl_tax / ( 1 + rate_factor )
28- product . final_price_tax = product . final_price_incl_tax - product . final_price
29- } else {
30- product . final_price = parseFloat ( product . final_price ) // final price does include tax
31- product . final_price_tax = product . final_price * rate_factor
32- product . final_price_incl_tax = product . final_price + product . final_price_tax
70+ const hasOriginalPrices = (
71+ product . hasOwnProperty ( 'original_price' ) &&
72+ product . hasOwnProperty ( 'original_final_price' ) &&
73+ product . hasOwnProperty ( 'original_special_price' )
74+ )
75+ // build objects with original price and tax
76+ // for first calculation use `price`, for next one use `original_price`
77+ const priceWithTax = createSinglePrice ( parseFloat ( product . original_price || product . price ) , rate_factor , sourcePriceInclTax && ! hasOriginalPrices )
78+ const finalPriceWithTax = createSinglePrice ( parseFloat ( product . original_final_price || product . final_price ) , rate_factor , finalPriceInclTax && ! hasOriginalPrices )
79+ const specialPriceWithTax = createSinglePrice ( parseFloat ( product . original_special_price || product . special_price ) , rate_factor , sourcePriceInclTax && ! hasOriginalPrices )
80+
81+ // save original prices
82+ if ( ! hasOriginalPrices ) {
83+ assignPrice ( { product, target : 'original_price' , ...priceWithTax , deprecatedPriceFieldsSupport} )
84+
85+ product . original_final_price = finalPriceWithTax . price
86+ product . original_special_price = specialPriceWithTax . price
3387 }
34- product . price = parseFloat ( product . price )
35- product . special_price = parseFloat ( product . special_price )
88+
89+ // reset previous calculation
90+ assignPrice ( { product, target : 'price' , ...priceWithTax , deprecatedPriceFieldsSupport} )
91+ assignPrice ( { product, target : 'final_price' , ...finalPriceWithTax , deprecatedPriceFieldsSupport} )
92+ assignPrice ( { product, target : 'special_price' , ...specialPriceWithTax , deprecatedPriceFieldsSupport} )
3693
3794 if ( product . final_price ) {
3895 if ( product . final_price < product . price ) { // compare the prices with the product final price if provided; final prices is used in case of active catalog promo rules for example
3996 if ( product . final_price < product . special_price ) { // for VS - special_price is any price lowered than regular price (`price`); in Magento there is a separate mechanism for setting the `special_prices`
40- product . price = product . special_price // if the `final_price` is lower than the original `special_price` - it means some catalog rules were applied over it
97+ assignPrice ( { product, target : 'price' , ... specialPriceWithTax , deprecatedPriceFieldsSupport } ) // if the `final_price` is lower than the original `special_price` - it means some catalog rules were applied over it
4198 }
42- product . special_to_date = null
43- product . special_from_date = null
44- product . special_price = product . final_price
99+ assignPrice ( { product, target : 'special_price' , ...finalPriceWithTax , deprecatedPriceFieldsSupport} )
45100 } else {
46- product . price = product . final_price
101+ assignPrice ( { product, target : 'price' , ... finalPriceWithTax , deprecatedPriceFieldsSupport } )
47102 }
48103 }
49104
50- let price_excl_tax = product . price
51- if ( sourcePriceInclTax ) {
52- price_excl_tax = product . price / ( 1 + rate_factor )
53- product . price = price_excl_tax
54- }
55-
56- product . price_tax = price_excl_tax * rate_factor
57- product . price_incl_tax = price_excl_tax + product . price_tax
58-
59- let special_price_excl_tax = product . special_price
60- if ( sourcePriceInclTax ) {
61- special_price_excl_tax = product . special_price / ( 1 + rate_factor )
62- product . special_price = special_price_excl_tax
63- }
64-
65- product . special_price_tax = special_price_excl_tax * rate_factor
66- product . special_price_incl_tax = special_price_excl_tax + product . special_price_tax
67-
68- if ( deprecatedPriceFieldsSupport ) {
69- /** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
70- product . priceTax = product . price_tax
71- product . priceInclTax = product . price_incl_tax
72- product . specialPriceTax = product . special_price_tax
73- product . specialPriceInclTax = product . special_price_incl_tax
74- /** END */
75- }
76-
77- if ( product . special_price && ( product . special_price < product . price ) ) {
105+ if ( product . special_price && ( product . special_price < product . original_price ) ) {
78106 if ( ! isSpecialPriceActive ( product . special_from_date , product . special_to_date ) ) {
79- product . special_price = 0 // out of the dates period
107+ // out of the dates period
108+ assignPrice ( { product, target : 'special_price' , price : 0 , tax : 0 , deprecatedPriceFieldsSupport} )
80109 } else {
81- product . original_price = price_excl_tax
82- product . original_price_incl_tax = product . price_incl_tax
83- product . original_price_tax = product . price_tax
84-
85- product . price = special_price_excl_tax
86- product . price_incl_tax = product . special_price_incl_tax
87- product . price_tax = product . special_price_tax
88-
89- if ( deprecatedPriceFieldsSupport ) {
90- /** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
91- product . priceInclTax = product . price_incl_tax
92- product . priceTax = product . price_tax
93- product . originalPrice = product . original_price
94- product . originalPriceInclTax = product . original_price_incl_tax
95- product . originalPriceTax = product . original_price_tax
96- /** END */
97- }
110+ assignPrice ( { product, target : 'price' , ...specialPriceWithTax , deprecatedPriceFieldsSupport} )
98111 }
99112 } else {
100- product . special_price = 0 // the same price as original; it's not a promotion
113+ // the same price as original; it's not a promotion
114+ assignPrice ( { product, target : 'special_price' , price : 0 , tax : 0 , deprecatedPriceFieldsSupport} )
101115 }
102116
103117 if ( product . configurable_children ) {
@@ -107,100 +121,25 @@ export function updateProductPrices ({ product, rate, sourcePriceInclTax = false
107121 configurableChild [ opt . attribute_code ] = opt . value
108122 }
109123 }
110- configurableChild . price = parseFloat ( configurableChild . price )
111- configurableChild . special_price = parseFloat ( configurableChild . special_price )
112- configurableChild . final_price_incl_tax = parseFloat ( configurableChild . final_price ) // final price does include tax
113- configurableChild . final_price = configurableChild . final_price_incl_tax / ( 1 + rate_factor )
114-
115- if ( configurableChild . final_price ) {
116- if ( configurableChild . final_price < configurableChild . price ) { // compare the prices with the product final price if provided; final prices is used in case of active catalog promo rules for example
117- if ( configurableChild . final_price < configurableChild . special_price ) { // for VS - special_price is any price lowered than regular price (`price`); in Magento there is a separate mechanism for setting the `special_prices`
118- configurableChild . price = configurableChild . special_price // if the `final_price` is lower than the original `special_price` - it means some catalog rules were applied over it
119- }
120- configurableChild . special_to_date = null
121- configurableChild . special_from_date = null
122- configurableChild . special_price = product . final_price
123- } else {
124- configurableChild . price = configurableChild . final_price
125- }
126- }
127-
128- let price_excl_tax = configurableChild . price
129- if ( sourcePriceInclTax ) {
130- price_excl_tax = configurableChild . price / ( 1 + rate_factor )
131- configurableChild . price = price_excl_tax
132- }
133-
134- configurableChild . price_tax = price_excl_tax * rate_factor
135- configurableChild . price_incl_tax = price_excl_tax + configurableChild . price_tax
136-
137- let special_price_excl_tax = parseFloat ( configurableChild . special_price )
138-
139- if ( sourcePriceInclTax ) {
140- special_price_excl_tax = configurableChild . special_price / ( 1 + rate_factor )
141- configurableChild . special_price = special_price_excl_tax
142- }
143124
144- configurableChild . special_price_tax = special_price_excl_tax * rate_factor
145- configurableChild . special_price_incl_tax = special_price_excl_tax + configurableChild . special_price_tax
146-
147- if ( deprecatedPriceFieldsSupport ) {
148- /** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
149- configurableChild . priceTax = configurableChild . price_tax
150- configurableChild . priceInclTax = configurableChild . price_incl_tax
151- configurableChild . specialPriceTax = configurableChild . special_price_tax
152- configurableChild . specialPriceInclTax = configurableChild . special_price_incl_tax
153- /** END */
154- }
155-
156- if ( configurableChild . special_price && ( configurableChild . special_price < configurableChild . price ) ) {
157- if ( ! isSpecialPriceActive ( configurableChild . special_from_date , configurableChild . special_to_date ) ) {
158- configurableChild . special_price = 0 // out of the dates period
159- } else {
160- configurableChild . original_price = price_excl_tax
161- configurableChild . original_price_incl_tax = configurableChild . price_incl_tax
162- configurableChild . original_price_tax = configurableChild . price_tax
163-
164- configurableChild . price = special_price_excl_tax
165- configurableChild . price_incl_tax = configurableChild . special_price_incl_tax
166- configurableChild . price_tax = configurableChild . special_price_tax
167-
168- if ( deprecatedPriceFieldsSupport ) {
169- /** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
170- configurableChild . originalPrice = configurableChild . original_price
171- configurableChild . originalPriceInclTax = configurableChild . original_price_incl_tax
172- configurableChild . originalPriceTax = configurableChild . original_price_tax
173- configurableChild . priceInclTax = configurableChild . price_incl_tax
174- configurableChild . priceTax = configurableChild . price_tax
175- /** END */
176- }
177- }
178- } else {
179- configurableChild . special_price = 0
180- }
125+ // update children prices
126+ updateProductPrices ( { product : configurableChild , rate, sourcePriceInclTax, deprecatedPriceFieldsSupport, finalPriceInclTax } )
181127
182128 if ( ( configurableChild . price_incl_tax <= product . price_incl_tax ) || product . price === 0 ) { // always show the lowest price
183- product . price_incl_tax = configurableChild . price_incl_tax
184- product . price_tax = configurableChild . price_tax
185- product . price = configurableChild . price
186- product . special_price = configurableChild . special_price
187- product . special_price_incl_tax = configurableChild . special_price_incl_tax
188- product . special_price_tax = configurableChild . special_price_tax
189- product . original_price = configurableChild . original_price
190- product . original_price_incl_tax = configurableChild . original_price_incl_tax
191- product . original_price_tax = configurableChild . original_price_tax
192-
193- if ( deprecatedPriceFieldsSupport ) {
194- /** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
195- product . priceInclTax = product . price_incl_tax
196- product . priceTax = product . price_tax
197- product . specialPriceInclTax = product . special_price_incl_tax
198- product . specialPriceTax = product . special_price_tax
199- product . originalPrice = product . original_price
200- product . originalPriceInclTax = product . original_price_incl_tax
201- product . originalPriceTax = product . original_price_tax
202- /** END */
203- }
129+ assignPrice ( {
130+ product,
131+ target : 'price' ,
132+ price : configurableChild . price ,
133+ tax : configurableChild . price_tax ,
134+ deprecatedPriceFieldsSupport
135+ } )
136+ assignPrice ( {
137+ product,
138+ target : 'special_price' ,
139+ price : configurableChild . special_price ,
140+ tax : configurableChild . special_price_tax ,
141+ deprecatedPriceFieldsSupport
142+ } )
204143 }
205144 }
206145 }
0 commit comments