diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 303955628739..ee71b7e4e1d6 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -323,7 +323,12 @@ function MoneyRequestConfirmationList({ setCustomUnitRateID(transactionID, lastSelectedRate); }, [customUnitRateID, transactionID, lastSelectedRate, isDistanceRequest, isPolicyExpenseChat, isMovingTransactionFromTrackExpense]); - const mileageRate = DistanceRequestUtils.getRate({transaction, policy, 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/components/MoneyRequestConfirmationListFooter.tsx b/src/components/MoneyRequestConfirmationListFooter.tsx index b49a1555b6ba..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'); @@ -526,7 +527,7 @@ function MoneyRequestConfirmationListFooter({ return; } - if (!isPolicyExpenseChat) { + if (!isPolicyExpenseChat && (!isTrackExpense || !policyForMovingExpensesID)) { Navigation.navigate( ROUTES.MONEY_REQUEST_UPGRADE.getRoute({ action, diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx index 629b8c92d726..c206ed0048c1 100644 --- a/src/components/TransactionItemRow/index.tsx +++ b/src/components/TransactionItemRow/index.tsx @@ -39,7 +39,6 @@ import { isAmountMissing, isMerchantMissing, isScanning, - isUnreportedAndHasInvalidDistanceRateTransaction, } from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; @@ -214,8 +213,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); @@ -227,9 +225,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/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 1a3f1b119e73..cb3e4059f98a 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -289,12 +289,14 @@ function getCustomUnitRateID({ reportID, isPolicyExpenseChat, policy, + isTrackDistanceExpense = false, lastSelectedDistanceRates, }: { reportID: string | undefined; isPolicyExpenseChat: boolean; policy: OnyxEntry | undefined; lastSelectedDistanceRates?: OnyxEntry; + isTrackDistanceExpense?: boolean; }): string { let customUnitRateID: string = CONST.CUSTOM_UNITS.FAKE_P2P_ID; @@ -310,11 +312,11 @@ 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; - if (lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) { + if (!isTrackDistanceExpense && lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) { customUnitRateID = lastSelectedDistanceRateID; } else { const defaultMileageRate = getDefaultMileageRate(policy); @@ -359,21 +361,24 @@ function getRate({ policy, policyDraft, useTransactionDistanceUnit = true, + policyForMovingExpenses, }: { transaction: OnyxEntry; policy: OnyxEntry; policyDraft?: OnyxEntry; + policyForMovingExpenses?: OnyxEntry; useTransactionDistanceUnit?: boolean; }): MileageRate { let mileageRates = getMileageRates(policy, true, transaction?.comment?.customUnit?.customUnitRateID); if (isEmptyObject(mileageRates) && policyDraft) { mileageRates = getMileageRates(policyDraft, 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 { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 568c30bfad92..2947bca3703d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4832,7 +4832,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/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 8d7439c60458..6e01e5dfc6b8 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -1402,6 +1402,7 @@ function getActions( } const transaction = isTransaction ? data[key] : undefined; + // 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 78473e0babb8..deb4148c31b0 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 = { @@ -277,10 +276,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) { @@ -398,9 +393,7 @@ function createTransactionPreviewConditionals({ const shouldShowCategory = !!categoryForDisplay && isReportAPolicyExpenseChat; const hasAnyViolations = - isUnreportedAndHasInvalidDistanceRateTransaction(transaction) || - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - hasViolationsOfTypeNotice || + !!hasViolationsOfTypeNotice || hasWarningTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy) || hasViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy, true) || (isDistanceRequest(transaction) && diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 59a9b7d19204..28ffc3f1d2c1 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -2545,7 +2545,6 @@ export { createUnreportedExpenses, isDemoTransaction, shouldShowViolation, - isUnreportedAndHasInvalidDistanceRateTransaction, getTransactionViolationsOfTransaction, hasTransactionBeenRejected, isExpenseSplit, diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 209457f6e2dd..49913a9c4dc1 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -298,6 +298,7 @@ type InitMoneyRequestParams = { currentDate: string | undefined; lastSelectedDistanceRates?: OnyxEntry; currentUserPersonalDetails: CurrentUserPersonalDetails; + isTrackDistanceExpense?: boolean; hasOnlyPersonalPolicies: boolean; }; @@ -1051,6 +1052,7 @@ function initMoneyRequest({ policy, personalPolicy, isFromGlobalCreate, + isTrackDistanceExpense = false, currentIouRequestType, newIouRequestType, report, @@ -1094,7 +1096,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, name: CONST.CUSTOM_UNITS.NAME_DISTANCE}; } else if (hasOnlyPersonalPolicies) { comment.customUnit = {customUnitRateID: CONST.CUSTOM_UNITS.FAKE_P2P_ID, name: CONST.CUSTOM_UNITS.NAME_DISTANCE}; @@ -7080,6 +7082,7 @@ function trackExpense(params: CreateTrackExpenseParams) { createdReportActionIDForThread, waypoints: sanitizedWaypoints, customUnitRateID, + ...(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 8c4595f5e74c..e1a37dc8d5a6 100644 --- a/src/pages/iou/request/DistanceRequestStartPage.tsx +++ b/src/pages/iou/request/DistanceRequestStartPage.tsx @@ -11,6 +11,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 useThemeStyles from '@hooks/useThemeStyles'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; @@ -99,6 +100,8 @@ function DistanceRequestStartPage({ const navigateBack = () => { Navigation.closeRHPFlow(); }; + const {policyForMovingExpenses} = usePolicyForMovingExpenses(); + const isTrackDistanceExpense = iouType === CONST.IOU.TYPE.TRACK; const resetIOUTypeIfChanged = useCallback( (newIOUType: IOURequestType) => { @@ -108,9 +111,10 @@ function DistanceRequestStartPage({ } initMoneyRequest({ reportID, - policy, + policy: isTrackDistanceExpense ? policyForMovingExpenses : policy, personalPolicy, isFromGlobalCreate, + isTrackDistanceExpense, currentIouRequestType: transaction?.iouRequestType, newIouRequestType: newIOUType, report, @@ -132,6 +136,8 @@ function DistanceRequestStartPage({ currentDate, lastSelectedDistanceRates, currentUserPersonalDetails, + isTrackDistanceExpense, + policyForMovingExpenses, hasOnlyPersonalPolicies, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 83d2a05a55f4..00e7fded9520 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(); @@ -106,7 +108,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); @@ -208,7 +209,7 @@ function IOURequestStepDistanceManual({ participant, }, policyParams: { - policy, + policy: policyForMovingExpenses, }, transactionParams: { amount: 0, @@ -218,7 +219,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, @@ -312,12 +318,12 @@ function IOURequestStepDistanceManual({ lastSelectedDistanceRates, backToReport, isASAPSubmitBetaEnabled, - customUnitRateID, navigateToConfirmationPage, defaultExpensePolicy, personalPolicy?.autoReporting, transactionViolations, currentUserPersonalDetails.accountID, + policyForMovingExpenses, quickAction, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 6608f0f77c4b..b938a6309f61 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(); @@ -339,7 +341,7 @@ function IOURequestStepDistanceMap({ participant, }, policyParams: { - policy, + policy: policyForMovingExpenses, }, transactionParams: { amount: 0, @@ -350,7 +352,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, @@ -447,12 +454,12 @@ function IOURequestStepDistanceMap({ lastSelectedDistanceRates, backToReport, isASAPSubmitBetaEnabled, - customUnitRateID, navigateToConfirmationPage, personalPolicy?.autoReporting, reportID, transactionViolations, currentUserPersonalDetails.accountID, + policyForMovingExpenses, quickAction, ]); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 6649c1efda10..2710b91abf40 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -7,6 +7,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; +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'; @@ -71,7 +72,9 @@ function IOURequestStepDistanceRate({ const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - 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 = () => { diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 60a15a275e8f..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'; @@ -21,7 +22,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, @@ -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(() => { @@ -170,7 +172,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; } @@ -199,8 +201,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( @@ -225,7 +232,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[]) => { diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index cf0cac4115d7..33a8a1fdf199 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -5,9 +5,7 @@ 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 {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,40 +74,7 @@ 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 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, @@ -696,96 +661,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', () => {