From 97e31dda04bbfb485f5ee34fb9aba31574dc8dab Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 16:25:20 +0100 Subject: [PATCH 1/8] Revert changes --- src/CONST/index.ts | 3 - src/components/MoneyReportHeader.tsx | 2 +- src/components/MoneyRequestHeader.tsx | 2 +- .../ReportActionItem/MoneyRequestView.tsx | 12 +- src/hooks/useSelectedTransactionsActions.ts | 2 +- .../API/parameters/SplitTransactionParams.ts | 7 +- src/libs/API/types.ts | 2 - src/libs/TransactionUtils/index.ts | 45 +- src/libs/actions/IOU/Split.ts | 199 +--- src/libs/actions/IOU/index.ts | 16 +- src/libs/actions/Transaction.ts | 72 +- src/pages/Search/SearchPage.tsx | 4 +- .../iou/SplitExpenseCreateDateRagePage.tsx | 2 +- src/pages/iou/SplitExpenseEditPage.tsx | 91 +- src/pages/iou/SplitExpensePage.tsx | 16 +- .../request/step/IOURequestStepDistance.tsx | 79 +- .../step/IOURequestStepDistanceManual.tsx | 16 +- .../step/IOURequestStepDistanceMap.tsx | 84 +- .../step/IOURequestStepDistanceOdometer.tsx | 43 +- .../step/IOURequestStepDistanceRate.tsx | 33 +- .../request/step/IOURequestStepWaypoint.tsx | 33 +- src/types/onyx/IOU.ts | 16 - tests/actions/IOUTest/SplitTest.ts | 952 ------------------ 23 files changed, 140 insertions(+), 1591 deletions(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index dbcf5ffb3d808..530e55d05aa98 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1860,7 +1860,6 @@ const CONST = { STATE: { CURRENT: 'current', DRAFT: 'draft', - SPLIT_DRAFT: 'splitDraft', BACKUP: 'backup', }, LIABILITY_TYPE: { @@ -2980,8 +2979,6 @@ const CONST = { QUANTITY_MAX_LENGTH: 12, // This is the transactionID used when going through the create expense flow so that it mimics a real transaction (like the edit flow) OPTIMISTIC_TRANSACTION_ID: '1', - // This is the transactionID used when going through the distance split expense flow so that it mimics a draft transaction - OPTIMISTIC_DISTANCE_SPLIT_TRANSACTION_ID: '2', // Note: These payment types are used when building IOU reportAction message values in the server and should // not be changed. LOCATION_PERMISSION_PROMPT_THRESHOLD_DAYS: 7, diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 672f50b4e6c5e..e3d1b73341afc 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -1380,7 +1380,7 @@ function MoneyReportHeader({ return; } - initSplitExpense(allTransactions, allReports, currentTransaction, policy); + initSplitExpense(allTransactions, allReports, currentTransaction); }, }, [CONST.REPORT.SECONDARY_ACTIONS.MERGE]: { diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 9a5c97c5be939..4578d7b37f3b4 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -435,7 +435,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre icon: expensifyIcons.ArrowSplit, value: CONST.REPORT.SECONDARY_ACTIONS.SPLIT, onSelected: () => { - initSplitExpense(allTransactions, allReports, transaction, policy); + initSplitExpense(allTransactions, allReports, transaction); }, }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: { diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 1f0b2bd6f2bf6..e69575b55037a 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -604,6 +604,11 @@ function MoneyRequestView({ return; } + if (isExpenseSplit && isSplitAvailable) { + initSplitExpense(allTransactions, allReports, transaction); + return; + } + if (isOdometerDistanceRequest) { Navigation.navigate( ROUTES.MONEY_REQUEST_STEP_DISTANCE_ODOMETER.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport.reportID), @@ -652,6 +657,11 @@ function MoneyRequestView({ return; } + if (isExpenseSplit && isSplitAvailable) { + initSplitExpense(allTransactions, allReports, transaction); + return; + } + Navigation.navigate( ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute( CONST.IOU.ACTION.EDIT, @@ -840,7 +850,7 @@ function MoneyRequestView({ } if (isExpenseSplit && isSplitAvailable) { - initSplitExpense(allTransactions, allReports, transaction, policy); + initSplitExpense(allTransactions, allReports, transaction); return; } diff --git a/src/hooks/useSelectedTransactionsActions.ts b/src/hooks/useSelectedTransactionsActions.ts index 26e6a542ec03c..e44f05c88093a 100644 --- a/src/hooks/useSelectedTransactionsActions.ts +++ b/src/hooks/useSelectedTransactionsActions.ts @@ -370,7 +370,7 @@ function useSelectedTransactionsActions({ icon: expensifyIcons.ArrowSplit, value: SPLIT, onSelected: () => { - initSplitExpense(allTransactions, allReports, firstTransaction, policy); + initSplitExpense(allTransactions, allReports, firstTransaction); }, }); } diff --git a/src/libs/API/parameters/SplitTransactionParams.ts b/src/libs/API/parameters/SplitTransactionParams.ts index 5593d347b9731..3ffc0db281eb0 100644 --- a/src/libs/API/parameters/SplitTransactionParams.ts +++ b/src/libs/API/parameters/SplitTransactionParams.ts @@ -1,4 +1,4 @@ -import type {Comment, WaypointCollection} from '@src/types/onyx/Transaction'; +import type {Comment} from '@src/types/onyx/Transaction'; type SplitTransactionSplitParam = { transactionID: string; @@ -14,11 +14,6 @@ type SplitTransactionSplitParam = { reimbursable?: boolean; billable?: boolean; reportID?: string; - quantity?: number; - customUnitRateID?: string; - odometerStart?: number; - odometerEnd?: number; - waypoints?: WaypointCollection; }; type SplitTransactionSplitsParam = SplitTransactionSplitParam[]; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 411f27b445b72..f3b7682cf0524 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -1159,7 +1159,6 @@ const READ_COMMANDS = { GRAPHITE: 'Graphite', GET_ROUTE: 'GetRoute', GET_ROUTE_FOR_DRAFT: 'GetRouteForDraft', - GET_ROUTE_FOR_SPLIT_DRAFT: 'GetRouteForSplitDraft', GET_ROUTE_FOR_BACKUP: 'GetRouteForBackup', GET_STATEMENT_PDF: 'GetStatementPDF', OPEN_ONFIDO_FLOW: 'OpenOnfidoFlow', @@ -1244,7 +1243,6 @@ type ReadCommandParameters = { [READ_COMMANDS.GRAPHITE]: Parameters.GraphiteParams; [READ_COMMANDS.GET_ROUTE]: Parameters.GetRouteParams; [READ_COMMANDS.GET_ROUTE_FOR_DRAFT]: Parameters.GetRouteParams; - [READ_COMMANDS.GET_ROUTE_FOR_SPLIT_DRAFT]: Parameters.GetRouteParams; [READ_COMMANDS.GET_ROUTE_FOR_BACKUP]: Parameters.GetRouteParams; [READ_COMMANDS.GET_STATEMENT_PDF]: Parameters.GetStatementPDFParams; [READ_COMMANDS.OPEN_ONFIDO_FLOW]: null; diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index b4e5e1c636997..4198b14188520 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -75,7 +75,6 @@ import type {OnyxData} from '@src/types/onyx/Request'; import type { Comment, Receipt, - Routes, TransactionChanges, TransactionCustomUnit, TransactionPendingFieldsKey, @@ -114,17 +113,13 @@ type TransactionParams = { splitsStartDate?: string; splitsEndDate?: string; distance?: number; - customUnitRateID?: string; - waypoints?: WaypointCollection; odometerStart?: number; odometerEnd?: number; - routes?: Routes; gpsCoordinates?: string; type?: ValueOf; count?: number; rate?: number; unit?: ValueOf; - commentType?: ValueOf; }; type BuildOptimisticTransactionParams = { @@ -474,16 +469,12 @@ function buildOptimisticTransaction(params: BuildOptimisticTransactionParams): T splitExpensesTotal, participants, pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - customUnitRateID, - waypoints, odometerStart, odometerEnd, - routes, type, count, rate, unit, - commentType, } = transactionParams; // transactionIDs are random, positive, 64-bit numeric strings. // Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID) @@ -517,28 +508,14 @@ function buildOptimisticTransaction(params: BuildOptimisticTransactionParams): T if (splitExpensesTotal) { commentJSON.splitExpensesTotal = splitExpensesTotal; } - if (waypoints) { - commentJSON.waypoints = waypoints; - } - if (commentType) { - commentJSON.type = commentType; - } - const isMapDistanceTransaction = !!pendingFields?.waypoints || existingTransaction?.comment?.waypoints?.waypoint0; + const isMapDistanceTransaction = !!pendingFields?.waypoints; const isManualDistanceTransaction = isManualDistanceRequest(existingTransaction); const isOdometerDistanceTransaction = isOdometerDistanceRequest(existingTransaction); if (isMapDistanceTransaction || isManualDistanceTransaction || isOdometerDistanceTransaction) { - // If customUnit is provided (e.g., for split expenses), use it directly - // Otherwise, build customUnit from distance parameter - if (customUnit) { - lodashSet(commentJSON, 'customUnit', customUnit); - } else { - // Set the distance unit, which comes from the policy distance unit or the P2P rate data - lodashSet(commentJSON, 'customUnit.distanceUnit', DistanceRequestUtils.getUpdatedDistanceUnit({transaction: existingTransaction, policy})); - lodashSet(commentJSON, 'customUnit.quantity', distance); - lodashSet(commentJSON, 'customUnit.customUnitRateID', customUnitRateID); - lodashSet(commentJSON, 'customUnit.name', existingTransaction?.comment?.customUnit?.name ?? CONST.CUSTOM_UNITS.NAME_DISTANCE); - } + // Set the distance unit, which comes from the policy distance unit or the P2P rate data + lodashSet(commentJSON, 'customUnit.distanceUnit', DistanceRequestUtils.getUpdatedDistanceUnit({transaction: existingTransaction, policy})); + lodashSet(commentJSON, 'customUnit.quantity', distance); } const isPerDiemTransaction = !!pendingFields?.subRates; @@ -583,9 +560,6 @@ function buildOptimisticTransaction(params: BuildOptimisticTransactionParams): T cardID: existingTransaction?.cardID, cardName: existingTransaction?.cardName, cardNumber: existingTransaction?.cardNumber, - // Use conditional spread to avoid creating the key if it's undefined, which would break lodashHas checks. - ...(existingTransaction?.iouRequestType ? {iouRequestType: existingTransaction.iouRequestType} : {}), - routes, }; } @@ -692,14 +666,12 @@ function getUpdatedTransaction({ isFromExpenseReport, shouldUpdateReceiptState = true, policy = undefined, - isDraftSplitTransaction = false, }: { transaction: Transaction; transactionChanges: TransactionChanges; isFromExpenseReport: boolean; shouldUpdateReceiptState?: boolean; policy?: OnyxEntry; - isDraftSplitTransaction?: boolean; }): Transaction { const isUnReportedExpense = transaction?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID; @@ -734,10 +706,7 @@ function getUpdatedTransaction({ if (Object.hasOwn(transactionChanges, 'waypoints')) { updatedTransaction.modifiedWaypoints = transactionChanges.waypoints; - // For draft split transactions, we don't want to set isLoading to true as all the split transactions are in draft state - if (!isDraftSplitTransaction) { - updatedTransaction.isLoading = true; - } + updatedTransaction.isLoading = true; shouldStopSmartscan = true; if (!transactionChanges.routes?.route0?.geometry?.coordinates) { @@ -772,10 +741,6 @@ function getUpdatedTransaction({ } } - if (Object.hasOwn(transactionChanges, 'routes')) { - updatedTransaction.routes = transactionChanges.routes; - } - if (Object.hasOwn(transactionChanges, 'customUnitRateID')) { lodashSet(updatedTransaction, 'comment.customUnit.customUnitRateID', transactionChanges.customUnitRateID); lodashSet(updatedTransaction, 'comment.customUnit.defaultP2PRate', null); diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index 6d4de776a3b52..7565ad509ce61 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -1091,11 +1091,6 @@ function updateSplitTransactions({ comment: currentDescription, }, reimbursable: split?.reimbursable, - quantity: split.customUnit?.quantity ?? undefined, - customUnitRateID: split.customUnit?.customUnitRateID, - odometerStart: split.odometerStart, - odometerEnd: split.odometerEnd, - waypoints: split.waypoints, }; }) ?? []; changesInReportTotal -= splitExpensesTotal; @@ -1137,8 +1132,6 @@ function updateSplitTransactions({ return transactionID === existingTransactionID; }); - const splitExpenseMerchant = splitExpense.merchant ?? ''; - const requestMoneyInformation = { participantParams: { participant: participants.at(0) ?? ({} as Participant), @@ -1155,7 +1148,7 @@ function updateSplitTransactions({ modifiedAmount: splitExpense.amount ?? 0, currency: originalTransactionDetails?.currency ?? CONST.CURRENCY.USD, created: splitExpense.created, - merchant: splitExpenseMerchant, + merchant: splitExpense.merchant ?? '', comment: splitExpense.description, category: splitExpense.category, tag: splitExpense.tags?.[0], @@ -1169,12 +1162,6 @@ function updateSplitTransactions({ taxCode: originalTransactionDetails?.taxCode, taxAmount: calculateIOUAmount(splitExpenses.length - 1, originalTransactionDetails?.taxAmount ?? 0, originalTransactionDetails?.currency ?? CONST.CURRENCY.USD, false), billable: originalTransactionDetails?.billable, - waypoints: splitExpense.waypoints, - customUnit: splitExpense.customUnit, - // For distance transactions, also pass distance from customUnit.quantity so buildOptimisticTransaction sets it correctly - distance: splitExpense.customUnit?.quantity, - odometerStart: splitExpense.odometerStart, - odometerEnd: splitExpense.odometerEnd, }, parentChatReport: getReportOrDraftReport(getReportOrDraftReport(expenseReport?.chatReportID)?.parentReportID), existingTransaction: originalTransaction, @@ -1201,12 +1188,6 @@ function updateSplitTransactions({ taxCode: originalTransactionDetails?.taxCode, taxAmount: calculateIOUAmount(splitExpenses.length - 1, originalTransactionDetails?.taxAmount ?? 0, originalTransactionDetails?.currency ?? CONST.CURRENCY.USD, false), billable: originalTransactionDetails?.billable, - waypoints: splitExpense.waypoints, - customUnit: splitExpense.customUnit, - // For distance transactions, also pass distance from customUnit.quantity so buildOptimisticTransaction sets it correctly - distance: splitExpense.customUnit?.quantity ?? undefined, - odometerStart: splitExpense.odometerStart, - odometerEnd: splitExpense.odometerEnd, }; requestMoneyInformation.existingTransaction = undefined; } @@ -1215,13 +1196,7 @@ function updateSplitTransactions({ const parsedComment = getParsedComment(Parser.htmlToMarkdown(transactionParams.comment ?? '')); transactionParams.comment = parsedComment; - const { - transactionThreadReportID, - createdReportActionIDForThread, - onyxData, - iouAction, - transaction: optimisticTransactionFromGetMoneyRequest, - } = getMoneyRequestInformation({ + const {transactionThreadReportID, createdReportActionIDForThread, onyxData, iouAction} = getMoneyRequestInformation({ participantParams, parentChatReport, policyParams, @@ -1255,11 +1230,6 @@ function updateSplitTransactions({ comment: currentSplit?.comment?.comment, } as TransactionChanges; - const oldTransactionChanges = { - ...existing, - quantity: splitTransaction.comment?.customUnit?.quantity ?? existing?.distance, - } as TransactionChanges; - if (currentSplit) { currentSplit.reimbursable = splitTransaction.reimbursable; currentSplit.billable = splitTransaction.billable; @@ -1267,7 +1237,7 @@ function updateSplitTransactions({ for (const key of Object.keys(transactionChanges)) { const newValue = transactionChanges[key as keyof typeof transactionChanges]; - const oldValue = oldTransactionChanges?.[key as keyof typeof oldTransactionChanges]; + const oldValue = existing?.[key as keyof typeof existing]; if (newValue === oldValue) { delete transactionChanges[key as keyof typeof transactionChanges]; // Ensure we pass the currency to getUpdateMoneyRequestParams as well, so the amount message is created correctly @@ -1314,23 +1284,6 @@ function updateSplitTransactions({ currentSplit.splitReportActionID = iouAction.reportActionID; } - // Ensure merchant from splitExpense is preserved in optimisticData for new and existing transactions - const transactionIDFromOptimistic = optimisticTransactionFromGetMoneyRequest?.transactionID; - if (transactionIDFromOptimistic && onyxData.optimisticData) { - const transactionUpdate = onyxData.optimisticData.find((update) => update.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionIDFromOptimistic}`); - if (transactionUpdate && 'value' in transactionUpdate && typeof transactionUpdate.value === 'object' && transactionUpdate.value !== null) { - const transactionUpdateValue = transactionUpdate.value as OnyxTypes.Transaction; - const expectedMerchant = optimisticTransactionFromGetMoneyRequest?.merchant; - if (expectedMerchant && transactionUpdateValue.merchant !== expectedMerchant) { - transactionUpdateValue.merchant = expectedMerchant; - // For distance transactions, also update modifiedMerchant to ensure consistency - if (isDistanceRequestTransactionUtils(transactionUpdateValue)) { - transactionUpdateValue.modifiedMerchant = expectedMerchant; - } - } - } - } - optimisticData.push(...(onyxData.optimisticData ?? []), ...(updateMoneyRequestParamsOnyxData.optimisticData ?? [])); successData.push(...(onyxData.successData ?? []), ...(updateMoneyRequestParamsOnyxData.successData ?? [])); failureData.push(...(onyxData.failureData ?? []), ...(updateMoneyRequestParamsOnyxData.failureData ?? [])); @@ -1728,7 +1681,6 @@ function setDraftSplitTransaction( isFromExpenseReport: false, shouldUpdateReceiptState: false, policy, - isDraftSplitTransaction: true, }) : null; @@ -1829,10 +1781,6 @@ function initSplitExpenseItemData( statusNum: transactionReport?.statusNum ?? 0, reportID: reportID ?? transaction?.reportID ?? String(CONST.DEFAULT_NUMBER_ID), reimbursable: transactionDetails?.reimbursable, - customUnit: customUnit ?? transaction?.comment?.customUnit ?? undefined, - waypoints: transaction?.comment?.waypoints ?? undefined, - odometerStart: transaction?.comment?.odometerStart ?? undefined, - odometerEnd: transaction?.comment?.odometerEnd ?? undefined, }; } @@ -1989,13 +1937,6 @@ function initDraftSplitExpenseDataForEdit(draftTransaction: OnyxEntry, - draftTransaction: OnyxEntry, - transactionReport: OnyxEntry, - policy?: OnyxEntry, -) { +function addSplitExpenseField(transaction: OnyxEntry, draftTransaction: OnyxEntry, transactionReport: OnyxEntry) { if (!transaction || !draftTransaction) { return; } - const isDistanceRequest = isDistanceRequestTransactionUtils(transaction); - let merchant: string | undefined; - let customUnit: TransactionCustomUnit | undefined; - - // Calculate merchant and customUnit for distance transactions - if (isDistanceRequest) { - // For new split expense with amount = 0, distance will also be 0 - // But we still need to set up customUnit structure - customUnit = transaction?.comment?.customUnit - ? { - ...transaction.comment.customUnit, - quantity: 0, - } - : undefined; - - const mileageRate = DistanceRequestUtils.getRate({transaction, policy: policy ?? undefined}); - const {unit, rate} = mileageRate; - - if (rate && rate > 0) { - // For amount = 0, distance = 0, but we still calculate merchant format - const currency = mileageRate?.currency ?? transaction.currency ?? CONST.CURRENCY.USD; - merchant = getDistanceMerchantForSplitExpense(0, unit, rate, currency, transaction.currency); - } - } - const newSplitExpense = initSplitExpenseItemData(transaction, transactionReport, { amount: 0, transactionID: NumberUtils.rand64(), reportID: draftTransaction?.reportID, - customUnit, - merchant, }); Onyx.merge(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`, { @@ -2065,7 +1974,7 @@ function addSplitExpenseField( * - Works entirely on the provided `draftTransaction` to avoid direct Onyx reads. * - Uses `calculateAmount` utility to handle currency subunits and rounding consistently with existing logic. */ -function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry, transaction?: OnyxEntry, policy?: OnyxEntry) { +function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry, transaction?: OnyxEntry) { if (!draftTransaction) { return; } @@ -2082,8 +1991,6 @@ function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry 0) { - // Calculate distance from amount: distance = amount / rate - // Both amount and rate are in cents, so the result is in distance units - const distanceInUnits = Math.abs(amount) / rate; - const quantity = Number(distanceInUnits.toFixed(CONST.DISTANCE_DECIMAL_PLACES)); - - updatedSplitExpense = { - ...updatedSplitExpense, - customUnit: { - ...splitExpense.customUnit, - quantity, - }, - }; - - // Update merchant for distance transactions - const currencyForMerchant = mileageRate?.currency ?? transaction.currency ?? CONST.CURRENCY.USD; - updatedSplitExpense.merchant = getDistanceMerchantForSplitExpense(distanceInUnits, unit, rate, currencyForMerchant, transaction.currency); - } - } - return updatedSplitExpense; }); @@ -2160,8 +2042,6 @@ function resetSplitExpensesByDateRange( const total = transactionDetails?.amount ?? 0; const currency = transactionDetails?.currency ?? CONST.CURRENCY.USD; - const isDistanceRequest = isDistanceRequestTransactionUtils(transaction); - // Create split expenses for each date with proportional amounts const lastIndex = dates.length - 1; const newSplitExpenses: SplitExpense[] = dates.map((date, index) => { @@ -2173,31 +2053,6 @@ function resetSplitExpensesByDateRange( created: format(date, CONST.DATE.FNS_FORMAT_STRING), }); - // Update distance for distance transactions based on new amount and rate - if (isDistanceRequest && splitExpense.customUnit && amount !== 0) { - const mileageRate = DistanceRequestUtils.getRate({transaction, policy: policy ?? undefined}); - const {unit, rate} = mileageRate; - - if (rate && rate > 0) { - // Calculate distance from amount: distance = amount / rate - // Both amount and rate are in cents, so the result is in distance units - const distanceInUnits = Math.abs(amount) / rate; - const quantity = Number(distanceInUnits.toFixed(CONST.DISTANCE_DECIMAL_PLACES)); - - splitExpense = { - ...splitExpense, - customUnit: { - ...splitExpense.customUnit, - quantity, - }, - }; - - // Update merchant for distance transactions - const currencyForMerchant = mileageRate?.currency ?? transaction.currency ?? CONST.CURRENCY.USD; - splitExpense.merchant = getDistanceMerchantForSplitExpense(distanceInUnits, unit, rate, currencyForMerchant, transaction.currency); - } - } - return splitExpense; }); @@ -2249,14 +2104,6 @@ function updateSplitExpenseField( if (transactionDetails?.created !== item.created) { shouldResetDateRange = true; } - let quantity: number | undefined; - if (splitExpenseDraftTransaction?.routes?.route0?.distance && splitExpenseDraftTransaction?.comment?.customUnit?.distanceUnit) { - quantity = DistanceRequestUtils.convertDistanceUnit(splitExpenseDraftTransaction?.routes?.route0?.distance, splitExpenseDraftTransaction?.comment?.customUnit?.distanceUnit); - } else if (splitExpenseDraftTransaction?.comment?.customUnit?.quantity) { - quantity = splitExpenseDraftTransaction?.comment?.customUnit?.quantity; - } else { - quantity = undefined; - } const updatedItem: SplitExpense = { ...item, @@ -2264,15 +2111,7 @@ function updateSplitExpenseField( category: transactionDetails?.category, tags: splitExpenseDraftTransaction?.tag ? [splitExpenseDraftTransaction?.tag] : [], created: transactionDetails?.created ?? DateUtils.formatWithUTCTimeZone(DateUtils.getDBTime(), CONST.DATE.FNS_FORMAT_STRING), - waypoints: splitExpenseDraftTransaction?.modifiedWaypoints ?? splitExpenseDraftTransaction?.comment?.waypoints ?? undefined, - customUnit: { - ...(splitExpenseDraftTransaction?.comment?.customUnit ?? undefined), - quantity, - }, - odometerStart: splitExpenseDraftTransaction?.comment?.odometerStart ?? undefined, - odometerEnd: splitExpenseDraftTransaction?.comment?.odometerEnd ?? undefined, amount: splitExpenseDraftTransaction?.amount ?? 0, - routes: splitExpenseDraftTransaction?.routes ?? undefined, merchant: splitExpenseDraftTransaction?.modifiedMerchant ? splitExpenseDraftTransaction.modifiedMerchant : (splitExpenseDraftTransaction?.merchant ?? ''), }; @@ -2321,14 +2160,13 @@ function updateSplitExpenseField( }); } -function updateSplitExpenseAmountField(draftTransaction: OnyxEntry, currentItemTransactionID: string, amount: number, policy?: OnyxEntry) { +function updateSplitExpenseAmountField(draftTransaction: OnyxEntry, currentItemTransactionID: string, amount: number) { if (!draftTransaction?.transactionID || !currentItemTransactionID) { return; } const originalTransactionID = draftTransaction?.comment?.originalTransactionID; const originalTransaction = getAllTransactions()?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`]; - const isDistanceRequest = originalTransaction && isDistanceRequestTransactionUtils(originalTransaction); const updatedSplitExpenses = draftTransaction.comment?.splitExpenses?.map((splitExpense) => { if (splitExpense.transactionID === currentItemTransactionID) { @@ -2337,31 +2175,6 @@ function updateSplitExpenseAmountField(draftTransaction: OnyxEntry 0) { - // Calculate distance from amount: distance = amount / rate - // Both amount and rate are in cents, so the result is in distance units - const distanceInUnits = Math.abs(amount) / rate; - const quantity = Number(distanceInUnits.toFixed(CONST.DISTANCE_DECIMAL_PLACES)); - - updatedSplitExpense = { - ...updatedSplitExpense, - customUnit: { - ...splitExpense.customUnit, - quantity, - }, - }; - - // Update merchant for distance transactions - const currency = mileageRate?.currency ?? originalTransaction.currency ?? CONST.CURRENCY.USD; - updatedSplitExpense.merchant = getDistanceMerchantForSplitExpense(distanceInUnits, unit, rate, currency, originalTransaction.currency); - } - } - return updatedSplitExpense; } return splitExpense; diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 400fe56a83c29..0112e9c17bbbe 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -465,9 +465,6 @@ type RequestMoneyTransactionParams = Omit & { pendingFields?: PendingFields; distance?: number; isLinkedTrackedExpenseReportArchived?: boolean; - customUnit?: TransactionCustomUnit; - odometerStart?: number; - odometerEnd?: number; /** Transaction type (e.g., 'time' for time tracking expenses) */ type?: ValueOf; @@ -3468,18 +3465,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma // I want to clean this up at some point, but it's possible this will live in the code for a while so I've created https://github.com/Expensify/App/issues/25417 // to remind me to do this. if (isDistanceRequest && existingTransaction) { - // For split expenses, exclude merchant from merge to preserve merchant from splitExpense - if (isSplitExpense) { - // Preserve merchant from transactionParams (splitExpense.merchant) before merge - const preservedMerchant = merchant || optimisticTransaction.merchant; - const {merchant: omittedMerchant, ...existingTransactionWithoutMerchant} = existingTransaction; - optimisticTransaction = fastMerge(existingTransactionWithoutMerchant, optimisticTransaction, false) as OnyxTypes.Transaction; - - // Explicitly set merchant from splitExpense to ensure it's not overwritten - optimisticTransaction.merchant = preservedMerchant; - } else { - optimisticTransaction = fastMerge(existingTransaction, optimisticTransaction, false); - } + optimisticTransaction = fastMerge(existingTransaction, optimisticTransaction, false); } if (isSplitExpense && existingTransaction) { diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index 1e6cc344be743..f8b49c7c995f0 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -1,6 +1,6 @@ import {getUnixTime} from 'date-fns'; import lodashClone from 'lodash/clone'; -import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxUpdate} from 'react-native-onyx'; +import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; import type { @@ -117,16 +117,9 @@ type SaveWaypointProps = { waypoint: RecentWaypoint | null; isDraft?: boolean; recentWaypointsList?: RecentWaypoint[]; - isSplitDraftTransaction?: boolean; }; -function saveWaypoint({transactionID, index, waypoint, isDraft = false, recentWaypointsList = [], isSplitDraftTransaction = false}: SaveWaypointProps) { - let key: OnyxKey = `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`; - if (isDraft) { - key = `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`; - } else if (isSplitDraftTransaction) { - key = `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; - } +function saveWaypoint({transactionID, index, waypoint, isDraft = false, recentWaypointsList = []}: SaveWaypointProps) { // Saving a waypoint should completely overwrite the existing one at the given index (if any). // Onyx merge performs noop on undefined fields. Thus we should fallback to null so the existing fields are cleared. const waypointOnyxUpdate: Required> | null = waypoint @@ -140,7 +133,7 @@ function saveWaypoint({transactionID, index, waypoint, isDraft = false, recentWa } : null; - Onyx.merge(key, { + Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { comment: { waypoints: { [`waypoint${index}`]: waypointOnyxUpdate, @@ -183,21 +176,13 @@ function saveWaypoint({transactionID, index, waypoint, isDraft = false, recentWa } } -function removeWaypoint(transaction: OnyxEntry, currentIndex: string, isDraft?: boolean, splitDraftTransaction?: OnyxEntry): Promise { - // Check if there's a split draft transaction for editing split expenses - const shouldUseSplitDraft = !isDraft && !!splitDraftTransaction; - const currentTransaction = shouldUseSplitDraft ? splitDraftTransaction : transaction; - - if (!currentTransaction?.transactionID) { - return Promise.resolve(); - } - +function removeWaypoint(transaction: OnyxEntry, currentIndex: string, isDraft?: boolean): Promise { // Index comes from the route params and is a string const index = Number(currentIndex); if (index === -1) { return Promise.resolve(); } - const existingWaypoints = currentTransaction?.comment?.waypoints ?? {}; + const existingWaypoints = transaction?.comment?.waypoints ?? {}; const totalWaypoints = Object.keys(existingWaypoints).length; const waypointValues = Object.values(existingWaypoints); @@ -223,12 +208,12 @@ function removeWaypoint(transaction: OnyxEntry, currentIndex: strin // Doing a deep clone of the transaction to avoid mutating the original object and running into a cache issue when using Onyx.set let newTransaction: Transaction = { // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - ...currentTransaction, + ...(transaction as Transaction), comment: { - ...currentTransaction?.comment, + ...transaction?.comment, waypoints: reIndexedWaypoints, customUnit: { - ...currentTransaction?.comment?.customUnit, + ...transaction?.comment?.customUnit, quantity: null, }, }, @@ -256,29 +241,21 @@ function removeWaypoint(transaction: OnyxEntry, currentIndex: strin }, }; } - if (shouldUseSplitDraft) { - return Onyx.set(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${currentTransaction?.transactionID}` as const, newTransaction); - } if (isDraft) { - return Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${currentTransaction?.transactionID}` as const, newTransaction); + return Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction?.transactionID}`, newTransaction); } - return Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${currentTransaction?.transactionID}` as const, newTransaction); + return Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction?.transactionID}`, newTransaction); } function getOnyxDataForRouteRequest( transactionID: string, transactionState: TransactionState = CONST.TRANSACTION.STATE.CURRENT, -): OnyxData< - typeof ONYXKEYS.COLLECTION.TRANSACTION_DRAFT | typeof ONYXKEYS.COLLECTION.TRANSACTION_BACKUP | typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT -> { +): OnyxData { let keyPrefix; switch (transactionState) { case CONST.TRANSACTION.STATE.DRAFT: keyPrefix = ONYXKEYS.COLLECTION.TRANSACTION_DRAFT; break; - case CONST.TRANSACTION.STATE.SPLIT_DRAFT: - keyPrefix = ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT; - break; case CONST.TRANSACTION.STATE.BACKUP: keyPrefix = ONYXKEYS.COLLECTION.TRANSACTION_BACKUP; break; @@ -369,9 +346,6 @@ function getRoute(transactionID: string, waypoints: WaypointCollection, routeTyp case CONST.TRANSACTION.STATE.DRAFT: command = READ_COMMANDS.GET_ROUTE_FOR_DRAFT; break; - case CONST.TRANSACTION.STATE.SPLIT_DRAFT: - command = READ_COMMANDS.GET_ROUTE_FOR_SPLIT_DRAFT; - break; case CONST.TRANSACTION.STATE.CURRENT: command = READ_COMMANDS.GET_ROUTE; break; @@ -388,10 +362,10 @@ function getRoute(transactionID: string, waypoints: WaypointCollection, routeTyp * Updates all waypoints stored in the transaction specified by the provided transactionID. * * @param transactionID - The ID of the transaction to be updated - * @param waypoints - An object containing all the waypoints which will replace the existing ones. - * @param transactionState - The state of the transaction that should be updated + * @param waypoints - An object containing all the waypoints + * which will replace the existing ones. */ -function updateWaypoints(transactionID: string, waypoints: WaypointCollection, transactionState: TransactionState = CONST.TRANSACTION.STATE.CURRENT): Promise { +function updateWaypoints(transactionID: string, waypoints: WaypointCollection, isDraft = false): Promise { // Updating waypoints should completely overwrite the existing ones. // Onyx merge performs noop on undefined fields. Thus we should fallback to null so the existing fields are cleared. const waypointsOnyxUpdate = Object.keys(waypoints).reduce( @@ -416,21 +390,7 @@ function updateWaypoints(transactionID: string, waypoints: WaypointCollection, t {} as Record>>, ); - let keyPrefix; - switch (transactionState) { - case CONST.TRANSACTION.STATE.DRAFT: - keyPrefix = ONYXKEYS.COLLECTION.TRANSACTION_DRAFT; - break; - case CONST.TRANSACTION.STATE.SPLIT_DRAFT: - keyPrefix = ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT; - break; - case CONST.TRANSACTION.STATE.CURRENT: - default: - keyPrefix = ONYXKEYS.COLLECTION.TRANSACTION; - break; - } - - return Onyx.merge(`${keyPrefix}${transactionID}`, { + return Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { comment: { waypoints: waypointsOnyxUpdate, customUnit: { @@ -439,7 +399,7 @@ function updateWaypoints(transactionID: string, waypoints: WaypointCollection, t }, // We want to reset the amount only for draft transactions (when creating the expense). // When modifying an existing transaction, the amount will be updated on the actual IOU update operation. - ...(transactionState === CONST.TRANSACTION.STATE.DRAFT && {amount: CONST.IOU.DEFAULT_AMOUNT}), + ...(isDraft && {amount: CONST.IOU.DEFAULT_AMOUNT}), // Empty out errors when we're saving new waypoints as this indicates the user is updating their input errorFields: { route: null, diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index be08bd1a10915..2dd407d49c58c 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -1022,9 +1022,7 @@ function SearchPage({route}: SearchPageProps) { icon: expensifyIcons.ArrowSplit, value: CONST.SEARCH.BULK_ACTION_TYPES.SPLIT, onSelected: () => { - const report = firstTransaction?.reportID ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${firstTransaction.reportID}`] : undefined; - const transactionPolicy = report?.policyID ? policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] : undefined; - initSplitExpense(allTransactions, allReports, firstTransaction, transactionPolicy); + initSplitExpense(allTransactions, allReports, firstTransaction); }, }); } diff --git a/src/pages/iou/SplitExpenseCreateDateRagePage.tsx b/src/pages/iou/SplitExpenseCreateDateRagePage.tsx index ebdb298871360..4e7487bed3455 100644 --- a/src/pages/iou/SplitExpenseCreateDateRagePage.tsx +++ b/src/pages/iou/SplitExpenseCreateDateRagePage.tsx @@ -53,7 +53,7 @@ function SplitExpenseCreateDateRagePage({route}: SplitExpenseCreateDateRagePageP const {login, accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const updateDate = (value: FormOnyxValues) => { - resetSplitExpensesByDateRange(transaction, currentReport, value[INPUT_IDS.START_DATE], value[INPUT_IDS.END_DATE], currentPolicy); + resetSplitExpensesByDateRange(transaction, currentReport, value[INPUT_IDS.START_DATE], value[INPUT_IDS.END_DATE]); Navigation.goBack(backTo); }; diff --git a/src/pages/iou/SplitExpenseEditPage.tsx b/src/pages/iou/SplitExpenseEditPage.tsx index 120502855c472..e33b1fad53d9d 100644 --- a/src/pages/iou/SplitExpenseEditPage.tsx +++ b/src/pages/iou/SplitExpenseEditPage.tsx @@ -9,32 +9,29 @@ import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import {useSearchContext} from '@components/Search/SearchContext'; import useAllTransactions from '@hooks/useAllTransactions'; -import useCurrencyList from '@hooks/useCurrencyList'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; -import {initDraftSplitExpenseDataForEdit, removeSplitExpenseField, updateSplitExpenseField} from '@libs/actions/IOU/Split'; +import {removeSplitExpenseField, updateSplitExpenseField} from '@libs/actions/IOU/Split'; import {openPolicyCategoriesPage} from '@libs/actions/Policy/Category'; import {openPolicyTagsPage} from '@libs/actions/Policy/Tag'; import {getDecodedCategoryName, isCategoryDescriptionRequired} from '@libs/CategoryUtils'; import {convertToDisplayString} from '@libs/CurrencyUtils'; -import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SplitExpenseParamList} from '@libs/Navigation/types'; import Parser from '@libs/Parser'; import {getTagLists} from '@libs/PolicyUtils'; -import {getReportName} from '@libs/ReportNameUtils'; +import {computeReportName} from '@libs/ReportNameUtils'; import {isSplitAction} from '@libs/ReportSecondaryActionUtils'; import type {TransactionDetails} from '@libs/ReportUtils'; import {getParsedComment, getReportOrDraftReport, getTransactionDetails} from '@libs/ReportUtils'; import {getTagVisibility, hasEnabledTags} from '@libs/TagsOptionsListUtils'; -import {getDistanceInMeters, getTag, getTagForDisplay, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest} from '@libs/TransactionUtils'; +import {getTag, getTagForDisplay} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -45,9 +42,7 @@ type SplitExpensePageProps = PlatformStackScreenProps v.shouldShow)) ?? []; - const isDistance = isDistanceRequest(splitExpenseDraftTransaction); - const isManualDistance = isManualDistanceRequest(splitExpenseDraftTransaction); - const isOdometerDistance = isOdometerDistanceRequest(splitExpenseDraftTransaction); - const {unit, rate} = DistanceRequestUtils.getRate({transaction: splitExpenseDraftTransaction, policy: currentPolicy}); - const distance = getDistanceInMeters(splitExpenseDraftTransaction, unit); - const currency = splitExpenseDraftTransactionDetails.currency ?? CONST.CURRENCY.USD; - const rateToDisplay = DistanceRequestUtils.getRateForDisplay(unit, rate, currency, translate, toLocaleDigit, getCurrencySymbol, isOffline); - const distanceToDisplay = DistanceRequestUtils.getDistanceForDisplay(true, distance, unit, rate, translate); - - const distanceRequestFields = isDistance ? ( - <> - { - if (isOdometerDistance) { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DISTANCE_ODOMETER.getRoute(CONST.IOU.ACTION.EDIT, CONST.IOU.TYPE.SPLIT_EXPENSE, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, reportID), - ); - return; - } - - if (isManualDistance) { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DISTANCE_MANUAL.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.SPLIT_EXPENSE, - CONST.IOU.OPTIMISTIC_TRANSACTION_ID, - reportID, - Navigation.getActiveRoute(), - ), - ); - return; - } - - initDraftSplitExpenseDataForEdit(originalTransactionDraft, splitExpenseTransactionID, reportID, CONST.IOU.OPTIMISTIC_DISTANCE_SPLIT_TRANSACTION_ID); - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.SPLIT_EXPENSE, - CONST.IOU.OPTIMISTIC_DISTANCE_SPLIT_TRANSACTION_ID, - reportID, - Navigation.getActiveRoute(), - ), - ); - }} - /> - { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.SPLIT_EXPENSE, - CONST.IOU.OPTIMISTIC_TRANSACTION_ID, - reportID, - Navigation.getActiveRoute(), - ), - ); - }} - /> - - ) : null; - return ( @@ -234,7 +156,6 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { numberOfLinesTitle={2} rightLabel={isDescriptionRequired ? translate('common.required') : ''} /> - {distanceRequestFields} {shouldShowCategory && ( { - updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, transaction, currentPolicy); + updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, originalTransaction); Navigation.goBack(backTo); }} pressOnEnter diff --git a/src/pages/iou/SplitExpensePage.tsx b/src/pages/iou/SplitExpensePage.tsx index e3983e7817d9d..80bbc16f4d234 100644 --- a/src/pages/iou/SplitExpensePage.tsx +++ b/src/pages/iou/SplitExpensePage.tsx @@ -50,7 +50,7 @@ import {isSplitAction} from '@libs/ReportSecondaryActionUtils'; import {getReportOrDraftReport, getTransactionDetails, isReportApproved, isSettled as isSettledReportUtils} from '@libs/ReportUtils'; import type {TransactionDetails} from '@libs/ReportUtils'; import type {TranslationPathOrText} from '@libs/TransactionPreviewUtils'; -import {getChildTransactions, getExpenseTypeTranslationKey, getTransactionType, isDistanceRequest, isManagedCardTransaction, isPerDiemRequest} from '@libs/TransactionUtils'; +import {getChildTransactions, getExpenseTypeTranslationKey, getTransactionType, isManagedCardTransaction, isPerDiemRequest} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -114,7 +114,6 @@ function SplitExpensePage({route}: SplitExpensePageProps) { const currencySymbol = getCurrencySymbol(transactionDetails.currency ?? '') ?? transactionDetails.currency ?? CONST.CURRENCY.USD; const isPerDiem = isPerDiemRequest(transaction); - const isDistance = isDistanceRequest(transaction); const isCard = isManagedCardTransaction(transaction); const originalTransactionID = draftTransaction?.comment?.originalTransactionID ?? CONST.IOU.OPTIMISTIC_TRANSACTION_ID; const iouActions = getIOUActionForTransactions([originalTransactionID], expenseReport?.reportID); @@ -156,14 +155,14 @@ function SplitExpensePage({route}: SplitExpensePageProps) { if (draftTransaction?.errors) { clearSplitTransactionDraftErrors(transactionID); } - addSplitExpenseField(transaction, draftTransaction, transactionReport, currentPolicy); + addSplitExpenseField(transaction, draftTransaction, transactionReport); }; const onMakeSplitsEven = () => { if (!draftTransaction) { return; } - evenlyDistributeSplitExpenseAmounts(draftTransaction, transaction, currentPolicy); + evenlyDistributeSplitExpenseAmounts(draftTransaction); }; const onSaveSplitExpense = () => { @@ -201,12 +200,12 @@ function SplitExpensePage({route}: SplitExpensePageProps) { if (draftTransaction?.errors) { clearSplitTransactionDraftErrors(transactionID); } - if (sumOfSplitExpenses > transactionDetailsAmount && !isDistance) { + if (sumOfSplitExpenses > transactionDetailsAmount) { const difference = sumOfSplitExpenses - transactionDetailsAmount; setErrorMessage(translate('iou.totalAmountGreaterThanOriginal', {amount: convertToDisplayString(difference, transactionDetails?.currency)})); return; } - if (sumOfSplitExpenses < transactionDetailsAmount && (isPerDiem || isCard) && !isDistance) { + if (sumOfSplitExpenses < transactionDetailsAmount && (isPerDiem || isCard)) { const difference = transactionDetailsAmount - sumOfSplitExpenses; setErrorMessage(translate('iou.totalAmountLessThanOriginal', {amount: convertToDisplayString(difference, transactionDetails?.currency)})); return; @@ -252,10 +251,10 @@ function SplitExpensePage({route}: SplitExpensePageProps) { const onSplitExpenseValueChange = (id: string, value: number, mode: ValueOf) => { if (mode === CONST.TAB.SPLIT.AMOUNT || mode === CONST.TAB.SPLIT.DATE) { const amountInCents = convertToBackendAmount(value); - updateSplitExpenseAmountField(draftTransaction, id, amountInCents, currentPolicy); + updateSplitExpenseAmountField(draftTransaction, id, amountInCents); } else { const amountInCents = calculateSplitAmountFromPercentage(transactionDetailsAmount, value); - updateSplitExpenseAmountField(draftTransaction, id, amountInCents, currentPolicy); + updateSplitExpenseAmountField(draftTransaction, id, amountInCents); } }; @@ -419,7 +418,6 @@ function SplitExpensePage({route}: SplitExpensePageProps) { // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { initDraftSplitExpenseDataForEdit(draftTransaction, item.transactionID, item.reportID ?? reportID); - Navigation.navigate(ROUTES.SPLIT_EXPENSE_EDIT.getRoute(item.reportID ?? reportID, originalTransactionID, item.transactionID, Navigation.getActiveRoute())); }); }; diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index d12a045e44742..b098e7da20b79 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -30,7 +30,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWaypointItems from '@hooks/useWaypointItems'; import {getIOURequestPolicyID, setMoneyRequestAmount, updateMoneyRequestDistance} from '@libs/actions/IOU'; import {handleMoneyRequestStepDistanceNavigation} from '@libs/actions/IOU/MoneyRequest'; -import {setDraftSplitTransaction, setSplitShares} from '@libs/actions/IOU/Split'; +import {setSplitShares} from '@libs/actions/IOU/Split'; import {init, stop} from '@libs/actions/MapboxToken'; import {openReport} from '@libs/actions/Report'; import {openDraftDistanceExpense, removeWaypoint, updateWaypoints as updateWaypointsUtil} from '@libs/actions/Transaction'; @@ -45,7 +45,6 @@ import {getPolicy} from '@libs/PolicyUtils'; import {isArchivedReport, isPolicyExpenseChat as isPolicyExpenseChatUtil} from '@libs/ReportUtils'; import {getDistanceInMeters, getRateID, getRequestType, hasRoute, isCustomUnitRateIDForP2P, isWaypointNullIsland} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; -import type {IOUType} from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; @@ -54,7 +53,6 @@ import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import type Transaction from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type TransactionStateType from '@src/types/utils/TransactionStateType'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; @@ -85,8 +83,6 @@ function IOURequestStepDistance({ const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [transactionBackup] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_BACKUP}${transactionID}`, {canBeMissing: true}); - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); - const [originalSplitTransactionDraft] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`, {canBeMissing: true}); const selfDMReport = useSelfDMReport(); const policy = usePolicy(report?.policyID); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policy?.id}`, {canBeMissing: true}); @@ -101,15 +97,10 @@ function IOURequestStepDistance({ const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); - const {policyForMovingExpenses} = usePolicyForMovingExpenses(); const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true}); - const isEditing = action === CONST.IOU.ACTION.EDIT; - const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; - const currentTransaction = isEditingSplit && !isEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction; - - const transactionWaypoints = currentTransaction?.comment?.waypoints; + const transactionWaypoints = transaction?.comment?.waypoints; const areTransactionWaypointsEmpty = !transactionWaypoints || Object.values(transactionWaypoints).every((w) => isEmptyObject(w)); const waypoints = useMemo(() => { @@ -126,26 +117,25 @@ function IOURequestStepDistance({ const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); - let transactionState: TransactionStateType = CONST.TRANSACTION.STATE.CURRENT; - if (isEditingSplit) { - transactionState = CONST.TRANSACTION.STATE.SPLIT_DRAFT; - } else if (shouldUseTransactionDraft(action)) { - transactionState = CONST.TRANSACTION.STATE.DRAFT; - } const backupWaypoints = transactionBackup?.pendingFields?.waypoints ? transactionBackup?.comment?.waypoints : undefined; // When online, fetch the backup route to ensure the map is populated even if the user does not save the transaction. // Fetch the backup route first to ensure the backup transaction map is updated before the main transaction map. // This prevents a scenario where the main map loads, the user dismisses the map editor, and the backup map has not yet loaded due to delay. useFetchRoute(transactionBackup, backupWaypoints, action, CONST.TRANSACTION.STATE.BACKUP); - const {shouldFetchRoute, validatedWaypoints} = useFetchRoute(currentTransaction, waypoints, action, transactionState); + const {shouldFetchRoute, validatedWaypoints} = useFetchRoute( + transaction, + waypoints, + action, + shouldUseTransactionDraft(action) ? CONST.TRANSACTION.STATE.DRAFT : CONST.TRANSACTION.STATE.CURRENT, + ); const previousWaypoints = usePrevious(waypoints); const numberOfWaypoints = Object.keys(waypoints).length; const numberOfPreviousWaypoints = Object.keys(previousWaypoints).length; const scrollViewRef = useRef(null); - const isLoadingRoute = currentTransaction?.comment?.isLoading ?? false; - const isLoading = currentTransaction?.isLoading ?? false; + const isLoadingRoute = transaction?.comment?.isLoading ?? false; + const isLoading = transaction?.isLoading ?? false; const isSplitRequest = iouType === CONST.IOU.TYPE.SPLIT; - const hasRouteError = !!currentTransaction?.errorFields?.route; + const hasRouteError = !!transaction?.errorFields?.route; const [shouldShowAtLeastTwoDifferentWaypointsError, setShouldShowAtLeastTwoDifferentWaypointsError] = useState(false); const isWaypointEmpty = (waypoint?: Waypoint) => { if (!waypoint) { @@ -163,14 +153,15 @@ function IOURequestStepDistance({ [nonEmptyWaypointsCount, validatedWaypoints], ); const atLeastTwoDifferentWaypointsError = useMemo(() => Object.keys(validatedWaypoints).length < 2, [validatedWaypoints]); + const isEditing = action === CONST.IOU.ACTION.EDIT; const transactionWasSaved = useRef(false); const isCreatingNewRequest = !(backTo || isEditing); const [recentWaypoints, {status: recentWaypointsStatus}] = useOnyx(ONYXKEYS.NVP_RECENT_WAYPOINTS, {canBeMissing: true}); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); - const iouRequestType = getRequestType(currentTransaction); - const customUnitRateID = getRateID(currentTransaction); + const iouRequestType = getRequestType(transaction); + const customUnitRateID = getRateID(transaction); // eslint-disable-next-line rulesdir/no-negated-variables - const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, currentTransaction); + const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); @@ -261,7 +252,7 @@ function IOURequestStepDistance({ // original transaction, letting the user modify the current transaction, and then if the user ever // cancels out of the modal without saving changes, the original transaction is restored from the backup. useEffect(() => { - if (isCreatingNewRequest || isEditingSplit) { + if (isCreatingNewRequest) { return () => {}; } const isDraft = shouldUseTransactionDraft(action); @@ -296,15 +287,11 @@ function IOURequestStepDistance({ */ const navigateToWaypointEditPage = useCallback( (index: number) => { - let iouWaypointType = CONST.IOU.TYPE.SUBMIT as IOUType; - if (isEditingSplit) { - iouWaypointType = CONST.IOU.TYPE.SPLIT_EXPENSE; - } Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_WAYPOINT.getRoute(action, iouWaypointType, transactionID, report?.reportID ?? reportID, index.toString(), Navigation.getActiveRoute()), + ROUTES.MONEY_REQUEST_STEP_WAYPOINT.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, report?.reportID ?? reportID, index.toString(), Navigation.getActiveRoute()), ); }, - [action, transactionID, report?.reportID, reportID, isEditingSplit], + [action, transactionID, report?.reportID, reportID], ); const navigateToNextStep = useCallback(() => { @@ -378,7 +365,7 @@ function IOURequestStepDistance({ const getError = () => { // Get route error if available else show the invalid number of waypoints error. if (hasRouteError) { - return getLatestErrorField(currentTransaction, 'route'); + return getLatestErrorField(transaction, 'route'); } if (isWaypointsNullIslandError) { return {isWaypointsNullIslandError: `${translate('common.please')} ${translate('common.fixTheErrors')} ${translate('common.inTheFormBeforeContinuing')}.`} as Errors; @@ -415,16 +402,14 @@ function IOURequestStepDistance({ } setOptimisticWaypoints(newWaypoints); - const shouldPassSplitDraft = isEditingSplit && !isEmpty(splitDraftTransaction); - Promise.all([ - removeWaypoint(currentTransaction, emptyWaypointIndex.toString(), shouldUseTransactionDraft(action), shouldPassSplitDraft ? splitDraftTransaction : undefined), - updateWaypointsUtil(transactionID, newWaypoints, transactionState), + removeWaypoint(transaction, emptyWaypointIndex.toString(), shouldUseTransactionDraft(action)), + updateWaypointsUtil(transactionID, newWaypoints, shouldUseTransactionDraft(action)), ]).then(() => { setOptimisticWaypoints(null); }); }, - [waypointItems, getWaypoint, waypoints, isEditingSplit, splitDraftTransaction, currentTransaction, action, transactionID, transactionState], + [transactionID, transaction, waypoints, action, waypointItems, getWaypoint], ); const submitWaypoints = useCallback(() => { @@ -437,18 +422,6 @@ function IOURequestStepDistance({ transactionWasSaved.current = true; } if (isEditing) { - // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value in transaction with CONST.IOU.OPTIMISTIC_DISTANCE_SPLIT_TRANSACTION_ID - if (isEditingSplit && originalSplitTransactionDraft) { - setDraftSplitTransaction( - CONST.IOU.OPTIMISTIC_TRANSACTION_ID, - originalSplitTransactionDraft, - {waypoints: currentTransaction?.comment?.waypoints, routes: currentTransaction?.routes}, - policy, - ); - navigateBack(); - return; - } - // If nothing was changed, simply go to transaction thread // We compare only addresses because numbers are rounded while backup const oldWaypoints = transactionBackup?.comment?.waypoints ?? {}; @@ -492,19 +465,15 @@ function IOURequestStepDistance({ isLoading, isCreatingNewRequest, navigateToNextStep, - isEditingSplit, - originalSplitTransactionDraft, transactionBackup, waypoints, transaction?.routes, transaction?.transactionID, report, navigateBack, - currentTransaction?.comment?.waypoints, - currentTransaction?.routes, - policy, parentReport, recentWaypoints, + policy, policyTags, policyCategories, currentUserAccountIDParam, @@ -533,7 +502,7 @@ function IOURequestStepDistance({ headerTitle={translate('common.distance')} onBackButtonPress={navigateBack} testID="IOURequestStepDistance" - shouldShowNotFoundPage={(isEditing && !currentTransaction?.comment?.waypoints) || shouldShowNotFoundPage} + shouldShowNotFoundPage={(isEditing && !transaction?.comment?.waypoints) || shouldShowNotFoundPage} shouldShowWrapper={!isCreatingNewRequest} > <> diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 7cf82c8a355e1..ac09c7c65e047 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import {useFocusEffect} from '@react-navigation/native'; import reportsSelector from '@selectors/Attributes'; -import lodashIsEmpty from 'lodash/isEmpty'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import Button from '@components/Button'; @@ -93,11 +92,7 @@ function IOURequestStepDistanceManual({ const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true}); - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); - const isEditing = action === CONST.IOU.ACTION.EDIT; - const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; - const currentTransaction = isEditingSplit && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction; const isCreatingNewRequest = !(backTo || isEditing); const isTransactionDraft = shouldUseTransactionDraft(action, iouType); @@ -158,13 +153,6 @@ function IOURequestStepDistanceManual({ setMoneyRequestDistance(transactionID, distanceAsFloat, isTransactionDraft); if (action === CONST.IOU.ACTION.EDIT) { - // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value - if (isEditingSplit && transaction) { - setDraftSplitTransaction(transaction.transactionID, splitDraftTransaction, {distance: distanceAsFloat}, policy); - Navigation.goBack(backTo); - return; - } - if (distance !== distanceAsFloat) { updateMoneyRequestDistance({ transactionID: transaction?.transactionID, @@ -249,10 +237,8 @@ function IOURequestStepDistanceManual({ introSelected, activePolicyID, reportNameValuePairs?.private_isArchived, - isEditingSplit, - distance, - splitDraftTransaction, policyForMovingExpenses, + distance, parentReport, policyTags, policyCategories, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 1d10b68759092..6fd511cef9810 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -30,7 +30,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWaypointItems from '@hooks/useWaypointItems'; import {getIOURequestPolicyID, setMoneyRequestAmount, updateMoneyRequestDistance} from '@libs/actions/IOU'; import {handleMoneyRequestStepDistanceNavigation} from '@libs/actions/IOU/MoneyRequest'; -import {setDraftSplitTransaction, setSplitShares} from '@libs/actions/IOU/Split'; +import {setSplitShares} from '@libs/actions/IOU/Split'; import {init, stop} from '@libs/actions/MapboxToken'; import {openReport} from '@libs/actions/Report'; import {openDraftDistanceExpense, removeWaypoint, updateWaypoints as updateWaypointsUtil} from '@libs/actions/Transaction'; @@ -53,7 +53,6 @@ import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import type Transaction from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type TransactionStateType from '@src/types/utils/TransactionStateType'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; @@ -84,7 +83,6 @@ function IOURequestStepDistanceMap({ const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [transactionBackup] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_BACKUP}${transactionID}`, {canBeMissing: true}); - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); const selfDMReport = useSelfDMReport(); const policy = usePolicy(report?.policyID); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policy?.id}`, {canBeMissing: true}); @@ -99,13 +97,8 @@ function IOURequestStepDistanceMap({ const [optimisticWaypoints, setOptimisticWaypoints] = useState(null); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true}); - const isEditing = action === CONST.IOU.ACTION.EDIT; - const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; - const currentTransaction = isEditingSplit && !isEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction; - - const transactionWaypoints = currentTransaction?.comment?.waypoints; + const transactionWaypoints = transaction?.comment?.waypoints; const areTransactionWaypointsEmpty = !transactionWaypoints || Object.values(transactionWaypoints).every((w) => isEmptyObject(w)); - const waypoints = useMemo(() => { return ( optimisticWaypoints ?? @@ -117,29 +110,27 @@ function IOURequestStepDistanceMap({ : transactionWaypoints) ); }, [optimisticWaypoints, transactionWaypoints, areTransactionWaypointsEmpty]); - const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); - let transactionState: TransactionStateType = CONST.TRANSACTION.STATE.CURRENT; - if (isEditingSplit) { - transactionState = CONST.TRANSACTION.STATE.SPLIT_DRAFT; - } else if (shouldUseTransactionDraft(action)) { - transactionState = CONST.TRANSACTION.STATE.DRAFT; - } const backupWaypoints = transactionBackup?.pendingFields?.waypoints ? transactionBackup?.comment?.waypoints : undefined; // When online, fetch the backup route to ensure the map is populated even if the user does not save the transaction. // Fetch the backup route first to ensure the backup transaction map is updated before the main transaction map. // This prevents a scenario where the main map loads, the user dismisses the map editor, and the backup map has not yet loaded due to delay. useFetchRoute(transactionBackup, backupWaypoints, action, CONST.TRANSACTION.STATE.BACKUP); - const {shouldFetchRoute, validatedWaypoints} = useFetchRoute(currentTransaction, waypoints, action, transactionState); + const {shouldFetchRoute, validatedWaypoints} = useFetchRoute( + transaction, + waypoints, + action, + shouldUseTransactionDraft(action) ? CONST.TRANSACTION.STATE.DRAFT : CONST.TRANSACTION.STATE.CURRENT, + ); const previousWaypoints = usePrevious(waypoints); const numberOfWaypoints = Object.keys(waypoints).length; const numberOfPreviousWaypoints = Object.keys(previousWaypoints).length; const scrollViewRef = useRef(null); - const isLoadingRoute = currentTransaction?.comment?.isLoading ?? false; - const isLoading = currentTransaction?.isLoading ?? false; + const isLoadingRoute = transaction?.comment?.isLoading ?? false; + const isLoading = transaction?.isLoading ?? false; const isSplitRequest = iouType === CONST.IOU.TYPE.SPLIT; - const hasRouteError = !!currentTransaction?.errorFields?.route; + const hasRouteError = !!transaction?.errorFields?.route; const [shouldShowAtLeastTwoDifferentWaypointsError, setShouldShowAtLeastTwoDifferentWaypointsError] = useState(false); const isWaypointEmpty = (waypoint?: Waypoint) => { if (!waypoint) { @@ -156,13 +147,14 @@ function IOURequestStepDistanceMap({ [nonEmptyWaypointsCount, validatedWaypoints], ); const atLeastTwoDifferentWaypointsError = useMemo(() => Object.keys(validatedWaypoints).length < 2, [validatedWaypoints]); + const isEditing = action === CONST.IOU.ACTION.EDIT; const transactionWasSaved = useRef(false); const isCreatingNewRequest = !(backTo || isEditing); const [recentWaypoints, {status: recentWaypointsStatus}] = useOnyx(ONYXKEYS.NVP_RECENT_WAYPOINTS, {canBeMissing: true}); - const iouRequestType = getRequestType(currentTransaction); - const customUnitRateID = getRateID(currentTransaction); + const iouRequestType = getRequestType(transaction); + const customUnitRateID = getRateID(transaction); // eslint-disable-next-line rulesdir/no-negated-variables - const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, currentTransaction); + const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); @@ -370,7 +362,7 @@ function IOURequestStepDistanceMap({ const getError = () => { // Get route error if available else show the invalid number of waypoints error. if (hasRouteError) { - return getLatestErrorField(currentTransaction, 'route'); + return getLatestErrorField(transaction, 'route'); } if (isWaypointsNullIslandError) { return {isWaypointsNullIslandError: `${translate('common.please')} ${translate('common.fixTheErrors')} ${translate('common.inTheFormBeforeContinuing')}.`} as Errors; @@ -407,16 +399,14 @@ function IOURequestStepDistanceMap({ } setOptimisticWaypoints(newWaypoints); - const shouldPassSplitDraft = isEditingSplit && !isEmpty(splitDraftTransaction); - Promise.all([ - removeWaypoint(currentTransaction, emptyWaypointIndex.toString(), shouldUseTransactionDraft(action), shouldPassSplitDraft ? splitDraftTransaction : undefined), - updateWaypointsUtil(transactionID, newWaypoints, transactionState), + removeWaypoint(transaction, emptyWaypointIndex.toString(), shouldUseTransactionDraft(action)), + updateWaypointsUtil(transactionID, newWaypoints, shouldUseTransactionDraft(action)), ]).then(() => { setOptimisticWaypoints(null); }); }, - [waypointItems, isEditingSplit, splitDraftTransaction, currentTransaction, action, transactionID, transactionState, getWaypoint, waypoints], + [transactionID, transaction, waypoints, waypointItems, action, getWaypoint], ); const submitWaypoints = useCallback(() => { @@ -429,13 +419,6 @@ function IOURequestStepDistanceMap({ transactionWasSaved.current = true; } if (isEditing) { - // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value - if (isEditingSplit && transaction) { - setDraftSplitTransaction(transaction.transactionID, splitDraftTransaction, {waypoints}, policy); - navigateBack(); - return; - } - // If nothing was changed, simply go to transaction thread // We compare only addresses because numbers are rounded while backup const oldWaypoints = transactionBackup?.comment?.waypoints ?? {}; @@ -471,28 +454,27 @@ function IOURequestStepDistanceMap({ navigateToNextStep(); }, [ - duplicateWaypointsError, atLeastTwoDifferentWaypointsError, + currentUserAccountIDParam, + currentUserEmailParam, + duplicateWaypointsError, hasRouteError, - isLoadingRoute, + isASAPSubmitBetaEnabled, + isCreatingNewRequest, isEditing, isLoading, - isCreatingNewRequest, - navigateToNextStep, - isEditingSplit, - transaction, - transactionBackup, - waypoints, - report, + isLoadingRoute, navigateBack, - splitDraftTransaction, - policy, + navigateToNextStep, parentReport, + policy, policyTags, policyCategories, - currentUserAccountIDParam, - currentUserEmailParam, - isASAPSubmitBetaEnabled, + report, + transaction?.routes, + transaction?.transactionID, + transactionBackup, + waypoints, parentReportNextStep, recentWaypoints, ]); @@ -522,7 +504,7 @@ function IOURequestStepDistanceMap({ headerTitle={translate('common.distance')} onBackButtonPress={navigateBack} testID="IOURequestStepDistanceMap" - shouldShowNotFoundPage={(isEditing && !currentTransaction?.comment?.waypoints) || shouldShowNotFoundPage} + shouldShowNotFoundPage={(isEditing && !transaction?.comment?.waypoints) || shouldShowNotFoundPage} shouldShowWrapper={!isCreatingNewRequest} > <> diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index f478691aede5c..3ba2ad4085417 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -1,5 +1,4 @@ import reportsSelector from '@selectors/Attributes'; -import lodashIsEmpty from 'lodash/isEmpty'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -111,7 +110,6 @@ function IOURequestStepDistanceOdometer({ const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: true}); - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const policy = usePolicy(report?.policyID); @@ -124,8 +122,6 @@ function IOURequestStepDistanceOdometer({ // isEditing: we're changing an already existing odometer expense; isEditingConfirmation: we navigated here by pressing 'Distance' field from the confirmation step during the creation of a new odometer expense to adjust the input before submitting const isEditing = action === CONST.IOU.ACTION.EDIT; - const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; - const currentTransaction = isEditingSplit && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction; const isEditingConfirmation = routeName !== SCREENS.MONEY_REQUEST.DISTANCE_CREATE && !isEditing; const isCreatingNewRequest = !isEditingConfirmation && !isEditing; const isTransactionDraft = shouldUseTransactionDraft(action, iouType); @@ -135,7 +131,7 @@ function IOURequestStepDistanceOdometer({ const shouldUseDefaultExpensePolicy = useMemo(() => shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy), [iouType, defaultExpensePolicy]); - const unit = DistanceRequestUtils.getRate({transaction: currentTransaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}).unit; + const unit = DistanceRequestUtils.getRate({transaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}).unit; const shouldSkipConfirmation: boolean = !skipConfirmation || !report?.reportID ? false : !(isArchived || isPolicyExpenseChatUtils(report)); @@ -179,27 +175,22 @@ function IOURequestStepDistanceOdometer({ if (hasInitializedRefs.current) { return; } - const currentStart = currentTransaction?.comment?.odometerStart; - const currentEnd = currentTransaction?.comment?.odometerEnd; + const currentStart = transaction?.comment?.odometerStart; + const currentEnd = transaction?.comment?.odometerEnd; const startValue = currentStart !== null && currentStart !== undefined ? currentStart.toString() : ''; const endValue = currentEnd !== null && currentEnd !== undefined ? currentEnd.toString() : ''; initialStartReadingRef.current = startValue; initialEndReadingRef.current = endValue; - initialStartImageRef.current = currentTransaction?.comment?.odometerStartImage; - initialEndImageRef.current = currentTransaction?.comment?.odometerEndImage; + initialStartImageRef.current = transaction?.comment?.odometerStartImage; + initialEndImageRef.current = transaction?.comment?.odometerEndImage; hasInitializedRefs.current = true; - }, [ - currentTransaction?.comment?.odometerStart, - currentTransaction?.comment?.odometerEnd, - currentTransaction?.comment?.odometerStartImage, - currentTransaction?.comment?.odometerEndImage, - ]); + }, [transaction?.comment?.odometerStart, transaction?.comment?.odometerEnd, transaction?.comment?.odometerStartImage, transaction?.comment?.odometerEndImage]); // Initialize values from transaction when editing or when transaction has data (but not when switching tabs) // This updates the current state, but NOT the initial refs (those are set only once on mount) useEffect(() => { - const currentStart = currentTransaction?.comment?.odometerStart; - const currentEnd = currentTransaction?.comment?.odometerEnd; + const currentStart = transaction?.comment?.odometerStart; + const currentEnd = transaction?.comment?.odometerEnd; // Only initialize if: // 1. We haven't initialized yet AND transaction has data, OR @@ -223,7 +214,7 @@ function IOURequestStepDistanceOdometer({ endReadingRef.current = endValue; } } - }, [currentTransaction?.comment?.odometerStart, currentTransaction?.comment?.odometerEnd, isEditing]); + }, [transaction?.comment?.odometerStart, transaction?.comment?.odometerEnd, isEditing]); // Calculate total distance - updated live after every input change const totalDistance = (() => { @@ -370,22 +361,6 @@ function IOURequestStepDistanceOdometer({ setMoneyRequestDistance(transactionID, calculatedDistance, isTransactionDraft); if (isEditing) { - // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value - if (isEditingSplit && transaction) { - setDraftSplitTransaction( - transaction.transactionID, - splitDraftTransaction, - { - distance: calculatedDistance, - odometerStart: start, - odometerEnd: end, - }, - policy, - ); - Navigation.goBack(); - return; - } - // Update existing transaction const previousDistance = transaction?.comment?.customUnit?.quantity; const previousStart = transaction?.comment?.odometerStart; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 44375e450d290..f7233cad08f64 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -1,4 +1,3 @@ -import lodashIsEmpty from 'lodash/isEmpty'; import React, {useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import SelectionList from '@components/SelectionList'; @@ -12,7 +11,6 @@ import usePermissions from '@hooks/usePermissions'; import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep'; import useThemeStyles from '@hooks/useThemeStyles'; import {getIOURequestPolicyID, setMoneyRequestDistanceRate, setMoneyRequestTaxAmount, setMoneyRequestTaxRate, updateMoneyRequestDistanceRate} from '@libs/actions/IOU'; -import {setDraftSplitTransaction} from '@libs/actions/IOU/Split'; import {convertToBackendAmount} from '@libs/CurrencyUtils'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; @@ -61,22 +59,18 @@ function IOURequestStepDistanceRate({ /* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); - const policy: OnyxEntry = policyReal ?? policyDraft; const styles = useThemeStyles(); const {translate, toLocaleDigit, localeCompare} = useLocalize(); - const isEditing = action === CONST.IOU.ACTION.EDIT; - const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; - const currentTransaction = isEditingSplit && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction; - const isDistanceRequest = isDistanceRequestTransactionUtils(currentTransaction); const {getCurrencySymbol, getCurrencyDecimals} = useCurrencyList(); + const isDistanceRequest = isDistanceRequestTransactionUtils(transaction); const isPolicyExpenseChat = isReportInGroupPolicy(report); const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest); + const isEditing = action === CONST.IOU.ACTION.EDIT; - const currentRateID = getRateID(currentTransaction); - const transactionCurrency = getCurrency(currentTransaction); + const currentRateID = getRateID(transaction); + const transactionCurrency = getCurrency(transaction); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserAccountIDParam = currentUserPersonalDetails.accountID; const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; @@ -91,7 +85,7 @@ function IOURequestStepDistanceRate({ }; const options = sortedRates.map((rate) => { - const unit = currentTransaction?.comment?.customUnit?.customUnitRateID === rate.customUnitRateID ? DistanceRequestUtils.getDistanceUnit(currentTransaction, rate) : rate.unit; + const unit = transaction?.comment?.customUnit?.customUnitRateID === rate.customUnitRateID ? DistanceRequestUtils.getDistanceUnit(transaction, rate) : rate.unit; const isSelected = currentRateID ? currentRateID === rate.customUnitRateID : DistanceRequestUtils.getDefaultMileageRate(policy)?.customUnitRateID === rate.customUnitRateID; const rateForDisplay = DistanceRequestUtils.getRateForDisplay(unit, rate.rate, isSelected ? transactionCurrency : rate.currency, translate, toLocaleDigit, getCurrencySymbol); return { @@ -104,7 +98,7 @@ function IOURequestStepDistanceRate({ }; }); // eslint-disable-next-line rulesdir/no-negated-variables - const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, currentTransaction); + const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction); const initiallyFocusedOption = options.find((item) => item.isSelected)?.keyForList; @@ -113,25 +107,18 @@ function IOURequestStepDistanceRate({ let taxRateExternalID; if (shouldShowTax) { const policyCustomUnitRate = getDistanceRateCustomUnitRate(policy, customUnitRateID); - const defaultTaxCode = getDefaultTaxCode(policy, currentTransaction) ?? ''; + const defaultTaxCode = getDefaultTaxCode(policy, transaction) ?? ''; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing taxRateExternalID = policyCustomUnitRate?.attributes?.taxRateExternalID || defaultTaxCode; - const unit = DistanceRequestUtils.getDistanceUnit(currentTransaction, rates[customUnitRateID]); - const taxableAmount = DistanceRequestUtils.getTaxableAmount(policy, customUnitRateID, getDistanceInMeters(currentTransaction, unit)); - const taxPercentage = taxRateExternalID ? getTaxValue(policy, currentTransaction, taxRateExternalID) : undefined; + const unit = DistanceRequestUtils.getDistanceUnit(transaction, rates[customUnitRateID]); + const taxableAmount = DistanceRequestUtils.getTaxableAmount(policy, customUnitRateID, getDistanceInMeters(transaction, unit)); + const taxPercentage = taxRateExternalID ? getTaxValue(policy, transaction, taxRateExternalID) : undefined; taxAmount = convertToBackendAmount(calculateTaxAmount(taxPercentage, taxableAmount, getCurrencyDecimals(rates[customUnitRateID].currency))); setMoneyRequestTaxAmount(transactionID, taxAmount, shouldUseTransactionDraft(action)); setMoneyRequestTaxRate(transactionID, taxRateExternalID ?? null, shouldUseTransactionDraft(action)); } if (currentRateID !== customUnitRateID) { - // In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value - if (isEditingSplit && transaction) { - setDraftSplitTransaction(transaction.transactionID, splitDraftTransaction, {customUnitRateID}, policy); - navigateBack(); - return; - } - setMoneyRequestDistanceRate(transactionID, customUnitRateID, policy, shouldUseTransactionDraft(action)); if (isEditing && transaction?.transactionID) { diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index 615f23c77b093..1a4558966668d 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -1,5 +1,4 @@ import {useNavigation} from '@react-navigation/native'; -import lodashIsEmpty from 'lodash/isEmpty'; import React, {useCallback, useMemo, useRef, useState} from 'react'; import type {TextInput} from 'react-native'; import {View} from 'react-native'; @@ -71,15 +70,7 @@ function IOURequestStepWaypoint({ const {isOffline} = useNetwork(); const textInput = useRef(null); const parsedWaypointIndex = parseInt(pageIndex, 10); - - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); - - const isEditing = action === CONST.IOU.ACTION.EDIT; - const isEditingSplit = (iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.SPLIT_EXPENSE) && isEditing; - const currentTransaction = isEditingSplit && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction; - const shouldPassSplitDraft = isEditingSplit && !lodashIsEmpty(splitDraftTransaction); - - const allWaypoints = currentTransaction?.comment?.waypoints ?? {}; + const allWaypoints = transaction?.comment?.waypoints ?? {}; const currentWaypoint = allWaypoints[`waypoint${pageIndex}`] ?? {}; const waypointCount = Object.keys(allWaypoints).length; const filledWaypointCount = Object.values(allWaypoints).filter((waypoint) => !isEmptyObject(waypoint)).length; @@ -129,21 +120,14 @@ function IOURequestStepWaypoint({ }; const save = (waypoint: FormOnyxValues<'waypointForm'>) => { - saveWaypoint({ - transactionID, - index: pageIndex, - waypoint, - isDraft: shouldUseTransactionDraft(action), - recentWaypointsList: allRecentWaypoints, - isSplitDraftTransaction: shouldPassSplitDraft, - }); + saveWaypoint({transactionID, index: pageIndex, waypoint, isDraft: shouldUseTransactionDraft(action), recentWaypointsList: allRecentWaypoints}); }; const submit = (values: FormOnyxValues<'waypointForm'>) => { const waypointValue = values[`waypoint${pageIndex}`] ?? ''; // Allows letting you set a waypoint to an empty value if (waypointValue === '') { - removeWaypoint(currentTransaction, pageIndex, shouldUseTransactionDraft(action), shouldPassSplitDraft ? splitDraftTransaction : undefined); + removeWaypoint(transaction, pageIndex, shouldUseTransactionDraft(action)); } // While the user is offline, the auto-complete address search will not work @@ -172,14 +156,7 @@ function IOURequestStepWaypoint({ keyForList: `${values.name ?? 'waypoint'}_${Date.now()}`, }; - saveWaypoint({ - transactionID, - index: pageIndex, - waypoint, - isDraft: shouldUseTransactionDraft(action), - recentWaypointsList: allRecentWaypoints, - isSplitDraftTransaction: shouldPassSplitDraft, - }); + saveWaypoint({transactionID, index: pageIndex, waypoint, isDraft: shouldUseTransactionDraft(action), recentWaypointsList: allRecentWaypoints}); goBack(); }; @@ -232,7 +209,7 @@ function IOURequestStepWaypoint({ text={translate('common.remove')} style={[styles.mb3]} onPress={() => { - removeWaypoint(transaction, pageIndex, shouldUseTransactionDraft(action), shouldPassSplitDraft ? splitDraftTransaction : undefined); + removeWaypoint(transaction, pageIndex, shouldUseTransactionDraft(action)); goBack(); }} large diff --git a/src/types/onyx/IOU.ts b/src/types/onyx/IOU.ts index 94aab6bf056e0..5858e25da3b6c 100644 --- a/src/types/onyx/IOU.ts +++ b/src/types/onyx/IOU.ts @@ -4,7 +4,6 @@ import type CONST from '@src/CONST'; import type {IOUType} from '@src/CONST'; import type {Icon} from './OnyxCommon'; import type Report from './Report'; -import type {Routes, TransactionCustomUnit, WaypointCollection} from './Transaction'; /** Model of IOU participant */ type Participant = { @@ -160,21 +159,6 @@ type SplitExpense = { /** Whether the split expense is reimbursable (out-of-pocket) or non-reimbursable (company spend) */ reimbursable?: boolean; - - /** Custom unit data for distance requests */ - customUnit?: TransactionCustomUnit; - - /** Collection of waypoints associated with the transaction */ - waypoints?: WaypointCollection; - - /** Odometer start reading for distance expenses */ - odometerStart?: number; - - /** Odometer end reading for distance expenses */ - odometerEnd?: number; - - /** Existing routes */ - routes?: Routes; }; /** Model of IOU request */ diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts index 5f01734fb88fc..b4388009debcf 100644 --- a/tests/actions/IOUTest/SplitTest.ts +++ b/tests/actions/IOUTest/SplitTest.ts @@ -2498,98 +2498,6 @@ describe('initSplitExpense', () => { expect(splitExpenses?.[0]?.amount).toBe(900); expect(splitExpenses?.[1]?.amount).toBe(800); }); - - it('should initialize split expense for distance transaction with customUnit and merchant', async () => { - const customUnitRateID = 'rate-123'; - const customUnitID = 'distance-unit'; - const policy: Policy = { - ...createRandomPolicy(1), - customUnits: { - [customUnitID]: { - customUnitID, - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - enabled: true, - attributes: { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - }, - rates: { - [customUnitRateID]: { - customUnitRateID, - currency: CONST.CURRENCY.USD, - rate: 100, - enabled: true, - name: 'Default Rate', - subRates: [], - }, - }, - }, - }, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - await waitForBatchedUpdates(); - - const transaction: Transaction = { - transactionID: '123', - amount: -20000, - currency: 'USD', - merchant: '', - comment: { - comment: 'Distance expense', - splitExpenses: [], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - let allTransactions: OnyxCollection; - let allReports: OnyxCollection; - await getOnyxData({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (value) => { - allTransactions = value; - }, - }); - await getOnyxData({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (value) => { - allReports = value; - }, - }); - - initSplitExpense(allTransactions, allReports, transaction, policy); - await waitForBatchedUpdates(); - - const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`); - - expect(draftTransaction).toBeTruthy(); - - const splitExpenses = draftTransaction?.comment?.splitExpenses; - expect(splitExpenses).toHaveLength(2); - expect(draftTransaction?.amount).toBe(20000); - expect(draftTransaction?.currency).toBe('USD'); - - expect(splitExpenses?.[0].amount).toBe(10000); - expect(splitExpenses?.[1].amount).toBe(10000); - expect(splitExpenses?.[0].customUnit?.quantity).toBe(100); - expect(splitExpenses?.[1].customUnit?.quantity).toBe(100); - expect(splitExpenses?.[0].merchant).toBeTruthy(); - expect(splitExpenses?.[0].merchant).toContain('100'); - expect(splitExpenses?.[1].merchant).toBeTruthy(); - expect(splitExpenses?.[1].merchant).toContain('100'); - }); }); describe('addSplitExpenseField', () => { @@ -2728,114 +2636,6 @@ describe('addSplitExpenseField', () => { // Verify: The existing split should still have reimbursable: false expect(splitExpenses?.[0].reimbursable).toBe(false); }); - - it('should add new split expense field for distance transaction with customUnit and merchant', async () => { - const customUnitRateID = 'rate-456'; - const customUnitID = 'distance-unit'; - const policy: Policy = { - ...createRandomPolicy(1), - customUnits: { - [customUnitID]: { - customUnitID, - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - enabled: true, - attributes: { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - }, - rates: { - [customUnitRateID]: { - customUnitRateID, - currency: CONST.CURRENCY.USD, - rate: 100, - enabled: true, - name: 'Default Rate', - subRates: [], - }, - }, - }, - }, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - await waitForBatchedUpdates(); - - const transaction: Transaction = { - transactionID: '123', - amount: -20000, - currency: 'USD', - merchant: '', - comment: { - comment: 'Distance expense', - splitExpenses: [], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - const draftTransaction: Transaction = { - transactionID: '123', - amount: 20000, - currency: 'USD', - merchant: '', - comment: { - comment: 'Distance expense', - splitExpenses: [ - { - transactionID: '789', - amount: 10000, - description: 'Distance expense', - category: 'Car', - tags: [], - created: DateUtils.getDBTime(), - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 100, - }, - }, - ], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - const transactionReport: Report = { - reportID: '456', - type: CONST.REPORT.TYPE.EXPENSE, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, - total: 20000, - currency: 'USD', - }; - - addSplitExpenseField(transaction, draftTransaction, transactionReport, policy); - await waitForBatchedUpdates(); - - const updatedDraftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`); - expect(updatedDraftTransaction).toBeTruthy(); - - const splitExpenses = updatedDraftTransaction?.comment?.splitExpenses; - expect(splitExpenses).toHaveLength(2); - expect(splitExpenses?.[1].amount).toBe(0); - expect(splitExpenses?.[1].customUnit).toBeTruthy(); - expect(splitExpenses?.[1].customUnit?.quantity).toBe(0); - expect(splitExpenses?.[1].merchant).toBeDefined(); - }); }); describe('evenlyDistributeSplitExpenseAmounts', () => { @@ -3076,113 +2876,6 @@ describe('evenlyDistributeSplitExpenseAmounts', () => { expect(amounts).toEqual([-50, -51]); expect(amounts.reduce((a, b) => a + b, 0)).toBe(-101); }); - - it('should update distance and merchant for distance transactions when distributing amounts', async () => { - const customUnitRateID = 'rate-dist'; - const customUnitID = 'distance-unit'; - const originalTransactionID = 'orig-dist'; - const policy: Policy = { - ...createRandomPolicy(1), - customUnits: { - [customUnitID]: { - customUnitID, - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - enabled: true, - attributes: { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - }, - rates: { - [customUnitRateID]: { - customUnitRateID, - currency: CONST.CURRENCY.USD, - rate: 100, - enabled: true, - name: 'Default Rate', - subRates: [], - }, - }, - }, - }, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, { - transactionID: originalTransactionID, - amount: -20000, - currency: 'USD', - comment: { - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - }); - await waitForBatchedUpdates(); - - const draftTransaction: Transaction = { - transactionID: 'draft-dist', - amount: 20000, - currency: 'USD', - merchant: 'Test Merchant', - comment: { - comment: 'Test comment', - originalTransactionID, - splitExpenses: [ - { - transactionID: 'x', - amount: 0, - description: 'X', - created: DateUtils.getDBTime(), - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 0, - }, - }, - { - transactionID: 'y', - amount: 0, - description: 'Y', - created: DateUtils.getDBTime(), - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 0, - }, - }, - ], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - created: DateUtils.getDBTime(), - reportID: 'rep-dist', - }; - - const originalTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`); - evenlyDistributeSplitExpenseAmounts(draftTransaction, originalTransaction, policy); - await waitForBatchedUpdates(); - - const updatedDraft = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`); - expect(updatedDraft).toBeTruthy(); - const splitExpenses = updatedDraft?.comment?.splitExpenses ?? []; - - expect(splitExpenses.at(0)?.amount).toBe(10000); - expect(splitExpenses.at(1)?.amount).toBe(10000); - expect(splitExpenses.at(0)?.customUnit?.quantity).toBe(100); - expect(splitExpenses.at(1)?.customUnit?.quantity).toBe(100); - expect(splitExpenses.at(0)?.merchant).toBeTruthy(); - expect(splitExpenses.at(0)?.merchant).toContain('100'); - expect(splitExpenses.at(1)?.merchant).toBeTruthy(); - expect(splitExpenses.at(1)?.merchant).toContain('100'); - }); }); describe('updateSplitExpenseAmountField', () => { @@ -3225,99 +2918,6 @@ describe('updateSplitExpenseAmountField', () => { const splitExpenses = updatedDraftTransaction?.comment?.splitExpenses; expect(splitExpenses?.[0].amount).toBe(20); }); - - it('should update distance and merchant for distance transactions when amount changes', async () => { - const customUnitRateID = 'rate-update'; - const customUnitID = 'distance-unit'; - const originalTransactionID = '123'; - const currentTransactionID = '789'; - const policy: Policy = { - ...createRandomPolicy(1), - customUnits: { - [customUnitID]: { - customUnitID, - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - enabled: true, - attributes: { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - }, - rates: { - [customUnitRateID]: { - customUnitRateID, - currency: CONST.CURRENCY.USD, - rate: 100, - enabled: true, - name: 'Default Rate', - subRates: [], - }, - }, - }, - }, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, { - transactionID: originalTransactionID, - amount: -20000, - currency: 'USD', - comment: { - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - }); - await waitForBatchedUpdates(); - - const draftTransaction: Transaction = { - transactionID: '234', - amount: 20000, - currency: 'USD', - merchant: 'Test Merchant', - comment: { - comment: 'Test comment', - originalTransactionID, - splitExpenses: [ - { - transactionID: currentTransactionID, - amount: 10000, - description: 'Test comment', - category: 'Car', - tags: [], - created: DateUtils.getDBTime(), - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 100, - }, - }, - ], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - updateSplitExpenseAmountField(draftTransaction, currentTransactionID, 15000, policy); - await waitForBatchedUpdates(); - - const updatedDraftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`); - expect(updatedDraftTransaction).toBeTruthy(); - - const splitExpenses = updatedDraftTransaction?.comment?.splitExpenses; - expect(splitExpenses?.[0].amount).toBe(15000); - expect(splitExpenses?.[0].customUnit?.quantity).toBe(150); - expect(splitExpenses?.[0].merchant).toBeTruthy(); - expect(splitExpenses?.[0].merchant).toContain('150'); - }); }); describe('setDraftSplitTransaction', () => { @@ -3477,188 +3077,6 @@ describe('initSplitExpenseItemData', () => { expect(splitExpense.merchant).toBe('Test Merchant'); expect(splitExpense.reportID).toBe('456'); }); - - it('should use provided parameters over transaction data', () => { - const transaction: Transaction = { - transactionID: '123', - amount: -100, - currency: 'USD', - merchant: 'Original Merchant', - comment: { - comment: 'Original comment', - splitExpenses: [], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - category: 'Food', - tag: 'lunch', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - const customUnit: TransactionCustomUnit = { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID: 'distance-unit', - customUnitRateID: 'rate-123', - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 50, - }; - - const transactionReport: Report = { - reportID: '456', - type: CONST.REPORT.TYPE.EXPENSE, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, - }; - - const splitExpense = initSplitExpenseItemData(transaction, transactionReport, { - amount: 200, - transactionID: '999', - reportID: '888', - created: '2024-01-01', - merchant: 'Custom Merchant', - customUnit, - }); - - expect(splitExpense.transactionID).toBe('999'); - expect(splitExpense.amount).toBe(200); - expect(splitExpense.reportID).toBe('888'); - expect(splitExpense.created).toBe('2024-01-01'); - expect(splitExpense.merchant).toBe('Custom Merchant'); - expect(splitExpense.customUnit).toEqual(customUnit); - }); - - it('should handle transaction with waypoints and odometer readings', () => { - const transaction: Transaction = { - transactionID: '123', - amount: -100, - currency: 'USD', - merchant: 'Test Merchant', - comment: { - comment: 'Test comment', - splitExpenses: [], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - waypoints: { - waypoint0: {lat: 0, lng: 0, name: 'Start'}, - waypoint1: {lat: 1, lng: 1, name: 'End'}, - }, - odometerStart: 1000, - odometerEnd: 1200, - }, - category: 'Food', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - const transactionReport: Report = { - reportID: '456', - type: CONST.REPORT.TYPE.EXPENSE, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, - }; - - const splitExpense = initSplitExpenseItemData(transaction, transactionReport); - - expect(splitExpense.waypoints).toEqual(transaction.comment?.waypoints); - expect(splitExpense.odometerStart).toBe(1000); - expect(splitExpense.odometerEnd).toBe(1200); - }); -}); - -describe('initDraftSplitExpenseDataForEdit', () => { - it('should create draft transaction for editing split expense', async () => { - const originalTransactionID = 'orig-123'; - const splitExpenseTransactionID = 'split-456'; - const reportID = 'report-789'; - - const originalTransaction: Transaction = { - transactionID: originalTransactionID, - amount: -20000, - currency: 'USD', - merchant: 'Original Merchant', - comment: { - comment: 'Original comment', - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID: 'distance-unit', - customUnitRateID: 'rate-123', - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, originalTransaction); - await waitForBatchedUpdates(); - - const draftTransaction: Transaction = { - transactionID: 'draft-123', - amount: 20000, - currency: 'USD', - merchant: 'Draft Merchant', - comment: { - comment: 'Draft comment', - originalTransactionID, - splitExpenses: [ - { - transactionID: splitExpenseTransactionID, - amount: 10000, - description: 'Split expense', - category: 'Car', - tags: ['tag1'], - created: DateUtils.getDBTime(), - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID: 'distance-unit', - customUnitRateID: 'rate-123', - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 100, - }, - waypoints: { - waypoint0: {lat: 0, lng: 0, name: 'Start'}, - }, - odometerStart: 1000, - odometerEnd: 1100, - }, - ], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - participants: [{accountID: 1}] as IOUParticipant[], - created: DateUtils.getDBTime(), - reportID, - }; - - initDraftSplitExpenseDataForEdit(draftTransaction, splitExpenseTransactionID, reportID); - await waitForBatchedUpdates(); - - const editDraftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`); - expect(editDraftTransaction).toBeTruthy(); - expect(editDraftTransaction?.amount).toBe(10000); - expect(editDraftTransaction?.currency).toBe('USD'); - expect(editDraftTransaction?.comment?.comment).toBe('Split expense'); - expect(editDraftTransaction?.category).toBe('Car'); - expect(editDraftTransaction?.tag).toBe('tag1'); - expect(editDraftTransaction?.comment?.customUnit?.quantity).toBe(100); - expect(editDraftTransaction?.comment?.waypoints).toEqual({ - waypoint0: {lat: 0, lng: 0, name: 'Start'}, - }); - expect(editDraftTransaction?.comment?.odometerStart).toBe(1000); - expect(editDraftTransaction?.comment?.odometerEnd).toBe(1100); - }); - - it('should not create draft if draftTransaction or splitExpenseTransactionID is missing', async () => { - initDraftSplitExpenseDataForEdit(undefined, 'split-456', 'report-789'); - await waitForBatchedUpdates(); - - const editDraftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`); - expect(editDraftTransaction).toBeFalsy(); - }); }); describe('resetSplitExpensesByDateRange', () => { @@ -3709,88 +3127,6 @@ describe('resetSplitExpensesByDateRange', () => { expect(draftTransaction?.comment?.splitsEndDate).toBe(endDate); }); - it('should handle distance transactions with customUnit and merchant', async () => { - const customUnitRateID = 'rate-date'; - const customUnitID = 'distance-unit'; - const transactionID = 'trans-date'; - const startDate = '2024-01-01'; - const endDate = '2024-01-02'; - - const policy: Policy = { - ...createRandomPolicy(1), - customUnits: { - [customUnitID]: { - customUnitID, - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - enabled: true, - attributes: { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - }, - rates: { - [customUnitRateID]: { - customUnitRateID, - currency: CONST.CURRENCY.USD, - rate: 100, - enabled: true, - name: 'Default Rate', - subRates: [], - }, - }, - }, - }, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - await waitForBatchedUpdates(); - - const transaction: Transaction = { - transactionID, - amount: -20000, - currency: 'USD', - merchant: '', - comment: { - comment: 'Distance expense', - splitExpenses: [], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - const transactionReport: Report = { - reportID: '456', - type: CONST.REPORT.TYPE.EXPENSE, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, - }; - - resetSplitExpensesByDateRange(transaction, transactionReport, startDate, endDate, policy); - await waitForBatchedUpdates(); - - const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`); - expect(draftTransaction).toBeTruthy(); - - const splitExpenses = draftTransaction?.comment?.splitExpenses; - expect(splitExpenses).toHaveLength(2); - expect(splitExpenses?.[0].amount).toBe(10000); - expect(splitExpenses?.[1].amount).toBe(10000); - expect(splitExpenses?.[0].customUnit?.quantity).toBe(100); - expect(splitExpenses?.[1].customUnit?.quantity).toBe(100); - expect(splitExpenses?.[0].merchant).toBeTruthy(); - expect(splitExpenses?.[0].merchant).toContain('100'); - expect(splitExpenses?.[1].merchant).toBeTruthy(); - expect(splitExpenses?.[1].merchant).toContain('100'); - }); - it('should not reset if transaction, startDate, or endDate is missing', async () => { resetSplitExpensesByDateRange(undefined, undefined, '2024-01-01', '2024-01-03'); await waitForBatchedUpdates(); @@ -3860,291 +3196,3 @@ describe('removeSplitExpenseField', () => { await waitForBatchedUpdates(); }); }); - -describe('updateSplitExpenseField', () => { - it('should update split expense field with new transaction details', async () => { - const originalTransactionID = 'orig-update'; - const splitExpenseTransactionID = 'split-update'; - - const originalTransaction: Transaction = { - transactionID: originalTransactionID, - amount: -20000, - currency: 'USD', - merchant: 'Original Merchant', - comment: { - comment: 'Original comment', - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - category: 'Food', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, originalTransaction); - await waitForBatchedUpdates(); - - const originalTransactionDraft: Transaction = { - transactionID: 'draft-orig', - amount: 20000, - currency: 'USD', - merchant: 'Draft Merchant', - comment: { - comment: 'Draft comment', - originalTransactionID, - splitExpenses: [ - { - transactionID: splitExpenseTransactionID, - amount: 10000, - description: 'Original description', - category: 'Food', - tags: ['tag1'], - created: '2024-01-01', - }, - ], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - created: DateUtils.getDBTime(), - reportID: '456', - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`, originalTransactionDraft); - await waitForBatchedUpdates(); - - const splitExpenseDraftTransaction: Transaction = { - transactionID: 'draft-split', - amount: 15000, - currency: 'USD', - merchant: 'Updated Merchant', - comment: { - comment: 'Updated description', - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - originalTransactionID, - waypoints: { - waypoint0: {lat: 0, lng: 0, name: 'Start'}, - }, - odometerStart: 1000, - odometerEnd: 1100, - }, - category: 'Car', - tag: 'tag2', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, originalTransaction); - await waitForBatchedUpdates(); - - const updatedDraft = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`); - expect(updatedDraft).toBeTruthy(); - - const splitExpenses = updatedDraft?.comment?.splitExpenses; - const updatedSplit = splitExpenses?.find((s) => s.transactionID === splitExpenseTransactionID); - expect(updatedSplit).toBeTruthy(); - expect(updatedSplit?.amount).toBe(15000); - expect(updatedSplit?.description).toBe('Updated description'); - expect(updatedSplit?.category).toBe('Car'); - expect(updatedSplit?.tags).toEqual(['tag2']); - expect(updatedSplit?.waypoints).toEqual({ - waypoint0: {lat: 0, lng: 0, name: 'Start'}, - }); - expect(updatedSplit?.odometerStart).toBe(1000); - expect(updatedSplit?.odometerEnd).toBe(1100); - }); - - it('should recalculate amount for distance transactions when distance changes', async () => { - const customUnitRateID = 'rate-update-field'; - const customUnitID = 'distance-unit'; - const originalTransactionID = 'orig-dist-update'; - const splitExpenseTransactionID = 'split-dist-update'; - - const policy: Policy = { - ...createRandomPolicy(1), - customUnits: { - [customUnitID]: { - customUnitID, - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - enabled: true, - attributes: { - unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - }, - rates: { - [customUnitRateID]: { - customUnitRateID, - currency: CONST.CURRENCY.USD, - rate: 100, - enabled: true, - name: 'Default Rate', - subRates: [], - }, - }, - }, - }, - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - await waitForBatchedUpdates(); - - const originalTransaction: Transaction = { - transactionID: originalTransactionID, - amount: -20000, - currency: 'USD', - merchant: '', - comment: { - comment: 'Distance expense', - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 200, - }, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, originalTransaction); - await waitForBatchedUpdates(); - - const originalTransactionDraft: Transaction = { - transactionID: 'draft-orig-dist', - amount: 20000, - currency: 'USD', - merchant: '', - comment: { - comment: 'Draft comment', - originalTransactionID, - splitExpenses: [ - { - transactionID: splitExpenseTransactionID, - amount: 10000, - description: 'Original', - category: 'Car', - tags: [], - created: DateUtils.getDBTime(), - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 100, - }, - }, - ], - attendees: [], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - created: DateUtils.getDBTime(), - reportID: '456', - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`, originalTransactionDraft); - await waitForBatchedUpdates(); - - const splitExpenseDraftTransaction: Transaction = { - transactionID: 'draft-split-dist', - amount: 0, - currency: 'USD', - merchant: '', - comment: { - comment: 'Updated description', - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - originalTransactionID, - customUnit: { - name: CONST.CUSTOM_UNITS.NAME_DISTANCE, - customUnitID, - customUnitRateID, - distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, - quantity: 150, - }, - }, - category: 'Car', - created: DateUtils.getDBTime(), - reportID: '456', - }; - - updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, originalTransaction, policy); - await waitForBatchedUpdates(); - - const updatedDraft = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`); - expect(updatedDraft).toBeTruthy(); - - const splitExpenses = updatedDraft?.comment?.splitExpenses; - const updatedSplit = splitExpenses?.find((s) => s.transactionID === splitExpenseTransactionID); - expect(updatedSplit).toBeTruthy(); - expect(updatedSplit?.amount).toBe(15000); - expect(updatedSplit?.customUnit?.quantity).toBe(150); - expect(updatedSplit?.merchant).toBeTruthy(); - expect(updatedSplit?.merchant).toContain('150'); - }); - - it('should reset date range if created date is modified', async () => { - const originalTransactionID = 'orig-date-reset'; - const splitExpenseTransactionID = 'split-date-reset'; - - const originalTransaction: Transaction = { - transactionID: originalTransactionID, - amount: -20000, - currency: 'USD', - merchant: '', - comment: { - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - created: DateUtils.getDBTime(), - reportID: '456', - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, originalTransaction); - await waitForBatchedUpdates(); - - const originalTransactionDraft: Transaction = { - transactionID: 'draft-date', - amount: 20000, - currency: 'USD', - merchant: '', - comment: { - originalTransactionID, - splitsStartDate: '2024-01-01', - splitsEndDate: '2024-01-03', - splitExpenses: [ - { - transactionID: splitExpenseTransactionID, - amount: 10000, - description: 'Test', - created: '2024-01-01', - }, - ], - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - }, - created: DateUtils.getDBTime(), - reportID: '456', - }; - - await Onyx.set(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`, originalTransactionDraft); - await waitForBatchedUpdates(); - - const splitExpenseDraftTransaction: Transaction = { - transactionID: 'draft-split-date', - amount: 10000, - currency: 'USD', - merchant: '', - comment: { - type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, - originalTransactionID, - }, - created: '2024-01-05', - reportID: '456', - }; - - updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, originalTransaction); - await waitForBatchedUpdates(); - - const updatedDraft = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${originalTransactionID}`); - expect(updatedDraft).toBeTruthy(); - expect(updatedDraft?.comment?.splitsStartDate).toBeFalsy(); - expect(updatedDraft?.comment?.splitsEndDate).toBeFalsy(); - }); -}); From c4c995a8d4f38c55c4f199f3b0e728a071b0a267 Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 16:46:55 +0100 Subject: [PATCH 2/8] Fix lint issues --- src/libs/actions/IOU/Split.ts | 18 +++++------------- src/pages/iou/SplitExpenseEditPage.tsx | 6 +++--- .../step/IOURequestStepDistanceOdometer.tsx | 1 - tests/actions/IOUTest/SplitTest.ts | 5 +---- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index 7565ad509ce61..e0a7eaf51d773 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -1765,7 +1765,6 @@ function initSplitExpenseItemData( reportID, created, merchant, - customUnit, }: {amount?: number; transactionID?: string; reportID?: string; created?: string; merchant?: string; customUnit?: TransactionCustomUnit} = {}, ): SplitExpense { const transactionDetails = getTransactionDetails(transaction); @@ -1974,7 +1973,7 @@ function addSplitExpenseField(transaction: OnyxEntry, dra * - Works entirely on the provided `draftTransaction` to avoid direct Onyx reads. * - Uses `calculateAmount` utility to handle currency subunits and rounding consistently with existing logic. */ -function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry, transaction?: OnyxEntry) { +function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry) { if (!draftTransaction) { return; } @@ -1997,7 +1996,7 @@ function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry { const amount = calculateIOUAmount(splitCount - 1, total, currency, index === lastIndex, true); - let updatedSplitExpense: SplitExpense = { + const updatedSplitExpense: SplitExpense = { ...splitExpense, amount, }; @@ -2021,13 +2020,7 @@ function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry, - transactionReport: OnyxEntry, - startDate: string, - endDate: string, - policy?: OnyxEntry, -) { +function resetSplitExpensesByDateRange(transaction: OnyxEntry, transactionReport: OnyxEntry, startDate: string, endDate: string) { if (!transaction || !startDate || !endDate) { return; } @@ -2046,7 +2039,7 @@ function resetSplitExpensesByDateRange( const lastIndex = dates.length - 1; const newSplitExpenses: SplitExpense[] = dates.map((date, index) => { const amount = calculateIOUAmount(lastIndex, total, currency, index === lastIndex, true); - let splitExpense = initSplitExpenseItemData(transaction, transactionReport, { + const splitExpense = initSplitExpenseItemData(transaction, transactionReport, { amount, transactionID: NumberUtils.rand64(), reportID: transaction?.reportID, @@ -2166,11 +2159,10 @@ function updateSplitExpenseAmountField(draftTransaction: OnyxEntry { if (splitExpense.transactionID === currentItemTransactionID) { - let updatedSplitExpense: SplitExpense = { + const updatedSplitExpense: SplitExpense = { ...splitExpense, amount, }; diff --git a/src/pages/iou/SplitExpenseEditPage.tsx b/src/pages/iou/SplitExpenseEditPage.tsx index e33b1fad53d9d..4f2187c101d77 100644 --- a/src/pages/iou/SplitExpenseEditPage.tsx +++ b/src/pages/iou/SplitExpenseEditPage.tsx @@ -26,7 +26,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig import type {SplitExpenseParamList} from '@libs/Navigation/types'; import Parser from '@libs/Parser'; import {getTagLists} from '@libs/PolicyUtils'; -import {computeReportName} from '@libs/ReportNameUtils'; +import {getReportName} from '@libs/ReportNameUtils'; import {isSplitAction} from '@libs/ReportSecondaryActionUtils'; import type {TransactionDetails} from '@libs/ReportUtils'; import {getParsedComment, getReportOrDraftReport, getTransactionDetails} from '@libs/ReportUtils'; @@ -105,7 +105,7 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { const isSplitAvailable = report && transaction && isSplitAction(currentReport, [transaction], originalTransaction, login ?? '', currentUserAccountID, currentPolicy); const isCategoryRequired = !!currentPolicy?.requiresCategory; - const reportName = computeReportName(currentReport, undefined, undefined, undefined, undefined, undefined, undefined, currentUserAccountID); + const reportName = getReportName(currentReport); const isDescriptionRequired = isCategoryDescriptionRequired(policyCategories, splitExpenseDraftTransactionDetails?.category, currentPolicy?.areRulesEnabled); const shouldShowTags = !!currentPolicy?.areTagsEnabled && !!(transactionTag || hasEnabledTags(policyTagLists)); @@ -270,7 +270,7 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { style={[styles.w100]} text={translate('common.save')} onPress={() => { - updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, originalTransaction); + updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, transaction); Navigation.goBack(backTo); }} pressOnEnter diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index 3ba2ad4085417..a5f3910522562 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -33,7 +33,6 @@ import { trackExpense, updateMoneyRequestDistance, } from '@libs/actions/IOU'; -import {setDraftSplitTransaction} from '@libs/actions/IOU/Split'; import {setTransactionReport} from '@libs/actions/Transaction'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts index b4388009debcf..d59bc51224553 100644 --- a/tests/actions/IOUTest/SplitTest.ts +++ b/tests/actions/IOUTest/SplitTest.ts @@ -14,7 +14,6 @@ import { addSplitExpenseField, completeSplitBill, evenlyDistributeSplitExpenseAmounts, - initDraftSplitExpenseDataForEdit, initSplitExpense, initSplitExpenseItemData, removeSplitExpenseField, @@ -23,7 +22,6 @@ import { splitBill, startSplitBill, updateSplitExpenseAmountField, - updateSplitExpenseField, updateSplitTransactionsFromSplitExpensesFlow, } from '@userActions/IOU/Split'; import CONST from '@src/CONST'; @@ -31,12 +29,11 @@ import IntlStore from '@src/languages/IntlStore'; import DateUtils from '@src/libs/DateUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, RecentlyUsedTags, Report, ReportNameValuePairs, SearchResults} from '@src/types/onyx'; -import type {Participant as IOUParticipant, SplitExpense} from '@src/types/onyx/IOU'; +import type {SplitExpense} from '@src/types/onyx/IOU'; import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails'; import type {Participant} from '@src/types/onyx/Report'; import type ReportAction from '@src/types/onyx/ReportAction'; import type Transaction from '@src/types/onyx/Transaction'; -import type {TransactionCustomUnit} from '@src/types/onyx/Transaction'; import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import currencyList from '../../unit/currencyList.json'; From 8094dd734e3704ba154c22850682416889fa837c Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 17:01:30 +0100 Subject: [PATCH 3/8] Return navigation --- src/pages/iou/SplitExpensePage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/iou/SplitExpensePage.tsx b/src/pages/iou/SplitExpensePage.tsx index 80bbc16f4d234..9bbf4fe92f39d 100644 --- a/src/pages/iou/SplitExpensePage.tsx +++ b/src/pages/iou/SplitExpensePage.tsx @@ -418,6 +418,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { initDraftSplitExpenseDataForEdit(draftTransaction, item.transactionID, item.reportID ?? reportID); + Navigation.navigate(ROUTES.SPLIT_EXPENSE_EDIT.getRoute(item.reportID ?? reportID, originalTransactionID, item.transactionID, Navigation.getActiveRoute())); }); }; From a012bb6e68953fbb05a8bb38cb475039d0fa48ee Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 18:04:19 +0100 Subject: [PATCH 4/8] Remove unused code --- src/libs/actions/IOU/Split.ts | 111 ++-------------------------------- 1 file changed, 5 insertions(+), 106 deletions(-) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index e0a7eaf51d773..a4cfd473c7f50 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -1733,39 +1733,10 @@ function setIndividualShare(transactionID: string, participantAccountID: number, }); } -/** - * Calculate merchant for distance transactions based on distance and rate - */ -function getDistanceMerchantForSplitExpense(distanceInUnits: number, unit: Unit | undefined, rate: number | undefined, currency: string, transactionCurrency?: string): string { - if (!rate || rate <= 0 || !unit) { - return ''; - } - - const distanceInMeters = DistanceRequestUtils.convertToDistanceInMeters(distanceInUnits, unit); - const currencyForMerchant = currency ?? transactionCurrency ?? CONST.CURRENCY.USD; - const currentLocale = IntlStore.getCurrentLocale(); - return DistanceRequestUtils.getDistanceMerchant( - true, - distanceInMeters, - unit, - rate, - currencyForMerchant, - (phrase, ...parameters) => Localize.translate(currentLocale, phrase, ...parameters), - (digit) => toLocaleDigit(currentLocale, digit), - getCurrencySymbol, - ); -} - function initSplitExpenseItemData( transaction: OnyxEntry, transactionReport: OnyxEntry, - { - amount, - transactionID, - reportID, - created, - merchant, - }: {amount?: number; transactionID?: string; reportID?: string; created?: string; merchant?: string; customUnit?: TransactionCustomUnit} = {}, + {amount, transactionID, reportID, created}: {amount?: number; transactionID?: string; reportID?: string; created?: string} = {}, ): SplitExpense { const transactionDetails = getTransactionDetails(transaction); @@ -1776,7 +1747,7 @@ function initSplitExpenseItemData( category: transactionDetails?.category, tags: transaction?.tag ? [transaction?.tag] : [], created: created ?? transactionDetails?.created ?? DateUtils.formatWithUTCTimeZone(DateUtils.getDBTime(), CONST.DATE.FNS_FORMAT_STRING), - merchant: merchant ?? (transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? '')), + merchant: transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? ''), statusNum: transactionReport?.statusNum ?? 0, reportID: reportID ?? transaction?.reportID ?? String(CONST.DEFAULT_NUMBER_ID), reimbursable: transactionDetails?.reimbursable, @@ -1786,12 +1757,7 @@ function initSplitExpenseItemData( /** * Create a draft transaction to set up split expense details for the split expense flow */ -function initSplitExpense( - transactions: OnyxCollection, - reports: OnyxCollection, - transaction: OnyxEntry, - policy?: OnyxEntry, -) { +function initSplitExpense(transactions: OnyxCollection, reports: OnyxCollection, transaction: OnyxEntry) { if (!transaction) { return; } @@ -1836,49 +1802,14 @@ function initSplitExpense( const transactionDetailsAmount = transactionDetails?.amount ?? 0; const transactionReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`]; - const splitAmounts = [ - calculateIOUAmount(1, transactionDetailsAmount, transactionDetails?.currency ?? '', false), - calculateIOUAmount(1, transactionDetailsAmount, transactionDetails?.currency ?? '', true), - ]; - const splitCustomUnits: Array = [undefined, undefined]; - const splitMerchants: Array = [undefined, undefined]; - - if (isDistanceRequestTransactionUtils(transaction)) { - const mileageRate = DistanceRequestUtils.getRate({transaction, policy: policy ?? undefined}); - const {unit, rate} = mileageRate; - const currency = mileageRate?.currency ?? transactionDetails?.currency ?? CONST.CURRENCY.USD; - - if (rate && rate > 0 && transaction?.comment?.customUnit) { - for (let i = 0; i < splitAmounts.length; i++) { - if (splitAmounts.at(i)) { - // Calculate distance from amount and rate: distance = amount / rate - // Both amount and rate are in cents, so the result is in distance units - const distanceInUnits = Math.abs(splitAmounts.at(i) ?? 0) / rate; - const quantity = Number(distanceInUnits.toFixed(CONST.DISTANCE_DECIMAL_PLACES)); - - splitCustomUnits[i] = { - ...(transaction.comment.customUnit ?? {}), - quantity, - }; - - splitMerchants[i] = getDistanceMerchantForSplitExpense(distanceInUnits, unit, rate, currency, transactionDetails?.currency); - } - } - } - } - const splitExpenses = [ initSplitExpenseItemData(transaction, transactionReport, { - amount: splitAmounts.at(0) ?? 0, + amount: calculateIOUAmount(1, transactionDetailsAmount, transactionDetails?.currency ?? '', false) ?? 0, transactionID: NumberUtils.rand64(), - customUnit: splitCustomUnits.at(0), - merchant: splitMerchants.at(0), }), initSplitExpenseItemData(transaction, transactionReport, { - amount: splitAmounts.at(1) ?? 0, + amount: calculateIOUAmount(1, transactionDetailsAmount, transactionDetails?.currency ?? '', true) ?? 0, transactionID: NumberUtils.rand64(), - customUnit: splitCustomUnits.at(1), - merchant: splitMerchants.at(1), }), ]; @@ -2081,14 +2012,12 @@ function updateSplitExpenseField( originalTransactionDraft: OnyxEntry, splitExpenseTransactionID: string, originalTransaction: OnyxEntry, - policy?: OnyxEntry, ) { if (!splitExpenseDraftTransaction || !splitExpenseTransactionID || !originalTransactionDraft) { return; } const originalTransactionID = splitExpenseDraftTransaction?.comment?.originalTransactionID; - const isDistanceRequest = originalTransaction && isDistanceRequestTransactionUtils(originalTransaction); const transactionDetails = getTransactionDetails(splitExpenseDraftTransaction); let shouldResetDateRange = false; @@ -2108,36 +2037,6 @@ function updateSplitExpenseField( merchant: splitExpenseDraftTransaction?.modifiedMerchant ? splitExpenseDraftTransaction.modifiedMerchant : (splitExpenseDraftTransaction?.merchant ?? ''), }; - // Recalculate amount for distance transactions when rate or distance changes - if (isDistanceRequest && originalTransaction) { - const mileageRate = DistanceRequestUtils.getRate({transaction: splitExpenseDraftTransaction, policy: policy ?? undefined}); - const {unit, rate} = mileageRate; - - if (rate && rate > 0) { - // Get distance from routes or customUnit.quantity (same logic as in initSplitExpense) - let distanceInUnits: number | undefined; - if (splitExpenseDraftTransaction?.routes?.route0?.distance && splitExpenseDraftTransaction?.comment?.customUnit?.distanceUnit) { - distanceInUnits = DistanceRequestUtils.convertDistanceUnit( - splitExpenseDraftTransaction.routes.route0.distance, - splitExpenseDraftTransaction.comment.customUnit.distanceUnit, - ); - } else if (splitExpenseDraftTransaction?.comment?.customUnit?.quantity) { - distanceInUnits = splitExpenseDraftTransaction.comment.customUnit.quantity; - } - - if (distanceInUnits !== undefined) { - // Calculate amount from distance and rate: amount = distance * rate - // Both amount and rate are in cents, distance is in units - const calculatedAmount = distanceInUnits > 0 ? Math.round(distanceInUnits * rate) : 0; - updatedItem.amount = calculatedAmount; - - // Update merchant for distance transactions - const currency = mileageRate?.currency ?? originalTransaction.currency ?? CONST.CURRENCY.USD; - updatedItem.merchant = getDistanceMerchantForSplitExpense(distanceInUnits, unit, rate, currency, originalTransaction.currency); - } - } - } - return updatedItem; } return item; From 14dcd9c818e8c4ecd49bf07e9796b8509daa1065 Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 18:12:15 +0100 Subject: [PATCH 5/8] Remove unused code x2 --- src/libs/actions/IOU/Split.ts | 18 ++++-------------- src/pages/iou/SplitExpenseEditPage.tsx | 2 +- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index a4cfd473c7f50..7bb6a63a18c3e 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -7,14 +7,10 @@ import type {SearchContextProps} from '@components/Search/types'; import * as API from '@libs/API'; import type {CompleteSplitBillParams, RevertSplitTransactionParams, SplitBillParams, SplitTransactionParams, SplitTransactionSplitsParam, StartSplitBillParams} from '@libs/API/parameters'; import {WRITE_COMMANDS} from '@libs/API/types'; -import {getCurrencySymbol} from '@libs/CurrencyUtils'; import DateUtils from '@libs/DateUtils'; -import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils'; import {calculateAmount as calculateIOUAmount, updateIOUOwnerAndTotal} from '@libs/IOUUtils'; -import {toLocaleDigit} from '@libs/LocaleDigitUtils'; import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; -import * as Localize from '@libs/Localize'; import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute'; import Navigation, {navigationRef} from '@libs/Navigation/Navigation'; import * as NumberUtils from '@libs/NumberUtils'; @@ -57,7 +53,6 @@ import {buildOptimisticPolicyRecentlyUsedTags} from '@userActions/Policy/Tag'; import {notifyNewAction} from '@userActions/Report'; import {removeDraftSplitTransaction, removeDraftTransaction} from '@userActions/TransactionEdit'; import CONST from '@src/CONST'; -import IntlStore from '@src/languages/IntlStore'; import NAVIGATORS from '@src/NAVIGATORS'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -65,11 +60,10 @@ import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {Attendee, Participant, Split, SplitExpense} from '@src/types/onyx/IOU'; import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails'; -import type {Unit} from '@src/types/onyx/Policy'; import type RecentlyUsedTags from '@src/types/onyx/RecentlyUsedTags'; import type ReportAction from '@src/types/onyx/ReportAction'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {SplitShares, TransactionChanges, TransactionCustomUnit} from '@src/types/onyx/Transaction'; +import type {SplitShares, TransactionChanges} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import { buildMinimalTransactionForFormula, @@ -1840,7 +1834,7 @@ function initSplitExpense(transactions: OnyxCollection, r /** * Create a draft transaction to set up split expense details for edit split details */ -function initDraftSplitExpenseDataForEdit(draftTransaction: OnyxEntry, splitExpenseTransactionID: string, reportID: string, transactionID?: string) { +function initDraftSplitExpenseDataForEdit(draftTransaction: OnyxEntry, splitExpenseTransactionID: string, reportID: string) { if (!draftTransaction || !splitExpenseTransactionID) { return; } @@ -1850,12 +1844,9 @@ function initDraftSplitExpenseDataForEdit(draftTransaction: OnyxEntry, originalTransactionDraft: OnyxEntry, splitExpenseTransactionID: string, - originalTransaction: OnyxEntry, ) { if (!splitExpenseDraftTransaction || !splitExpenseTransactionID || !originalTransactionDraft) { return; diff --git a/src/pages/iou/SplitExpenseEditPage.tsx b/src/pages/iou/SplitExpenseEditPage.tsx index 4f2187c101d77..55be5818267d3 100644 --- a/src/pages/iou/SplitExpenseEditPage.tsx +++ b/src/pages/iou/SplitExpenseEditPage.tsx @@ -270,7 +270,7 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) { style={[styles.w100]} text={translate('common.save')} onPress={() => { - updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID, transaction); + updateSplitExpenseField(splitExpenseDraftTransaction, originalTransactionDraft, splitExpenseTransactionID); Navigation.goBack(backTo); }} pressOnEnter From 5ae46cd746a35a9e5c712c000a6710d7cdd785ea Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 18:54:38 +0100 Subject: [PATCH 6/8] Remove policy annotation --- src/libs/actions/IOU/Split.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index 7bb6a63a18c3e..6efeb015ab471 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -1940,7 +1940,6 @@ function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry, transactionReport: OnyxEntry, startDate: string, endDate: string) { if (!transaction || !startDate || !endDate) { @@ -2023,7 +2022,7 @@ function updateSplitExpenseField( category: transactionDetails?.category, tags: splitExpenseDraftTransaction?.tag ? [splitExpenseDraftTransaction?.tag] : [], created: transactionDetails?.created ?? DateUtils.formatWithUTCTimeZone(DateUtils.getDBTime(), CONST.DATE.FNS_FORMAT_STRING), - amount: splitExpenseDraftTransaction?.amount ?? 0, + amount: splitExpenseDraftTransaction?.amount, merchant: splitExpenseDraftTransaction?.modifiedMerchant ? splitExpenseDraftTransaction.modifiedMerchant : (splitExpenseDraftTransaction?.merchant ?? ''), }; From 319c51c13c53fc0c2f446010af9691b53d6e7282 Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 18:58:05 +0100 Subject: [PATCH 7/8] Remove unused code x3 --- src/libs/actions/IOU/Split.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index 6efeb015ab471..84a32e0233908 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -2022,8 +2022,6 @@ function updateSplitExpenseField( category: transactionDetails?.category, tags: splitExpenseDraftTransaction?.tag ? [splitExpenseDraftTransaction?.tag] : [], created: transactionDetails?.created ?? DateUtils.formatWithUTCTimeZone(DateUtils.getDBTime(), CONST.DATE.FNS_FORMAT_STRING), - amount: splitExpenseDraftTransaction?.amount, - merchant: splitExpenseDraftTransaction?.modifiedMerchant ? splitExpenseDraftTransaction.modifiedMerchant : (splitExpenseDraftTransaction?.merchant ?? ''), }; return updatedItem; From f2f41b149596e3734dbd8d77734009d39b0f0129 Mon Sep 17 00:00:00 2001 From: Yauheni Horbach Date: Wed, 11 Feb 2026 19:05:45 +0100 Subject: [PATCH 8/8] Add minor change --- src/libs/actions/IOU/Split.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index 84a32e0233908..101cd2bf6423e 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -1938,6 +1938,7 @@ function evenlyDistributeSplitExpenseAmounts(draftTransaction: OnyxEntry