@@ -23,6 +23,7 @@ import useOnyx from '@hooks/useOnyx';
2323import useOptimisticDraftTransactions from '@hooks/useOptimisticDraftTransactions' ;
2424import useParticipantsPolicies from '@hooks/useParticipantsPolicies' ;
2525import usePermissions from '@hooks/usePermissions' ;
26+ import usePersonalPolicy from '@hooks/usePersonalPolicy' ;
2627import usePolicyForTransaction from '@hooks/usePolicyForTransaction' ;
2728import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap' ;
2829import useReportAttributes from '@hooks/useReportAttributes' ;
@@ -35,6 +36,7 @@ import {setMoneyRequestBillable, setMoneyRequestReimbursable} from '@libs/action
3536import { setTransactionReport } from '@libs/actions/Transaction' ;
3637import { isMobileSafari } from '@libs/Browser' ;
3738import { canUseTouchScreen } from '@libs/DeviceCapabilities' ;
39+ import DistanceRequestUtils from '@libs/DistanceRequestUtils' ;
3840import getIsNarrowLayout from '@libs/getIsNarrowLayout' ;
3941import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID' ;
4042import {
@@ -54,7 +56,7 @@ import {submitWithDismissFirst} from '@libs/Navigation/helpers/submitWithDismiss
5456import Navigation , { navigationRef } from '@libs/Navigation/Navigation' ;
5557import type { MoneyRequestNavigatorParamList } from '@libs/Navigation/types' ;
5658import { getParticipantsOption , getReportOption } from '@libs/OptionsListUtils' ;
57- import { findSelfDMReportID , getReportOrDraftReport , isMoneyRequestReport , isPolicyExpenseChat as isPolicyExpenseChatUtils } from '@libs/ReportUtils' ;
59+ import { findSelfDMReportID , generateReportID , getReportOrDraftReport , isMoneyRequestReport , isPolicyExpenseChat as isPolicyExpenseChatUtils } from '@libs/ReportUtils' ;
5860import { buildCannedSearchQuery , getCurrentSearchQueryJSON } from '@libs/SearchQueryUtils' ;
5961import { cancelTracking , getPendingSubmitFollowUpAction , isTracking } from '@libs/telemetry/submitFollowUpAction' ;
6062import type { SkeletonSpanReasonAttributes } from '@libs/telemetry/useSkeletonSpan' ;
@@ -67,7 +69,7 @@ import {
6769 isScanRequest ,
6870} from '@libs/TransactionUtils' ;
6971
70- import { getIOURequestPolicyID , setMoneyRequestParticipants , setMoneyRequestParticipantsFromReport } from '@userActions/IOU/MoneyRequest' ;
72+ import { getIOURequestPolicyID , setCustomUnitRateID , setMoneyRequestCategory , setMoneyRequestParticipants , setMoneyRequestParticipantsFromReport } from '@userActions/IOU/MoneyRequest' ;
7173import { setMoneyRequestReceipt } from '@userActions/IOU/Receipt' ;
7274import { removeDraftTransaction , replaceDefaultDraftTransaction } from '@userActions/TransactionEdit' ;
7375
@@ -124,6 +126,7 @@ function IOURequestStepConfirmation({
124126 const participantsAutoAssignedFromRoute = route . name === SCREENS . MONEY_REQUEST . STEP_CONFIRMATION ? ( params as StepConfirmationParams ) . participantsAutoAssigned : undefined ;
125127
126128 const currentUserPersonalDetails = useCurrentUserPersonalDetails ( ) ;
129+ const personalPolicy = usePersonalPolicy ( ) ;
127130 const selfDMReport = useSelfDMReport ( ) ;
128131 const personalDetails = usePersonalDetails ( ) ;
129132 const allPolicyCategories = usePolicyCategories ( ) ;
@@ -227,6 +230,7 @@ function IOURequestStepConfirmation({
227230 const isOdometerDistanceRequest = isOdometerDistanceRequestTransactionUtils ( transaction ) ;
228231 const isTimeRequest = requestType === CONST . IOU . REQUEST_TYPE . TIME ;
229232 const [ lastLocationPermissionPrompt ] = useOnyx ( ONYXKEYS . NVP_LAST_LOCATION_PERMISSION_PROMPT ) ;
233+ const [ lastSelectedDistanceRates ] = useOnyx ( ONYXKEYS . NVP_LAST_SELECTED_DISTANCE_RATES ) ;
230234 const privateIsArchivedMap = usePrivateIsArchivedMap ( ) ;
231235
232236 const receiptFilename = transaction ?. receipt ?. filename ;
@@ -341,15 +345,55 @@ function IOURequestStepConfirmation({
341345 }
342346 setMoneyRequestParticipants ( activeTransactionID , participantsList ) ;
343347 const firstParticipant = participantsList . at ( 0 ) ;
344- if ( iouType !== CONST . IOU . TYPE . SPLIT ) {
345- setTransactionReport ( activeTransactionID , { reportID : firstParticipant ?. reportID ?? reportID } , true ) ;
348+ if ( iouType !== CONST . IOU . TYPE . SPLIT && firstParticipant ) {
349+ const isPolicyExpenseChatParticipant = ! ! firstParticipant . isPolicyExpenseChat ;
350+
351+ // A brand-new recipient picked by email has no chat yet (no reportID). Reusing the route's `reportID`
352+ // (which points at the flow's origin report - e.g. the default workspace chat this distance flow was
353+ // seeded with) leaves the expense bound to that workspace, so the backend rejects it with
354+ // "There is a previously existing chat between these users." Generate a fresh optimistic reportID for
355+ // P2P recipients, mirroring the legacy participants-step flow (useParticipantSubmission).
356+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
357+ const participantReportID = firstParticipant . reportID || ( isPolicyExpenseChatParticipant ? reportID : generateReportID ( ) ) ;
358+ setTransactionReport ( activeTransactionID , { reportID : participantReportID } , true ) ;
359+
360+ // When switching from the auto-assigned default workspace to a P2P recipient we must also undo the
361+ // workspace-specific defaults the distance step applied: reset the mileage rate to the P2P rate and
362+ // clear the workspace's default category (and the category-derived tax). Otherwise the confirmation
363+ // keeps the workspace "Default Rate"/category and the expense stays bound to that workspace. This
364+ // mirrors what the legacy addParticipant/goToNextStep path does when a P2P recipient is selected.
365+ if ( ! isPolicyExpenseChatParticipant ) {
366+ if ( isDistanceRequest ) {
367+ const p2pRateID = DistanceRequestUtils . getCustomUnitRateID ( {
368+ reportID : firstParticipant . reportID ,
369+ isPolicyExpenseChat : false ,
370+ policy : undefined ,
371+ lastSelectedDistanceRates,
372+ expenseDate : transaction ?. created ,
373+ } ) ;
374+ setCustomUnitRateID ( activeTransactionID , p2pRateID , transaction , undefined , false , personalPolicy ?. outputCurrency ) ;
375+ }
376+ setMoneyRequestCategory ( activeTransactionID , '' , undefined ) ;
377+ }
346378 }
347379 }
348380 if ( participantsList . length > 0 ) {
349381 closeParticipantPicker ( ) ;
350382 }
351383 } ,
352- [ activeTransactionID , closeParticipantPicker , currentUserPersonalDetails . accountID , navigation , selfDMReport , iouType , transaction ?. amount , transaction ?. participants , reportID ] ,
384+ [
385+ activeTransactionID ,
386+ closeParticipantPicker ,
387+ currentUserPersonalDetails . accountID ,
388+ navigation ,
389+ selfDMReport ,
390+ iouType ,
391+ reportID ,
392+ isDistanceRequest ,
393+ lastSelectedDistanceRates ,
394+ transaction ,
395+ personalPolicy ?. outputCurrency ,
396+ ] ,
353397 ) ;
354398
355399 useEffect ( ( ) => {
0 commit comments