Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow selecting an existing invoice room as the receiver in the Send Invoice flow from FAB #42714

Merged
6 changes: 5 additions & 1 deletion src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
16 changes: 14 additions & 2 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ type GetOptionsConfig = {
policyReportFieldOptions?: string[];
recentlyUsedPolicyReportFieldOptions?: string[];
transactionViolations?: OnyxCollection<TransactionViolation[]>;
includeInvoiceRooms?: boolean;
};

type GetUserToInviteConfig = {
Expand Down Expand Up @@ -1746,6 +1747,7 @@ function getOptions(
includePolicyReportFieldOptions = false,
policyReportFieldOptions = [],
recentlyUsedPolicyReportFieldOptions = [],
includeInvoiceRooms = false,
}: GetOptionsConfig,
): Options {
if (includeCategories) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -2136,6 +2146,7 @@ function getFilteredOptions(
policyReportFieldOptions: string[] = [],
recentlyUsedPolicyReportFieldOptions: string[] = [],
maxRecentReportsToShow = 5,
includeInvoiceRooms = false,
) {
return getOptions(
{reports, personalDetails},
Expand All @@ -2162,6 +2173,7 @@ function getFilteredOptions(
includePolicyReportFieldOptions,
policyReportFieldOptions,
recentlyUsedPolicyReportFieldOptions,
includeInvoiceRooms,
},
);
}
Expand Down
7 changes: 4 additions & 3 deletions src/pages/iou/request/MoneyRequestParticipantsSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -116,6 +117,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic
undefined,
undefined,
isCategorizeOrShareAction ? 0 : undefined,
iouType === CONST.IOU.TYPE.INVOICE,
);

const formatResults = OptionsListUtils.formatSectionsFromSearchTerm(
Expand Down Expand Up @@ -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,
Expand Down
15 changes: 9 additions & 6 deletions src/pages/iou/request/step/IOURequestStepParticipants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down
2 changes: 2 additions & 0 deletions src/types/onyx/IOU.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -25,6 +26,7 @@ type Participant = {
isSelfDM?: boolean;
isSender?: boolean;
iouType?: string;
item?: Report;
ownerAccountID?: number;
};

Expand Down
Loading