From aa4be9e61984816836cbf388a17329186c5f0259 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Thu, 30 May 2024 11:11:27 +0800 Subject: [PATCH 1/8] always convert the amount to cent --- src/libs/MoneyRequestUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/MoneyRequestUtils.ts b/src/libs/MoneyRequestUtils.ts index 1d55c0f49356..44c9bf7a2161 100644 --- a/src/libs/MoneyRequestUtils.ts +++ b/src/libs/MoneyRequestUtils.ts @@ -40,10 +40,10 @@ function addLeadingZero(amount: string): string { /** * Calculate the length of the amount with leading zeroes */ -function calculateAmountLength(amount: string, decimals: number): number { +function calculateAmountLength(amount: string): number { const leadingZeroes = amount.match(/^0+/); const leadingZeroesLength = leadingZeroes?.[0]?.length ?? 0; - const absAmount = parseFloat((Number(stripCommaFromAmount(amount)) * 10 ** decimals).toFixed(2)).toString(); + const absAmount = parseFloat((Number(stripCommaFromAmount(amount)) * 100).toFixed(2)).toString(); if (/\D/.test(absAmount)) { return CONST.IOU.AMOUNT_MAX_LENGTH + 1; @@ -61,7 +61,7 @@ function validateAmount(amount: string, decimals: number, amountMaxLength: numbe ? `^\\d+(,\\d*)*$` // Don't allow decimal point if decimals === 0 : `^\\d+(,\\d*)*(\\.\\d{0,${decimals}})?$`; // Allow the decimal point and the desired number of digits after the point const decimalNumberRegex = new RegExp(regexString, 'i'); - return amount === '' || (decimalNumberRegex.test(amount) && calculateAmountLength(amount, decimals) <= amountMaxLength); + return amount === '' || (decimalNumberRegex.test(amount) && calculateAmountLength(amount) <= amountMaxLength); } /** From 08e85dc299a94e8fe71fc3448a91bc8dc7509040 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Thu, 30 May 2024 11:12:04 +0800 Subject: [PATCH 2/8] don't allow NaN, Infinity, and number with scientific notation --- src/libs/MoneyRequestUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/MoneyRequestUtils.ts b/src/libs/MoneyRequestUtils.ts index 44c9bf7a2161..db11b7db9adb 100644 --- a/src/libs/MoneyRequestUtils.ts +++ b/src/libs/MoneyRequestUtils.ts @@ -45,7 +45,8 @@ function calculateAmountLength(amount: string): number { const leadingZeroesLength = leadingZeroes?.[0]?.length ?? 0; const absAmount = parseFloat((Number(stripCommaFromAmount(amount)) * 100).toFixed(2)).toString(); - if (/\D/.test(absAmount)) { + // Don't allow the amount if the parsing to number results in NaN, Infinity, or with a scientific notation (e.g., 1e+26) + if (/NaN|Infinity|e\+/.test(absAmount)) { return CONST.IOU.AMOUNT_MAX_LENGTH + 1; } From 6319c887347c742aa92b612b736974cbb15e4de9 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Thu, 30 May 2024 11:29:24 +0800 Subject: [PATCH 3/8] remove dot when calculating the length --- src/libs/MoneyRequestUtils.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libs/MoneyRequestUtils.ts b/src/libs/MoneyRequestUtils.ts index db11b7db9adb..e476f02e3075 100644 --- a/src/libs/MoneyRequestUtils.ts +++ b/src/libs/MoneyRequestUtils.ts @@ -10,6 +10,13 @@ function stripCommaFromAmount(amount: string): string { return amount.replace(/,/g, ''); } +/** + * Strip dot from the amount + */ +function stripDotFromAmount(amount: string): string { + return amount.replace(/\./g, ''); +} + /** * Strip spaces from the amount */ @@ -50,7 +57,7 @@ function calculateAmountLength(amount: string): number { return CONST.IOU.AMOUNT_MAX_LENGTH + 1; } - return leadingZeroesLength + (absAmount === '0' ? 2 : absAmount.length); + return leadingZeroesLength + (absAmount === '0' ? 2 : stripDotFromAmount(absAmount).length); } /** From 261d3074cfe905131b71ada556a18a9265395b02 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 3 Jun 2024 11:46:55 +0800 Subject: [PATCH 4/8] refactor max amount digit logic --- src/CONST.ts | 2 +- src/libs/MoneyRequestUtils.ts | 22 +++---------------- src/pages/workspace/taxes/ValuePage.tsx | 2 +- .../taxes/WorkspaceCreateTaxPage.tsx | 2 +- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 4f622cc0b3bf..a8101a7c64db 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1571,7 +1571,7 @@ const CONST = { APPROVE: 'approve', TRACK: 'track', }, - AMOUNT_MAX_LENGTH: 10, + AMOUNT_MAX_LENGTH: 8, RECEIPT_STATE: { SCANREADY: 'SCANREADY', OPEN: 'OPEN', diff --git a/src/libs/MoneyRequestUtils.ts b/src/libs/MoneyRequestUtils.ts index e476f02e3075..5999ce2dcbcf 100644 --- a/src/libs/MoneyRequestUtils.ts +++ b/src/libs/MoneyRequestUtils.ts @@ -44,32 +44,16 @@ function addLeadingZero(amount: string): string { return amount.startsWith('.') ? `0${amount}` : amount; } -/** - * Calculate the length of the amount with leading zeroes - */ -function calculateAmountLength(amount: string): number { - const leadingZeroes = amount.match(/^0+/); - const leadingZeroesLength = leadingZeroes?.[0]?.length ?? 0; - const absAmount = parseFloat((Number(stripCommaFromAmount(amount)) * 100).toFixed(2)).toString(); - - // Don't allow the amount if the parsing to number results in NaN, Infinity, or with a scientific notation (e.g., 1e+26) - if (/NaN|Infinity|e\+/.test(absAmount)) { - return CONST.IOU.AMOUNT_MAX_LENGTH + 1; - } - - return leadingZeroesLength + (absAmount === '0' ? 2 : stripDotFromAmount(absAmount).length); -} - /** * Check if amount is a decimal up to 3 digits */ function validateAmount(amount: string, decimals: number, amountMaxLength: number = CONST.IOU.AMOUNT_MAX_LENGTH): boolean { const regexString = decimals === 0 - ? `^\\d+(,\\d*)*$` // Don't allow decimal point if decimals === 0 - : `^\\d+(,\\d*)*(\\.\\d{0,${decimals}})?$`; // Allow the decimal point and the desired number of digits after the point + ? `^\\d{1,${amountMaxLength}}$` // Don't allow decimal point if decimals === 0 + : `^\\d{1,${amountMaxLength}}(\\.\\d{0,${decimals}})?$`; // Allow the decimal point and the desired number of digits after the point const decimalNumberRegex = new RegExp(regexString, 'i'); - return amount === '' || (decimalNumberRegex.test(amount) && calculateAmountLength(amount) <= amountMaxLength); + return amount === '' || decimalNumberRegex.test(amount); } /** diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index d73e5997a5ed..654618f299bd 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -89,7 +89,7 @@ function ValuePage({ // The default currency uses 2 decimal places, so we substract it extraDecimals={CONST.MAX_TAX_RATE_DECIMAL_PLACES - 2} // We increase the amount max length to support the extra decimals. - amountMaxLength={CONST.MAX_TAX_RATE_DECIMAL_PLACES + CONST.MAX_TAX_RATE_INTEGER_PLACES} + amountMaxLength={CONST.MAX_TAX_RATE_INTEGER_PLACES} extraSymbol={%} ref={inputCallbackRef} /> diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx index 1301ad100d77..2045ffe3e79b 100644 --- a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx @@ -105,7 +105,7 @@ function WorkspaceCreateTaxPage({ // The default currency uses 2 decimal places, so we substract it extraDecimals={CONST.MAX_TAX_RATE_DECIMAL_PLACES - 2} // We increase the amount max length to support the extra decimals. - amountMaxLength={CONST.MAX_TAX_RATE_DECIMAL_PLACES + CONST.MAX_TAX_RATE_INTEGER_PLACES} + amountMaxLength={CONST.MAX_TAX_RATE_DECIMAL_PLACES} extraSymbol={%} /> From 2c9e8cc50cff3dadcdd514cfab5cf88556ee953d Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 3 Jun 2024 11:53:00 +0800 Subject: [PATCH 5/8] add unit test --- tests/unit/MoneyRequestUtilsTest.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/unit/MoneyRequestUtilsTest.ts diff --git a/tests/unit/MoneyRequestUtilsTest.ts b/tests/unit/MoneyRequestUtilsTest.ts new file mode 100644 index 000000000000..f8e2c75c360b --- /dev/null +++ b/tests/unit/MoneyRequestUtilsTest.ts @@ -0,0 +1,22 @@ +import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; + +describe('ReportActionsUtils', () => { + describe('validateAmount', () => { + it('should pass the validation when amount is within the max digit and decimal', () => { + expect(MoneyRequestUtils.validateAmount('12345678', 2, 8)).toBe(true); + expect(MoneyRequestUtils.validateAmount('12345678', 0, 8)).toBe(true); + expect(MoneyRequestUtils.validateAmount('12345678.12', 2, 8)).toBe(true); + expect(MoneyRequestUtils.validateAmount('1234567.1', 2, 8)).toBe(true); + expect(MoneyRequestUtils.validateAmount('12345678.123', 3, 8)).toBe(true); + expect(MoneyRequestUtils.validateAmount('1234.1234', 4, 4)).toBe(true); + }); + + it("shouldn't pass the validation when amount is bigger than the max digit and decimal", () => { + expect(MoneyRequestUtils.validateAmount('12345678.123', 2, 8)).toBe(false); + expect(MoneyRequestUtils.validateAmount('12345678.1', 0, 8)).toBe(false); + expect(MoneyRequestUtils.validateAmount('123456789.12', 2, 8)).toBe(false); + expect(MoneyRequestUtils.validateAmount('123456789.1234', 3, 8)).toBe(false); + expect(MoneyRequestUtils.validateAmount('1234.12345', 4, 4)).toBe(false); + }); + }); +}); \ No newline at end of file From cc87e5280a47eabdc9925ff5ed20c134c7639dc3 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 3 Jun 2024 11:53:33 +0800 Subject: [PATCH 6/8] remove unused function --- src/libs/MoneyRequestUtils.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libs/MoneyRequestUtils.ts b/src/libs/MoneyRequestUtils.ts index 5999ce2dcbcf..67ba9f62421d 100644 --- a/src/libs/MoneyRequestUtils.ts +++ b/src/libs/MoneyRequestUtils.ts @@ -10,13 +10,6 @@ function stripCommaFromAmount(amount: string): string { return amount.replace(/,/g, ''); } -/** - * Strip dot from the amount - */ -function stripDotFromAmount(amount: string): string { - return amount.replace(/\./g, ''); -} - /** * Strip spaces from the amount */ From 63819bfc672d154090648c93ed33ef688e937197 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 3 Jun 2024 11:53:38 +0800 Subject: [PATCH 7/8] prettier --- tests/unit/MoneyRequestUtilsTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/MoneyRequestUtilsTest.ts b/tests/unit/MoneyRequestUtilsTest.ts index f8e2c75c360b..dfd339049d37 100644 --- a/tests/unit/MoneyRequestUtilsTest.ts +++ b/tests/unit/MoneyRequestUtilsTest.ts @@ -19,4 +19,4 @@ describe('ReportActionsUtils', () => { expect(MoneyRequestUtils.validateAmount('1234.12345', 4, 4)).toBe(false); }); }); -}); \ No newline at end of file +}); From 8d75abfffddab16157bb4b41336c5c27e8461c03 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 3 Jun 2024 12:02:16 +0800 Subject: [PATCH 8/8] use the correct const --- src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx index 2045ffe3e79b..5a8f6df383d6 100644 --- a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx @@ -105,7 +105,7 @@ function WorkspaceCreateTaxPage({ // The default currency uses 2 decimal places, so we substract it extraDecimals={CONST.MAX_TAX_RATE_DECIMAL_PLACES - 2} // We increase the amount max length to support the extra decimals. - amountMaxLength={CONST.MAX_TAX_RATE_DECIMAL_PLACES} + amountMaxLength={CONST.MAX_TAX_RATE_INTEGER_PLACES} extraSymbol={%} />