Skip to content
This repository was archived by the owner on Sep 8, 2021. It is now read-only.

Commit c263fbf

Browse files
committed
Fix rounding issue in tax calculationsg
1 parent d3d5c5e commit c263fbf

File tree

2 files changed

+201
-401
lines changed

2 files changed

+201
-401
lines changed

src/calculator.js

+115-65
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {checkClaims} from './claims';
1+
import { checkClaims } from "./claims";
22

33
class Price {
44
constructor() {
@@ -42,29 +42,30 @@ function couponValidFor(claims, coupon, item) {
4242
}
4343

4444
function fixedAmount(amounts, currency) {
45-
const fixed = amounts && amounts.filter((amount) => amount.currency === currency)[0];
45+
const fixed =
46+
amounts && amounts.filter(amount => amount.currency === currency)[0];
4647
return (fixed && Math.round(parseFloat(fixed.amount) * 100)) || 0;
4748
}
4849

4950
function discountItem(type, percentage = 0, fixed = 0) {
5051
return {
5152
type,
5253
percentage,
53-
fixed,
54+
fixed
5455
};
5556
}
5657

5758
function calculateDiscount(amountToDiscount, percentage = 0, fixed = 0) {
5859
let discount = 0;
59-
if (percentage > 0) {
60-
discount = Math.round(amountToDiscount * percentage / 100);
61-
}
62-
discount += fixed;
63-
64-
if (discount > amountToDiscount) {
65-
return amountToDiscount;
66-
}
67-
return discount;
60+
if (percentage > 0) {
61+
discount = Math.round((amountToDiscount * percentage) / 100);
62+
}
63+
discount += fixed;
64+
65+
if (discount > amountToDiscount) {
66+
return amountToDiscount;
67+
}
68+
return discount;
6869
}
6970

7071
function calculateTaxes(amountToTax, originalPrice, item, settings, country) {
@@ -73,90 +74,139 @@ function calculateTaxes(amountToTax, originalPrice, item, settings, country) {
7374

7475
const taxAmounts = [];
7576
if (item.vat) {
76-
taxAmounts.push({price: amountToTax, percentage: parseInt(item.vat, 10)});
77+
taxAmounts.push({ price: amountToTax, percentage: parseInt(item.vat, 10) });
7778
} else if (settings && item.price.items && item.price.items.length) {
78-
item.price.items.forEach((priceItem) => {
79+
item.price.items.forEach(priceItem => {
7980
const realPrice = priceItem.cents * ratio;
8081
const tax = findTax(settings, country, priceItem.type);
81-
taxAmounts.push({price: realPrice, percentage: tax ? tax.percentage : 0});
82+
taxAmounts.push({
83+
price: Math.round(realPrice),
84+
percentage: tax ? tax.percentage : 0
85+
});
8286
});
8387
} else {
8488
const tax = findTax(settings, country, item.type);
8589
if (tax) {
86-
taxAmounts.push({price: amountToTax, percentage: tax.percentage});
90+
taxAmounts.push({ price: amountToTax, percentage: tax.percentage });
8791
}
8892
}
8993

94+
console.log("Calculating taxes: ", includeTaxes, ratio, taxAmounts);
95+
9096
let taxes = 0;
9197
let netTotal = 0;
9298
if (taxAmounts.length) {
93-
taxAmounts.forEach((tax) => {
99+
taxAmounts.forEach(tax => {
94100
if (includeTaxes) {
95-
tax.price = Math.round(tax.price / (100 + tax.percentage) * 100);
101+
tax.price = Math.round((tax.price / (100 + tax.percentage)) * 100);
96102
}
97103
netTotal += tax.price;
98-
taxes += Math.round(tax.price * tax.percentage / 100);
104+
taxes += Math.round((tax.price * tax.percentage) / 100);
99105
});
100106
} else {
101107
netTotal = amountToTax;
102108
}
103109

104110
return {
105111
taxes,
106-
netTotal,
112+
netTotal
107113
};
108114
}
109115

110-
111-
export function calculatePrices(settings, claims, country, currency, coupon, items) {
116+
export function calculatePrices(
117+
settings,
118+
claims,
119+
country,
120+
currency,
121+
coupon,
122+
items
123+
) {
124+
console.log("Calculating price for item");
112125
const price = new Price();
113126
price.items = [];
114-
items && items.forEach((item) => {
115-
const itemPrice = new Price();
116-
itemPrice.quantity = item.quantity || 1;
127+
items &&
128+
items.forEach(item => {
129+
const itemPrice = new Price();
130+
itemPrice.quantity = item.quantity || 1;
131+
132+
const originalPrice =
133+
item.price.cents + (item.addonPrice ? item.addonPrice.cents : 0);
134+
const { netTotal: subtotal } = calculateTaxes(
135+
originalPrice,
136+
originalPrice,
137+
item,
138+
settings,
139+
country
140+
);
141+
itemPrice.subtotal = subtotal;
142+
143+
if (coupon && couponValidFor(claims, coupon, item)) {
144+
itemPrice.discount = calculateDiscount(
145+
originalPrice,
146+
coupon.percentage,
147+
fixedAmount(coupon.fixed, currency)
148+
);
149+
itemPrice.couponDiscount = itemPrice.discount;
150+
itemPrice.discountItems.push(
151+
discountItem(
152+
"coupon",
153+
coupon.percentage,
154+
fixedAmount(coupon.fixed, currency)
155+
)
156+
);
157+
}
158+
if (settings && settings.member_discounts) {
159+
console.log("Adding member discounts");
160+
settings.member_discounts.forEach(discount => {
161+
if (couponValidFor(claims, discount, item)) {
162+
const memberDiscount = calculateDiscount(
163+
originalPrice,
164+
discount.percentage,
165+
fixedAmount(discount.fixed, currency)
166+
);
167+
console.log("Calculated discounts to be: ", memberDiscount);
168+
console.log("itemPrice before: ", itemPrice);
169+
itemPrice.discount = itemPrice.discount || 0;
170+
itemPrice.discount += memberDiscount;
171+
itemPrice.memberDiscount = itemPrice.memberDiscount || 0;
172+
itemPrice.memberDiscount += memberDiscount;
173+
itemPrice.discountItems.push(
174+
discountItem(
175+
"member",
176+
discount.percentage,
177+
fixedAmount(discount.fixed, currency)
178+
)
179+
);
180+
console.log("itemPrice after: ", itemPrice);
181+
}
182+
});
183+
}
117184

118-
const originalPrice = item.price.cents + (item.addonPrice ? item.addonPrice.cents : 0);
119-
const { netTotal: subtotal } = calculateTaxes(originalPrice, originalPrice, item, settings, country);
120-
itemPrice.subtotal = subtotal;
185+
const discountedPrice = Math.max(0, originalPrice - itemPrice.discount);
186+
console.log("Discounted price before taxes: ", discountedPrice);
121187

122-
if (coupon && couponValidFor(claims, coupon, item)) {
123-
itemPrice.discount = calculateDiscount(
124-
originalPrice, coupon.percentage, fixedAmount(coupon.fixed, currency)
188+
const { taxes, netTotal } = calculateTaxes(
189+
discountedPrice,
190+
originalPrice,
191+
item,
192+
settings,
193+
country
125194
);
126-
itemPrice.couponDiscount = itemPrice.discount;
127-
itemPrice.discountItems.push(discountItem("coupon", coupon.percentage, fixedAmount(coupon.fixed, currency)))
128-
}
129-
if (settings && settings.member_discounts) {
130-
settings.member_discounts.forEach((discount) => {
131-
if (couponValidFor(claims, discount, item)) {
132-
const memberDiscount = calculateDiscount(
133-
originalPrice, discount.percentage, fixedAmount(discount.fixed, currency)
134-
);
135-
itemPrice.discount = itemPrice.discount || 0;
136-
itemPrice.discount += memberDiscount;
137-
itemPrice.memberDiscount = itemPrice.memberDiscount || 0;
138-
itemPrice.memberDiscount += memberDiscount;
139-
itemPrice.discountItems.push(discountItem("member", discount.percentage, fixedAmount(discount.fixed, currency)))
140-
}
141-
});
142-
}
143-
144-
const discountedPrice = Math.max(0, originalPrice - itemPrice.discount);
145-
146-
const { taxes, netTotal } = calculateTaxes(discountedPrice, originalPrice, item, settings, country);
147-
itemPrice.taxes = taxes;
148-
itemPrice.netTotal = netTotal;
149-
itemPrice.total = itemPrice.netTotal + itemPrice.taxes;
150-
price.items.push(itemPrice);
151-
152-
price.subtotal += (itemPrice.subtotal * itemPrice.quantity);
153-
price.discount += (itemPrice.discount * itemPrice.quantity);
154-
price.couponDiscount += (itemPrice.couponDiscount * itemPrice.quantity);
155-
price.memberDiscount += (itemPrice.memberDiscount * itemPrice.quantity);
156-
price.netTotal += (itemPrice.netTotal * itemPrice.quantity);
157-
price.taxes += (itemPrice.taxes * itemPrice.quantity);
158-
price.total += (itemPrice.total * itemPrice.quantity);
159-
});
195+
console.log("Calculated taxes: ", taxes, netTotal);
196+
itemPrice.taxes = taxes;
197+
itemPrice.netTotal = netTotal;
198+
itemPrice.total = itemPrice.netTotal + itemPrice.taxes;
199+
console.log("Final item price: ", itemPrice);
200+
price.items.push(itemPrice);
201+
202+
price.subtotal += itemPrice.subtotal * itemPrice.quantity;
203+
price.discount += itemPrice.discount * itemPrice.quantity;
204+
price.couponDiscount += itemPrice.couponDiscount * itemPrice.quantity;
205+
price.memberDiscount += itemPrice.memberDiscount * itemPrice.quantity;
206+
price.netTotal += itemPrice.netTotal * itemPrice.quantity;
207+
price.taxes += itemPrice.taxes * itemPrice.quantity;
208+
price.total += itemPrice.total * itemPrice.quantity;
209+
});
160210

161211
return price;
162212
}

0 commit comments

Comments
 (0)