Skip to content
This repository was archived by the owner on May 28, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Error responses for mailchimp - @andrzejewsky (#3337)
- Replaced function arguments to object destructuring in `calculateProductTax` - @andrzejewsky (#3337)
- Refactor `taxcalc.js` similar to frontend - @gibkigonzo (#356)

## [1.10.0] - 2019.08.12

Expand Down
8 changes: 4 additions & 4 deletions src/api/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ export default ({config, db}) => {
userApi.get('/order-history', (req, res) => {
const userProxy = _getProxy(req)
userProxy.orderHistory(
req.query.token,
req.query.pageSize || 20,
req.query.currentPage || 1
).then((result) => {
req.query.token,
req.query.pageSize || 20,
req.query.currentPage || 1
).then((result) => {
apiStatus(res, result, 200);
}).catch(err => {
apiError(res, err);
Expand Down
245 changes: 92 additions & 153 deletions src/lib/taxcalc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import camelCase from 'lodash/camelCase'

function isSpecialPriceActive (fromDate, toDate) {
if (!fromDate && !toDate) {
return true
Expand All @@ -20,84 +22,96 @@ function isSpecialPriceActive (fromDate, toDate) {
}
}

/**
* change object keys to camelCase
*/
function toCamelCase (obj = {}) {
return Object.keys(obj).reduce((accObj, currKey) => {
accObj[camelCase(currKey)] = obj[currKey]
return accObj
}, {})
}

/**
* Create price object with base price and tax
* @param price - product price which is used to extract tax value
* @param rateFactor - tax % in decimal
* @param isPriceInclTax - determines if price already include tax
*/
function createSinglePrice (price = 0, rateFactor = 0, isPriceInclTax) {
const _price = isPriceInclTax ? price / (1 + rateFactor) : price
const tax = _price * rateFactor

return { price: _price, tax }
}

/**
* assign price and tax to product with proper keys
* @param AssignPriceParams
*/
function assignPrice ({ product, target, price = 0, tax = 0, deprecatedPriceFieldsSupport = true }) {
let priceUpdate = {
[target]: price,
[`${target}_tax`]: tax,
[`${target}_incl_tax`]: price + tax
}

if (deprecatedPriceFieldsSupport) {
/** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
priceUpdate = Object.assign(priceUpdate, toCamelCase(priceUpdate))
/** END */
}

Object.assign(product, priceUpdate)
}

export function updateProductPrices ({ product, rate, sourcePriceInclTax = false, deprecatedPriceFieldsSupport = false, finalPriceInclTax = true }) {
const rate_factor = parseFloat(rate.rate) / 100
if (finalPriceInclTax) {
product.final_price_incl_tax = parseFloat(product.final_price) // final price does include tax
product.final_price = product.final_price_incl_tax / (1 + rate_factor)
product.final_price_tax = product.final_price_incl_tax - product.final_price
} else {
product.final_price = parseFloat(product.final_price) // final price does include tax
product.final_price_tax = product.final_price * rate_factor
product.final_price_incl_tax = product.final_price + product.final_price_tax
const hasOriginalPrices = (
product.hasOwnProperty('original_price') &&
product.hasOwnProperty('original_final_price') &&
product.hasOwnProperty('original_special_price')
)
// build objects with original price and tax
// for first calculation use `price`, for next one use `original_price`
const priceWithTax = createSinglePrice(parseFloat(product.original_price || product.price), rate_factor, sourcePriceInclTax && !hasOriginalPrices)
const finalPriceWithTax = createSinglePrice(parseFloat(product.original_final_price || product.final_price), rate_factor, finalPriceInclTax && !hasOriginalPrices)
const specialPriceWithTax = createSinglePrice(parseFloat(product.original_special_price || product.special_price), rate_factor, sourcePriceInclTax && !hasOriginalPrices)

// save original prices
if (!hasOriginalPrices) {
assignPrice({product, target: 'original_price', ...priceWithTax, deprecatedPriceFieldsSupport})

product.original_final_price = finalPriceWithTax.price
product.original_special_price = specialPriceWithTax.price
}
product.price = parseFloat(product.price)
product.special_price = parseFloat(product.special_price)

// reset previous calculation
assignPrice({product, target: 'price', ...priceWithTax, deprecatedPriceFieldsSupport})
assignPrice({product, target: 'final_price', ...finalPriceWithTax, deprecatedPriceFieldsSupport})
assignPrice({product, target: 'special_price', ...specialPriceWithTax, deprecatedPriceFieldsSupport})

if (product.final_price) {
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
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`
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
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
}
product.special_to_date = null
product.special_from_date = null
product.special_price = product.final_price
assignPrice({product, target: 'special_price', ...finalPriceWithTax, deprecatedPriceFieldsSupport})
} else {
product.price = product.final_price
assignPrice({product, target: 'price', ...finalPriceWithTax, deprecatedPriceFieldsSupport})
}
}

let price_excl_tax = product.price
if (sourcePriceInclTax) {
price_excl_tax = product.price / (1 + rate_factor)
product.price = price_excl_tax
}

product.price_tax = price_excl_tax * rate_factor
product.price_incl_tax = price_excl_tax + product.price_tax

let special_price_excl_tax = product.special_price
if (sourcePriceInclTax) {
special_price_excl_tax = product.special_price / (1 + rate_factor)
product.special_price = special_price_excl_tax
}

product.special_price_tax = special_price_excl_tax * rate_factor
product.special_price_incl_tax = special_price_excl_tax + product.special_price_tax

if (deprecatedPriceFieldsSupport) {
/** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
product.priceTax = product.price_tax
product.priceInclTax = product.price_incl_tax
product.specialPriceTax = product.special_price_tax
product.specialPriceInclTax = product.special_price_incl_tax
/** END */
}

if (product.special_price && (product.special_price < product.price)) {
if (product.special_price && (product.special_price < product.original_price)) {
if (!isSpecialPriceActive(product.special_from_date, product.special_to_date)) {
product.special_price = 0 // out of the dates period
// out of the dates period
assignPrice({product, target: 'special_price', price: 0, tax: 0, deprecatedPriceFieldsSupport})
} else {
product.original_price = price_excl_tax
product.original_price_incl_tax = product.price_incl_tax
product.original_price_tax = product.price_tax

product.price = special_price_excl_tax
product.price_incl_tax = product.special_price_incl_tax
product.price_tax = product.special_price_tax

if (deprecatedPriceFieldsSupport) {
/** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
product.priceInclTax = product.price_incl_tax
product.priceTax = product.price_tax
product.originalPrice = product.original_price
product.originalPriceInclTax = product.original_price_incl_tax
product.originalPriceTax = product.original_price_tax
/** END */
}
assignPrice({product, target: 'price', ...specialPriceWithTax, deprecatedPriceFieldsSupport})
}
} else {
product.special_price = 0 // the same price as original; it's not a promotion
// the same price as original; it's not a promotion
assignPrice({product, target: 'special_price', price: 0, tax: 0, deprecatedPriceFieldsSupport})
}

if (product.configurable_children) {
Expand All @@ -107,100 +121,25 @@ export function updateProductPrices ({ product, rate, sourcePriceInclTax = false
configurableChild[opt.attribute_code] = opt.value
}
}
configurableChild.price = parseFloat(configurableChild.price)
configurableChild.special_price = parseFloat(configurableChild.special_price)
configurableChild.final_price_incl_tax = parseFloat(configurableChild.final_price) // final price does include tax
configurableChild.final_price = configurableChild.final_price_incl_tax / (1 + rate_factor)

if (configurableChild.final_price) {
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
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`
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
}
configurableChild.special_to_date = null
configurableChild.special_from_date = null
configurableChild.special_price = product.final_price
} else {
configurableChild.price = configurableChild.final_price
}
}

let price_excl_tax = configurableChild.price
if (sourcePriceInclTax) {
price_excl_tax = configurableChild.price / (1 + rate_factor)
configurableChild.price = price_excl_tax
}

configurableChild.price_tax = price_excl_tax * rate_factor
configurableChild.price_incl_tax = price_excl_tax + configurableChild.price_tax

let special_price_excl_tax = parseFloat(configurableChild.special_price)

if (sourcePriceInclTax) {
special_price_excl_tax = configurableChild.special_price / (1 + rate_factor)
configurableChild.special_price = special_price_excl_tax
}

configurableChild.special_price_tax = special_price_excl_tax * rate_factor
configurableChild.special_price_incl_tax = special_price_excl_tax + configurableChild.special_price_tax

if (deprecatedPriceFieldsSupport) {
/** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
configurableChild.priceTax = configurableChild.price_tax
configurableChild.priceInclTax = configurableChild.price_incl_tax
configurableChild.specialPriceTax = configurableChild.special_price_tax
configurableChild.specialPriceInclTax = configurableChild.special_price_incl_tax
/** END */
}

if (configurableChild.special_price && (configurableChild.special_price < configurableChild.price)) {
if (!isSpecialPriceActive(configurableChild.special_from_date, configurableChild.special_to_date)) {
configurableChild.special_price = 0 // out of the dates period
} else {
configurableChild.original_price = price_excl_tax
configurableChild.original_price_incl_tax = configurableChild.price_incl_tax
configurableChild.original_price_tax = configurableChild.price_tax

configurableChild.price = special_price_excl_tax
configurableChild.price_incl_tax = configurableChild.special_price_incl_tax
configurableChild.price_tax = configurableChild.special_price_tax

if (deprecatedPriceFieldsSupport) {
/** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
configurableChild.originalPrice = configurableChild.original_price
configurableChild.originalPriceInclTax = configurableChild.original_price_incl_tax
configurableChild.originalPriceTax = configurableChild.original_price_tax
configurableChild.priceInclTax = configurableChild.price_incl_tax
configurableChild.priceTax = configurableChild.price_tax
/** END */
}
}
} else {
configurableChild.special_price = 0
}
// update children prices
updateProductPrices({ product: configurableChild, rate, sourcePriceInclTax, deprecatedPriceFieldsSupport, finalPriceInclTax })

if ((configurableChild.price_incl_tax <= product.price_incl_tax) || product.price === 0) { // always show the lowest price
product.price_incl_tax = configurableChild.price_incl_tax
product.price_tax = configurableChild.price_tax
product.price = configurableChild.price
product.special_price = configurableChild.special_price
product.special_price_incl_tax = configurableChild.special_price_incl_tax
product.special_price_tax = configurableChild.special_price_tax
product.original_price = configurableChild.original_price
product.original_price_incl_tax = configurableChild.original_price_incl_tax
product.original_price_tax = configurableChild.original_price_tax

if (deprecatedPriceFieldsSupport) {
/** BEGIN @deprecated - inconsitent naming kept just for the backward compatibility */
product.priceInclTax = product.price_incl_tax
product.priceTax = product.price_tax
product.specialPriceInclTax = product.special_price_incl_tax
product.specialPriceTax = product.special_price_tax
product.originalPrice = product.original_price
product.originalPriceInclTax = product.original_price_incl_tax
product.originalPriceTax = product.original_price_tax
/** END */
}
assignPrice({
product,
target: 'price',
price: configurableChild.price,
tax: configurableChild.price_tax,
deprecatedPriceFieldsSupport
})
assignPrice({
product,
target: 'special_price',
price: configurableChild.special_price,
tax: configurableChild.special_price_tax,
deprecatedPriceFieldsSupport
})
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/platform/magento2/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class UserProxy extends AbstractUserProxy {

return this.api.customers.me(requestToken)
}
orderHistory (requestToken, pageSize = 20, currentPage = 1) {
orderHistory (requestToken, pageSize = 20, currentPage = 1) {
return this.api.customers.orderHistory(requestToken, pageSize, currentPage)
}
resetPassword (emailData) {
Expand Down