Skip to content
This repository was archived by the owner on May 28, 2023. It is now read-only.

Commit 0b82cbe

Browse files
authored
Merge pull request #356 from gibkigonzo/feature/refactor-taxcalc
refactor taxcalc similar to frontend
2 parents abc618c + f10e525 commit 0b82cbe

File tree

4 files changed

+98
-158
lines changed

4 files changed

+98
-158
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
### Changed
2626
- Error responses for mailchimp - @andrzejewsky (#3337)
2727
- Replaced function arguments to object destructuring in `calculateProductTax` - @andrzejewsky (#3337)
28+
- Refactor `taxcalc.js` similar to frontend - @gibkigonzo (#356)
2829

2930
## [1.10.0] - 2019.08.12
3031

src/api/user.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,10 @@ export default ({config, db}) => {
150150
userApi.get('/order-history', (req, res) => {
151151
const userProxy = _getProxy(req)
152152
userProxy.orderHistory(
153-
req.query.token,
154-
req.query.pageSize || 20,
155-
req.query.currentPage || 1
156-
).then((result) => {
153+
req.query.token,
154+
req.query.pageSize || 20,
155+
req.query.currentPage || 1
156+
).then((result) => {
157157
apiStatus(res, result, 200);
158158
}).catch(err => {
159159
apiError(res, err);

src/lib/taxcalc.js

Lines changed: 92 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import camelCase from 'lodash/camelCase'
2+
13
function 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+
2368
export 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
}

src/platform/magento2/user.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class UserProxy extends AbstractUserProxy {
2121

2222
return this.api.customers.me(requestToken)
2323
}
24-
orderHistory (requestToken, pageSize = 20, currentPage = 1) {
24+
orderHistory (requestToken, pageSize = 20, currentPage = 1) {
2525
return this.api.customers.orderHistory(requestToken, pageSize, currentPage)
2626
}
2727
resetPassword (emailData) {

0 commit comments

Comments
 (0)