Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,9 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo
};

// Payment button derivations
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, true, undefined, invoiceReceiverPolicy);
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', accountID, undefined, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere =
!canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', accountID, undefined, true, undefined, invoiceReceiverPolicy);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;
const hasOnlyPendingTransactions = allTransactions.length > 0 && allTransactions.every((t) => isExpensifyCardTransaction(t) && isPending(t));
const shouldShowApproveButton =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,9 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn

const canAllowSettlement = hasUpdatedTotal(moneyRequestReport, policy);
const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions, convertToDisplayString);
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, true, undefined, invoiceReceiverPolicy);
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', accountID, undefined, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere =
!canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', accountID, undefined, true, undefined, invoiceReceiverPolicy);
const isPayable = hasPayAction && canIOUBePaid;

const confirmPayment = ({paymentType: type, payAsBusiness, methodID, paymentMethod}: PaymentActionParams) => {
Expand Down
6 changes: 4 additions & 2 deletions src/components/MoneyReportHeaderModals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {useRef, useState} from 'react';
import type {ReactNode} from 'react';
// eslint-disable-next-line no-restricted-imports
import {InteractionManager} from 'react-native';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useDecisionModal from '@hooks/useDecisionModal';
import useHoldMenuModal from '@hooks/useHoldMenuModal';
import useLocalize from '@hooks/useLocalize';
Expand Down Expand Up @@ -39,10 +40,11 @@ function MoneyReportHeaderModals({reportID, children}: MoneyReportHeaderModalsPr

const {transactions: reportTransactions} = useTransactionsAndViolationsForReport(moneyRequestReport?.reportID);
const transactions = Object.values(reportTransactions);
const {accountID, login: currentUserLogin} = useCurrentUserPersonalDetails();

// Derive data for hold menu
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, true);
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', accountID);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', accountID, undefined, true);
const shouldShowPayButton = canIOUBePaid || onlyShowPayElsewhere;
const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(moneyRequestReport, shouldShowPayButton);
const hasOnlyHeldExpenses = hasOnlyHeldExpensesReportUtils(moneyRequestReport?.reportID, transactions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,32 @@ function PayPrimaryAction({reportID, chatReportID}: PayPrimaryActionProps) {
const hasOnlyPendingTransactions = transactions.length > 0 && transactions.every((t) => isExpensifyCardTransaction(t) && isPending(t));
const nonPendingDeleteTransactions = transactions.filter((t): t is Transaction => !!t && (isOffline || t.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE));

const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, false, undefined, invoiceReceiverPolicy);
const canIOUBePaid = canIOUBePaidAction(
moneyRequestReport,
chatReport,
policy,
bankAccountList,
currentUserLogin ?? '',
accountID,
transaction ? [transaction] : undefined,
false,
undefined,
invoiceReceiverPolicy,
);
const onlyShowPayElsewhere =
!canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, true, undefined, invoiceReceiverPolicy);
!canIOUBePaid &&
canIOUBePaidAction(
moneyRequestReport,
chatReport,
policy,
bankAccountList,
currentUserLogin ?? '',
accountID,
transaction ? [transaction] : undefined,
true,
undefined,
invoiceReceiverPolicy,
);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;
const shouldShowApproveButton = (canApproveIOU(moneyRequestReport, policy, reportMetadata, accountID, transactions) && !hasOnlyPendingTransactions) || isApprovedAnimationRunning;
const shouldDisableApproveButton = shouldShowApproveButton && !isAllowedToApproveExpenseReport(moneyRequestReport);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,32 @@ function PayActionButton({
const canAllowSettlement = hasUpdatedTotal(iouReport, policy);
const hasViolations = hasViolationsReportUtils(iouReport?.reportID, transactionViolations, currentUserAccountID, currentUserEmail);

const canIOUBePaid = canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, true, undefined, invoiceReceiverPolicy);
const canIOUBePaid = canIOUBePaidIOUActions(
iouReport,
chatReport,
policy,
bankAccountList,
currentUserDetails.login ?? '',
currentUserDetails.accountID,
transactions,
false,
undefined,
invoiceReceiverPolicy,
);
const onlyShowPayElsewhere =
!canIOUBePaid &&
canIOUBePaidIOUActions(
iouReport,
chatReport,
policy,
bankAccountList,
currentUserDetails.login ?? '',
currentUserDetails.accountID,
transactions,
true,
undefined,
invoiceReceiverPolicy,
);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;
const shouldShowOnlyPayElsewhere = !canIOUBePaid && onlyShowPayElsewhere;
const canIOUBePaidAndApproved = canIOUBePaid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,32 @@ function ReportPreviewActionButton({
const isDEWSubmitPending = hasPendingDEWSubmit(iouReportMetadata, isDEWPolicy);
const connectedIntegration = getConnectedIntegration(policy);

const canIOUBePaid = canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, true, undefined, invoiceReceiverPolicy);
const canIOUBePaid = canIOUBePaidIOUActions(
iouReport,
chatReport,
policy,
bankAccountList,
currentUserDetails.login ?? '',
currentUserDetails.accountID,
transactions,
false,
undefined,
invoiceReceiverPolicy,
);
const onlyShowPayElsewhere =
!canIOUBePaid &&
canIOUBePaidIOUActions(
iouReport,
chatReport,
policy,
bankAccountList,
currentUserDetails.login ?? '',
currentUserDetails.accountID,
transactions,
true,
undefined,
invoiceReceiverPolicy,
);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;

const buttonMaxWidth =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {SearchScopeProvider} from '@components/Search/SearchScopeProvider';
import SettlementButton from '@components/SettlementButton';
import type {PaymentActionParams} from '@components/SettlementButton/types';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePolicy from '@hooks/usePolicy';
Expand Down Expand Up @@ -39,8 +40,11 @@ function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall,
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`);
const invoiceReceiverPolicyID = chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined;
const invoiceReceiverPolicy = usePolicy(invoiceReceiverPolicyID);
const canBePaid = canIOUBePaid(iouReport, chatReport, policy, bankAccountList, transactions, false, undefined, invoiceReceiverPolicy);
const shouldOnlyShowElsewhere = !canBePaid && canIOUBePaid(iouReport, chatReport, policy, bankAccountList, transactions, true, undefined, invoiceReceiverPolicy);
const {login: currentUserLogin, accountID: currentUserAccountID} = useCurrentUserPersonalDetails();

const canBePaid = canIOUBePaid(iouReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', currentUserAccountID, transactions, false, undefined, invoiceReceiverPolicy);
const shouldOnlyShowElsewhere =
!canBePaid && canIOUBePaid(iouReport, chatReport, policy, bankAccountList, currentUserLogin ?? '', currentUserAccountID, transactions, true, undefined, invoiceReceiverPolicy);

const {currency} = iouReport ?? {};

Expand Down
36 changes: 33 additions & 3 deletions src/hooks/useSearchBulkActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,41 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
const invoiceReceiverPolicy = invoiceReceiverPolicyID ? currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`] : undefined;
return (
report &&
!canIOUBePaid(report, chatReport, selectedPolicy, bankAccountList, undefined, false, undefined, invoiceReceiverPolicy) &&
canIOUBePaid(report, chatReport, selectedPolicy, bankAccountList, undefined, true, undefined, invoiceReceiverPolicy)
!canIOUBePaid(
report,
chatReport,
selectedPolicy,
bankAccountList,
currentUserPersonalDetails?.login ?? '',
currentUserPersonalDetails.accountID,
undefined,
false,
undefined,
invoiceReceiverPolicy,
) &&
canIOUBePaid(
report,
chatReport,
selectedPolicy,
bankAccountList,
currentUserPersonalDetails?.login ?? '',
currentUserPersonalDetails.accountID,
undefined,
true,
undefined,
invoiceReceiverPolicy,
)
);
});
}, [currentSearchResults?.data, selectedPolicyIDs, selectedReportIDs, selectedTransactionReportIDs, bankAccountList]);
}, [
selectedPolicyIDs,
currentSearchResults?.data,
selectedTransactionReportIDs,
selectedReportIDs,
bankAccountList,
currentUserPersonalDetails?.login,
currentUserPersonalDetails.accountID,
]);

const {bulkPayButtonOptions, businessBankAccountOptions, shouldShowBusinessBankAccountOptions} = useBulkPayOptions({
selectedPolicyID: selectedPolicyIDs.at(0),
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSelectionModeReportActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function useSelectionModeReportActions({
const nonPendingDeleteTransactions = transactions.filter((t): t is OnyxTypes.Transaction => !!t && (isOffline || t.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE));

const getCanIOUBePaid = (onlyShowPayElsewhere = false) =>
canIOUBePaidAction(report, chatReport, policy, bankAccountList, transactions, onlyShowPayElsewhere, undefined, invoiceReceiverPolicy);
canIOUBePaidAction(report, chatReport, policy, bankAccountList, currentUserLogin ?? '', currentUserAccountID, transactions, onlyShowPayElsewhere, undefined, invoiceReceiverPolicy);

const canIOUBePaid = getCanIOUBePaid();
const onlyShowPayElsewhere = !canIOUBePaid && getCanIOUBePaid(true);
Expand Down
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2903,7 +2903,7 @@ function hasOutstandingChildRequest(
// eslint-disable-next-line @typescript-eslint/no-deprecated
const invoiceReceiverPolicy = getPolicy(invoiceReceiverPolicyID);
return (
canIOUBePaid(iouReport, chatReport, policy, bankAccountList, transactions, undefined, undefined, invoiceReceiverPolicy) ||
canIOUBePaid(iouReport, chatReport, policy, bankAccountList, currentUserEmailParam, currentUserAccountIDParam, transactions, undefined, undefined, invoiceReceiverPolicy) ||
canApproveIOU(iouReport, policy, reportMetadata, currentUserAccountIDParam, transactions) ||
canSubmitAndIsAwaitingForCurrentUser(
iouReport,
Expand Down
15 changes: 13 additions & 2 deletions src/libs/SearchUIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2330,8 +2330,19 @@ function getActions(
: undefined;

const chatReport = getChatReport(data, report);
const canBePaid = canIOUBePaid(report, chatReport, policy, bankAccountList, allReportTransactions, false, chatReportRNVP, invoiceReceiverPolicy);
const canOnlyBePaidElsewhere = canIOUBePaid(report, chatReport, policy, bankAccountList, allReportTransactions, true, chatReportRNVP, invoiceReceiverPolicy);
const canBePaid = canIOUBePaid(report, chatReport, policy, bankAccountList, currentUserLogin, currentUserAccountID, allReportTransactions, false, chatReportRNVP, invoiceReceiverPolicy);
const canOnlyBePaidElsewhere = canIOUBePaid(
report,
chatReport,
policy,
bankAccountList,
currentUserLogin,
currentUserAccountID,
allReportTransactions,
true,
chatReportRNVP,
invoiceReceiverPolicy,
);
const shouldOnlyShowElsewhere = !canBePaid && canOnlyBePaidElsewhere;

// We're not supporting pay partial amount on search page now.
Expand Down
12 changes: 7 additions & 5 deletions src/libs/actions/IOU/ReportWorkflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import type * as OnyxTypes from '@src/types/onyx';
import type ReportAction from '@src/types/onyx/ReportAction';
import type {OnyxData} from '@src/types/onyx/Request';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import {getAllReportActionsFromIOU, getAllReportNameValuePairs, getAllTransactionViolations, getCurrentUserEmail, getUserAccountID} from '.';
import {getAllReportActionsFromIOU, getAllReportNameValuePairs, getAllTransactionViolations} from '.';
import {getReportFromHoldRequestsOnyxData} from './Hold';

type ApproveMoneyRequestFunctionParams = {
Expand Down Expand Up @@ -162,6 +162,8 @@ function canIOUBePaid(
chatReport: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Report>,
policy: OnyxTypes.OnyxInputOrEntry<OnyxTypes.Policy>,
bankAccountList: OnyxEntry<OnyxTypes.BankAccountList>,
currentUserLogin: string,
currentUserAccountID: number,
transactions?: OnyxTypes.Transaction[],
onlyShowPayElsewhere = false,
chatReportRNVP?: OnyxTypes.ReportNameValuePairs,
Expand Down Expand Up @@ -189,12 +191,12 @@ function canIOUBePaid(
return false;
}
if (chatReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) {
return chatReport?.invoiceReceiver?.accountID === getUserAccountID();
return chatReport?.invoiceReceiver?.accountID === currentUserAccountID;
}
return invoiceReceiverPolicy?.role === CONST.POLICY.ROLE.ADMIN;
}

const isPayer = isPayerReportUtils(getUserAccountID(), getCurrentUserEmail(), iouReport, bankAccountList, policy, onlyShowPayElsewhere);
const isPayer = isPayerReportUtils(currentUserAccountID, currentUserLogin, iouReport, bankAccountList, policy, onlyShowPayElsewhere);

const {reimbursableSpend, nonReimbursableSpend} = getMoneyRequestSpendBreakdown(iouReport);
const isAutoReimbursable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES ? false : canBeAutoReimbursed(iouReport, policy);
Expand Down Expand Up @@ -271,8 +273,8 @@ function getBadgeFromIOUReport(
): ValueOf<typeof CONST.REPORT.ACTION_BADGE> | undefined {
// Show to the actual payer, or to policy admins via the pay-elsewhere path for negative expenses
if (
canIOUBePaid(iouReport, chatReport, policy, undefined, undefined, undefined, undefined, invoiceReceiverPolicy) ||
canIOUBePaid(iouReport, chatReport, policy, undefined, undefined, true, undefined, invoiceReceiverPolicy)
canIOUBePaid(iouReport, chatReport, policy, undefined, currentUserLogin, currentUserAccountID, undefined, undefined, undefined, invoiceReceiverPolicy) ||
canIOUBePaid(iouReport, chatReport, policy, undefined, currentUserLogin, currentUserAccountID, undefined, true, undefined, invoiceReceiverPolicy)
) {
return CONST.REPORT.ACTION_BADGE.PAY;
}
Expand Down
Loading
Loading