From 2169530a3d81ec7afec8daea7d12b9b1fb194f57 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Mon, 5 Feb 2024 10:38:52 +0200 Subject: [PATCH 01/13] Corrected Currency Display: Enforce Two Decimal Places in Amounts --- src/libs/CurrencyUtils.ts | 16 +++++++++++++--- src/pages/iou/steps/MoneyRequestAmountForm.js | 6 +++--- tests/unit/CurrencyUtilsTest.js | 17 ++++++++++++++--- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index 42387e03c80b..32d2e62e8af1 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -88,10 +88,19 @@ function convertToBackendAmount(amountAsFloat: number): number { * * @note we do not support any currencies with more than two decimal places. */ -function convertToFrontendAmount(amountAsInt: number): number { +function convertToFrontendAmountAsInteger(amountAsInt: number): number { return Math.trunc(amountAsInt) / 100.0; } +/** + * Takes an amount in "cents" as an integer and converts it to a string amount used in the frontend. + * + * @note we do not support any currencies with more than two decimal places. + */ +function convertToFrontendAmountAsString(amountAsInt: number): string { + return convertToFrontendAmountAsInteger(amountAsInt).toFixed(2); +} + /** * Given an amount in the "cents", convert it to a string for display in the UI. * The backend always handle things in "cents" (subunit equal to 1/100) @@ -105,7 +114,7 @@ function convertToDisplayString(amountInCents = 0, currency: string = CONST.CURR return Localize.translateLocal('common.tbd'); } - const convertedAmount = convertToFrontendAmount(amountInCents); + const convertedAmount = convertToFrontendAmountAsInteger(amountInCents); return NumberFormatUtils.format(BaseLocaleListener.getPreferredLocale(), convertedAmount, { style: 'currency', currency, @@ -131,7 +140,8 @@ export { getCurrencySymbol, isCurrencySymbolLTR, convertToBackendAmount, - convertToFrontendAmount, + convertToFrontendAmountAsInteger, + convertToFrontendAmountAsString, convertToDisplayString, isValidCurrencyCode, }; diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 8775562d4476..3d140a9e16b8 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -68,7 +68,7 @@ const getNewSelection = (oldSelection, prevLength, newLength) => { }; const isAmountInvalid = (amount) => !amount.length || parseFloat(amount) < 0.01; -const isTaxAmountInvalid = (currentAmount, taxAmount, isTaxAmountForm) => isTaxAmountForm && currentAmount > CurrencyUtils.convertToFrontendAmount(taxAmount); +const isTaxAmountInvalid = (currentAmount, taxAmount, isTaxAmountForm) => isTaxAmountForm && currentAmount > CurrencyUtils.convertToFrontendAmountAsInteger(taxAmount); const AMOUNT_VIEW_ID = 'amountView'; const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView'; @@ -83,7 +83,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount'); const decimals = CurrencyUtils.getCurrencyDecimals(currency); - const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmount(amount).toString() : ''; + const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmountAsString(amount) : ''; const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString); const [formError, setFormError] = useState(''); @@ -119,7 +119,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward }; const initializeAmount = useCallback((newAmount) => { - const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmount(newAmount).toString() : ''; + const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmountAsString(newAmount) : ''; setCurrentAmount(frontendAmount); setSelection({ start: frontendAmount.length, diff --git a/tests/unit/CurrencyUtilsTest.js b/tests/unit/CurrencyUtilsTest.js index 89e1e2ffb3be..c2b0a294c467 100644 --- a/tests/unit/CurrencyUtilsTest.js +++ b/tests/unit/CurrencyUtilsTest.js @@ -106,18 +106,29 @@ describe('CurrencyUtils', () => { }); }); - describe('convertToFrontendAmount', () => { + describe('convertToFrontendAmountAsInteger', () => { test.each([ [2500, 25], [2550, 25.5], [25, 0.25], [2500, 25], [2500.5, 25], // The backend should never send a decimal .5 value - ])('Correctly converts %s to amount in units handled in frontend', (amount, expectedResult) => { - expect(CurrencyUtils.convertToFrontendAmount(amount)).toBe(expectedResult); + ])('Correctly converts %s to amount in units handled in frontend as an integer', (amount, expectedResult) => { + expect(CurrencyUtils.convertToFrontendAmountAsInteger(amount)).toBe(expectedResult); }); }); + describe('convertToFrontendAmountAsString', () => { + test.each([ + [2500, '25.00'], + [2550, '25.50'], + [25, '0.25'], + [2500, '25.00'], + [2500.5, '25.00'], + ])('Correctly converts %s to amount in units handled in frontend as a string', (amount, expectedResult) => { + expect(CurrencyUtils.convertToFrontendAmountAsString(amount)).toBe(expectedResult); + }); + }); describe('convertToDisplayString', () => { test.each([ [CONST.CURRENCY.USD, 25, '$0.25'], From 72d282fba6972d757af95451b3f19f40f47a297b Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 6 Feb 2024 22:49:57 +0200 Subject: [PATCH 02/13] fix the case where there is no decimal value passed --- src/libs/CurrencyUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index 32d2e62e8af1..9e8475b0efe0 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -98,7 +98,8 @@ function convertToFrontendAmountAsInteger(amountAsInt: number): number { * @note we do not support any currencies with more than two decimal places. */ function convertToFrontendAmountAsString(amountAsInt: number): string { - return convertToFrontendAmountAsInteger(amountAsInt).toFixed(2); + const shouldShowDecimal = amountAsInt % 100 === 0; + return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(shouldShowDecimal ? 0 : 2) : ''; } /** From 8e80ffbf002b2198fc43f5c9f244515cd6ba62ec Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 6 Feb 2024 22:50:45 +0200 Subject: [PATCH 03/13] cleaning --- src/pages/iou/steps/MoneyRequestAmountForm.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 3d140a9e16b8..aec204772bc5 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -83,8 +83,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount'); const decimals = CurrencyUtils.getCurrencyDecimals(currency); - const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmountAsString(amount) : ''; - + const selectedAmountAsString = CurrencyUtils.convertToFrontendAmountAsString(amount); const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString); const [formError, setFormError] = useState(''); const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true); @@ -119,7 +118,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward }; const initializeAmount = useCallback((newAmount) => { - const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmountAsString(newAmount) : ''; + const frontendAmount = CurrencyUtils.convertToFrontendAmountAsString(newAmount); setCurrentAmount(frontendAmount); setSelection({ start: frontendAmount.length, From 8315492b481df524ab720d2751ba9dfe8e241d29 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 6 Feb 2024 22:57:07 +0200 Subject: [PATCH 04/13] fixing tests --- tests/unit/CurrencyUtilsTest.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/CurrencyUtilsTest.js b/tests/unit/CurrencyUtilsTest.js index c2b0a294c467..2178f029240c 100644 --- a/tests/unit/CurrencyUtilsTest.js +++ b/tests/unit/CurrencyUtilsTest.js @@ -120,10 +120,9 @@ describe('CurrencyUtils', () => { describe('convertToFrontendAmountAsString', () => { test.each([ - [2500, '25.00'], + [2500, '25'], [2550, '25.50'], [25, '0.25'], - [2500, '25.00'], [2500.5, '25.00'], ])('Correctly converts %s to amount in units handled in frontend as a string', (amount, expectedResult) => { expect(CurrencyUtils.convertToFrontendAmountAsString(amount)).toBe(expectedResult); From 65f90db3c27e1e4b8c15feac636c2c8134fb3087 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sun, 18 Feb 2024 23:35:27 +0200 Subject: [PATCH 05/13] keeping the user input when clicking next --- src/libs/CurrencyUtils.ts | 3 +-- src/pages/iou/steps/MoneyRequestAmountForm.js | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index 2e3089c355d0..d16192b808aa 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -97,8 +97,7 @@ function convertToFrontendAmountAsInteger(amountAsInt: number): number { * @note we do not support any currencies with more than two decimal places. */ function convertToFrontendAmountAsString(amountAsInt: number): string { - const shouldShowDecimal = amountAsInt % 100 === 0; - return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(shouldShowDecimal ? 0 : 2) : ''; + return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(2) : ''; } /** diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 9d58fe04872f..95a3c89ade75 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -236,13 +236,8 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward return; } - // Update display amount string post-edit to ensure consistency with backend amount - // Reference: https://github.com/Expensify/App/issues/30505 - const backendAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount)); - initializeAmount(backendAmount); - onSubmitButtonPress({amount: currentAmount, currency}); - }, [onSubmitButtonPress, currentAmount, taxAmount, currency, isTaxAmountForm, formattedTaxAmount, initializeAmount]); + }, [onSubmitButtonPress, currentAmount, taxAmount, currency, isTaxAmountForm, formattedTaxAmount]); /** * Input handler to check for a forward-delete key (or keyboard shortcut) press. From 3fa6bb93d476be6d5256812b1f457a7404b50075 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sun, 18 Feb 2024 23:43:34 +0200 Subject: [PATCH 06/13] Fixing tests --- tests/unit/CurrencyUtilsTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/CurrencyUtilsTest.js b/tests/unit/CurrencyUtilsTest.js index 2178f029240c..59e73488c11c 100644 --- a/tests/unit/CurrencyUtilsTest.js +++ b/tests/unit/CurrencyUtilsTest.js @@ -120,7 +120,7 @@ describe('CurrencyUtils', () => { describe('convertToFrontendAmountAsString', () => { test.each([ - [2500, '25'], + [2500, '25.00'], [2550, '25.50'], [25, '0.25'], [2500.5, '25.00'], From 6c40f80a113ffb75682dcd2304d88b0dc61815bc Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Thu, 22 Feb 2024 14:03:32 +0200 Subject: [PATCH 07/13] Removing the amount from the useEffect dependencies --- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index 555ada528ab7..934a758050b4 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -116,7 +116,7 @@ function MoneyRequestAmountForm( } }; - const initializeAmount = useCallback((newAmount) => { + const initializeAmount = useCallback((newAmount: number) => { const frontendAmount = CurrencyUtils.convertToFrontendAmountAsString(newAmount); setCurrentAmount(frontendAmount); setSelection({ @@ -132,7 +132,7 @@ function MoneyRequestAmountForm( initializeAmount(amount); // we want to re-initialize the state only when the selected tab or amount changes // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedTab, amount]); + }, [selectedTab]); /** * Sets the selection and the amount accordingly to the value passed to the input From c9614cc5ee72f98a065619cdd8458b5ece33e68e Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Thu, 22 Feb 2024 14:06:45 +0200 Subject: [PATCH 08/13] minor change --- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index 934a758050b4..ed4bb4e5deec 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -130,7 +130,7 @@ function MoneyRequestAmountForm( return; } initializeAmount(amount); - // we want to re-initialize the state only when the selected tab or amount changes + // we want to re-initialize the state only when the selected tab // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedTab]); From 4441216eecbdbf59b31e4fbb4bd00174871690d3 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Mon, 11 Mar 2024 01:49:56 +0200 Subject: [PATCH 09/13] initialize amount only if the form is an edit form --- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index 457f623a7142..73333d1d4a68 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -1,7 +1,7 @@ -import React, {useCallback, useEffect, useRef, useState} from 'react'; import type {ForwardedRef} from 'react'; -import {View} from 'react-native'; +import React, {useCallback, useEffect, useRef, useState} from 'react'; import type {NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; +import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; import BigNumberPad from '@components/BigNumberPad'; import Button from '@components/Button'; @@ -83,7 +83,7 @@ function MoneyRequestAmountForm( const textInput = useRef(null); const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount'); - + const isEditAmountForm = Navigation.getActiveRoute().includes('amount'); const decimals = CurrencyUtils.getCurrencyDecimals(currency); const selectedAmountAsString = CurrencyUtils.convertToFrontendAmountAsString(amount); const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString); @@ -127,13 +127,13 @@ function MoneyRequestAmountForm( }, []); useEffect(() => { - if (!currency || typeof amount !== 'number') { + if (!currency || typeof amount !== 'number' || !isEditAmountForm) { return; } initializeAmount(amount); - // we want to re-initialize the state only when the selected tab + // we want to re-initialize the state only when the selected tab or amount changes // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedTab]); + }, [selectedTab, amount]); /** * Sets the selection and the amount accordingly to the value passed to the input From 10e0185eb0182cdcfa7d880ead27d1378cd8a457 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sat, 16 Mar 2024 04:59:34 +0200 Subject: [PATCH 10/13] fixing the display of the entered IOU amount --- src/components/transactionPropTypes.js | 3 +++ src/libs/Permissions.ts | 1 + src/libs/actions/IOU.ts | 6 +++--- src/pages/iou/request/IOURequestStartPage.js | 9 ++++++++- src/pages/iou/request/step/IOURequestStepAmount.js | 8 +++++++- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 11 +++++++---- src/types/onyx/Transaction.ts | 3 +++ 7 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/components/transactionPropTypes.js b/src/components/transactionPropTypes.js index 7eb1b776358c..b1a69ca42441 100644 --- a/src/components/transactionPropTypes.js +++ b/src/components/transactionPropTypes.js @@ -14,6 +14,9 @@ export default PropTypes.shape({ /** The original transaction amount */ amount: PropTypes.number, + /** Whether the original input should be shown */ + shouldShowOriginalAmount: PropTypes.bool, + /** The edited transaction amount */ modifiedAmount: PropTypes.number, diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 26df03134fd5..1a913820e331 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -3,6 +3,7 @@ import CONST from '@src/CONST'; import type Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: OnyxEntry): boolean { + return true; return !!betas?.includes(CONST.BETAS.ALL); } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 4b88bb7a77a8..af0d1869d8c5 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -308,12 +308,12 @@ function startMoneyRequest_temporaryForRefactor(iouType: ValueOf - {() => } + + {() => ( + + )} + {() => } {shouldDisplayDistanceRequest && {() => }} diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js index 9fdd2bea24f4..24a8783925ad 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.js +++ b/src/pages/iou/request/step/IOURequestStepAmount.js @@ -34,6 +34,9 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, + /** Whether the user input should be kept or not */ + shouldKeepUserInput: PropTypes.bool, + /** The policy of the report */ policy: PropTypes.shape({ /** @@ -57,6 +60,7 @@ const defaultProps = { report: {}, transaction: {}, policy: {}, + shouldKeepUserInput: false, }; const getTaxAmount = (transaction, defaultTaxValue, amount) => { @@ -72,6 +76,7 @@ function IOURequestStepAmount({ transaction, transaction: {currency}, policy, + shouldKeepUserInput, }) { const {translate} = useLocalize(); const textInput = useRef(null); @@ -133,7 +138,7 @@ function IOURequestStepAmount({ IOU.setMoneyRequestTaxAmount(transaction.transactionID, taxAmountInSmallestCurrencyUnits); } - IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD, true); + IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD, true, shouldKeepUserInput); if (backTo) { Navigation.goBack(backTo); @@ -167,6 +172,7 @@ function IOURequestStepAmount({ currency={currency} amount={transaction.amount} ref={(e) => (textInput.current = e)} + shouldKeepUserInput={transaction.shouldShowOriginalAmount} onCurrencyButtonPress={navigateToCurrencySelectionPage} onSubmitButtonPress={navigateToNextPage} selectedTab={iouRequestType} diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index 73333d1d4a68..1fd4da020cc7 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -28,6 +28,9 @@ type MoneyRequestAmountFormProps = { /** Calculated tax amount based on selected tax rate */ taxAmount?: number; + /** Whether the user input should be kept or not */ + shouldKeepUserInput?: boolean; + /** Currency chosen by user or saved in Onyx */ currency?: string; @@ -74,6 +77,7 @@ function MoneyRequestAmountForm( onCurrencyButtonPress, onSubmitButtonPress, selectedTab = CONST.TAB_REQUEST.MANUAL, + shouldKeepUserInput = false, }: MoneyRequestAmountFormProps, forwardedRef: ForwardedRef, ) { @@ -83,7 +87,6 @@ function MoneyRequestAmountForm( const textInput = useRef(null); const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount'); - const isEditAmountForm = Navigation.getActiveRoute().includes('amount'); const decimals = CurrencyUtils.getCurrencyDecimals(currency); const selectedAmountAsString = CurrencyUtils.convertToFrontendAmountAsString(amount); const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString); @@ -127,13 +130,13 @@ function MoneyRequestAmountForm( }, []); useEffect(() => { - if (!currency || typeof amount !== 'number' || !isEditAmountForm) { + if (!currency || typeof amount !== 'number' || shouldKeepUserInput) { return; } initializeAmount(amount); // we want to re-initialize the state only when the selected tab or amount changes // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedTab, amount]); + }, [selectedTab, amount, shouldKeepUserInput]); /** * Sets the selection and the amount accordingly to the value passed to the input @@ -235,7 +238,7 @@ function MoneyRequestAmountForm( } onSubmitButtonPress({amount: currentAmount, currency}); - }, [onSubmitButtonPress, currentAmount, taxAmount, currency, isTaxAmountForm, formattedTaxAmount]); + }, [currentAmount, taxAmount, isTaxAmountForm, onSubmitButtonPress, currency, formattedTaxAmount]); /** * Input handler to check for a forward-delete key (or keyboard shortcut) press. diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 1a7541955720..96c36b072a1e 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -103,6 +103,9 @@ type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback< /** Whether the request is billable */ billable?: boolean; + /** Whether the user input should be kept */ + shouldShowOriginalAmount?: boolean; + /** The category name */ category?: string; From 0a08a01e556335716942e46a3d0d6cf018d9e1d9 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 19 Mar 2024 14:44:19 +0200 Subject: [PATCH 11/13] cleanup --- src/libs/Permissions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 1a913820e331..26df03134fd5 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -3,7 +3,6 @@ import CONST from '@src/CONST'; import type Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: OnyxEntry): boolean { - return true; return !!betas?.includes(CONST.BETAS.ALL); } From 0000b2bb40a59f721dec2ebd838fa63353ea67c3 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Thu, 28 Mar 2024 17:45:33 +0200 Subject: [PATCH 12/13] Adding edge cases tests --- src/libs/CurrencyUtils.ts | 7 +++++-- tests/unit/CurrencyUtilsTest.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index d16192b808aa..4530dc105e03 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -96,8 +96,11 @@ function convertToFrontendAmountAsInteger(amountAsInt: number): number { * * @note we do not support any currencies with more than two decimal places. */ -function convertToFrontendAmountAsString(amountAsInt: number): string { - return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(2) : ''; +function convertToFrontendAmountAsString(amountAsInt: number | null | undefined): string { + if (amountAsInt === null || amountAsInt === undefined) { + return ''; + } + return convertToFrontendAmountAsInteger(amountAsInt).toFixed(2); } /** diff --git a/tests/unit/CurrencyUtilsTest.ts b/tests/unit/CurrencyUtilsTest.ts index 18a9c9fbf42c..141d5df359f6 100644 --- a/tests/unit/CurrencyUtilsTest.ts +++ b/tests/unit/CurrencyUtilsTest.ts @@ -123,8 +123,12 @@ describe('CurrencyUtils', () => { [2550, '25.50'], [25, '0.25'], [2500.5, '25.00'], - ])('Correctly converts %s to amount in units handled in frontend as a string', (amount, expectedResult) => { - expect(CurrencyUtils.convertToFrontendAmountAsString(amount)).toBe(expectedResult); + [null, ''], + [undefined, ''], + ['', '0.00'], + [0, '0.00'], + ])('Correctly converts %s to amount in units handled in frontend as a string', (input, expectedResult) => { + expect(CurrencyUtils.convertToFrontendAmountAsString(input)).toBe(expectedResult); }); }); describe('convertToDisplayString', () => { From 89d4d773d7b222859884a860db1353255751bb0d Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Thu, 28 Mar 2024 23:52:51 +0200 Subject: [PATCH 13/13] minor edit --- tests/unit/CurrencyUtilsTest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/CurrencyUtilsTest.ts b/tests/unit/CurrencyUtilsTest.ts index 141d5df359f6..201bede00071 100644 --- a/tests/unit/CurrencyUtilsTest.ts +++ b/tests/unit/CurrencyUtilsTest.ts @@ -125,7 +125,6 @@ describe('CurrencyUtils', () => { [2500.5, '25.00'], [null, ''], [undefined, ''], - ['', '0.00'], [0, '0.00'], ])('Correctly converts %s to amount in units handled in frontend as a string', (input, expectedResult) => { expect(CurrencyUtils.convertToFrontendAmountAsString(input)).toBe(expectedResult);