Skip to content

Commit a1f9cec

Browse files
authored
Merge pull request #39610 from eVoloshchak/revert-35797-preserving-the-transactions-amounts-the-same-as-the-user-entered
Revert "35797-preserving-the-transactions-amounts-the-same-as-entered"
2 parents 819df53 + 789beb2 commit a1f9cec

File tree

8 files changed

+24
-68
lines changed

8 files changed

+24
-68
lines changed

src/components/transactionPropTypes.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ export default PropTypes.shape({
1414
/** The original transaction amount */
1515
amount: PropTypes.number,
1616

17-
/** Whether the original input should be shown */
18-
shouldShowOriginalAmount: PropTypes.bool,
19-
2017
/** The edited transaction amount */
2118
modifiedAmount: PropTypes.number,
2219

src/libs/CurrencyUtils.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,9 @@ function convertToBackendAmount(amountAsFloat: number): number {
8787
*
8888
* @note we do not support any currencies with more than two decimal places.
8989
*/
90-
function convertToFrontendAmountAsInteger(amountAsInt: number): number {
90+
function convertToFrontendAmount(amountAsInt: number): number {
9191
return Math.trunc(amountAsInt) / 100.0;
9292
}
93-
94-
/**
95-
* Takes an amount in "cents" as an integer and converts it to a string amount used in the frontend.
96-
*
97-
* @note we do not support any currencies with more than two decimal places.
98-
*/
99-
function convertToFrontendAmountAsString(amountAsInt: number | null | undefined): string {
100-
if (amountAsInt === null || amountAsInt === undefined) {
101-
return '';
102-
}
103-
return convertToFrontendAmountAsInteger(amountAsInt).toFixed(2);
104-
}
105-
10693
/**
10794
* Given an amount in the "cents", convert it to a string for display in the UI.
10895
* The backend always handle things in "cents" (subunit equal to 1/100)
@@ -111,7 +98,7 @@ function convertToFrontendAmountAsString(amountAsInt: number | null | undefined)
11198
* @param currency - IOU currency
11299
*/
113100
function convertToDisplayString(amountInCents = 0, currency: string = CONST.CURRENCY.USD): string {
114-
const convertedAmount = convertToFrontendAmountAsInteger(amountInCents);
101+
const convertedAmount = convertToFrontendAmount(amountInCents);
115102
return NumberFormatUtils.format(BaseLocaleListener.getPreferredLocale(), convertedAmount, {
116103
style: 'currency',
117104
currency,
@@ -152,8 +139,7 @@ export {
152139
getCurrencySymbol,
153140
isCurrencySymbolLTR,
154141
convertToBackendAmount,
155-
convertToFrontendAmountAsInteger,
156-
convertToFrontendAmountAsString,
142+
convertToFrontendAmount,
157143
convertToDisplayString,
158144
convertAmountToDisplayString,
159145
isValidCurrencyCode,

src/libs/actions/IOU.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,12 @@ function startMoneyRequest(iouType: ValueOf<typeof CONST.IOU.TYPE>, reportID: st
356356
}
357357

358358
// eslint-disable-next-line @typescript-eslint/naming-convention
359-
function setMoneyRequestAmount_temporaryForRefactor(transactionID: string, amount: number, currency: string, removeOriginalCurrency = false, shouldShowOriginalAmount = false) {
359+
function setMoneyRequestAmount_temporaryForRefactor(transactionID: string, amount: number, currency: string, removeOriginalCurrency = false) {
360360
if (removeOriginalCurrency) {
361-
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency, originalCurrency: null, shouldShowOriginalAmount});
361+
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency, originalCurrency: null});
362362
return;
363363
}
364-
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency, shouldShowOriginalAmount});
364+
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency});
365365
}
366366

367367
// eslint-disable-next-line @typescript-eslint/naming-convention

src/pages/iou/request/IOURequestStartPage.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,7 @@ function IOURequestStartPage({
165165
onTabSelected={resetIOUTypeIfChanged}
166166
tabBar={TabSelector}
167167
>
168-
<TopTab.Screen name={CONST.TAB_REQUEST.MANUAL}>
169-
{() => (
170-
<IOURequestStepAmount
171-
shouldKeepUserInput
172-
route={route}
173-
/>
174-
)}
175-
</TopTab.Screen>
168+
<TopTab.Screen name={CONST.TAB_REQUEST.MANUAL}>{() => <IOURequestStepAmount route={route} />}</TopTab.Screen>
176169
<TopTab.Screen name={CONST.TAB_REQUEST.SCAN}>{() => <IOURequestStepScan route={route} />}</TopTab.Screen>
177170
{shouldDisplayDistanceRequest && <TopTab.Screen name={CONST.TAB_REQUEST.DISTANCE}>{() => <IOURequestStepDistance route={route} />}</TopTab.Screen>}
178171
</OnyxTabNavigator>

src/pages/iou/request/step/IOURequestStepAmount.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {useFocusEffect} from '@react-navigation/native';
22
import lodashGet from 'lodash/get';
33
import lodashIsEmpty from 'lodash/isEmpty';
4-
import PropTypes from 'prop-types';
54
import React, {useCallback, useEffect, useRef} from 'react';
65
import {withOnyx} from 'react-native-onyx';
76
import transactionPropTypes from '@components/transactionPropTypes';
@@ -38,9 +37,6 @@ const propTypes = {
3837
/** The draft transaction that holds data to be persisted on the current transaction */
3938
splitDraftTransaction: transactionPropTypes,
4039

41-
/** Whether the user input should be kept or not */
42-
shouldKeepUserInput: PropTypes.bool,
43-
4440
/** The draft transaction object being modified in Onyx */
4541
draftTransaction: transactionPropTypes,
4642
};
@@ -50,7 +46,6 @@ const defaultProps = {
5046
transaction: {},
5147
splitDraftTransaction: {},
5248
draftTransaction: {},
53-
shouldKeepUserInput: false,
5449
};
5550

5651
function IOURequestStepAmount({
@@ -61,7 +56,6 @@ function IOURequestStepAmount({
6156
transaction,
6257
splitDraftTransaction,
6358
draftTransaction,
64-
shouldKeepUserInput,
6559
}) {
6660
const {translate} = useLocalize();
6761
const textInput = useRef(null);
@@ -131,7 +125,7 @@ function IOURequestStepAmount({
131125
isSaveButtonPressed.current = true;
132126
const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount));
133127

134-
IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD, true, shouldKeepUserInput);
128+
IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD, true);
135129

136130
if (backTo) {
137131
Navigation.goBack(backTo);
@@ -189,7 +183,6 @@ function IOURequestStepAmount({
189183
currency={currency}
190184
amount={Math.abs(transactionAmount)}
191185
ref={(e) => (textInput.current = e)}
192-
shouldKeepUserInput={transaction.shouldShowOriginalAmount}
193186
onCurrencyButtonPress={navigateToCurrencySelectionPage}
194187
onSubmitButtonPress={saveAmountAndCurrency}
195188
selectedTab={iouRequestType}

src/pages/iou/steps/MoneyRequestAmountForm.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ type MoneyRequestAmountFormProps = {
3030
/** Calculated tax amount based on selected tax rate */
3131
taxAmount?: number;
3232

33-
/** Whether the user input should be kept or not */
34-
shouldKeepUserInput?: boolean;
35-
3633
/** Currency chosen by user or saved in Onyx */
3734
currency?: string;
3835

@@ -67,7 +64,7 @@ const getNewSelection = (oldSelection: Selection, prevLength: number, newLength:
6764

6865
const isAmountInvalid = (amount: string) => !amount.length || parseFloat(amount) < 0.01;
6966
const isTaxAmountInvalid = (currentAmount: string, taxAmount: number, isTaxAmountForm: boolean) =>
70-
isTaxAmountForm && Number.parseFloat(currentAmount) > CurrencyUtils.convertToFrontendAmountAsInteger(Math.abs(taxAmount));
67+
isTaxAmountForm && Number.parseFloat(currentAmount) > CurrencyUtils.convertToFrontendAmount(Math.abs(taxAmount));
7168

7269
const AMOUNT_VIEW_ID = 'amountView';
7370
const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView';
@@ -83,7 +80,6 @@ function MoneyRequestAmountForm(
8380
onCurrencyButtonPress,
8481
onSubmitButtonPress,
8582
selectedTab = CONST.TAB_REQUEST.MANUAL,
86-
shouldKeepUserInput = false,
8783
}: MoneyRequestAmountFormProps,
8884
forwardedRef: ForwardedRef<BaseTextInputRef>,
8985
) {
@@ -93,8 +89,10 @@ function MoneyRequestAmountForm(
9389

9490
const textInput = useRef<BaseTextInputRef | null>(null);
9591
const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount');
92+
9693
const decimals = CurrencyUtils.getCurrencyDecimals(currency);
97-
const selectedAmountAsString = CurrencyUtils.convertToFrontendAmountAsString(amount);
94+
const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmount(amount).toString() : '';
95+
9896
const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString);
9997
const [formError, setFormError] = useState<MaybePhraseKey>('');
10098
const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true);
@@ -127,7 +125,7 @@ function MoneyRequestAmountForm(
127125
};
128126

129127
const initializeAmount = useCallback((newAmount: number) => {
130-
const frontendAmount = CurrencyUtils.convertToFrontendAmountAsString(newAmount);
128+
const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmount(newAmount).toString() : '';
131129
setCurrentAmount(frontendAmount);
132130
setSelection({
133131
start: frontendAmount.length,
@@ -136,13 +134,13 @@ function MoneyRequestAmountForm(
136134
}, []);
137135

138136
useEffect(() => {
139-
if (!currency || typeof amount !== 'number' || shouldKeepUserInput) {
137+
if (!currency || typeof amount !== 'number') {
140138
return;
141139
}
142140
initializeAmount(amount);
143141
// we want to re-initialize the state only when the selected tab or amount changes
144142
// eslint-disable-next-line react-hooks/exhaustive-deps
145-
}, [selectedTab, amount, shouldKeepUserInput]);
143+
}, [selectedTab, amount]);
146144

147145
/**
148146
* Sets the selection and the amount accordingly to the value passed to the input
@@ -243,8 +241,13 @@ function MoneyRequestAmountForm(
243241
return;
244242
}
245243

244+
// Update display amount string post-edit to ensure consistency with backend amount
245+
// Reference: https://github.com/Expensify/App/issues/30505
246+
const backendAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount));
247+
initializeAmount(backendAmount);
248+
246249
onSubmitButtonPress({amount: currentAmount, currency});
247-
}, [currentAmount, taxAmount, isTaxAmountForm, onSubmitButtonPress, currency, formattedTaxAmount]);
250+
}, [currentAmount, taxAmount, isTaxAmountForm, onSubmitButtonPress, currency, formattedTaxAmount, initializeAmount]);
248251

249252
/**
250253
* Input handler to check for a forward-delete key (or keyboard shortcut) press.

src/types/onyx/Transaction.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback<
111111
/** Whether the request is billable */
112112
billable?: boolean;
113113

114-
/** Whether the user input should be kept */
115-
shouldShowOriginalAmount?: boolean;
116-
117114
/** The category name */
118115
category?: string;
119116

tests/unit/CurrencyUtilsTest.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,31 +105,18 @@ describe('CurrencyUtils', () => {
105105
});
106106
});
107107

108-
describe('convertToFrontendAmountAsInteger', () => {
108+
describe('convertToFrontendAmount', () => {
109109
test.each([
110110
[2500, 25],
111111
[2550, 25.5],
112112
[25, 0.25],
113113
[2500, 25],
114114
[2500.5, 25], // The backend should never send a decimal .5 value
115-
])('Correctly converts %s to amount in units handled in frontend as an integer', (amount, expectedResult) => {
116-
expect(CurrencyUtils.convertToFrontendAmountAsInteger(amount)).toBe(expectedResult);
115+
])('Correctly converts %s to amount in units handled in frontend', (amount, expectedResult) => {
116+
expect(CurrencyUtils.convertToFrontendAmount(amount)).toBe(expectedResult);
117117
});
118118
});
119119

120-
describe('convertToFrontendAmountAsString', () => {
121-
test.each([
122-
[2500, '25.00'],
123-
[2550, '25.50'],
124-
[25, '0.25'],
125-
[2500.5, '25.00'],
126-
[null, ''],
127-
[undefined, ''],
128-
[0, '0.00'],
129-
])('Correctly converts %s to amount in units handled in frontend as a string', (input, expectedResult) => {
130-
expect(CurrencyUtils.convertToFrontendAmountAsString(input)).toBe(expectedResult);
131-
});
132-
});
133120
describe('convertToDisplayString', () => {
134121
test.each([
135122
[CONST.CURRENCY.USD, 25, '$0.25'],

0 commit comments

Comments
 (0)