Skip to content
Merged
3 changes: 1 addition & 2 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,7 @@ function MoneyReportHeader({

const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${moneyRequestReport?.reportID}`, {canBeMissing: true});
const getCanIOUBePaid = useCallback(
(onlyShowPayElsewhere = false, shouldCheckApprovedState = true) =>
canIOUBePaidAction(moneyRequestReport, chatReport, policy, transaction ? [transaction] : undefined, onlyShowPayElsewhere, undefined, undefined, shouldCheckApprovedState),
(onlyShowPayElsewhere = false) => canIOUBePaidAction(moneyRequestReport, chatReport, policy, transaction ? [transaction] : undefined, onlyShowPayElsewhere),
[moneyRequestReport, chatReport, policy, transaction],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ function MoneyRequestReportPreviewContent({
const hasViolations = hasViolationsReportUtils(iouReport?.reportID, transactionViolations, currentUserDetails.accountID, currentUserDetails.email ?? '');

const getCanIOUBePaid = useCallback(
(shouldShowOnlyPayElsewhere = false, shouldCheckApprovedState = true) =>
canIOUBePaidIOUActions(iouReport, chatReport, policy, transactions, shouldShowOnlyPayElsewhere, undefined, undefined, shouldCheckApprovedState),
(shouldShowOnlyPayElsewhere = false) => canIOUBePaidIOUActions(iouReport, chatReport, policy, transactions, shouldShowOnlyPayElsewhere),
[iouReport, chatReport, policy, transactions],
);

Expand All @@ -181,7 +180,7 @@ function MoneyRequestReportPreviewContent({
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;

const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(iouReport, shouldShowPayButton);
const canIOUBePaidAndApproved = useMemo(() => getCanIOUBePaid(false, false), [getCanIOUBePaid]);
const canIOUBePaidAndApproved = useMemo(() => getCanIOUBePaid(false), [getCanIOUBePaid]);
const connectedIntegration = getConnectedIntegration(policy);
const hasOnlyHeldExpenses = hasOnlyHeldExpensesReportUtils(iouReport?.reportID);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ function ActionCell({
const [iouReport, transactions] = useReportWithTransactionsAndViolations(reportID);
const policy = usePolicy(policyID);
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`, {canBeMissing: true});
const canBePaid = canIOUBePaid(iouReport, chatReport, policy, transactions, false, undefined, undefined, true);
const shouldOnlyShowElsewhere = !canBePaid && canIOUBePaid(iouReport, chatReport, policy, transactions, true, undefined, undefined, true);
const canBePaid = canIOUBePaid(iouReport, chatReport, policy, transactions, false);
const shouldOnlyShowElsewhere = !canBePaid && canIOUBePaid(iouReport, chatReport, policy, transactions, true);
const text = isChildListItem ? translate(actionTranslationsMap[CONST.SEARCH.ACTION_TYPES.VIEW]) : translate(actionTranslationsMap[action]);
const shouldUseViewAction = action === CONST.SEARCH.ACTION_TYPES.VIEW || (parentAction === CONST.SEARCH.ACTION_TYPES.PAID && action === CONST.SEARCH.ACTION_TYPES.PAID);

Expand Down
20 changes: 13 additions & 7 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
isPayAtEndExpenseReport as isPayAtEndExpenseReportReportUtils,
isPayer as isPayerReportUtils,
isPolicyExpenseChat as isPolicyExpenseChatReportUtil,
isProcessingReport,
isReportApproved,
isReportManager,
isSelectedManagerMcTest,
Expand Down Expand Up @@ -738,7 +739,7 @@
};

let allPersonalDetails: OnyxTypes.PersonalDetailsList = {};
Onyx.connect({

Check warning on line 742 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand Down Expand Up @@ -832,7 +833,7 @@
};

let allTransactions: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 836 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -846,7 +847,7 @@
});

let allTransactionDrafts: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 850 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -855,7 +856,7 @@
});

let allTransactionViolations: NonNullable<OnyxCollection<OnyxTypes.TransactionViolations>> = {};
Onyx.connect({

Check warning on line 859 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -869,7 +870,7 @@
});

let allNextSteps: NonNullable<OnyxCollection<OnyxTypes.ReportNextStepDeprecated>> = {};
Onyx.connect({

Check warning on line 873 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.NEXT_STEP,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -878,7 +879,7 @@
});

const allPolicies: OnyxCollection<OnyxTypes.Policy> = {};
Onyx.connect({

Check warning on line 882 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
callback: (val, key) => {
if (!key) {
Expand All @@ -897,14 +898,14 @@
// `allRecentlyUsedTags` was moved here temporarily from `src/libs/actions/Policy/Tag.ts` during the `Deprecate Onyx.connect` refactor.
// All uses of this variable should be replaced with `useOnyx`.
let allRecentlyUsedTags: OnyxCollection<RecentlyUsedTags> = {};
Onyx.connect({

Check warning on line 901 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS,
waitForCollectionCallback: true,
callback: (val) => (allRecentlyUsedTags = val),
});

let allReports: OnyxCollection<OnyxTypes.Report>;
Onyx.connect({

Check warning on line 908 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -913,7 +914,7 @@
});

let allReportNameValuePairs: OnyxCollection<OnyxTypes.ReportNameValuePairs>;
Onyx.connect({

Check warning on line 917 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -923,7 +924,7 @@

let userAccountID = -1;
let currentUserEmail = '';
Onyx.connect({

Check warning on line 927 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
currentUserEmail = value?.email ?? '';
Expand Down Expand Up @@ -10536,7 +10537,6 @@
onlyShowPayElsewhere = false,
chatReportRNVP?: OnyxTypes.ReportNameValuePairs,
invoiceReceiverPolicy?: OnyxTypes.Policy,
shouldCheckApprovedState = true,
) {
const reportNameValuePairs = chatReportRNVP ?? allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${chatReport?.reportID}`];
const isChatReportArchived = isArchivedReport(reportNameValuePairs);
Expand Down Expand Up @@ -10577,23 +10577,29 @@
policy,
);

const isOpenExpenseReport = isOpenExpenseReportReportUtils(iouReport);

const {reimbursableSpend} = getMoneyRequestSpendBreakdown(iouReport);
const isAutoReimbursable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES ? false : canBeAutoReimbursed(iouReport, policy);
const shouldBeApproved = canApproveIOU(iouReport, policy, transactions);
const isPayAtEndExpenseReport = isPayAtEndExpenseReportReportUtils(iouReport ?? undefined, transactions);
const isProcessing = isProcessingReport(iouReport);
const isApprovalEnabled = policy ? policy.approvalMode && policy.approvalMode !== CONST.POLICY.APPROVAL_MODE.OPTIONAL : false;
const isSubmittedWithoutApprovalsEnabled = !isApprovalEnabled && isProcessing;
const isApproved = isReportApproved({report: iouReport}) || isSubmittedWithoutApprovalsEnabled;
const isClosed = isClosedReportUtil(iouReport);
const isReportFinished = (isApproved || isClosed) && !iouReport?.isWaitingOnBankAccount;
const isIOU = isIOUReport(iouReport);
const canShowMarkedAsPaidForNegativeAmount = onlyShowPayElsewhere && reimbursableSpend < 0;

if (isIOU && isPayer && !iouSettled && reimbursableSpend > 0) {
return true;
}

return (
isPayer &&
!isOpenExpenseReport &&
isReportFinished &&
!iouSettled &&
!iouReport?.isWaitingOnBankAccount &&
(reimbursableSpend > 0 || canShowMarkedAsPaidForNegativeAmount) &&
!isChatReportArchived &&
!isAutoReimbursable &&
(!shouldBeApproved || !shouldCheckApprovedState) &&
!isPayAtEndExpenseReport &&
(!isExpenseReport(iouReport) || arePaymentsEnabled(policy as OnyxEntry<OnyxTypes.Policy>))
);
Expand Down
46 changes: 18 additions & 28 deletions tests/actions/IOUTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5428,10 +5428,8 @@ describe('actions/IOU', () => {
});
resolve();

expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, true)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, false)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false)).toBe(false);
},
});
}),
Expand All @@ -5451,10 +5449,8 @@ describe('actions/IOU', () => {
expect(expenseReport?.stateNum).toBe(0);
expect(expenseReport?.statusNum).toBe(0);

expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false)).toBe(false);
},
});
}),
Expand All @@ -5481,10 +5477,8 @@ describe('actions/IOU', () => {
expect(expenseReport?.stateNum).toBe(2);
expect(expenseReport?.statusNum).toBe(2);

expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, true)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, false)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false)).toBe(false);
},
});
}),
Expand Down Expand Up @@ -5524,10 +5518,8 @@ describe('actions/IOU', () => {
Onyx.disconnect(connection);
chatReport = Object.values(allReports ?? {}).find((report) => report?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT);

expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false)).toBe(false);
resolve();
},
});
Expand Down Expand Up @@ -5624,10 +5616,8 @@ describe('actions/IOU', () => {
stateNum: 0,
});

expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, true)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, false)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true)).toBe(true);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false)).toBe(false);
resolve();
},
});
Expand Down Expand Up @@ -5672,10 +5662,8 @@ describe('actions/IOU', () => {
// Report was submitted with some fail
expect(expenseReport?.stateNum).toBe(0);
expect(expenseReport?.statusNum).toBe(0);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false, undefined, undefined, false)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], true)).toBe(false);
expect(canIOUBePaid(expenseReport, chatReport, policy, [], false)).toBe(false);
resolve();
},
});
Expand Down Expand Up @@ -6897,13 +6885,13 @@ describe('actions/IOU', () => {
});

describe('canIOUBePaid', () => {
it('should return false if the report has negative total and onlyShowPayElsewhere is false', () => {
it('should return false if the report has negative total and onlyShowPayElsewhere is false', async () => {
const policyChat = createRandomReport(1, CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT);
const fakePolicy: Policy = {
...createRandomPolicy(Number('AA')),
id: 'AA',
type: CONST.POLICY.TYPE.TEAM,
approvalMode: CONST.POLICY.APPROVAL_MODE.BASIC,
approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
reimbursementChoice: CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES,
role: CONST.POLICY.ROLE.ADMIN,
};
Expand All @@ -6920,8 +6908,10 @@ describe('actions/IOU', () => {
total: 100, // positive amount in the DB means negative amount in the UI
};

expect(canIOUBePaid(fakeReport, policyChat, fakePolicy, [], false, undefined, undefined, false)).toBeFalsy();
expect(canIOUBePaid(fakeReport, policyChat, fakePolicy, [], true, undefined, undefined, false)).toBeTruthy();
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy);

expect(canIOUBePaid(fakeReport, policyChat, fakePolicy, [], false)).toBeFalsy();
expect(canIOUBePaid(fakeReport, policyChat, fakePolicy, [], true)).toBeTruthy();
});
});

Expand Down
Loading