Skip to content

Commit

Permalink
fix: price calculation (#774)
Browse files Browse the repository at this point in the history
  • Loading branch information
leoslr committed Feb 16, 2022
1 parent c047df3 commit 6773e0c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 19 deletions.
35 changes: 16 additions & 19 deletions packages/data-format/src/format/rnf_invoice/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BigNumber } from 'ethers';
import { BigNumber, FixedNumber } from 'ethers';
import { Invoice, InvoiceItem } from './types';

export const getInvoiceTotal = (invoice: Invoice): BigNumber => {
Expand All @@ -9,11 +9,6 @@ export const getInvoiceTotal = (invoice: Invoice): BigNumber => {
};

export const getInvoiceLineTotal = (item: InvoiceItem): BigNumber => {
// Every amount in currency is a big number with the good number of decimals for this currency
// Tax percent is not an amount in currency. To allow a big number multiplication, we convert
// it temporarily with preciselyOne (allows 6 decimals, ie 0.123456%)
const preciselyOne = 1000000;

// Support for rnf_version < 0.0.3
const tax = item.taxPercent
? { type: 'percentage', amount: String(item.taxPercent) }
Expand All @@ -24,18 +19,20 @@ export const getInvoiceLineTotal = (item: InvoiceItem): BigNumber => {
tax.amount && tax.type === 'fixed' ? BigNumber.from(tax.amount) : BigNumber.from(0);
const discount = item.discount ? BigNumber.from(item.discount) : BigNumber.from(0);

return (
BigNumber.from(item.unitPrice)
// account for floating quantities
.mul(Number(item.quantity * preciselyOne).toFixed(0))
.div(preciselyOne)
.sub(discount)
// Artificially offset the decimal to let the multiplication work
.mul(Number(taxPercent * preciselyOne).toFixed(0))
// Remove the decimal offset
.div(preciselyOne)
// Remove the percentage multiplier
.div(100)
.add(taxFixed)
return BigNumber.from(
// Removes the resulting decimal (.0)
Number(
FixedNumber.from(item.unitPrice)
// accounts for floating quantities
.mulUnsafe(FixedNumber.fromString(item.quantity.toString()))
.subUnsafe(FixedNumber.from(discount))
// accounts for floating taxes
.mulUnsafe(FixedNumber.fromString(taxPercent.toString()))
// Removes the percentage multiplier
.divUnsafe(FixedNumber.from(100))
.addUnsafe(FixedNumber.from(taxFixed))
.round(0)
.toString(),
),
);
};
18 changes: 18 additions & 0 deletions packages/data-format/test/rnf_invoice/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,22 @@ describe('getInvoiceTotal', () => {
}).toString(),
).toEqual('1515165');
});

it('rounds the total correctly', () => {
expect(
getInvoiceTotal({
...baseInvoice,
invoiceItems: [
{
...baseInvoiceItem,
unitPrice: '3333',
tax: {
type: 'percentage',
amount: '20',
},
},
],
}).toString(),
).toEqual('4000');
});
});

0 comments on commit 6773e0c

Please sign in to comment.