Repository navigation
fix(invoice): count on from an invoice number of more than 15 digits - #448
Merged
anurag629 merged 1 commit intoOct 31, 2026
Merged
Conversation
…osing digits (codercops#445) nextInvoiceNumber() read the trailing digits with parseInt and wrote value + 1 back as a JS number, so a number of more than 15 digits lost precision (a 17-digit number came back one lower) and one of 22 digits or more was printed as 1e+22. It now uses BigInt, and keeps the prefix and the zero-padding.
anurag629
approved these changes
Oct 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
nextInvoiceNumber()now counts on from a number of any length. Before, a number of more than 15 digits lost precision and the next one could come back lower than the one before.Closes #445
Cause
nextInvoiceNumber()(lib/invoice-types.ts) read the trailing digits withparseInt(match[2], 10)and wroteString(highest.value + 1)back. That is a JavaScript number, which holds a whole number exactly only up to 2^53 (16 digits at most, and 15 to be safe). So:20261031143012345(a timestamp with milliseconds) gave20261031143012344, one lower.INV-9007199254740993gaveINV-9007199254740992.INV-9999999999999999999999(22 digits) gaveINV-000000000000000001e+22.The "New invoice" and "Duplicate" buttons both call it, so the number field would show one of those.
What changed
BigInt:BigInt(match[2])picks the highest (same rule as before, the later one wins a tie), andString(highest.value + BigInt(1))is padded to the same width as before. The prefix and zero-padding rules from Invoice generator: the next number addsINVto plain numbers and changes the padding #220 are untouched. I wroteBigInt(1)and not1n, sincetsconfigtargets ES2017, the same aslib/time-difference.tsdoes.How I Tested This
lib/__tests__/invoice-types.test.tsfirst, and 7 of the new ones failed on the old code:20261031143012345,INV-9007199254740993,INV-9007199254740992, the 22-digitINV-9999999999999999999999, a 29-digit number, the pick of the highest between numbers a JS number can't tell apart (in both orders, and with three long numbers one of which is zero-padded), and a 40-digit number of nines giving1followed by 40 zeros. The other new ones are guards that passed before as well: a 20-digit number whose old result happened to be right, and zero-padded long numbers with a small value (INV-0000000000000000000007,2026-00000000000000000099).parseInt, adding with a JS number, no padding, the first number always winning, the lowest winning); a test fails for each.npx tsc --noEmitis clean, lint is atdevelop's 11 warnings, and all 2,534 tests pass (the existing invoice number tests from Invoice generator: the next number addsINVto plain numbers and changes the padding #220 included).next buildhere, so CI will be the first to build it.BigIntis already used inlib/time-difference.ts, so it is in the supported browsers.AI assistance
An AI coding assistant helped write the fix and the tests. I ran the checks listed above.