From 2c9a4f8edda282b5b86619ba082d3189a6df7c71 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 12 Nov 2025 19:29:52 +0300 Subject: [PATCH 01/14] show rates from policyForMovingExpenses --- src/components/MoneyRequestConfirmationListFooter.tsx | 3 ++- src/libs/DistanceRequestUtils.ts | 4 +++- src/libs/ReportUtils.ts | 2 +- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 5 ++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/MoneyRequestConfirmationListFooter.tsx b/src/components/MoneyRequestConfirmationListFooter.tsx index 86d8c030a51e..baf5d8568e5a 100644 --- a/src/components/MoneyRequestConfirmationListFooter.tsx +++ b/src/components/MoneyRequestConfirmationListFooter.tsx @@ -513,8 +513,9 @@ function MoneyRequestConfirmationListFooter({ if (!transactionID) { return; } + const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK; - if (!isPolicyExpenseChat) { + if (!isPolicyExpenseChat && (!isTrackExpense || !policyForMovingExpensesID)) { Navigation.navigate( ROUTES.MONEY_REQUEST_UPGRADE.getRoute({ action, diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 0d363d599be5..c4f8721aefec 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -354,11 +354,13 @@ function getRate({ policy, policyDraft, useTransactionDistanceUnit = true, + isTrackExpense, }: { transaction: OnyxEntry; policy: OnyxEntry; policyDraft?: OnyxEntry; useTransactionDistanceUnit?: boolean; + isTrackExpense?: boolean; }): MileageRate { let mileageRates = getMileageRates(policy, true, transaction?.comment?.customUnit?.customUnitRateID); if (isEmptyObject(mileageRates) && policyDraft) { @@ -369,7 +371,7 @@ function getRate({ const customUnitRateID = getRateID(transaction); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const customMileageRate = (customUnitRateID && mileageRates?.[customUnitRateID]) || defaultMileageRate; - const mileageRate = isCustomUnitRateIDForP2P(transaction) ? getRateForP2P(policyCurrency, transaction) : customMileageRate; + const mileageRate = isCustomUnitRateIDForP2P(transaction) && (!isTrackExpense || !customMileageRate) ? getRateForP2P(policyCurrency, transaction) : customMileageRate; const unit = getDistanceUnit(useTransactionDistanceUnit ? transaction : undefined, mileageRate); return { ...mileageRate, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 687e1e5e2b52..1ac990358e03 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4614,7 +4614,7 @@ function canEditFieldOfMoneyRequest( if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DISTANCE_RATE) { // The distance rate can be modified only on the distance expense reports - return isExpenseReport(moneyRequestReport) && isDistanceRequest(transaction); + return (isExpenseReport(moneyRequestReport) || isTrackExpenseAction(reportAction)) && isDistanceRequest(transaction); } if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.REPORT) { diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 5c0cd662fbd5..a09684926bfb 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -5,6 +5,7 @@ import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep'; import useThemeStyles from '@hooks/useThemeStyles'; import {getIOURequestPolicyID, setMoneyRequestDistanceRate, setMoneyRequestTaxAmount, setMoneyRequestTaxRate, updateMoneyRequestDistanceRate} from '@libs/actions/IOU'; @@ -56,7 +57,9 @@ function IOURequestStepDistanceRate({ const currentRateID = getRateID(transaction); const transactionCurrency = getCurrency(transaction); - const rates = DistanceRequestUtils.getMileageRates(policy, false, currentRateID); + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); + const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK; + const rates = DistanceRequestUtils.getMileageRates(isTrackExpense ? policyForMovingExpenses : policy, false, currentRateID); const sortedRates = useMemo(() => Object.values(rates).sort((a, b) => localeCompare(a.name ?? '', b.name ?? '')), [rates, localeCompare]); const navigateBack = () => { From 81c56b467a36a05d4a406189dd35a102832f52e0 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 21 Nov 2025 00:15:02 +0300 Subject: [PATCH 02/14] pass policyID param --- src/libs/actions/IOU.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 6e0c0dfb1402..2eef9db080b8 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -6593,6 +6593,7 @@ function trackExpense(params: CreateTrackExpenseParams) { createdReportActionIDForThread, waypoints: sanitizedWaypoints, customUnitRateID, + policyID: policy?.id, description: parsedComment, }; if (actionableWhisperReportActionIDParam) { From c77d8550c65138360f79bdeb8008599693d2859e Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 2 Dec 2025 23:41:55 +0300 Subject: [PATCH 03/14] second part implementation --- src/components/MoneyRequestConfirmationList.tsx | 2 +- src/libs/API/parameters/TrackExpenseParams.ts | 1 + src/libs/DistanceRequestUtils.ts | 4 +++- src/libs/actions/IOU.ts | 6 ++++-- src/pages/iou/request/DistanceRequestStartPage.tsx | 10 ++++++++-- .../iou/request/step/IOURequestStepParticipants.tsx | 13 ++++++++++--- 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 3a65c74e6837..26957e3d8ff7 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -322,7 +322,7 @@ function MoneyRequestConfirmationList({ setCustomUnitRateID(transactionID, lastSelectedRate); }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense]); - const mileageRate = DistanceRequestUtils.getRate({transaction, policy, policyDraft}); + const mileageRate = DistanceRequestUtils.getRate({transaction, policy: isMovingTransactionFromTrackExpense ? policyForMovingExpenses : policy, policyDraft}); const rate = mileageRate.rate; const prevRate = usePrevious(rate); const unit = mileageRate.unit; diff --git a/src/libs/API/parameters/TrackExpenseParams.ts b/src/libs/API/parameters/TrackExpenseParams.ts index 9b653d5a2a3c..43d0e8d088dd 100644 --- a/src/libs/API/parameters/TrackExpenseParams.ts +++ b/src/libs/API/parameters/TrackExpenseParams.ts @@ -33,6 +33,7 @@ type TrackExpenseParams = { waypoints?: string; actionableWhisperReportActionID?: string; customUnitRateID?: string; + policyID?: string; description?: string; distance?: number; }; diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 91f57d6e0db4..abc6bebf4e44 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -289,12 +289,14 @@ function getCustomUnitRateID({ reportID, isPolicyExpenseChat, policy, + isTrackDistanceExpense, lastSelectedDistanceRates, }: { reportID: string | undefined; isPolicyExpenseChat: boolean; policy: OnyxEntry | undefined; lastSelectedDistanceRates?: OnyxEntry; + isTrackDistanceExpense?: boolean; }): string { let customUnitRateID: string = CONST.CUSTOM_UNITS.FAKE_P2P_ID; @@ -310,7 +312,7 @@ function getCustomUnitRateID({ return customUnitRateID; } - if (isPolicyExpenseChat) { + if (isPolicyExpenseChat || isTrackDistanceExpense) { const distanceUnit = Object.values(policy.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); const lastSelectedDistanceRateID = lastSelectedDistanceRates?.[policy.id]; const lastSelectedDistanceRate = lastSelectedDistanceRateID ? distanceUnit?.rates[lastSelectedDistanceRateID] : undefined; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index fd22704b2d91..eadad8552a96 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -299,6 +299,7 @@ type InitMoneyRequestParams = { currentDate: string | undefined; lastSelectedDistanceRates?: OnyxEntry; currentUserPersonalDetails: CurrentUserPersonalDetails; + isTrackDistanceExpense?: boolean; }; type MoneyRequestInformation = { @@ -1032,6 +1033,7 @@ function initMoneyRequest({ reportID, policy, isFromGlobalCreate, + isTrackDistanceExpense = false, currentIouRequestType, newIouRequestType, report, @@ -1077,7 +1079,7 @@ function initMoneyRequest({ if (newIouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE || newIouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE_MAP || newIouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE_MANUAL) { if (!isFromGlobalCreate) { const isPolicyExpenseChat = isPolicyExpenseChatReportUtil(report) || isPolicyExpenseChatReportUtil(parentReport); - const customUnitRateID = DistanceRequestUtils.getCustomUnitRateID({reportID, isPolicyExpenseChat, policy, lastSelectedDistanceRates}); + const customUnitRateID = DistanceRequestUtils.getCustomUnitRateID({reportID, isPolicyExpenseChat, isTrackDistanceExpense, policy, lastSelectedDistanceRates}); comment.customUnit = {customUnitRateID}; } else if (hasOnlyPersonalPolicies(allPolicies)) { comment.customUnit = {customUnitRateID: CONST.CUSTOM_UNITS.FAKE_P2P_ID}; @@ -6850,7 +6852,7 @@ function trackExpense(params: CreateTrackExpenseParams) { createdReportActionIDForThread, waypoints: sanitizedWaypoints, customUnitRateID, - policyID: policy?.id, + ...(policy && customUnitRateID && customUnitRateID !== CONST.CUSTOM_UNITS.FAKE_P2P_ID && {policyID: policy?.id}), description: parsedComment, }; if (actionableWhisperReportActionIDParam) { diff --git a/src/pages/iou/request/DistanceRequestStartPage.tsx b/src/pages/iou/request/DistanceRequestStartPage.tsx index 8d8fbf39513b..65bf55a8cfa0 100644 --- a/src/pages/iou/request/DistanceRequestStartPage.tsx +++ b/src/pages/iou/request/DistanceRequestStartPage.tsx @@ -9,6 +9,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; @@ -18,6 +19,7 @@ import OnyxTabNavigator, {TabScreenWithFocusTrapWrapper, TopTab} from '@libs/Nav import Performance from '@libs/Performance'; import {getPayeeName} from '@libs/ReportUtils'; import {endSpan} from '@libs/telemetry/activeSpans'; +import {isDistanceRequest} from '@libs/TransactionUtils'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {IOURequestType} from '@userActions/IOU'; import {initMoneyRequest} from '@userActions/IOU'; @@ -91,6 +93,8 @@ function DistanceRequestStartPage({ const navigateBack = () => { Navigation.closeRHPFlow(); }; + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); + const isTrackDistanceExpense = iouType === CONST.IOU.TYPE.TRACK; // This useEffect is used to initialize the money request, so that currency will be reset to default currency on page reload. useEffect(() => { @@ -99,7 +103,8 @@ function DistanceRequestStartPage({ } initMoneyRequest({ reportID, - policy, + policy: isTrackDistanceExpense ? policyForMovingExpenses : policy, + isTrackDistanceExpense, isFromGlobalCreate, currentIouRequestType: transaction?.iouRequestType, newIouRequestType: transaction?.iouRequestType, @@ -120,8 +125,9 @@ function DistanceRequestStartPage({ } initMoneyRequest({ reportID, - policy, + policy: isTrackDistanceExpense ? policyForMovingExpenses : policy, isFromGlobalCreate, + isTrackDistanceExpense, currentIouRequestType: transaction?.iouRequestType, newIouRequestType: newIOUType, report, diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index bb3776bfa0c5..34ed62a62a27 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -7,6 +7,7 @@ import FormHelpMessage from '@components/FormHelpMessage'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import useThemeStyles from '@hooks/useThemeStyles'; import {setTransactionReport} from '@libs/actions/Transaction'; import {READ_COMMANDS} from '@libs/API/types'; @@ -22,7 +23,7 @@ import {isPaidGroupPolicy} from '@libs/PolicyUtils'; import {findSelfDMReportID, generateReportID, isInvoiceRoomWithID} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {endSpan} from '@libs/telemetry/activeSpans'; -import {getRequestType, isCorporateCardTransaction, isPerDiemRequest} from '@libs/TransactionUtils'; +import {getRequestType, isCorporateCardTransaction, isDistanceRequest, isPerDiemRequest} from '@libs/TransactionUtils'; import MoneyRequestParticipantsSelector from '@pages/iou/request/MoneyRequestParticipantsSelector'; import { navigateToStartStepIfScanFileCannotBeRead, @@ -78,6 +79,7 @@ function IOURequestStepParticipants({ const {translate} = useLocalize(); const styles = useThemeStyles(); const isFocused = useIsFocused(); + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${initialTransactionID}`, {canBeMissing: true}); const [optimisticTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, { selector: transactionDraftValuesSelector, @@ -162,7 +164,7 @@ function IOURequestStepParticipants({ // because we want to first check if the p2p rate exists on the workspace. // If it doesn't exist - we'll show an error message to force the user to choose a valid rate from the workspace. useEffect(() => { - if (!isMovingTransactionFromTrackExpense) { + if (!isMovingTransactionFromTrackExpense || !isFocused) { return; } @@ -191,8 +193,13 @@ function IOURequestStepParticipants({ return; } - const rateID = CONST.CUSTOM_UNITS.FAKE_P2P_ID; for (const transaction of transactions) { + const rateID = DistanceRequestUtils.getCustomUnitRateID({ + reportID: selfDMReportID, + isTrackDistanceExpense: isDistanceRequest(transaction), + policy: policyForMovingExpenses, + isPolicyExpenseChat: false, + }); setCustomUnitRateID(transaction.transactionID, rateID); const shouldSetParticipantAutoAssignment = iouType === CONST.IOU.TYPE.CREATE; setMoneyRequestParticipantsFromReport( From 826611bb63990b0136ec79b51f896ad001cd1f53 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 2 Dec 2025 23:56:59 +0300 Subject: [PATCH 04/14] removed violation for track expenses --- src/components/TransactionItemRow/index.tsx | 17 +--- src/libs/SearchUIUtils.ts | 5 +- src/libs/TransactionPreviewUtils.ts | 7 -- src/libs/TransactionUtils/index.ts | 26 ------ tests/unit/TransactionUtilsTest.ts | 90 --------------------- 5 files changed, 4 insertions(+), 141 deletions(-) diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx index 50571bcabfcf..3496b18802e1 100644 --- a/src/components/TransactionItemRow/index.tsx +++ b/src/components/TransactionItemRow/index.tsx @@ -21,16 +21,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {isCategoryMissing} from '@libs/CategoryUtils'; import {isSettled} from '@libs/ReportUtils'; import StringUtils from '@libs/StringUtils'; -import { - getDescription, - getMerchant, - getCreated as getTransactionCreated, - hasMissingSmartscanFields, - isAmountMissing, - isMerchantMissing, - isScanning, - isUnreportedAndHasInvalidDistanceRateTransaction, -} from '@libs/TransactionUtils'; +import {getDescription, getMerchant, getCreated as getTransactionCreated, hasMissingSmartscanFields, isAmountMissing, isMerchantMissing, isScanning} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import type {PersonalDetails, Report, TransactionViolation} from '@src/types/onyx'; @@ -183,8 +174,7 @@ function TransactionItemRow({ return ''; } - const isCustomUnitOutOfPolicy = isUnreportedAndHasInvalidDistanceRateTransaction(transactionItem); - const hasFieldErrors = hasMissingSmartscanFields(transactionItem, report) || isCustomUnitOutOfPolicy; + const hasFieldErrors = hasMissingSmartscanFields(transactionItem, report); if (hasFieldErrors) { const amountMissing = isAmountMissing(transactionItem); const merchantMissing = isMerchantMissing(transactionItem); @@ -196,9 +186,8 @@ function TransactionItemRow({ error = translate('iou.missingAmount'); } else if (merchantMissing && !isSettled(report)) { error = translate('iou.missingMerchant'); - } else if (isCustomUnitOutOfPolicy) { - error = translate('violations.customUnitOutOfPolicy'); } + return error; } }, [transactionItem, translate, report]); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 7e26a8f07eb6..de0aeb593d9c 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -123,7 +123,6 @@ import { getMerchant as getTransactionMerchant, isPending, isScanning, - isUnreportedAndHasInvalidDistanceRateTransaction, isViolationDismissed, } from './TransactionUtils'; import shouldShowTransactionYear from './TransactionUtils/shouldShowTransactionYear'; @@ -1242,9 +1241,7 @@ function getActions( } const transaction = isTransaction ? data[key] : undefined; - if (isUnreportedAndHasInvalidDistanceRateTransaction(transaction)) { - return [CONST.SEARCH.ACTION_TYPES.REVIEW]; - } + // Tracked and unreported expenses don't have a report, so we return early. if (!report) { return [CONST.SEARCH.ACTION_TYPES.VIEW]; diff --git a/src/libs/TransactionPreviewUtils.ts b/src/libs/TransactionPreviewUtils.ts index dbb716b4e285..20da002fdebf 100644 --- a/src/libs/TransactionPreviewUtils.ts +++ b/src/libs/TransactionPreviewUtils.ts @@ -43,7 +43,6 @@ import { isPending, isPerDiemRequest, isScanning, - isUnreportedAndHasInvalidDistanceRateTransaction, } from './TransactionUtils'; const emptyPersonalDetails: OnyxTypes.PersonalDetails = { @@ -276,10 +275,6 @@ function getTransactionPreviewTextAndTranslationPaths({ if (isDistanceRequest(transaction)) { previewHeaderText = [{translationPath: 'common.distance'}]; - - if (RBRMessage === undefined && isUnreportedAndHasInvalidDistanceRateTransaction(transaction)) { - RBRMessage = {translationPath: 'violations.customUnitOutOfPolicy'}; - } } else if (isPerDiemRequest(transaction)) { previewHeaderText = [{translationPath: 'common.perDiem'}]; } else if (isTransactionScanning) { @@ -393,8 +388,6 @@ function createTransactionPreviewConditionals({ const shouldShowCategory = !!categoryForDisplay && isReportAPolicyExpenseChat; const hasAnyViolations = - isUnreportedAndHasInvalidDistanceRateTransaction(transaction) || - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing hasViolationsOfTypeNotice || hasWarningTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy) || hasViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy, true) || diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 74bf60d87289..ec94cb6ba906 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -834,25 +834,6 @@ function isFetchingWaypointsFromServer(transaction: OnyxInputOrEntry, policyParam: OnyxEntry = undefined) { - if (transaction && isDistanceRequest(transaction)) { - const report = getReportOrDraftReport(transaction.reportID); - // eslint-disable-next-line @typescript-eslint/no-deprecated - const policy = policyParam ?? getPolicy(report?.policyID); - const {rate} = DistanceRequestUtils.getRate({transaction, policy}); - const isUnreportedExpense = !transaction.reportID || transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID || String(transaction.reportID) === CONST.REPORT.SPLIT_REPORT_ID; - - if (isUnreportedExpense && !rate) { - return true; - } - } - - return false; -} - /** * Return the merchant field from the transaction, return the modifiedMerchant if present. */ @@ -865,12 +846,6 @@ function getMerchant(transaction: OnyxInputOrEntry, policyParam: On const mileageRate = DistanceRequestUtils.getRate({transaction, policy}); const {unit, rate} = mileageRate; const distanceInMeters = getDistanceInMeters(transaction, unit); - if (policy?.customUnits && !isUnreportedAndHasInvalidDistanceRateTransaction(transaction, policy)) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - return DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction.currency, translateLocal, (digit) => - toLocaleDigit(IntlStore.getCurrentLocale(), digit), - ); - } } return transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? ''); } @@ -2332,7 +2307,6 @@ export { createUnreportedExpenseSections, isDemoTransaction, shouldShowViolation, - isUnreportedAndHasInvalidDistanceRateTransaction, getTransactionViolationsOfTransaction, isExpenseSplit, getAttendeesListDisplayString, diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index b0a727e02bdf..fe475841a5ab 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -696,96 +696,6 @@ describe('TransactionUtils', () => { }); }); - describe('isUnreportedAndHasInvalidDistanceRateTransaction', () => { - it('should be false when transaction is null', () => { - const fakePolicy: Policy = { - ...createRandomPolicy(0), - customUnits: defaultCustomUnitPolicyID1, - }; - const result = TransactionUtils.isUnreportedAndHasInvalidDistanceRateTransaction(null, fakePolicy); - expect(result).toBe(false); - }); - it('should be false when transaction is not distance type transaction', () => { - const fakePolicy: Policy = { - ...createRandomPolicy(0), - customUnits: defaultCustomUnitPolicyID1, - }; - const transaction: Transaction = { - ...generateTransaction(), - iouRequestType: CONST.IOU.REQUEST_TYPE.MANUAL, - }; - const result = TransactionUtils.isUnreportedAndHasInvalidDistanceRateTransaction(transaction, fakePolicy); - expect(result).toBe(false); - }); - it('should be false when transaction is reported', () => { - const fakePolicy: Policy = { - ...createRandomPolicy(0), - customUnits: defaultCustomUnitPolicyID1, - }; - const transaction: Transaction = { - ...generateTransaction(), - iouRequestType: CONST.IOU.REQUEST_TYPE.DISTANCE, - reportID: '1', - }; - const result = TransactionUtils.isUnreportedAndHasInvalidDistanceRateTransaction(transaction, fakePolicy); - expect(result).toBe(false); - }); - it('should be false when transaction is unreported and has valid rate', () => { - const fakePolicy: Policy = { - ...createRandomPolicy(0), - customUnits: defaultCustomUnitPolicyID1, - }; - const transaction: Transaction = { - ...generateTransaction(), - iouRequestType: CONST.IOU.REQUEST_TYPE.DISTANCE, - reportID: '0', - comment: { - customUnit: distanceRateTransactionID1, - type: 'customUnit', - }, - }; - - const result = TransactionUtils.isUnreportedAndHasInvalidDistanceRateTransaction(transaction, fakePolicy); - expect(result).toBe(false); - }); - it('should be false when transaction is unreported, has invalid rate but policy has default rate', () => { - const fakePolicy: Policy = { - ...createRandomPolicy(0), - customUnits: defaultCustomUnitPolicyID1, - }; - const transaction: Transaction = { - ...generateTransaction(), - iouRequestType: CONST.IOU.REQUEST_TYPE.DISTANCE, - reportID: '0', - comment: { - customUnit: distanceRateTransactionID2, - type: 'customUnit', - }, - }; - - const result = TransactionUtils.isUnreportedAndHasInvalidDistanceRateTransaction(transaction, fakePolicy); - expect(result).toBe(false); - }); - it('should be true when transaction is unreported, has invalid rate and policy has no default rate', () => { - const fakePolicy: Policy = { - ...createRandomPolicy(0), - customUnits: {}, - }; - const transaction: Transaction = { - ...generateTransaction(), - iouRequestType: CONST.IOU.REQUEST_TYPE.DISTANCE, - reportID: '0', - comment: { - customUnit: distanceRateTransactionID2, - type: 'customUnit', - }, - }; - - const result = TransactionUtils.isUnreportedAndHasInvalidDistanceRateTransaction(transaction, fakePolicy); - expect(result).toBe(true); - }); - }); - describe('isViolationDismissed', () => { describe('Current user dismissed it themselves', () => { it('should return true when current user dismissed the violation', () => { From 11e6ce9b5b5b3c18ea3026f3e57adf2a0564069a Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 3 Dec 2025 15:04:22 +0300 Subject: [PATCH 05/14] lint fixes --- src/libs/TransactionUtils/index.ts | 9 ------- .../iou/request/DistanceRequestStartPage.tsx | 1 - tests/unit/TransactionUtilsTest.ts | 25 +------------------ 3 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index e038d6131a16..7c0add3b2f9a 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -840,15 +840,6 @@ function isFetchingWaypointsFromServer(transaction: OnyxInputOrEntry, policyParam: OnyxEntry = undefined): string { - if (transaction && isDistanceRequest(transaction)) { - const report = getReportOrDraftReport(transaction.reportID); - // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 - // eslint-disable-next-line @typescript-eslint/no-deprecated - const policy = policyParam ?? getPolicy(report?.policyID); - const mileageRate = DistanceRequestUtils.getRate({transaction, policy}); - const {unit, rate} = mileageRate; - const distanceInMeters = getDistanceInMeters(transaction, unit); - } return transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? ''); } diff --git a/src/pages/iou/request/DistanceRequestStartPage.tsx b/src/pages/iou/request/DistanceRequestStartPage.tsx index 65bf55a8cfa0..6fece171cea9 100644 --- a/src/pages/iou/request/DistanceRequestStartPage.tsx +++ b/src/pages/iou/request/DistanceRequestStartPage.tsx @@ -19,7 +19,6 @@ import OnyxTabNavigator, {TabScreenWithFocusTrapWrapper, TopTab} from '@libs/Nav import Performance from '@libs/Performance'; import {getPayeeName} from '@libs/ReportUtils'; import {endSpan} from '@libs/telemetry/activeSpans'; -import {isDistanceRequest} from '@libs/TransactionUtils'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {IOURequestType} from '@userActions/IOU'; import {initMoneyRequest} from '@userActions/IOU'; diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index fe475841a5ab..3fca83f2de8c 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -86,30 +86,7 @@ const defaultDistanceRatePolicyID1: Record = { subRates: [], }, }; -const distanceRateTransactionID1: TransactionCustomUnit = { - customUnitID: 'customUnitID1', - customUnitRateID: 'customUnitRateID1', - distanceUnit: 'mi', - name: 'Distance', -}; -const distanceRateTransactionID2: TransactionCustomUnit = { - customUnitID: 'customUnitID2', - customUnitRateID: 'customUnitRateID2', - distanceUnit: 'mi', - name: 'Distance', -}; -const defaultCustomUnitPolicyID1: Record = { - customUnitID1: { - attributes: { - unit: 'mi', - }, - customUnitID: 'customUnitID1', - defaultCategory: 'Car', - enabled: true, - name: 'Distance', - rates: defaultDistanceRatePolicyID1, - }, -}; + const currentUserPersonalDetails = { accountID: CURRENT_USER_ID, login: CURRENT_USER_EMAIL, From c8b655b07575db42c9c2c6ef082e25ef383c4cb6 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 3 Dec 2025 15:20:02 +0300 Subject: [PATCH 06/14] fix test --- src/libs/TransactionUtils/index.ts | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 7c0add3b2f9a..3b84b110a81a 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -836,10 +836,44 @@ function isFetchingWaypointsFromServer(transaction: OnyxInputOrEntry, policyParam: OnyxEntry = undefined) { + if (transaction && isDistanceRequest(transaction)) { + const report = getReportOrDraftReport(transaction.reportID); + // eslint-disable-next-line @typescript-eslint/no-deprecated + const policy = policyParam ?? getPolicy(report?.policyID); + const {rate} = DistanceRequestUtils.getRate({transaction, policy}); + const isUnreportedExpense = !transaction.reportID || transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID || String(transaction.reportID) === CONST.REPORT.SPLIT_REPORT_ID; + + if (isUnreportedExpense && !rate) { + return true; + } + } + + return false; +} + /** * Return the merchant field from the transaction, return the modifiedMerchant if present. */ function getMerchant(transaction: OnyxInputOrEntry, policyParam: OnyxEntry = undefined): string { + if (transaction && isDistanceRequest(transaction)) { + const report = getReportOrDraftReport(transaction.reportID); + // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 + // eslint-disable-next-line @typescript-eslint/no-deprecated + const policy = policyParam ?? getPolicy(report?.policyID); + const mileageRate = DistanceRequestUtils.getRate({transaction, policy}); + const {unit, rate} = mileageRate; + const distanceInMeters = getDistanceInMeters(transaction, unit); + if (policy?.customUnits && !isUnreportedAndHasInvalidDistanceRateTransaction(transaction, policy)) { + // eslint-disable-next-line @typescript-eslint/no-deprecated + return DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction.currency, translateLocal, (digit) => + toLocaleDigit(IntlStore.getCurrentLocale(), digit), + ); + } + } return transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? ''); } From 3429cd531726aab102296af7af1f4a46de09197a Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 3 Dec 2025 16:47:31 +0300 Subject: [PATCH 07/14] minor fixes --- src/components/MoneyRequestConfirmationList.tsx | 2 +- .../MoneyRequestConfirmationListFooter.tsx | 1 - src/libs/DistanceRequestUtils.ts | 13 ++++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 6b836b27d521..2c1ac74cef75 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -322,7 +322,7 @@ function MoneyRequestConfirmationList({ setCustomUnitRateID(transactionID, lastSelectedRate); }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense]); - const mileageRate = DistanceRequestUtils.getRate({transaction, policy: isMovingTransactionFromTrackExpense ? policyForMovingExpenses : policy, policyDraft}); + const mileageRate = DistanceRequestUtils.getRate({transaction, policy, ...(isMovingTransactionFromTrackExpense && {policyForMovingExpenses}), policyDraft}); const rate = mileageRate.rate; const prevRate = usePrevious(rate); const unit = mileageRate.unit; diff --git a/src/components/MoneyRequestConfirmationListFooter.tsx b/src/components/MoneyRequestConfirmationListFooter.tsx index fac21e774c8d..7ed6e29d669e 100644 --- a/src/components/MoneyRequestConfirmationListFooter.tsx +++ b/src/components/MoneyRequestConfirmationListFooter.tsx @@ -528,7 +528,6 @@ function MoneyRequestConfirmationListFooter({ if (!transactionID) { return; } - const isTrackExpense = iouType === CONST.IOU.TYPE.TRACK; if (!isPolicyExpenseChat && (!isTrackExpense || !policyForMovingExpensesID)) { Navigation.navigate( diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index abc6bebf4e44..5e4e2369da8c 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -289,7 +289,7 @@ function getCustomUnitRateID({ reportID, isPolicyExpenseChat, policy, - isTrackDistanceExpense, + isTrackDistanceExpense = false, lastSelectedDistanceRates, }: { reportID: string | undefined; @@ -316,7 +316,7 @@ function getCustomUnitRateID({ const distanceUnit = Object.values(policy.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); const lastSelectedDistanceRateID = lastSelectedDistanceRates?.[policy.id]; const lastSelectedDistanceRate = lastSelectedDistanceRateID ? distanceUnit?.rates[lastSelectedDistanceRateID] : undefined; - if (lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) { + if (!isTrackDistanceExpense && lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) { customUnitRateID = lastSelectedDistanceRateID; } else { const defaultMileageRate = getDefaultMileageRate(policy); @@ -361,24 +361,27 @@ function getRate({ policy, policyDraft, useTransactionDistanceUnit = true, - isTrackExpense, + policyForMovingExpenses, }: { transaction: OnyxEntry; policy: OnyxEntry; policyDraft?: OnyxEntry; + policyForMovingExpenses?: OnyxEntry; useTransactionDistanceUnit?: boolean; - isTrackExpense?: boolean; }): MileageRate { let mileageRates = getMileageRates(policy, true, transaction?.comment?.customUnit?.customUnitRateID); if (isEmptyObject(mileageRates) && policyDraft) { mileageRates = getMileageRates(policyDraft, true, transaction?.comment?.customUnit?.customUnitRateID); } + if (isEmptyObject(mileageRates) && policyForMovingExpenses) { + mileageRates = getMileageRates(policyForMovingExpenses, true, transaction?.comment?.customUnit?.customUnitRateID); + } const policyCurrency = policy?.outputCurrency ?? getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; const defaultMileageRate = getDefaultMileageRate(policy); const customUnitRateID = getRateID(transaction); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const customMileageRate = (customUnitRateID && mileageRates?.[customUnitRateID]) || defaultMileageRate; - const mileageRate = isCustomUnitRateIDForP2P(transaction) && (!isTrackExpense || !customMileageRate) ? getRateForP2P(policyCurrency, transaction) : customMileageRate; + const mileageRate = isCustomUnitRateIDForP2P(transaction) ? getRateForP2P(policyCurrency, transaction) : customMileageRate; const unit = getDistanceUnit(useTransactionDistanceUnit ? transaction : undefined, mileageRate); return { ...mileageRate, From f95d0a4e2f22d2cc0f879985525ae0c4fe59daac Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 3 Dec 2025 16:49:24 +0300 Subject: [PATCH 08/14] fix lint --- src/libs/TransactionPreviewUtils.ts | 2 +- tests/unit/TransactionUtilsTest.ts | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/libs/TransactionPreviewUtils.ts b/src/libs/TransactionPreviewUtils.ts index d356b3bb4bcb..025095f3f3aa 100644 --- a/src/libs/TransactionPreviewUtils.ts +++ b/src/libs/TransactionPreviewUtils.ts @@ -395,7 +395,7 @@ function createTransactionPreviewConditionals({ const shouldShowCategory = !!categoryForDisplay && isReportAPolicyExpenseChat; const hasAnyViolations = - hasViolationsOfTypeNotice || + !!hasViolationsOfTypeNotice || hasWarningTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy) || hasViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy, true) || (isDistanceRequest(transaction) && diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index 3fca83f2de8c..e9039e08d010 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -5,9 +5,8 @@ import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Attendee} from '@src/types/onyx/IOU'; -import type {CustomUnit, Rate} from '@src/types/onyx/Policy'; +import type {Rate} from '@src/types/onyx/Policy'; import type {ReportCollectionDataSet} from '@src/types/onyx/Report'; -import type {TransactionCustomUnit} from '@src/types/onyx/Transaction'; import * as TransactionUtils from '../../src/libs/TransactionUtils'; import type {Policy, Report, Transaction} from '../../src/types/onyx'; import type {CardList} from '../../src/types/onyx/Card'; @@ -76,16 +75,6 @@ const reportCollectionDataSet: ReportCollectionDataSet = { [`${ONYXKEYS.COLLECTION.REPORT}${FAKE_APPROVED_REPORT_ID}`]: approvedReport, [`${ONYXKEYS.COLLECTION.REPORT}${FAKE_OPEN_REPORT_SECOND_USER_ID}`]: secondUserOpenReport, }; -const defaultDistanceRatePolicyID1: Record = { - customUnitRateID1: { - currency: 'USD', - customUnitRateID: 'customUnitRateID1', - enabled: true, - name: 'Default Rate', - rate: 70, - subRates: [], - }, -}; const currentUserPersonalDetails = { accountID: CURRENT_USER_ID, From 4a9c2e47d724aa5c2e950ab45182d236339007d8 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 3 Dec 2025 17:30:25 +0300 Subject: [PATCH 09/14] handled quick action navigation case --- .../iou/request/step/IOURequestStepDistanceManual.tsx | 11 +++++++++-- .../iou/request/step/IOURequestStepDistanceMap.tsx | 11 +++++++++-- tests/unit/TransactionUtilsTest.ts | 1 - 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 3bac31a0919b..be07040c4538 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -15,6 +15,7 @@ import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePersonalPolicy from '@hooks/usePersonalPolicy'; import usePolicy from '@hooks/usePolicy'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import { @@ -80,6 +81,7 @@ function IOURequestStepDistanceManual({ const [selectedTab, selectedTabResult] = useOnyx(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.DISTANCE_REQUEST_TYPE}`, {canBeMissing: true}); const isLoadingSelectedTab = isLoadingOnyxValue(selectedTabResult); const policy = usePolicy(report?.policyID); + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); const personalPolicy = usePersonalPolicy(); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const defaultExpensePolicy = useDefaultExpensePolicy(); @@ -206,7 +208,7 @@ function IOURequestStepDistanceManual({ participant, }, policyParams: { - policy, + policy: policyForMovingExpenses, }, transactionParams: { amount: 0, @@ -216,7 +218,12 @@ function IOURequestStepDistanceManual({ merchant: translate('iou.fieldPending'), receipt: {}, billable: false, - customUnitRateID, + customUnitRateID: DistanceRequestUtils.getCustomUnitRateID({ + reportID: report.reportID, + isTrackDistanceExpense: true, + policy: policyForMovingExpenses, + isPolicyExpenseChat: false, + }), attendees: transaction?.comment?.attendees, }, isASAPSubmitBetaEnabled, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 92f854c1b18c..c0cd0867ac92 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -22,6 +22,7 @@ import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePersonalPolicy from '@hooks/usePersonalPolicy'; import usePolicy from '@hooks/usePolicy'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import usePrevious from '@hooks/usePrevious'; import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -89,6 +90,7 @@ function IOURequestStepDistanceMap({ const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); const [transactionBackup] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_BACKUP}${transactionID}`, {canBeMissing: true}); const policy = usePolicy(report?.policyID); + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); const personalPolicy = usePersonalPolicy(); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const defaultExpensePolicy = useDefaultExpensePolicy(); @@ -337,7 +339,7 @@ function IOURequestStepDistanceMap({ participant, }, policyParams: { - policy, + policy: policyForMovingExpenses, }, transactionParams: { amount: 0, @@ -348,7 +350,12 @@ function IOURequestStepDistanceMap({ billable: false, reimbursable: true, validWaypoints: getValidWaypoints(waypoints, true), - customUnitRateID, + customUnitRateID: DistanceRequestUtils.getCustomUnitRateID({ + reportID: report.reportID, + isTrackDistanceExpense: true, + policy: policyForMovingExpenses, + isPolicyExpenseChat: false, + }), attendees: transaction?.comment?.attendees, }, isASAPSubmitBetaEnabled, diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index e9039e08d010..952058b16bd9 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -5,7 +5,6 @@ import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Attendee} from '@src/types/onyx/IOU'; -import type {Rate} from '@src/types/onyx/Policy'; import type {ReportCollectionDataSet} from '@src/types/onyx/Report'; import * as TransactionUtils from '../../src/libs/TransactionUtils'; import type {Policy, Report, Transaction} from '../../src/types/onyx'; From 4297392ea71b7fb679faf65fab7b9f7e759d2546 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 5 Dec 2025 17:05:57 +0300 Subject: [PATCH 10/14] lint fix --- .../request/step/IOURequestStepDistanceManual.tsx | 1 + .../iou/request/step/IOURequestStepDistanceMap.tsx | 1 + .../request/step/IOURequestStepParticipants.tsx | 14 +++++++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 4430f62ef8fb..1228f3e84028 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -321,6 +321,7 @@ function IOURequestStepDistanceManual({ personalPolicy?.autoReporting, transactionViolations, currentUserPersonalDetails.accountID, + policyForMovingExpenses, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index a568babbe698..64bc27105181 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -455,6 +455,7 @@ function IOURequestStepDistanceMap({ reportID, transactionViolations, currentUserPersonalDetails.accountID, + policyForMovingExpenses, ]); const getError = () => { diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 34ed62a62a27..249d28e449c8 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -224,7 +224,19 @@ function IOURequestStepParticipants({ }); } }); - }, [selfDMReportID, transactions, action, initialTransactionID, waitForKeyboardDismiss, iouType, selfDMReport, currentUserPersonalDetails.accountID, isActivePolicyRequest, backTo]); + }, [ + selfDMReportID, + transactions, + action, + initialTransactionID, + waitForKeyboardDismiss, + iouType, + selfDMReport, + currentUserPersonalDetails.accountID, + isActivePolicyRequest, + backTo, + policyForMovingExpenses, + ]); const addParticipant = useCallback( (val: Participant[]) => { From d0f64c1c67109af8d1008ec4dcc727023cfa938f Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 5 Dec 2025 17:18:12 +0300 Subject: [PATCH 11/14] lint fix --- src/pages/iou/request/step/IOURequestStepDistanceManual.tsx | 2 -- src/pages/iou/request/step/IOURequestStepDistanceMap.tsx | 1 - 2 files changed, 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 1228f3e84028..950bead23c14 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -107,7 +107,6 @@ function IOURequestStepDistanceManual({ [iouType, defaultExpensePolicy], ); - const customUnitRateID = getRateID(transaction); const unit = DistanceRequestUtils.getRate({transaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}).unit; const distance = transaction?.comment?.customUnit?.quantity ? roundToTwoDecimalPlaces(transaction.comment.customUnit.quantity) : undefined; const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); @@ -315,7 +314,6 @@ function IOURequestStepDistanceManual({ lastSelectedDistanceRates, backToReport, isASAPSubmitBetaEnabled, - customUnitRateID, navigateToConfirmationPage, defaultExpensePolicy, personalPolicy?.autoReporting, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 64bc27105181..c5d78d1ba359 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -449,7 +449,6 @@ function IOURequestStepDistanceMap({ lastSelectedDistanceRates, backToReport, isASAPSubmitBetaEnabled, - customUnitRateID, navigateToConfirmationPage, personalPolicy?.autoReporting, reportID, From 50406127a90ff22680cdb40474561661955add2b Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 5 Dec 2025 18:55:16 +0300 Subject: [PATCH 12/14] minor fix --- src/components/MoneyRequestConfirmationList.tsx | 7 ++++++- src/libs/DistanceRequestUtils.ts | 6 ++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 75c595772754..9a5e00634b7d 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -322,7 +322,12 @@ function MoneyRequestConfirmationList({ setCustomUnitRateID(transactionID, lastSelectedRate); }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense]); - const mileageRate = DistanceRequestUtils.getRate({transaction, policy, ...(isMovingTransactionFromTrackExpense && {policyForMovingExpenses}), policyDraft}); + const mileageRate = DistanceRequestUtils.getRate({ + transaction, + policy: isTrackExpense ? policyForMovingExpenses : policy, + ...(isMovingTransactionFromTrackExpense && {policyForMovingExpenses}), + policyDraft, + }); const rate = mileageRate.rate; const prevRate = usePrevious(rate); const unit = mileageRate.unit; diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 38972f939c5b..7f8cea95b889 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -373,14 +373,12 @@ function getRate({ if (isEmptyObject(mileageRates) && policyDraft) { mileageRates = getMileageRates(policyDraft, true, transaction?.comment?.customUnit?.customUnitRateID); } - if (isEmptyObject(mileageRates) && policyForMovingExpenses) { - mileageRates = getMileageRates(policyForMovingExpenses, true, transaction?.comment?.customUnit?.customUnitRateID); - } + const mileageRatesForMovingExpenses = getMileageRates(policyForMovingExpenses, true, transaction?.comment?.customUnit?.customUnitRateID); const policyCurrency = policy?.outputCurrency ?? getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD; const defaultMileageRate = getDefaultMileageRate(policy); const customUnitRateID = getRateID(transaction); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const customMileageRate = (customUnitRateID && mileageRates?.[customUnitRateID]) || defaultMileageRate; + const customMileageRate = (customUnitRateID && (mileageRates?.[customUnitRateID] ?? mileageRatesForMovingExpenses?.[customUnitRateID])) || defaultMileageRate; const mileageRate = isCustomUnitRateIDForP2P(transaction) ? getRateForP2P(policyCurrency, transaction) : customMileageRate; const unit = getDistanceUnit(useTransactionDistanceUnit ? transaction : undefined, mileageRate); return { From c4a5d1af96cbd4137e17dacc83acd8dd7377a311 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 17 Dec 2025 15:47:58 +0300 Subject: [PATCH 13/14] minor fix --- src/pages/iou/request/step/IOURequestStepParticipants.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index b33b28265075..0b7e33cc71eb 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -7,6 +7,7 @@ import FormHelpMessage from '@components/FormHelpMessage'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import useThemeStyles from '@hooks/useThemeStyles'; import {setTransactionReport} from '@libs/actions/Transaction'; import {READ_COMMANDS} from '@libs/API/types'; @@ -83,6 +84,7 @@ function IOURequestStepParticipants({ canBeMissing: true, }); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: policiesSelector, canBeMissing: true}); + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true}); const transactions = useMemo(() => { From ac4830b271db612496ff458d507d8803814b5dce Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 17 Dec 2025 16:04:32 +0300 Subject: [PATCH 14/14] fix lint --- src/components/MoneyRequestConfirmationListFooter.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/MoneyRequestConfirmationListFooter.tsx b/src/components/MoneyRequestConfirmationListFooter.tsx index dda6fa7f85be..9d4ace5dc111 100644 --- a/src/components/MoneyRequestConfirmationListFooter.tsx +++ b/src/components/MoneyRequestConfirmationListFooter.tsx @@ -346,6 +346,7 @@ function MoneyRequestConfirmationListFooter({ }, [allReports, shouldUseTransactionReport, transaction?.reportID, outstandingReportID]); const reportName = useMemo(() => { + // eslint-disable-next-line @typescript-eslint/no-deprecated const name = getReportName(selectedReport, selectedPolicy); if (!name) { return isUnreported ? translate('common.none') : translate('iou.newReport');