diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 40647e33849c..a367f8ec5a89 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -285,7 +285,11 @@ function MoneyRequestConfirmationList({ return allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${senderWorkspaceParticipant?.policyID}`]; }, [allPolicies, selectedParticipantsProp]); - const canUpdateSenderWorkspace = useMemo(() => PolicyUtils.canSendInvoice(allPolicies) && !!transaction?.isFromGlobalCreate, [allPolicies, transaction?.isFromGlobalCreate]); + const canUpdateSenderWorkspace = useMemo(() => { + const isInvoiceRoomParticipant = selectedParticipantsProp.some((participant) => participant.isInvoiceRoom); + + return PolicyUtils.canSendInvoice(allPolicies) && !!transaction?.isFromGlobalCreate && !isInvoiceRoomParticipant; + }, [allPolicies, selectedParticipantsProp, transaction?.isFromGlobalCreate]); const canModifyTaxFields = !isReadOnly && !isDistanceRequest; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index fef64b712ad6..8cd2615dc4a6 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -173,6 +173,7 @@ type GetOptionsConfig = { policyReportFieldOptions?: string[]; recentlyUsedPolicyReportFieldOptions?: string[]; transactionViolations?: OnyxCollection; + includeInvoiceRooms?: boolean; }; type GetUserToInviteConfig = { @@ -1746,6 +1747,7 @@ function getOptions( includePolicyReportFieldOptions = false, policyReportFieldOptions = [], recentlyUsedPolicyReportFieldOptions = [], + includeInvoiceRooms = false, }: GetOptionsConfig, ): Options { if (includeCategories) { @@ -1945,8 +1947,16 @@ function getOptions( const isCurrentUserOwnedPolicyExpenseChatThatCouldShow = reportOption.isPolicyExpenseChat && reportOption.ownerAccountID === currentUserAccountID && includeOwnedWorkspaceChats && !reportOption.isArchivedRoom; - // Skip if we aren't including multiple participant reports and this report has multiple participants - if (!isCurrentUserOwnedPolicyExpenseChatThatCouldShow && !includeMultipleParticipantReports && !reportOption.login) { + const shouldShowInvoiceRoom = includeInvoiceRooms && ReportUtils.isInvoiceRoom(reportOption.item) && ReportUtils.isPolicyAdmin(reportOption.policyID ?? '', policies); + + /** + Exclude the report option if it doesn't meet any of the following conditions: + - It is not an owned policy expense chat that could be shown + - Multiple participant reports are not included + - It doesn't have a login + - It is not an invoice room that should be shown + */ + if (!isCurrentUserOwnedPolicyExpenseChatThatCouldShow && !includeMultipleParticipantReports && !reportOption.login && !shouldShowInvoiceRoom) { continue; } @@ -2136,6 +2146,7 @@ function getFilteredOptions( policyReportFieldOptions: string[] = [], recentlyUsedPolicyReportFieldOptions: string[] = [], maxRecentReportsToShow = 5, + includeInvoiceRooms = false, ) { return getOptions( {reports, personalDetails}, @@ -2162,6 +2173,7 @@ function getFilteredOptions( includePolicyReportFieldOptions, policyReportFieldOptions, recentlyUsedPolicyReportFieldOptions, + includeInvoiceRooms, }, ); } diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 1e8e63ee2df3..3173311e77fd 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -22,6 +22,7 @@ import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import type {MaybePhraseKey} from '@libs/Localize'; import type {Options} from '@libs/OptionsListUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; +import * as ReportUtils from '@libs/ReportUtils'; import * as Policy from '@userActions/Policy/Policy'; import * as Report from '@userActions/Report'; import type {IOUAction, IOURequestType, IOUType} from '@src/CONST'; @@ -116,6 +117,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic undefined, undefined, isCategorizeOrShareAction ? 0 : undefined, + iouType === CONST.IOU.TYPE.INVOICE, ); const formatResults = OptionsListUtils.formatSectionsFromSearchTerm( @@ -189,10 +191,9 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic ]; if (iouType === CONST.IOU.TYPE.INVOICE) { - const primaryPolicy = Policy.getPrimaryPolicy(activePolicyID); - + const policyID = option.item && ReportUtils.isInvoiceRoom(option.item) ? option.policyID : Policy.getPrimaryPolicy(activePolicyID)?.id; newParticipants.push({ - policyID: primaryPolicy?.id, + policyID, isSender: true, selected: false, iouType, diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 7b592b657c84..d9d7a8d192a0 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -89,23 +89,26 @@ function IOURequestStepParticipants({ const addParticipant = useCallback( (val: Participant[]) => { HttpUtils.cancelPendingRequests(READ_COMMANDS.SEARCH_FOR_REPORTS); - IOU.setMoneyRequestParticipants(transactionID, val); - const rateID = DistanceRequestUtils.getCustomUnitRateID(val[0]?.reportID ?? ''); - IOU.setCustomUnitRateID(transactionID, rateID); + const firstParticipantReportID = val[0]?.reportID ?? ''; + const rateID = DistanceRequestUtils.getCustomUnitRateID(firstParticipantReportID); + const isInvoice = iouType === CONST.IOU.TYPE.INVOICE && ReportUtils.isInvoiceRoom(ReportUtils.getReport(firstParticipantReportID)); numberOfParticipants.current = val.length; + IOU.setMoneyRequestParticipants(transactionID, val); + IOU.setCustomUnitRateID(transactionID, rateID); + // When multiple participants are selected, the reportID is generated at the end of the confirmation step. // So we are resetting selectedReportID ref to the reportID coming from params. - if (val.length !== 1) { + if (val.length !== 1 && !isInvoice) { selectedReportID.current = reportID; return; } // When a participant is selected, the reportID needs to be saved because that's the reportID that will be used in the confirmation step. - selectedReportID.current = val[0]?.reportID ?? reportID; + selectedReportID.current = firstParticipantReportID || reportID; }, - [reportID, transactionID], + [iouType, reportID, transactionID], ); const goToNextStep = useCallback(() => { diff --git a/src/types/onyx/IOU.ts b/src/types/onyx/IOU.ts index 68e8836e149c..8ffac34f2512 100644 --- a/src/types/onyx/IOU.ts +++ b/src/types/onyx/IOU.ts @@ -1,6 +1,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type {Icon} from './OnyxCommon'; +import type Report from './Report'; type Participant = { accountID?: number; @@ -25,6 +26,7 @@ type Participant = { isSelfDM?: boolean; isSender?: boolean; iouType?: string; + item?: Report; ownerAccountID?: number; };