From a3ea8665f86123f47e4f6899c605a7039bab33a2 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Wed, 10 Apr 2024 17:52:37 +0200 Subject: [PATCH 01/15] Init: Edit Rate flow --- src/CONST.ts | 1 + .../ReportActionItem/MoneyRequestView.tsx | 11 ++--- src/libs/Navigation/types.ts | 1 + src/libs/TransactionUtils.ts | 9 +++- src/libs/actions/IOU.ts | 4 +- .../iou/request/step/IOURequestStepRate.tsx | 43 +++++++++++-------- .../step/withFullTransactionOrNotFound.tsx | 1 + 7 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 2a0c6c61a581..2c2ac54e89c5 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1902,6 +1902,7 @@ const CONST = { CATEGORY: 'category', RECEIPT: 'receipt', DISTANCE: 'distance', + RATE: 'rate', TAG: 'tag', TAX_RATE: 'taxRate', TAX_AMOUNT: 'taxAmount', diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 623de07a05f8..c880f6fd43d8 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -149,6 +149,7 @@ function MoneyRequestView({ const canEditDate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE); const canEditReceipt = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT); const canEditDistance = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE); + const canEditRate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RATE); // A flag for verifying that the current report is a sub-report of a workspace chat // if the policy of the report is either Collect or Control, then this report must be tied to workspace chat @@ -291,12 +292,12 @@ function MoneyRequestView({ {}} + onPress={() => + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_RATE.getRoute(CONST.IOU.ACTION.EDIT, CONST.IOU.TYPE.REQUEST, transaction?.transactionID ?? '', report.reportID)) + } /> diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 0bc20cb2baa1..3e11ecf9fa3c 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -440,6 +440,7 @@ type MoneyRequestNavigatorParamList = { reportID: string; }; [SCREENS.MONEY_REQUEST.STEP_RATE]: { + action: string; iouType: ValueOf; transactionID: string; backTo: Routes; diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index d42d0775d4b4..969395ac1755 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -633,11 +633,17 @@ function getEnabledTaxRateCount(options: TaxRates) { /** * Check if the customUnitRateID has a value default for P2P distance requests */ - function isCustomUnitRateIDForP2P(transaction: OnyxEntry): boolean { return transaction?.comment?.customUnit?.customUnitRateID === CONST.CUSTOM_UNITS.FAKE_P2P_ID; } +/** + * Check if the customUnitRateID has a value default for P2P distance requests + */ +function getRateID(transaction: OnyxEntry): string | undefined { + return transaction?.comment?.customUnit?.customUnitRateID?.toString(); +} + /** * Gets the default tax name */ @@ -710,6 +716,7 @@ export { getRecentTransactions, hasViolation, isCustomUnitRateIDForP2P, + getRateID, }; export type {TransactionChanges}; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index cfe19a897677..73ce4809afd1 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -441,9 +441,9 @@ function setCustomUnitRateID(transactionID: string, reportID: string) { } /** Update transaction distance rate */ -function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string) { +function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string, isDraft: boolean) { Onyx.merge(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {[policyID]: rateID}); - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {comment: {customUnit: {customUnitRateID: rateID}}}); + Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {comment: {customUnit: {customUnitRateID: rateID}}}); } /** Reset money request info from the store with its initial value */ diff --git a/src/pages/iou/request/step/IOURequestStepRate.tsx b/src/pages/iou/request/step/IOURequestStepRate.tsx index e56ea39e9b13..24db9614c956 100644 --- a/src/pages/iou/request/step/IOURequestStepRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepRate.tsx @@ -10,19 +10,18 @@ import * as IOU from '@libs/actions/IOU'; import type {MileageRate} from '@libs/DistanceRequestUtils'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; +import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; -import type {Policy} from '@src/types/onyx'; +import type {Policy, Transaction} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import StepScreenWrapper from './StepScreenWrapper'; +import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; type IOURequestStepRateOnyxProps = { - /** Object of last selected rates for the policies */ - lastSelectedDistanceRates: OnyxEntry>; - /** Policy details */ policy: OnyxEntry; @@ -30,42 +29,50 @@ type IOURequestStepRateOnyxProps = { rates: Record; }; -type IOURequestStepRateProps = IOURequestStepRateOnyxProps & WithWritableReportOrNotFoundProps; +type IOURequestStepRateProps = IOURequestStepRateOnyxProps & + WithWritableReportOrNotFoundProps & { + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + transaction: OnyxEntry; + }; function IOURequestStepRate({ policy, route: { - params: {backTo, transactionID}, + params: {action, backTo, transactionID}, }, - lastSelectedDistanceRates = {}, + transaction, rates, }: IOURequestStepRateProps) { const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); + const isEditing = action === CONST.IOU.ACTION.EDIT; - const lastSelectedRateID = lastSelectedDistanceRates?.[policy?.id ?? '0'] ?? rates[0]?.customUnitRateID ?? ''; + const currentRateID = TransactionUtils.getRateID(transaction) ?? ''; + const initiallyFocusedOption = rates[currentRateID]?.name ?? CONST.CUSTOM_UNITS.DEFAULT_RATE; const sections = Object.values(rates).map((rate) => ({ text: rate.name ?? '', alternateText: DistanceRequestUtils.getRateForDisplay(true, rate.unit, rate.rate, rate.currency, translate, toLocaleDigit), keyForList: rate.name ?? '', value: rate.customUnitRateID, - isSelected: lastSelectedRateID ? lastSelectedRateID === rate.customUnitRateID : Boolean(rate.name === CONST.CUSTOM_UNITS.DEFAULT_RATE), + isSelected: currentRateID ? currentRateID === rate.customUnitRateID : Boolean(rate.name === CONST.CUSTOM_UNITS.DEFAULT_RATE), })); const unit = (Object.values(rates)[0]?.unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer')) as Unit; - const initiallyFocusedOption = rates[lastSelectedRateID]?.name ?? CONST.CUSTOM_UNITS.DEFAULT_RATE; + const navigateBack = () => { + Navigation.goBack(backTo); + }; function selectDistanceRate(customUnitRateID: string) { - IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? ''); - Navigation.goBack(backTo); + IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? '', !isEditing); + navigateBack(); } return ( Navigation.goBack(backTo)} + onBackButtonPress={navigateBack} shouldShowWrapper={Boolean(backTo)} testID="rate" > @@ -87,13 +94,15 @@ const IOURequestStepRateWithOnyx = withOnyx `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, - lastSelectedDistanceRates: { - key: ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, - }, rates: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? '0'}`, selector: DistanceRequestUtils.getMileageRates, }, })(IOURequestStepRate); -export default withWritableReportOrNotFound(IOURequestStepRateWithOnyx); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepRateWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepRateWithOnyx); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepRateWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepRateWithWritableReportOrNotFound); + +export default IOURequestStepRateWithFullTransactionOrNotFound; diff --git a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx index 9fee88b45d0c..f1a374b14103 100644 --- a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx +++ b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx @@ -20,6 +20,7 @@ type WithFullTransactionOrNotFoundOnyxProps = { type MoneyRequestRouteName = | typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION + | typeof SCREENS.MONEY_REQUEST.STEP_RATE | typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY From 967921bd47b98f77722445b459ed3dceb8944e01 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Fri, 12 Apr 2024 08:47:52 +0200 Subject: [PATCH 02/15] Rate edit: initial commit --- src/languages/en.ts | 1 + src/libs/API/types.ts | 1 + src/libs/ModifiedExpenseMessage.ts | 13 +++++ src/libs/Permissions.ts | 2 +- src/libs/ReportUtils.ts | 13 +++++ src/libs/TransactionUtils.ts | 7 ++- src/libs/actions/IOU.ts | 29 +++++++++- .../iou/request/step/IOURequestStepRate.tsx | 57 +++++++++++++++---- .../step/withFullTransactionOrNotFound.tsx | 1 - src/types/onyx/Transaction.ts | 4 ++ 10 files changed, 110 insertions(+), 18 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index b7932a44134c..38f45dbdf0d7 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -613,6 +613,7 @@ export default { amount: 'Amount', taxAmount: 'Tax amount', taxRate: 'Tax rate', + mileageRate: 'Mileage rate', approve: 'Approve', approved: 'Approved', cash: 'Cash', diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index fc19ba60693c..6ec72f319841 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -148,6 +148,7 @@ const WRITE_COMMANDS = { UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance', UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory', UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription', + UPDATE_MONEY_REQUEST_RATE: 'UpdateMoneyRequestRate', UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY: 'UpdateMoneyRequestAmountAndCurrency', HOLD_MONEY_REQUEST: 'HoldRequest', UNHOLD_MONEY_REQUEST: 'UnHoldRequest', diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 0d961ea27115..68a6cacc58ec 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -261,6 +261,19 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr ); } + const hasModifiedDistanceRate = reportActionOriginalMessage && 'oldCustomUnitRate' in reportActionOriginalMessage && 'customUnitRate' in reportActionOriginalMessage; + if (hasModifiedDistanceRate) { + buildMessageFragmentForValue( + reportActionOriginalMessage?.customUnitRate ?? '', + reportActionOriginalMessage?.oldCustomUnitRate ?? '', + Localize.translateLocal('iou.mileageRate'), + false, + setFragments, + removalFragments, + changeFragments, + ); + } + const message = getMessageLine(`\n${Localize.translateLocal('iou.changed')}`, changeFragments) + getMessageLine(`\n${Localize.translateLocal('iou.set')}`, setFragments) + diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 105736faeba0..9cc91b8ea176 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -4,7 +4,7 @@ import type {IOUType} from '@src/CONST'; import type Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: OnyxEntry): boolean { - return !!betas?.includes(CONST.BETAS.ALL); + return true; } function canUseChronos(betas: OnyxEntry): boolean { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e49c2f25ccc4..e512110ac1a8 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -13,6 +13,7 @@ import type {FileObject} from '@components/AttachmentModal'; import * as Expensicons from '@components/Icon/Expensicons'; import * as defaultGroupAvatars from '@components/Icon/GroupDefaultAvatars'; import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars'; +import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import CONST from '@src/CONST'; import type {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -106,6 +107,8 @@ type ExpenseOriginalMessage = { taxAmount?: number; taxRate?: string; oldTaxRate?: string; + customUnitRate?: string; + oldCustomUnitRate?: string; }; type SpendBreakdown = { @@ -340,6 +343,7 @@ type TransactionDetails = { currency: string; merchant: string; waypoints?: WaypointCollection | string; + customUnitRateID?: string; comment: string; category: string; billable: boolean; @@ -2331,6 +2335,7 @@ function getTransactionDetails(transaction: OnyxEntry, createdDateF comment: TransactionUtils.getDescription(transaction), merchant: TransactionUtils.getMerchant(transaction), waypoints: TransactionUtils.getWaypoints(transaction), + customUnitRateID: TransactionUtils.getRateID(transaction), category: TransactionUtils.getCategory(transaction), billable: TransactionUtils.getBillable(transaction), tag: TransactionUtils.getTag(transaction), @@ -2800,6 +2805,14 @@ function getModifiedExpenseOriginalMessage( originalMessage.billable = transactionChanges?.billable ? Localize.translateLocal('common.billable').toLowerCase() : Localize.translateLocal('common.nonBillable').toLowerCase(); } + if ('customUnitRateID' in transactionChanges) { + const mileageRates = DistanceRequestUtils.getMileageRates(policy); + const oldRate = mileageRates[TransactionUtils.getRateID(oldTransaction) ?? '']; + const newRate = mileageRates[transactionChanges?.customUnitRateID ?? '']; + originalMessage.oldCustomUnitRate = oldRate.name ?? 'TODO'; + originalMessage.customUnitRate = newRate.name ?? 'TODO'; + } + return originalMessage; } diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 969395ac1755..4e419f3d5420 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -213,6 +213,11 @@ function getUpdatedTransaction(transaction: Transaction, transactionChanges: Tra shouldStopSmartscan = true; } + if (Object.hasOwn(transactionChanges, 'customUnitRateID')) { + updatedTransaction.modifiedCustomUnitRateID = transactionChanges.customUnitRateID; + shouldStopSmartscan = true; + } + if (Object.hasOwn(transactionChanges, 'taxAmount') && typeof transactionChanges.taxAmount === 'number') { updatedTransaction.taxAmount = isFromExpenseReport ? -transactionChanges.taxAmount : transactionChanges.taxAmount; shouldStopSmartscan = true; @@ -641,7 +646,7 @@ function isCustomUnitRateIDForP2P(transaction: OnyxEntry): boolean * Check if the customUnitRateID has a value default for P2P distance requests */ function getRateID(transaction: OnyxEntry): string | undefined { - return transaction?.comment?.customUnit?.customUnitRateID?.toString(); + return transaction?.modifiedCustomUnitRateID ?? transaction?.comment?.customUnit?.customUnitRateID?.toString(); } /** diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index d2a59cb1f4e4..e91b65ae4446 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -440,8 +440,7 @@ function setCustomUnitRateID(transactionID: string, reportID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {comment: {customUnit: {customUnitRateID}}}); } -/** Update transaction distance rate */ -function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string, isDraft: boolean) { +function setMoneyRequestDistanceRate(transactionID: string, rateID: string, policyID: string, isDraft: boolean) { Onyx.merge(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {[policyID]: rateID}); Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {comment: {customUnit: {customUnitRateID: rateID}}}); } @@ -2263,6 +2262,29 @@ function updateMoneyRequestDescription( API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION, params, onyxData); } +function updateMoneyRequestDistanceRate( + transactionID: string, + transactionThreadReportID: string, + rateID: string, + policy: OnyxEntry, + policyTagList: OnyxEntry, + policyCategories: OnyxEntry, +) { + const transactionChanges: TransactionChanges = { + customUnitRateID: rateID, + }; + const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`] ?? null; + + let data: UpdateMoneyRequestData; + if (ReportUtils.isTrackExpenseReport(transactionThreadReport)) { + data = getUpdateTrackExpenseParams(transactionID, transactionThreadReportID, transactionChanges, true, policy); + } else { + data = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, policy, policyTagList, policyCategories, true); + } + const {params, onyxData} = data; + API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_RATE, params, onyxData); +} + /** Edits an existing distance request */ function updateDistanceRequest( transactionID: string, @@ -5539,6 +5561,7 @@ export { setMoneyRequestTag, setMoneyRequestTaxAmount, setMoneyRequestTaxRate, + setMoneyRequestDistanceRate, setShownHoldUseExplanation, setCustomUnitRateID, updateMoneyRequestDate, @@ -5551,6 +5574,7 @@ export { updateMoneyRequestCategory, updateMoneyRequestAmountAndCurrency, updateMoneyRequestDescription, + updateMoneyRequestDistanceRate, replaceReceipt, detachReceipt, editMoneyRequest, @@ -5562,5 +5586,4 @@ export { trackExpense, canIOUBePaid, canApproveIOU, - updateDistanceRequestRate, }; diff --git a/src/pages/iou/request/step/IOURequestStepRate.tsx b/src/pages/iou/request/step/IOURequestStepRate.tsx index c7b85a9b3d8a..0c5d769ddfac 100644 --- a/src/pages/iou/request/step/IOURequestStepRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepRate.tsx @@ -14,7 +14,7 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; -import type {Policy, Transaction} from '@src/types/onyx'; +import type * as OnyxTypes from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; @@ -22,8 +22,14 @@ import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotF import withWritableReportOrNotFound from './withWritableReportOrNotFound'; type IOURequestStepRateOnyxProps = { - /** Policy details */ - policy: OnyxEntry; + /** The policy of the report */ + policy: OnyxEntry; + + /** Collection of categories attached to a policy */ + policyCategories: OnyxEntry; + + /** Collection of tags attached to a policy */ + policyTags: OnyxEntry; /** Mileage rates */ rates: Record; @@ -32,23 +38,28 @@ type IOURequestStepRateOnyxProps = { type IOURequestStepRateProps = IOURequestStepRateOnyxProps & WithWritableReportOrNotFoundProps & { /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - transaction: OnyxEntry; + transaction: OnyxEntry; }; function IOURequestStepRate({ - policy, route: { - params: {action, backTo, transactionID}, + params: {action, reportID, backTo, transactionID}, }, transaction, rates, + policy, + policyTags, + policyCategories, }: IOURequestStepRateProps) { const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); const isEditing = action === CONST.IOU.ACTION.EDIT; const currentRateID = TransactionUtils.getRateID(transaction) ?? ''; - const initiallyFocusedOption = rates[currentRateID]?.name ?? CONST.CUSTOM_UNITS.DEFAULT_RATE; + + const navigateBack = () => { + Navigation.goBack(backTo); + }; const sections = Object.values(rates).map((rate) => { const rateForDisplay = DistanceRequestUtils.getRateForDisplay(true, rate.unit, rate.rate, rate.currency, translate, toLocaleDigit); @@ -64,12 +75,28 @@ function IOURequestStepRate({ const unit = (Object.values(rates)[0]?.unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer')) as Unit; - const navigateBack = () => { - Navigation.goBack(backTo); - }; + const initiallyFocusedOption = rates[currentRateID]?.name ?? CONST.CUSTOM_UNITS.DEFAULT_RATE; function selectDistanceRate(customUnitRateID: string) { - IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? '', !isEditing); + // Only update the rateId if it has changed + if (customUnitRateID === currentRateID) { + navigateBack(); + return; + } + + // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value + // if (isEditingSplitBill) { + // // todo + // navigateBack(); + // return; + // } + + IOU.setMoneyRequestDistanceRate(transactionID, customUnitRateID, policy?.id ?? '', !isEditing); + + if (isEditing) { + IOU.updateMoneyRequestDistanceRate(transaction?.transactionID ?? '0', reportID, customUnitRateID, policy, policyTags, policyCategories); + } + navigateBack(); } @@ -77,7 +104,7 @@ function IOURequestStepRate({ {translate('iou.chooseARate', {unit})} @@ -98,6 +125,12 @@ const IOURequestStepRateWithOnyx = withOnyx `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, + policyCategories: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, + }, + policyTags: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, + }, rates: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? '0'}`, selector: DistanceRequestUtils.getMileageRates, diff --git a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx index 50e2f148b665..d1bbf3956bc2 100644 --- a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx +++ b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx @@ -20,7 +20,6 @@ type WithFullTransactionOrNotFoundOnyxProps = { type MoneyRequestRouteName = | typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION - | typeof SCREENS.MONEY_REQUEST.STEP_RATE | typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT | typeof SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS | typeof SCREENS.MONEY_REQUEST.STEP_MERCHANT diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 281b6b4228ce..ef9e4a43cef6 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -154,6 +154,9 @@ type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback< /** The edited waypoints for the distance request */ modifiedWaypoints?: WaypointCollection; + /** The edited distance rate for the distance request */ + modifiedCustomUnitRateID?: string; + /** * Used during the creation flow before the transaction is saved to the server and helps dictate where * the user is navigated to when pressing the back button on the confirmation step @@ -224,6 +227,7 @@ type TransactionPendingFieldsKey = KeysOfUnion; type AdditionalTransactionChanges = { comment?: string; waypoints?: WaypointCollection; + customUnitRateID?: string; oldAmount?: number; oldCurrency?: string; }; From 21054fefb8f97c0e090e6d982b1250d99d36940f Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Tue, 2 Jul 2024 12:44:55 +0200 Subject: [PATCH 03/15] Some progress with edit rate --- src/CONST.ts | 2 +- src/components/ReportActionItem/MoneyRequestView.tsx | 8 ++++---- src/libs/API/types.ts | 2 +- src/libs/ReportUtils.ts | 6 +++--- src/libs/actions/IOU.ts | 5 +++-- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 3 +-- src/types/onyx/OriginalMessage.ts | 6 ++++++ 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index b50933e98923..3f98361c081c 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2170,7 +2170,7 @@ const CONST = { CATEGORY: 'category', RECEIPT: 'receipt', DISTANCE: 'distance', - RATE: 'rate', + DISTANCE_RATE: 'distanceRate', TAG: 'tag', TAX_RATE: 'taxRate', TAX_AMOUNT: 'taxAmount', diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 4d1a1811096f..54e98d6e7e53 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -165,7 +165,7 @@ function MoneyRequestView({ const isReceiptBeingScanned = hasReceipt && TransactionUtils.isReceiptBeingScanned(transaction); const didRceiptScanSucceed = hasReceipt && TransactionUtils.didRceiptScanSucceed(transaction); const canEditDistance = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE); - const canEditRate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RATE); + const canEditDistanceRate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE_RATE); const isAdmin = policy?.role === 'admin'; const isApprover = ReportUtils.isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && session?.accountID === moneyRequestReport?.managerID; @@ -313,11 +313,11 @@ function MoneyRequestView({ - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_RATE.getRoute(CONST.IOU.ACTION.EDIT, CONST.IOU.TYPE.REQUEST, transaction?.transactionID ?? '', report.reportID)) + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '-1', report.reportID)) } /> diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 4326d0956765..4439b9f5ba11 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -155,9 +155,9 @@ const WRITE_COMMANDS = { UPDATE_MONEY_REQUEST_TAX_AMOUNT: 'UpdateMoneyRequestTaxAmount', UPDATE_MONEY_REQUEST_TAX_RATE: 'UpdateMoneyRequestTaxRate', UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance', + UPDATE_MONEY_REQUEST_DISTANCE_RATE: 'UpdateMoneyRequestDistanceRate', UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory', UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription', - UPDATE_MONEY_REQUEST_RATE: 'UpdateMoneyRequestRate', UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY: 'UpdateMoneyRequestAmountAndCurrency', HOLD_MONEY_REQUEST: 'HoldRequest', UPDATE_BILLING_CARD_CURRENCY: 'UpdateBillingCardCurrency', diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 43d3355e86e4..9472da027186 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3158,9 +3158,9 @@ function getModifiedExpenseOriginalMessage( if ('customUnitRateID' in transactionChanges) { const mileageRates = DistanceRequestUtils.getMileageRates(policy); - const oldRate = mileageRates[TransactionUtils.getRateID(oldTransaction) ?? '']; - const newRate = mileageRates[transactionChanges?.customUnitRateID ?? '']; - originalMessage.oldCustomUnitRate = oldRate.name ?? 'TODO'; + const oldRate = mileageRates[TransactionUtils.getRateID(oldTransaction) ?? '-1']; + const newRate = mileageRates[transactionChanges?.customUnitRateID ?? '-1']; + originalMessage.oldCustomUnitRate = oldRate.name ?? 'TODO'; // todo originalMessage.customUnitRate = newRate.name ?? 'TODO'; } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 4de03dd74255..3919f1045197 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -456,6 +456,7 @@ function setCustomUnitRateID(transactionID: string, customUnitRateID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {comment: {customUnit: {customUnitRateID}}}); } +/** Set the distance rate of a new transaction */ function setMoneyRequestDistanceRate(transactionID: string, rateID: string, policyID: string, isDraft: boolean) { Onyx.merge(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {[policyID]: rateID}); Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {comment: {customUnit: {customUnitRateID: rateID}}}); @@ -3123,6 +3124,7 @@ function updateMoneyRequestDescription( API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION, params, onyxData); } +/** Updates the distance rate of an expense */ function updateMoneyRequestDistanceRate( transactionID: string, transactionThreadReportID: string, @@ -3143,7 +3145,7 @@ function updateMoneyRequestDistanceRate( data = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, policy, policyTagList, policyCategories, true); } const {params, onyxData} = data; - API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_RATE, params, onyxData); + API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE_RATE, params, onyxData); } /** Edits an existing distance expense */ @@ -7071,7 +7073,6 @@ export { submitReport, trackExpense, unholdRequest, - updateDistanceRequestRate, updateMoneyRequestAmountAndCurrency, updateMoneyRequestBillable, updateMoneyRequestCategory, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 54d5d591eefb..0c51388fa655 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -52,7 +52,6 @@ function IOURequestStepDistanceRate({ }, transaction, rates, - policy, policyTags, policyCategories, }: IOURequestStepDistanceRateProps) { @@ -138,7 +137,7 @@ const IOURequestStepDistanceRateWithOnyx = withOnyx `${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? '-1'}`, - selector: (policy: OnyxEntry) => DistanceRequestUtils.getMileageRates(policy), + selector: (policy: OnyxEntry) => DistanceRequestUtils.getMileageRates(policy), }, })(IOURequestStepDistanceRate); diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index edeeeab551b0..bf7453686b5c 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -314,6 +314,12 @@ type OriginalMessageModifiedExpense = { /** Old expense tax rate */ oldTaxRate?: string; + /** Edited expense distance rate */ + customUnitRate?: string; + + /** Old expense distance rate */ + oldCustomUnitRate?: string; + /** Collection of accountIDs of users mentioned in expense report */ whisperedTo?: number[]; From 816759239e66be6cb49ebde98c1542c0eab9ff31 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Fri, 19 Jul 2024 12:38:15 +0200 Subject: [PATCH 04/15] Almost final changes for Rate Edit flow --- .../ReportActionItem/MoneyRequestView.tsx | 5 +- src/languages/en.ts | 1 - src/libs/ModifiedExpenseMessage.ts | 13 ---- src/libs/Permissions.ts | 2 +- src/libs/ReportUtils.ts | 15 ++-- src/libs/TransactionUtils.ts | 17 ++++- src/libs/actions/IOU.ts | 74 +++++++++++++------ .../step/IOURequestStepDistanceRate.tsx | 11 ++- src/types/onyx/OriginalMessage.ts | 6 -- src/types/onyx/Transaction.ts | 1 + 10 files changed, 85 insertions(+), 60 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 9154666c3e11..b7dc21ef2dcc 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -204,7 +204,7 @@ function MoneyRequestView({ let amountDescription = `${translate('iou.amount')}`; const hasRoute = TransactionUtils.hasRoute(transaction, isDistanceRequest); - const rateID = transaction?.comment.customUnit?.customUnitRateID ?? '-1'; + const rateID = TransactionUtils.getRateID(transaction) ?? '-1'; const currency = policy ? policy.outputCurrency : PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; @@ -311,8 +311,7 @@ function MoneyRequestView({ onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '-1', report.reportID))} /> - {/* TODO: correct the pending field action https://github.com/Expensify/App/issues/36987 */} - + ): boolean { - return true; + return !!betas?.includes(CONST.BETAS.ALL); } function canUseChronos(betas: OnyxEntry): boolean { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 4a29def605b8..448f2a869891 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -14,7 +14,6 @@ import type {FileObject} from '@components/AttachmentModal'; import {FallbackAvatar} from '@components/Icon/Expensicons'; import * as defaultGroupAvatars from '@components/Icon/GroupDefaultAvatars'; import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars'; -import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import type {MoneyRequestAmountInputProps} from '@components/MoneyRequestAmountInput'; import type {IOUAction, IOUType} from '@src/CONST'; import CONST from '@src/CONST'; @@ -2728,6 +2727,7 @@ function canEditFieldOfMoneyRequest(reportAction: OnyxInputOrEntry CONST.EDIT_REQUEST_FIELD.DATE, CONST.EDIT_REQUEST_FIELD.RECEIPT, CONST.EDIT_REQUEST_FIELD.DISTANCE, + CONST.EDIT_REQUEST_FIELD.DISTANCE_RATE, ]; if (!ReportActionsUtils.isMoneyRequestAction(reportAction) || !canEditMoneyRequest(reportAction)) { @@ -2767,6 +2767,11 @@ function canEditFieldOfMoneyRequest(reportAction: OnyxInputOrEntry return !isInvoiceReport(moneyRequestReport) && !TransactionUtils.isReceiptBeingScanned(transaction) && !TransactionUtils.isDistanceRequest(transaction) && isRequestor; } + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DISTANCE_RATE) { + // The distance rate can be modified only on the distance expense reports + return isExpenseReport(moneyRequestReport) && TransactionUtils.isDistanceRequest(transaction); + } + return true; } @@ -3203,14 +3208,6 @@ function getModifiedExpenseOriginalMessage( originalMessage.billable = transactionChanges?.billable ? Localize.translateLocal('common.billable').toLowerCase() : Localize.translateLocal('common.nonBillable').toLowerCase(); } - if ('customUnitRateID' in transactionChanges) { - const mileageRates = DistanceRequestUtils.getMileageRates(policy); - const oldRate = mileageRates[TransactionUtils.getRateID(oldTransaction) ?? '-1']; - const newRate = mileageRates[transactionChanges?.customUnitRateID ?? '-1']; - originalMessage.oldCustomUnitRate = oldRate.name ?? 'TODO'; // todo - originalMessage.customUnitRate = newRate.name ?? 'TODO'; - } - return originalMessage; } diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 4de8943d6c4d..71f7fea83692 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -7,6 +7,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Beta, OnyxInputOrEntry, Policy, RecentWaypoint, ReviewDuplicates, TaxRate, TaxRates, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; +import type {Unit} from '@src/types/onyx/Policy'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {IOURequestType} from './actions/IOU'; import {isCorporateCard, isExpensifyCard} from './CardUtils'; @@ -18,6 +19,7 @@ import Permissions from './Permissions'; import {getCleanedTagName, getCustomUnitRate} from './PolicyUtils'; // eslint-disable-next-line import/no-cycle import * as ReportActionsUtils from './ReportActionsUtils'; +import DistanceRequestUtils from './DistanceRequestUtils'; import * as ReportConnection from './ReportConnection'; let allTransactions: OnyxCollection = {}; @@ -387,6 +389,18 @@ function getMerchant(transaction: OnyxInputOrEntry): string { return transaction?.modifiedMerchant ? transaction.modifiedMerchant : transaction?.merchant ?? ''; } +function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: Unit) { + if (transaction?.routes?.route0?.distance) { + return transaction.routes.route0.distance; + } + + if (transaction?.comment?.customUnit?.quantity && unit) { + return DistanceRequestUtils.convertToDistanceInMeters(transaction.comment.customUnit.quantity, unit); + } + + return 0; +} + function getDistance(transaction: OnyxInputOrEntry): number { return transaction?.comment?.customUnit?.quantity ?? 0; } @@ -751,7 +765,7 @@ function hasReservationList(transaction: Transaction | undefined | null): boolea } /** - * Get rate ID from the transaction object + * Get custom unit rate (distance rate) ID from the transaction object */ function getRateID(transaction: OnyxInputOrEntry): string | undefined { return transaction?.modifiedCustomUnitRateID ?? transaction?.comment?.customUnit?.customUnitRateID?.toString(); @@ -937,6 +951,7 @@ export { getTaxCode, getCurrency, getDistance, + getDistanceInMeters, getCardID, getOriginalCurrency, getOriginalAmount, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 7e0aee466901..ee280366846c 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2449,30 +2449,43 @@ function calculateDiffAmount( return 0; } -function calculateAmountForUpdatedWaypoint( +function calculateAmountForUpdatedWaypointOrRate( transaction: OnyxTypes.OnyxInputOrEntry, transactionChanges: TransactionChanges, policy: OnyxTypes.OnyxInputOrEntry, iouReport: OnyxTypes.OnyxInputOrEntry, ) { - let updatedAmount: number = CONST.IOU.DEFAULT_AMOUNT; - let updatedMerchant = Localize.translateLocal('iou.fieldPending'); - if (!isEmptyObject(transactionChanges?.routes?.route0?.geometry)) { - const customUnitRateID = TransactionUtils.getRateID(transaction) ?? ''; - const mileageRates = DistanceRequestUtils.getMileageRates(policy, true); - const policyCurrency = policy?.outputCurrency ?? PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; - const mileageRate = TransactionUtils.isCustomUnitRateIDForP2P(transaction) - ? DistanceRequestUtils.getRateForP2P(policyCurrency) - : mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy); - const {unit, rate} = mileageRate; - const distance = TransactionUtils.getDistance(transaction); - const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, unit, rate ?? 0); - updatedAmount = ReportUtils.isExpenseReport(iouReport) ? -amount : amount; - updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distance, unit, rate, transaction?.currency ?? CONST.CURRENCY.USD, Localize.translateLocal, (digit) => - toLocaleDigit(preferredLocale, digit), - ); + const hasModifiedRate = !isEmptyObject(transactionChanges.customUnitRateID); + if (isEmptyObject(transactionChanges?.routes?.route0?.geometry) && !hasModifiedRate) { + return { + amount: CONST.IOU.DEFAULT_AMOUNT, + modifiedAmount: CONST.IOU.DEFAULT_AMOUNT, + modifiedMerchant: Localize.translateLocal('iou.fieldPending') + }; } - return {amount: updatedAmount, modifiedAmount: updatedAmount, modifiedMerchant: updatedMerchant}; + + const customUnitRateID = hasModifiedRate ? transactionChanges.customUnitRateID! : TransactionUtils.getRateID(transaction) ?? ''; + + const mileageRates = DistanceRequestUtils.getMileageRates(policy, true); + const policyCurrency = policy?.outputCurrency ?? PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; + const mileageRate = TransactionUtils.isCustomUnitRateIDForP2P(transaction) + ? DistanceRequestUtils.getRateForP2P(policyCurrency) + : mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy); + const {unit, rate} = mileageRate; + + const distanceInMeters = TransactionUtils.getDistanceInMeters(transaction, unit); + const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0); + const updatedAmount = ReportUtils.isExpenseReport(iouReport) ? -amount : amount; + const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction?.currency ?? CONST.CURRENCY.USD, Localize.translateLocal, (digit) => + toLocaleDigit(preferredLocale, digit), + ); + + return { + amount: updatedAmount, + modifiedAmount: updatedAmount, + modifiedMerchant: updatedMerchant, + modifiedCurrency: policyCurrency, + }; } /** @@ -2532,10 +2545,11 @@ function getUpdateMoneyRequestParams( }; const hasPendingWaypoints = 'waypoints' in transactionChanges; - if (transaction && updatedTransaction && hasPendingWaypoints) { + const hasModifiedDistanceRate = 'customUnitRateID' in transactionChanges; + if (transaction && updatedTransaction && (hasPendingWaypoints || hasModifiedDistanceRate)) { updatedTransaction = { ...updatedTransaction, - ...calculateAmountForUpdatedWaypoint(transaction, transactionChanges, policy, iouReport), + ...calculateAmountForUpdatedWaypointOrRate(transaction, transactionChanges, policy, iouReport), }; // Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors @@ -2558,6 +2572,13 @@ function getUpdateMoneyRequestParams( }); } + if (updatedTransaction && hasModifiedDistanceRate) { + // In order to build a proper optimistic action's originalMessage, we need to provide these values + transactionChanges.amount = updatedTransaction.modifiedAmount; + transactionChanges.merchant = updatedTransaction.modifiedMerchant; + transactionChanges.currency = updatedTransaction.modifiedCurrency; + } + // Step 3: Build the modified expense report actions // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server @@ -2836,10 +2857,11 @@ function getUpdateTrackExpenseParams( }; const hasPendingWaypoints = 'waypoints' in transactionChanges; - if (transaction && updatedTransaction && hasPendingWaypoints) { + const hasModifiedDistanceRate = 'customUnitRateID' in transactionChanges; + if (transaction && updatedTransaction && (hasPendingWaypoints || hasModifiedDistanceRate)) { updatedTransaction = { ...updatedTransaction, - ...calculateAmountForUpdatedWaypoint(transaction, transactionChanges, policy, transactionThread), + ...calculateAmountForUpdatedWaypointOrRate(transaction, transactionChanges, policy, transactionThread), }; // Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors @@ -2862,6 +2884,13 @@ function getUpdateTrackExpenseParams( }); } + if (updatedTransaction && hasModifiedDistanceRate) { + // In order to build a proper optimistic action's originalMessage, we need to provide these values + transactionChanges.amount = updatedTransaction.modifiedAmount; + transactionChanges.merchant = updatedTransaction.modifiedMerchant; + transactionChanges.currency = updatedTransaction.modifiedCurrency; + } + // Step 3: Build the modified expense report actions // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server @@ -3174,6 +3203,7 @@ function updateMoneyRequestDistanceRate( const transactionChanges: TransactionChanges = { customUnitRateID: rateID, }; + const allReports = ReportConnection.getAllReports(); const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`] ?? null; let data: UpdateMoneyRequestData; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 53712ceb292d..43a3519c58d7 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -76,7 +76,7 @@ function IOURequestStepDistanceRate({ alternateText: rate.name ? rateForDisplay : '', keyForList: rate.customUnitRateID, value: rate.customUnitRateID, - isSelected: currentRateID ? currentRateID === rate.customUnitRateID : !!(rate.name === CONST.CUSTOM_UNITS.DEFAULT_RATE), + isSelected: currentRateID ? currentRateID === rate.customUnitRateID : rate.name === CONST.CUSTOM_UNITS.DEFAULT_RATE, }; }); @@ -94,10 +94,13 @@ function IOURequestStepDistanceRate({ IOU.setMoneyRequestTaxAmount(transactionID, taxAmount); IOU.setMoneyRequestTaxRate(transactionID, taxRateExternalID); } - IOU.setMoneyRequestDistanceRate(transactionID, customUnitRateID, policy?.id ?? '-1', !isEditing); - if (isEditing) { - IOU.updateMoneyRequestDistanceRate(transaction?.transactionID ?? '-1', reportID, customUnitRateID, policy, policyTags, policyCategories); + if (currentRateID !== customUnitRateID) { + IOU.setMoneyRequestDistanceRate(transactionID, customUnitRateID, policy?.id ?? '-1', !isEditing); + + if (isEditing) { + IOU.updateMoneyRequestDistanceRate(transaction?.transactionID ?? '-1', reportID, customUnitRateID, policy, policyTags, policyCategories); + } } navigateBack(); diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 61b3b161652b..a24a3b3af502 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -314,12 +314,6 @@ type OriginalMessageModifiedExpense = { /** Old expense tax rate */ oldTaxRate?: string; - /** Edited expense distance rate */ - customUnitRate?: string; - - /** Old expense distance rate */ - oldCustomUnitRate?: string; - /** Collection of accountIDs of users mentioned in expense report */ whisperedTo?: number[]; diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index c5c9b0841a86..dfa8193a78e0 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -448,6 +448,7 @@ type AdditionalTransactionChanges = { /** Collection of modified waypoints */ waypoints?: WaypointCollection; + /** The ID of the distance rate */ customUnitRateID?: string; /** Previous amount before changes */ From 5cd792a7a7e1b0d2d7f8446089dc2b1ad2ba2ddf Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Fri, 19 Jul 2024 17:14:16 +0200 Subject: [PATCH 05/15] Use pending field indicator --- .../ReportActionItem/MoneyRequestView.tsx | 2 +- src/libs/ReportUtils.ts | 14 ++++++++++++- src/libs/actions/IOU.ts | 20 +++---------------- src/types/onyx/Transaction.ts | 2 +- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index b7dc21ef2dcc..9aab0e08a777 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -311,7 +311,7 @@ function MoneyRequestView({ onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '-1', report.reportID))} /> - + , + updatedTransaction: OnyxInputOrEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, policy: OnyxInputOrEntry, @@ -3208,6 +3209,16 @@ function getModifiedExpenseOriginalMessage( originalMessage.billable = transactionChanges?.billable ? Localize.translateLocal('common.billable').toLowerCase() : Localize.translateLocal('common.nonBillable').toLowerCase(); } + if ('customUnitRateID' in transactionChanges) { + originalMessage.oldAmount = TransactionUtils.getAmount(oldTransaction, isFromExpenseReport); + originalMessage.oldCurrency = TransactionUtils.getCurrency(oldTransaction); + originalMessage.oldMerchant = TransactionUtils.getMerchant(oldTransaction); + + originalMessage.amount = TransactionUtils.getAmount(updatedTransaction, isFromExpenseReport); + originalMessage.currency = TransactionUtils.getCurrency(updatedTransaction); + originalMessage.merchant = TransactionUtils.getMerchant(updatedTransaction); + } + return originalMessage; } @@ -4419,11 +4430,12 @@ function buildOptimisticActionableTrackExpenseWhisper(iouAction: OptimisticIOURe function buildOptimisticModifiedExpenseReportAction( transactionThread: OnyxInputOrEntry, oldTransaction: OnyxInputOrEntry, + updatedTransaction: OnyxInputOrEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, policy: OnyxInputOrEntry, ): OptimisticModifiedExpenseReportAction { - const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport, policy); + const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, updatedTransaction, transactionChanges, isFromExpenseReport, policy); return { actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, actorAccountID: currentUserAccountID, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index ee280366846c..60ac8f67d2f1 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2572,18 +2572,11 @@ function getUpdateMoneyRequestParams( }); } - if (updatedTransaction && hasModifiedDistanceRate) { - // In order to build a proper optimistic action's originalMessage, we need to provide these values - transactionChanges.amount = updatedTransaction.modifiedAmount; - transactionChanges.merchant = updatedTransaction.modifiedMerchant; - transactionChanges.currency = updatedTransaction.modifiedCurrency; - } - // Step 3: Build the modified expense report actions // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server // with the response from the MapBox API - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, updatedTransaction, transactionChanges, isFromExpenseReport, policy); if (!hasPendingWaypoints) { params.reportActionID = updatedReportAction.reportActionID; @@ -2884,18 +2877,11 @@ function getUpdateTrackExpenseParams( }); } - if (updatedTransaction && hasModifiedDistanceRate) { - // In order to build a proper optimistic action's originalMessage, we need to provide these values - transactionChanges.amount = updatedTransaction.modifiedAmount; - transactionChanges.merchant = updatedTransaction.modifiedMerchant; - transactionChanges.currency = updatedTransaction.modifiedCurrency; - } - // Step 3: Build the modified expense report actions // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server // with the response from the MapBox API - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, false, policy); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, updatedTransaction, transactionChanges, false, policy); if (!hasPendingWaypoints) { params.reportActionID = updatedReportAction.reportActionID; @@ -5065,8 +5051,8 @@ function editRegularMoneyRequest( const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); // STEP 2: Build new modified expense report action. - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null; + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, updatedTransaction, transactionChanges, isFromExpenseReport, policy); // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct // Should only update if the transaction matches the currency of the report, else we wait for the update diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index dfa8193a78e0..39e3255fb342 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -434,7 +434,7 @@ type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback< /** The linked report id for the tracked expense */ linkedTrackedExpenseReportID?: string; }, - keyof Comment + keyof Comment | keyof TransactionCustomUnit >; /** Keys of pending transaction fields */ From 05d522ea25b285217c0707825689843cdf4be8a9 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Sat, 20 Jul 2024 13:18:17 +0200 Subject: [PATCH 06/15] Move getDistanceInMeters to DistanceRequestUtils to avoid circular deps --- .../ReportActionItem/MoneyRequestView.tsx | 2 +- src/libs/API/types.ts | 1 + src/libs/DistanceRequestUtils.ts | 16 +++++++++++++++- src/libs/TransactionUtils.ts | 14 -------------- src/libs/actions/IOU.ts | 2 +- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 1e5035c17427..af9350bbd4a6 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -335,7 +335,7 @@ function MoneyRequestView({ shouldShowRightIcon={canEditDistanceRate} titleStyle={styles.flex1} onPress={() => - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '-1', report.reportID)) + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '-1', report?.reportID ?? '-1')) } /> diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 5953e1ae213d..a54ca47dfe93 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -469,6 +469,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_AMOUNT]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_RATE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE_RATE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.HOLD_MONEY_REQUEST]: Parameters.HoldMoneyRequestParams; diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 76d595dc6976..8a3056d7a1f2 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -4,7 +4,7 @@ import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {RateAndUnit} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {LastSelectedDistanceRates, OnyxInputOrEntry} from '@src/types/onyx'; +import type {LastSelectedDistanceRates, OnyxInputOrEntry, Transaction} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import type Policy from '@src/types/onyx/Policy'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -112,6 +112,19 @@ function convertDistanceUnit(distanceInMeters: number, unit: Unit): number { } } +// Get the distance in meters from the transaction +function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: Unit): number { + if (transaction?.routes?.route0?.distance) { + return transaction.routes.route0.distance; + } + + if (transaction?.comment?.customUnit?.quantity && unit) { + return convertToDistanceInMeters(transaction.comment.customUnit.quantity, unit); + } + + return 0; +} + /** * @param distanceInMeters Distance traveled * @param unit Unit that should be used to display the distance @@ -288,6 +301,7 @@ export default { getRateForDisplay, getMileageRates, getDistanceForDisplay, + getDistanceInMeters, getRateForP2P, getCustomUnitRateID, convertToDistanceInMeters, diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index a6cb0317fc49..85571b0877ae 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -20,7 +20,6 @@ import Permissions from './Permissions'; import {getCleanedTagName, getCustomUnitRate} from './PolicyUtils'; // eslint-disable-next-line import/no-cycle import * as ReportActionsUtils from './ReportActionsUtils'; -import DistanceRequestUtils from './DistanceRequestUtils'; import * as ReportConnection from './ReportConnection'; let allTransactions: OnyxCollection = {}; @@ -390,18 +389,6 @@ function getMerchant(transaction: OnyxInputOrEntry): string { return transaction?.modifiedMerchant ? transaction.modifiedMerchant : transaction?.merchant ?? ''; } -function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: Unit) { - if (transaction?.routes?.route0?.distance) { - return transaction.routes.route0.distance; - } - - if (transaction?.comment?.customUnit?.quantity && unit) { - return DistanceRequestUtils.convertToDistanceInMeters(transaction.comment.customUnit.quantity, unit); - } - - return 0; -} - function getDistance(transaction: OnyxInputOrEntry): number { return transaction?.comment?.customUnit?.quantity ?? 0; } @@ -996,7 +983,6 @@ export { getTaxCode, getCurrency, getDistance, - getDistanceInMeters, getCardID, getOriginalCurrency, getOriginalAmount, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 461dd6d8e527..bc7de4c16a71 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2473,7 +2473,7 @@ function calculateAmountForUpdatedWaypointOrRate( : mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy); const {unit, rate} = mileageRate; - const distanceInMeters = TransactionUtils.getDistanceInMeters(transaction, unit); + const distanceInMeters = DistanceRequestUtils.getDistanceInMeters(transaction, unit); const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0); const updatedAmount = ReportUtils.isExpenseReport(iouReport) ? -amount : amount; const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction?.currency ?? CONST.CURRENCY.USD, Localize.translateLocal, (digit) => From 03bd85442c6d0ebca91212fca32f7fd60fec0080 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Sat, 20 Jul 2024 13:26:42 +0200 Subject: [PATCH 07/15] Fix type --- src/libs/Navigation/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 30d7877a1322..e1e5a431207f 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -870,7 +870,7 @@ type MoneyRequestNavigatorParamList = { currency?: string; }; [SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE]: { - action: string; + action: IOUAction; iouType: ValueOf; transactionID: string; backTo: Routes; From b7fa71ea5c33033108f52c0a3ece8c6b867d3b0a Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Sat, 20 Jul 2024 13:37:53 +0200 Subject: [PATCH 08/15] Lint --- src/libs/TransactionUtils.ts | 1 - src/libs/actions/IOU.ts | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 85571b0877ae..2a4815cc22a0 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -7,7 +7,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Beta, OnyxInputOrEntry, Policy, RecentWaypoint, ReviewDuplicates, TaxRate, TaxRates, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; -import type {Unit} from '@src/types/onyx/Policy'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {IOURequestType} from './actions/IOU'; import type {TransactionMergeParams} from './API/parameters'; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index bc7de4c16a71..8ba227dd38f2 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2455,16 +2455,15 @@ function calculateAmountForUpdatedWaypointOrRate( policy: OnyxTypes.OnyxInputOrEntry, iouReport: OnyxTypes.OnyxInputOrEntry, ) { - const hasModifiedRate = !isEmptyObject(transactionChanges.customUnitRateID); - if (isEmptyObject(transactionChanges?.routes?.route0?.geometry) && !hasModifiedRate) { + if (isEmptyObject(transactionChanges?.routes?.route0?.geometry) && isEmptyObject(transactionChanges.customUnitRateID)) { return { amount: CONST.IOU.DEFAULT_AMOUNT, modifiedAmount: CONST.IOU.DEFAULT_AMOUNT, - modifiedMerchant: Localize.translateLocal('iou.fieldPending') + modifiedMerchant: Localize.translateLocal('iou.fieldPending'), }; } - const customUnitRateID = hasModifiedRate ? transactionChanges.customUnitRateID! : TransactionUtils.getRateID(transaction) ?? ''; + const customUnitRateID = !isEmptyObject(transactionChanges.customUnitRateID) ? transactionChanges.customUnitRateID : TransactionUtils.getRateID(transaction) ?? ''; const mileageRates = DistanceRequestUtils.getMileageRates(policy, true); const policyCurrency = policy?.outputCurrency ?? PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; From a2ad2db331cb991b7bacd94a95344bd3b56be867 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Tue, 30 Jul 2024 19:16:51 +0200 Subject: [PATCH 09/15] Move getDistanceInMeters into TransactionUtils --- src/libs/DistanceRequestUtils.ts | 14 ---------- .../TransactionUtils/getDistanceInMeters.ts | 22 ++++++++++++++++ .../index.ts} | 26 ++++++++++--------- src/libs/actions/IOU.ts | 2 +- .../TransactionBackupsToCollection.ts | 2 +- 5 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 src/libs/TransactionUtils/getDistanceInMeters.ts rename src/libs/{TransactionUtils.ts => TransactionUtils/index.ts} (98%) diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 8a3056d7a1f2..d4f8da958203 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -112,19 +112,6 @@ function convertDistanceUnit(distanceInMeters: number, unit: Unit): number { } } -// Get the distance in meters from the transaction -function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: Unit): number { - if (transaction?.routes?.route0?.distance) { - return transaction.routes.route0.distance; - } - - if (transaction?.comment?.customUnit?.quantity && unit) { - return convertToDistanceInMeters(transaction.comment.customUnit.quantity, unit); - } - - return 0; -} - /** * @param distanceInMeters Distance traveled * @param unit Unit that should be used to display the distance @@ -301,7 +288,6 @@ export default { getRateForDisplay, getMileageRates, getDistanceForDisplay, - getDistanceInMeters, getRateForP2P, getCustomUnitRateID, convertToDistanceInMeters, diff --git a/src/libs/TransactionUtils/getDistanceInMeters.ts b/src/libs/TransactionUtils/getDistanceInMeters.ts new file mode 100644 index 000000000000..a970c6811fcc --- /dev/null +++ b/src/libs/TransactionUtils/getDistanceInMeters.ts @@ -0,0 +1,22 @@ +import DistanceRequestUtils from '@libs/DistanceRequestUtils'; +import type {OnyxInputOrEntry, Transaction} from '@src/types/onyx'; +import type {Unit} from '@src/types/onyx/Policy'; + + +// Get the distance in meters from the transaction. +// This function is placed in a separate file to avoid circular dependencies. +function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: Unit | undefined) { + // If we are creating a new distance request, the distance is available in routes.route0.distance and it's already in meters. + if (transaction?.routes?.route0?.distance) { + return transaction.routes.route0.distance; + } + + // If the request is completed, transaction.routes is cleared and comment.customUnit.quantity holds the new distance in the selected unit. + // We need to convert it from the selected distance unit to meters. + if (transaction?.comment?.customUnit?.quantity && unit) { + return DistanceRequestUtils.convertToDistanceInMeters(transaction.comment.customUnit.quantity, unit); + } + return 0; +} + +export default getDistanceInMeters; \ No newline at end of file diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils/index.ts similarity index 98% rename from src/libs/TransactionUtils.ts rename to src/libs/TransactionUtils/index.ts index 49c837884894..9cf5690eeb37 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils/index.ts @@ -3,23 +3,24 @@ import lodashIsEqual from 'lodash/isEqual'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import type {TransactionMergeParams} from '@libs/API/parameters'; +import {isCorporateCard, isExpensifyCard} from '@libs/CardUtils'; +import {getCurrencyDecimals} from '@libs/CurrencyUtils'; +import DateUtils from '@libs/DateUtils'; +import * as Localize from '@libs/Localize'; +import * as NumberUtils from '@libs/NumberUtils'; +import Permissions from '@libs/Permissions'; +import {getCleanedTagName, getCustomUnitRate} from '@libs/PolicyUtils'; +// eslint-disable-next-line import/no-cycle +import * as ReportActionsUtils from '@libs/ReportActionsUtils'; +import * as ReportConnection from '@libs/ReportConnection'; +import type {IOURequestType} from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Beta, OnyxInputOrEntry, Policy, RecentWaypoint, ReviewDuplicates, TaxRate, TaxRates, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type {IOURequestType} from './actions/IOU'; -import type {TransactionMergeParams} from './API/parameters'; -import {isCorporateCard, isExpensifyCard} from './CardUtils'; -import {getCurrencyDecimals} from './CurrencyUtils'; -import DateUtils from './DateUtils'; -import * as Localize from './Localize'; -import * as NumberUtils from './NumberUtils'; -import Permissions from './Permissions'; -import {getCleanedTagName, getCustomUnitRate} from './PolicyUtils'; -// eslint-disable-next-line import/no-cycle -import * as ReportActionsUtils from './ReportActionsUtils'; -import * as ReportConnection from './ReportConnection'; +import getDistanceInMeters from './getDistanceInMeters'; let allTransactions: OnyxCollection = {}; Onyx.connect({ @@ -1004,6 +1005,7 @@ export { getTaxCode, getCurrency, getDistance, + getDistanceInMeters, getCardID, getOriginalCurrency, getOriginalAmount, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index e5b6a021fb42..3d2bed849cd7 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -2499,7 +2499,7 @@ function calculateAmountForUpdatedWaypointOrRate( : mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy); const {unit, rate} = mileageRate; - const distanceInMeters = DistanceRequestUtils.getDistanceInMeters(transaction, unit); + const distanceInMeters = TransactionUtils.getDistanceInMeters(transaction, unit); const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0); const updatedAmount = ReportUtils.isExpenseReport(iouReport) ? -amount : amount; const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction?.currency ?? CONST.CURRENCY.USD, Localize.translateLocal, (digit) => diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts index 53fa7e855e72..97d05d6cd44e 100644 --- a/src/libs/migrations/TransactionBackupsToCollection.ts +++ b/src/libs/migrations/TransactionBackupsToCollection.ts @@ -7,7 +7,7 @@ import type {Transaction} from '@src/types/onyx'; /** * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION, to a reserved collection that only * stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT. The purpose of the migration is that there is a possibility that transaction backups are - * not filtered by most functions, e.g, getAllReportTransactions (src/libs/TransactionUtils.ts). One problem that arose from storing transaction backups with + * not filtered by most functions, e.g, getAllReportTransactions (src/libs/index.ts). One problem that arose from storing transaction backups with * the other transactions is that for every distance expense which have their waypoints updated offline, we expect the ReportPreview component to display the * default image of a pending map. However, due to the presence of the transaction backup, the previous map image will be displayed alongside the pending map. * The problem was further discussed in this PR. https://github.com/Expensify/App/pull/30232#issuecomment-178110172 From b5544b1e6eb71798ee73c8ca3f1a08ff839aa171 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Tue, 30 Jul 2024 19:18:37 +0200 Subject: [PATCH 10/15] Lint --- src/libs/TransactionUtils/getDistanceInMeters.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/TransactionUtils/getDistanceInMeters.ts b/src/libs/TransactionUtils/getDistanceInMeters.ts index a970c6811fcc..0efe72759d5d 100644 --- a/src/libs/TransactionUtils/getDistanceInMeters.ts +++ b/src/libs/TransactionUtils/getDistanceInMeters.ts @@ -2,7 +2,6 @@ import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import type {OnyxInputOrEntry, Transaction} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; - // Get the distance in meters from the transaction. // This function is placed in a separate file to avoid circular dependencies. function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: Unit | undefined) { @@ -19,4 +18,4 @@ function getDistanceInMeters(transaction: OnyxInputOrEntry, unit: U return 0; } -export default getDistanceInMeters; \ No newline at end of file +export default getDistanceInMeters; From db7639acad8ad3f1289544a1c6986e38dcde39f5 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Tue, 30 Jul 2024 19:19:44 +0200 Subject: [PATCH 11/15] Fix file name --- src/libs/migrations/TransactionBackupsToCollection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts index 97d05d6cd44e..806a4a5999f5 100644 --- a/src/libs/migrations/TransactionBackupsToCollection.ts +++ b/src/libs/migrations/TransactionBackupsToCollection.ts @@ -7,7 +7,7 @@ import type {Transaction} from '@src/types/onyx'; /** * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION, to a reserved collection that only * stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT. The purpose of the migration is that there is a possibility that transaction backups are - * not filtered by most functions, e.g, getAllReportTransactions (src/libs/index.ts). One problem that arose from storing transaction backups with + * not filtered by most functions, e.g, getAllReportTransactions (src/libs/TransactionUtils/index.ts). One problem that arose from storing transaction backups with * the other transactions is that for every distance expense which have their waypoints updated offline, we expect the ReportPreview component to display the * default image of a pending map. However, due to the presence of the transaction backup, the previous map image will be displayed alongside the pending map. * The problem was further discussed in this PR. https://github.com/Expensify/App/pull/30232#issuecomment-178110172 From fe0e98e9955f4011e3d2d64a0fb2964df07e6df1 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Tue, 30 Jul 2024 19:31:38 +0200 Subject: [PATCH 12/15] Lint --- src/libs/DistanceRequestUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index d4f8da958203..76d595dc6976 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -4,7 +4,7 @@ import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {RateAndUnit} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {LastSelectedDistanceRates, OnyxInputOrEntry, Transaction} from '@src/types/onyx'; +import type {LastSelectedDistanceRates, OnyxInputOrEntry} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import type Policy from '@src/types/onyx/Policy'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; From 6ccacb8474ce28c76fe232d4365aa6b634bf9cc7 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Wed, 31 Jul 2024 11:07:53 +0200 Subject: [PATCH 13/15] Always show wrapper for the rate page --- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 43a3519c58d7..0e606095bbce 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -110,8 +110,8 @@ function IOURequestStepDistanceRate({ {translate('iou.chooseARate', {unit})} From 65a07ff24de8baa9fb23a40a085a4827c8296faa Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Sat, 3 Aug 2024 14:16:12 +0200 Subject: [PATCH 14/15] Edit Rate: code cleanup --- src/CONST.ts | 1 + src/libs/DistanceRequestUtils.ts | 6 ++- src/libs/ReportUtils.ts | 13 ++++--- src/libs/TransactionUtils/index.ts | 61 +++++++++++++++++++++++++++++- src/libs/actions/IOU.ts | 48 +++-------------------- 5 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 776753095f46..736d51be456b 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -13,6 +13,7 @@ import type {Unit} from './types/onyx/Policy'; type RateAndUnit = { unit: Unit; rate: number; + currency: string; }; type CurrencyDefaultMileageRate = Record; diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 76d595dc6976..fa98cf32ee39 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -210,7 +210,11 @@ function getDistanceMerchant( * @returns The rate and unit in RateAndUnit object. */ function getRateForP2P(currency: string): RateAndUnit { - return CONST.CURRENCY_TO_DEFAULT_MILEAGE_RATE[currency] ?? CONST.CURRENCY_TO_DEFAULT_MILEAGE_RATE.USD; + const currencyWithExistingRate = CONST.CURRENCY_TO_DEFAULT_MILEAGE_RATE[currency] ? currency : CONST.CURRENCY.USD; + return { + ...CONST.CURRENCY_TO_DEFAULT_MILEAGE_RATE[currencyWithExistingRate], + currency: currencyWithExistingRate, + }; } /** diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index bce509af8cb8..f514d04c62e1 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3237,7 +3237,6 @@ function getReportPreviewMessage( */ function getModifiedExpenseOriginalMessage( oldTransaction: OnyxInputOrEntry, - updatedTransaction: OnyxInputOrEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, policy: OnyxInputOrEntry, @@ -3305,9 +3304,12 @@ function getModifiedExpenseOriginalMessage( originalMessage.oldCurrency = TransactionUtils.getCurrency(oldTransaction); originalMessage.oldMerchant = TransactionUtils.getMerchant(oldTransaction); - originalMessage.amount = TransactionUtils.getAmount(updatedTransaction, isFromExpenseReport); - originalMessage.currency = TransactionUtils.getCurrency(updatedTransaction); - originalMessage.merchant = TransactionUtils.getMerchant(updatedTransaction); + const modifiedData = TransactionUtils.calculateAmountForUpdatedWaypointOrRate(oldTransaction, transactionChanges, policy, isFromExpenseReport); + + // For the originalMessage, we should use the non-negative amount, similar to what TransactionUtils.getAmount does for oldAmount + originalMessage.amount = Math.abs(modifiedData.modifiedAmount); + originalMessage.currency = modifiedData.modifiedCurrency; + originalMessage.merchant = modifiedData.modifiedMerchant; } return originalMessage; @@ -4573,12 +4575,11 @@ function buildOptimisticActionableTrackExpenseWhisper(iouAction: OptimisticIOURe function buildOptimisticModifiedExpenseReportAction( transactionThread: OnyxInputOrEntry, oldTransaction: OnyxInputOrEntry, - updatedTransaction: OnyxInputOrEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, policy: OnyxInputOrEntry, ): OptimisticModifiedExpenseReportAction { - const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, updatedTransaction, transactionChanges, isFromExpenseReport, policy); + const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport, policy); return { actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, actorAccountID: currentUserAccountID, diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 9cf5690eeb37..357787cec132 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -21,6 +21,11 @@ import type {Beta, OnyxInputOrEntry, Policy, RecentWaypoint, ReviewDuplicates, T import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import getDistanceInMeters from './getDistanceInMeters'; +import type * as OnyxTypes from '@src/types/onyx'; +import DistanceRequestUtils from '@libs/DistanceRequestUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import {toLocaleDigit} from '@libs/LocaleDigitUtils'; +import type DeepValueOf from '@src/types/utils/DeepValueOf'; let allTransactions: OnyxCollection = {}; Onyx.connect({ @@ -41,6 +46,17 @@ Onyx.connect({ callback: (value) => (allTransactionViolations = value), }); +let preferredLocale: DeepValueOf = CONST.LOCALES.DEFAULT; +Onyx.connect({ + key: ONYXKEYS.NVP_PREFERRED_LOCALE, + callback: (value) => { + if (!value) { + return; + } + preferredLocale = value; + }, +}); + let currentUserEmail = ''; let currentUserAccountID = -1; Onyx.connect({ @@ -203,7 +219,7 @@ function areRequiredFieldsEmpty(transaction: OnyxEntry): boolean { } /** - * Given the edit made to the expnse, return an updated transaction object. + * Given the edit made to the expense, return an updated transaction object. */ function getUpdatedTransaction(transaction: Transaction, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, shouldUpdateReceiptState = true): Transaction { // Only changing the first level fields so no need for deep clone now @@ -733,6 +749,48 @@ function calculateTaxAmount(percentage: string, amount: number, currency: string return parseFloat(taxAmount.toFixed(decimals)); } +/** + * Calculates updated amount, currency, and merchant for a distance request with modified waypoints or customUnitRateID + */ +function calculateAmountForUpdatedWaypointOrRate( + transaction: OnyxTypes.OnyxInputOrEntry, + transactionChanges: TransactionChanges, + policy: OnyxTypes.OnyxInputOrEntry, + isFromExpenseReport: boolean, +) { + if (isEmptyObject(transactionChanges?.routes?.route0?.geometry) && isEmptyObject(transactionChanges.customUnitRateID)) { + return { + amount: CONST.IOU.DEFAULT_AMOUNT, + modifiedAmount: CONST.IOU.DEFAULT_AMOUNT, + modifiedMerchant: Localize.translateLocal('iou.fieldPending'), + modifiedCurrency: Localize.translateLocal('iou.fieldPending'), + }; + } + + const customUnitRateID = transactionChanges.customUnitRateID ?? getRateID(transaction) ?? ''; + const mileageRates = DistanceRequestUtils.getMileageRates(policy, true); + const policyCurrency = policy?.outputCurrency ?? PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; + const mileageRate = isCustomUnitRateIDForP2P(transaction) + ? DistanceRequestUtils.getRateForP2P(policyCurrency) + : mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy); + const {unit, rate, currency} = mileageRate; + + const distanceInMeters = getDistanceInMeters(transaction, unit); + const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0); + const updatedAmount = isFromExpenseReport ? -amount : amount; + const updatedCurrency = currency ?? CONST.CURRENCY.USD; + const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, updatedCurrency, Localize.translateLocal, (digit) => + toLocaleDigit(preferredLocale, digit), + ); + + return { + amount: updatedAmount, + modifiedAmount: updatedAmount, + modifiedMerchant: updatedMerchant, + modifiedCurrency: updatedCurrency, + }; +} + /** * Calculates count of all tax enabled options */ @@ -989,6 +1047,7 @@ function buildTransactionsMergeParams(reviewDuplicates: OnyxEntry, - transactionChanges: TransactionChanges, - policy: OnyxTypes.OnyxInputOrEntry, - iouReport: OnyxTypes.OnyxInputOrEntry, -) { - if (isEmptyObject(transactionChanges?.routes?.route0?.geometry) && isEmptyObject(transactionChanges.customUnitRateID)) { - return { - amount: CONST.IOU.DEFAULT_AMOUNT, - modifiedAmount: CONST.IOU.DEFAULT_AMOUNT, - modifiedMerchant: Localize.translateLocal('iou.fieldPending'), - }; - } - - const customUnitRateID = !isEmptyObject(transactionChanges.customUnitRateID) ? transactionChanges.customUnitRateID : TransactionUtils.getRateID(transaction) ?? ''; - - const mileageRates = DistanceRequestUtils.getMileageRates(policy, true); - const policyCurrency = policy?.outputCurrency ?? PolicyUtils.getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; - const mileageRate = TransactionUtils.isCustomUnitRateIDForP2P(transaction) - ? DistanceRequestUtils.getRateForP2P(policyCurrency) - : mileageRates?.[customUnitRateID] ?? DistanceRequestUtils.getDefaultMileageRate(policy); - const {unit, rate} = mileageRate; - - const distanceInMeters = TransactionUtils.getDistanceInMeters(transaction, unit); - const amount = DistanceRequestUtils.getDistanceRequestAmount(distanceInMeters, unit, rate ?? 0); - const updatedAmount = ReportUtils.isExpenseReport(iouReport) ? -amount : amount; - const updatedMerchant = DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction?.currency ?? CONST.CURRENCY.USD, Localize.translateLocal, (digit) => - toLocaleDigit(preferredLocale, digit), - ); - - return { - amount: updatedAmount, - modifiedAmount: updatedAmount, - modifiedMerchant: updatedMerchant, - modifiedCurrency: policyCurrency, - }; -} - /** * @param transactionID * @param transactionThreadReportID @@ -2575,7 +2537,7 @@ function getUpdateMoneyRequestParams( if (transaction && updatedTransaction && (hasPendingWaypoints || hasModifiedDistanceRate)) { updatedTransaction = { ...updatedTransaction, - ...calculateAmountForUpdatedWaypointOrRate(transaction, transactionChanges, policy, iouReport), + ...TransactionUtils.calculateAmountForUpdatedWaypointOrRate(transaction, transactionChanges, policy, ReportUtils.isExpenseReport(iouReport)), }; // Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors @@ -2602,7 +2564,7 @@ function getUpdateMoneyRequestParams( // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server // with the response from the MapBox API - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, updatedTransaction, transactionChanges, isFromExpenseReport, policy); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); if (!hasPendingWaypoints) { params.reportActionID = updatedReportAction.reportActionID; @@ -2880,7 +2842,7 @@ function getUpdateTrackExpenseParams( if (transaction && updatedTransaction && (hasPendingWaypoints || hasModifiedDistanceRate)) { updatedTransaction = { ...updatedTransaction, - ...calculateAmountForUpdatedWaypointOrRate(transaction, transactionChanges, policy, transactionThread), + ...TransactionUtils.calculateAmountForUpdatedWaypointOrRate(transaction, transactionChanges, policy, ReportUtils.isExpenseReport(transactionThread)), }; // Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors @@ -2907,7 +2869,7 @@ function getUpdateTrackExpenseParams( // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server // with the response from the MapBox API - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, updatedTransaction, transactionChanges, false, policy); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, false, policy); if (!hasPendingWaypoints) { params.reportActionID = updatedReportAction.reportActionID; @@ -5078,7 +5040,7 @@ function editRegularMoneyRequest( // STEP 2: Build new modified expense report action. const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null; - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, updatedTransaction, transactionChanges, isFromExpenseReport, policy); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct // Should only update if the transaction matches the currency of the report, else we wait for the update From 63865a31fd9a3bddb2510c28e711637aa6dc7ac4 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Sat, 3 Aug 2024 14:53:51 +0200 Subject: [PATCH 15/15] Edit Rate: code cleanup --- src/libs/actions/IOU.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 2e484299a888..a9a78bb929f6 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -5046,8 +5046,8 @@ function editRegularMoneyRequest( const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); // STEP 2: Build new modified expense report action. - const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null; const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); + const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null; // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct // Should only update if the transaction matches the currency of the report, else we wait for the update