unit tests
The whole point of the OP code is to compute different results than FP would, a subtle difference that is challenging to see when just eyeballing some source code. This would have been stronger submission if accompanied by an automated test suite. As written, you are asking "did I follow a Big invocation pattern?" rather than "did I get the result correct down to the penny?"
specification
The OP code does not tell us the magnitudes it is expected to correctly operate upon, e.g. should this get the U.S. national debt correct to the penny?
In the Review Context you helpfully explain that only integer tax rates shall be supported, e.g. 19%. But assuming that "tax" describes what real world tax collection agencies levy, this is a rather surprising constraint, one worth commenting on so we understand where it comes from. A more usual requirement would be "tax rate shall be a rational number, with a power of ten in the denominator", ruling out e.g. a troublesome two-thirds of a percent rate.
contract
In calculateInvoiceSubtotal
and calculateInvoiceTotal
,
caller has a clear
responsibility
to pass in an invoice datastructure.
If they don't, it would be better to throw a fatal Exception
than to erroneously claim it was an empty invoice worth
zero dollars.
Then folks will notice the buggy caller and fix the code,
rather than silently accepting incorrect results.
consistently use same rounding mode
const final = total.round(0, Big.roundHalfUp)...
const final = total.round(0, Big.roundHalfUp)...
return subTotal.round(0, Big.roundHalfUp)...
return total.round(0, Big.roundHalfUp)...
const final = total.round(0, Big.roundHalfUp)...
The documentation explains that
... the rounding mode used to round the results of these methods is determined by the value of the ... RM propert[y] of the Big number constructor.
Big.RM = Big.roundHalfUp
Even if you chose not to set the RM
,
all those copy-pasta code fragments plus comment
would belong in a roundToCents()
helper.