Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/billing/lib/clients/orb/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export function orbAmountToCents(amount: string | null | undefined): number | nu

// Groups 2 and 3 are guaranteed by the pattern, but `noUncheckedIndexedAccess` can't see that.
const whole = match[2] ?? '0';
// Some invoices carry more than two decimals; the extra digits are dropped, not rounded.
const fraction = match[3] ?? '';
const cents = Number(whole) * 100 + Number(fraction.padEnd(2, '0').slice(0, 2));
const fraction = (match[3] ?? '').padEnd(3, '0');
const roundsUp = Number(fraction[2]) >= 5;
const cents = Number(whole) * 100 + Number(fraction.slice(0, 2)) + (roundsUp ? 1 : 0);
return match[1] === '-' ? -cents : cents;
}

Expand Down
12 changes: 10 additions & 2 deletions packages/billing/lib/clients/orb/adapters.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,21 @@ describe('orbAmountToCents', () => {
expect(orbAmountToCents('100')).toBe(10000);
});

it('drops sub-cent precision rather than rounding up', () => {
it('rounds sub-cent precision half-up', () => {
// Orb's costs endpoint answers in full float precision. This is a real value from it.
expect(orbAmountToCents('0.01999999999999999872')).toBe(2);
expect(orbAmountToCents('19.9900000000')).toBe(1999);
expect(orbAmountToCents('19.999')).toBe(1999);
expect(orbAmountToCents('19.994')).toBe(1999);
expect(orbAmountToCents('19.995')).toBe(2000);
expect(orbAmountToCents('19.9')).toBe(1990);
expect(orbAmountToCents('19.')).toBe(1900);
});

it('carries the rounding into the whole part', () => {
expect(orbAmountToCents('0.999')).toBe(100);
expect(orbAmountToCents('1.999')).toBe(200);
});

it('handles negative amounts', () => {
expect(orbAmountToCents('-5.00')).toBe(-500);
});
Expand Down
Loading