Files
einvoice/test/test.currency-utils.ts

128 lines
4.5 KiB
TypeScript
Raw Normal View History

import { tap, expect } from '@git.zone/tstest/tapbundle';
import {
getCurrencyMinorUnits,
roundToCurrency,
getCurrencyTolerance,
areMonetaryValuesEqual,
CurrencyCalculator,
RoundingMode
} from '../ts/formats/utils/currency.utils.js';
tap.test('Currency Utils - should handle different currency decimal places', async () => {
// Standard 2 decimal currencies
expect(getCurrencyMinorUnits('EUR')).toEqual(2);
expect(getCurrencyMinorUnits('USD')).toEqual(2);
expect(getCurrencyMinorUnits('GBP')).toEqual(2);
// Zero decimal currencies
expect(getCurrencyMinorUnits('JPY')).toEqual(0);
expect(getCurrencyMinorUnits('KRW')).toEqual(0);
// Three decimal currencies
expect(getCurrencyMinorUnits('KWD')).toEqual(3);
expect(getCurrencyMinorUnits('TND')).toEqual(3);
// Unknown currency defaults to 2
expect(getCurrencyMinorUnits('XXX')).toEqual(2);
});
tap.test('Currency Utils - should round values correctly', async () => {
// EUR - 2 decimals
expect(roundToCurrency(10.234, 'EUR')).toEqual(10.23);
expect(roundToCurrency(10.235, 'EUR')).toEqual(10.24); // Half-up
expect(roundToCurrency(10.236, 'EUR')).toEqual(10.24);
// JPY - 0 decimals
expect(roundToCurrency(1234.56, 'JPY')).toEqual(1235);
expect(roundToCurrency(1234.49, 'JPY')).toEqual(1234);
// KWD - 3 decimals
expect(roundToCurrency(10.2345, 'KWD')).toEqual(10.235); // Half-up
expect(roundToCurrency(10.2344, 'KWD')).toEqual(10.234);
});
tap.test('Currency Utils - should use different rounding modes', async () => {
const value = 10.235;
// Half-up (default)
expect(roundToCurrency(value, 'EUR', RoundingMode.HALF_UP)).toEqual(10.24);
// Half-down
expect(roundToCurrency(value, 'EUR', RoundingMode.HALF_DOWN)).toEqual(10.23);
// Half-even (banker's rounding)
expect(roundToCurrency(10.235, 'EUR', RoundingMode.HALF_EVEN)).toEqual(10.24); // 23 is odd, round up
expect(roundToCurrency(10.245, 'EUR', RoundingMode.HALF_EVEN)).toEqual(10.24); // 24 is even, round down
// Always up
expect(roundToCurrency(10.231, 'EUR', RoundingMode.UP)).toEqual(10.24);
// Always down (truncate)
expect(roundToCurrency(10.239, 'EUR', RoundingMode.DOWN)).toEqual(10.23);
});
tap.test('Currency Utils - should calculate correct tolerance', async () => {
// EUR - tolerance is 0.005 (half of 0.01)
expect(getCurrencyTolerance('EUR')).toEqual(0.005);
// JPY - tolerance is 0.5 (half of 1)
expect(getCurrencyTolerance('JPY')).toEqual(0.5);
// KWD - tolerance is 0.0005 (half of 0.001)
expect(getCurrencyTolerance('KWD')).toEqual(0.0005);
});
tap.test('Currency Utils - should compare monetary values with tolerance', async () => {
// EUR comparisons
expect(areMonetaryValuesEqual(10.23, 10.234, 'EUR')).toEqual(true); // Within tolerance
expect(areMonetaryValuesEqual(10.23, 10.236, 'EUR')).toEqual(false); // Outside tolerance
// JPY comparisons
expect(areMonetaryValuesEqual(1234, 1234.4, 'JPY')).toEqual(true); // Within tolerance
expect(areMonetaryValuesEqual(1234, 1235, 'JPY')).toEqual(false); // Outside tolerance
// KWD comparisons
expect(areMonetaryValuesEqual(10.234, 10.2344, 'KWD')).toEqual(true); // Within tolerance
expect(areMonetaryValuesEqual(10.234, 10.235, 'KWD')).toEqual(false); // Outside tolerance
});
tap.test('CurrencyCalculator - should perform EN16931 calculations', async () => {
// EUR calculator
const eurCalc = new CurrencyCalculator('EUR');
// Line net calculation
const lineNet = eurCalc.calculateLineNet(5, 19.99, 2.50);
expect(lineNet).toEqual(97.45); // (5 * 19.99) - 2.50 = 97.45
// VAT calculation
const vat = eurCalc.calculateVAT(100, 19);
expect(vat).toEqual(19.00);
// JPY calculator (no decimals)
const jpyCalc = new CurrencyCalculator('JPY');
const jpyLineNet = jpyCalc.calculateLineNet(3, 1234.56);
expect(jpyLineNet).toEqual(3704); // Rounded to no decimals
const jpyVat = jpyCalc.calculateVAT(10000, 8);
expect(jpyVat).toEqual(800);
});
tap.test('CurrencyCalculator - should handle edge cases', async () => {
const calc = new CurrencyCalculator('EUR');
// Rounding at exact midpoint
expect(calc.round(10.235)).toEqual(10.24); // Half-up
expect(calc.round(10.245)).toEqual(10.25); // Half-up
// Very small values
expect(calc.round(0.001)).toEqual(0.00);
expect(calc.round(0.004)).toEqual(0.00);
expect(calc.round(0.005)).toEqual(0.01);
// Negative values
expect(calc.round(-10.234)).toEqual(-10.23);
expect(calc.round(-10.235)).toEqual(-10.24);
});
tap.start();