I have written some functions to calculate the total cost of an invoice, gives its line items. Could someone please tell me if there seems to be a problem with the code. Since? Since it is something as serious as handling people's money, I need to be extra careful. I used Big.js to make sure that I do not get any of the JS weird-nessweirdness when it comes to arithmetical operations, but I am still unsure if I am doing it right.
Please take into account that the values in unitPriceunitPrice
in cents, and tax rates as integers. That means that a price of $12.34 would be saved as 1234, and a tax of 19% would be saved as 19.
const calculateItemUnitTotal = (item) => {
const unitPrice = new Big(item.unitPrice || 0);
const taxRate = new Big(item.taxRate || 0).div(100);
const total = unitPrice.times(taxRate.plus(1));
const final = total.round(0, Big.roundHalfUp).toNumber(); // Round to nearest integer (cents)
return final;
};
const calculateItemTotal = (item) => {
const quantity = new Big(item.quantity || 0);
const unitTotal = new Big(calculateItemUnitTotal(item));
const total = quantity.times(unitTotal);
const final = total.round(0, Big.roundHalfUp).toNumber(); // Round to nearest integer (cents)
return final;
};
const calculateItemSubTotal = (item) => {
const quantity = new Big(item.quantity || 0);
const unitPrice = new Big(item.unitPrice || 0);
const subTotal = quantity.times(unitPrice);
return subTotal.round(0, Big.roundHalfUp).toNumber(); // Round to nearest integer (cents)
};
const calculateInvoiceSubtotal = (lineItems) => {
if (!Array.isArray(lineItems)) return 0;
const total = lineItems?.reduce((acc, item) => {
const itemTotal = new Big(calculateItemSubTotal(item));
return acc.plus(itemTotal);
}, new Big(0));
return total.round(0, Big.roundHalfUp).toNumber(); // Round to nearest integer (cents)
};
const calculateInvoiceTotal = (lineItems) => {
if (!Array.isArray(lineItems)) return 0;
const total = lineItems?.reduce((acc, item) => {
const itemTotal = new Big(calculateItemTotal(item));
return acc.plus(itemTotal);
}, new Big(0));
const final = total.round(0, Big.roundHalfUp).toNumber(); // Round to nearest integer (cents)
return final;
```