Skip to content

Commit 989cd82

Browse files
Refactor to use getSortedReportActions and add unit test
Replace inline sorting logic in getIOUReportActionWithBadge and getReasonAndReportActionThatRequiresAttention with the existing getSortedReportActions utility from ReportActionsUtils. Add a unit test verifying that getIOUReportActionWithBadge returns the oldest matching report action when multiple actions have badges. Co-authored-by: Aimane Chnaif <aimane-chnaif@users.noreply.github.com>
1 parent f2636b4 commit 989cd82

3 files changed

Lines changed: 108 additions & 26 deletions

File tree

src/libs/ReportUtils.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4279,25 +4279,19 @@ function getReasonAndReportActionThatRequiresAttention(
42794279
}
42804280

42814281
if (isInvoiceRoom(optionOrReport)) {
4282-
let earliestAction: ReportAction | undefined;
4283-
for (const action of Object.values(reportActions)) {
4284-
if (
4285-
action.actionName !== CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW ||
4286-
!action.childReportID ||
4287-
!hasMissingInvoiceBankAccount(action.childReportID) ||
4288-
isSettled(action.childReportID)
4289-
) {
4290-
continue;
4291-
}
4292-
if (!earliestAction?.created || (action.created ?? '') < (earliestAction.created ?? '')) {
4293-
earliestAction = action;
4294-
}
4295-
}
4282+
const sortedActions = getSortedReportActions(Object.values(reportActions));
4283+
const reportAction = sortedActions.find(
4284+
(action) =>
4285+
action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW &&
4286+
action.childReportID &&
4287+
hasMissingInvoiceBankAccount(action.childReportID) &&
4288+
!isSettled(action.childReportID),
4289+
);
42964290

4297-
return earliestAction
4291+
return reportAction
42984292
? {
42994293
reason: CONST.REQUIRES_ATTENTION_REASONS.HAS_MISSING_INVOICE_BANK_ACCOUNT,
4300-
reportAction: earliestAction,
4294+
reportAction,
43014295
}
43024296
: null;
43034297
}

src/libs/actions/IOU/ReportWorkflow.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Navigation from '@libs/Navigation/Navigation';
1717
import {getIsOffline} from '@libs/NetworkState';
1818
import {buildNextStepNew, buildOptimisticNextStep} from '@libs/NextStepUtils';
1919
import {arePaymentsEnabled, getSubmitReportManagerAccountID, hasDynamicExternalWorkflow, isPaidGroupPolicy, isPolicyAdmin, isSubmitAndClose} from '@libs/PolicyUtils';
20-
import {getAllReportActions, getReportActionHtml, getReportActionText, hasPendingDEWApprove, isCreatedAction, isDeletedAction} from '@libs/ReportActionsUtils';
20+
import {getAllReportActions, getReportActionHtml, getReportActionText, getSortedReportActions, hasPendingDEWApprove, isCreatedAction, isDeletedAction} from '@libs/ReportActionsUtils';
2121
import {
2222
buildOptimisticApprovedReportAction,
2323
buildOptimisticChangeApproverReportAction,
@@ -308,21 +308,19 @@ function getIOUReportActionWithBadge(
308308
const chatReportActions = getAllReportActionsFromIOU()?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`] ?? {};
309309

310310
let actionBadge: ValueOf<typeof CONST.REPORT.ACTION_BADGE> | undefined;
311-
let reportAction: OnyxEntry<ReportAction>;
312-
for (const action of Object.values(chatReportActions)) {
311+
const sortedActions = getSortedReportActions(Object.values(chatReportActions));
312+
const reportAction = sortedActions.find((action) => {
313313
if (action?.actionName !== CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW || isDeletedAction(action)) {
314-
continue;
314+
return false;
315315
}
316316
const iouReport = getReportOrDraftReport(action.childReportID);
317317
const badge = getBadgeFromIOUReport(iouReport, chatReport, policy, reportMetadata, invoiceReceiverPolicy, currentUserLogin, currentUserAccountID);
318-
if (!badge) {
319-
continue;
320-
}
321-
if (!reportAction?.created || (action.created ?? '') < (reportAction.created ?? '')) {
322-
reportAction = action;
318+
if (badge) {
323319
actionBadge = badge;
320+
return true;
324321
}
325-
}
322+
return false;
323+
});
326324

327325
return {reportAction, actionBadge};
328326
}

tests/actions/IOUTest/ReportWorkflowTest.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3500,6 +3500,96 @@ describe('actions/IOU/ReportWorkflow', () => {
35003500
expect(result.actionBadge).toBeUndefined();
35013501
});
35023502

3503+
it('should return the oldest matching report action when multiple actions have badges', async () => {
3504+
const chatReportID = '500';
3505+
const olderIouReportID = '501';
3506+
const newerIouReportID = '502';
3507+
const policyID = '503';
3508+
3509+
const fakePolicy: Policy = {
3510+
...createRandomPolicy(Number(policyID)),
3511+
id: policyID,
3512+
type: CONST.POLICY.TYPE.TEAM,
3513+
approvalMode: CONST.POLICY.APPROVAL_MODE.BASIC,
3514+
};
3515+
3516+
const fakeChatReport: Report = {
3517+
...createRandomReport(Number(chatReportID), CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT),
3518+
reportID: chatReportID,
3519+
policyID,
3520+
};
3521+
3522+
// Two submitted expense reports — both will produce APPROVE badges
3523+
const olderIouReport: Report = {
3524+
...createRandomReport(Number(olderIouReportID), CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT),
3525+
reportID: olderIouReportID,
3526+
type: CONST.REPORT.TYPE.EXPENSE,
3527+
policyID,
3528+
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
3529+
statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
3530+
managerID: RORY_ACCOUNT_ID,
3531+
};
3532+
3533+
const newerIouReport: Report = {
3534+
...createRandomReport(Number(newerIouReportID), CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT),
3535+
reportID: newerIouReportID,
3536+
type: CONST.REPORT.TYPE.EXPENSE,
3537+
policyID,
3538+
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
3539+
statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
3540+
managerID: RORY_ACCOUNT_ID,
3541+
};
3542+
3543+
const olderTransaction: Transaction = {
3544+
...createRandomTransaction(0),
3545+
reportID: olderIouReportID,
3546+
amount: 100,
3547+
status: CONST.TRANSACTION.STATUS.POSTED,
3548+
bank: '',
3549+
};
3550+
3551+
const newerTransaction: Transaction = {
3552+
...createRandomTransaction(1),
3553+
reportID: newerIouReportID,
3554+
amount: 200,
3555+
status: CONST.TRANSACTION.STATUS.POSTED,
3556+
bank: '',
3557+
};
3558+
3559+
await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, fakePolicy);
3560+
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, fakeChatReport);
3561+
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${olderIouReportID}`, olderIouReport);
3562+
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${newerIouReportID}`, newerIouReport);
3563+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${olderTransaction.transactionID}`, olderTransaction);
3564+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${newerTransaction.transactionID}`, newerTransaction);
3565+
3566+
const olderReportPreview = {
3567+
reportActionID: 'older-preview',
3568+
actionName: CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW,
3569+
created: '2024-08-08 18:00:00.000',
3570+
childReportID: olderIouReportID,
3571+
message: [{type: 'TEXT', text: 'Older report preview'}],
3572+
};
3573+
3574+
const newerReportPreview = {
3575+
reportActionID: 'newer-preview',
3576+
actionName: CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW,
3577+
created: '2024-08-08 20:00:00.000',
3578+
childReportID: newerIouReportID,
3579+
message: [{type: 'TEXT', text: 'Newer report preview'}],
3580+
};
3581+
3582+
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`, {
3583+
[newerReportPreview.reportActionID]: newerReportPreview,
3584+
[olderReportPreview.reportActionID]: olderReportPreview,
3585+
});
3586+
await waitForBatchedUpdates();
3587+
3588+
const result = getIOUReportActionWithBadge(fakeChatReport, fakePolicy, {}, undefined, RORY_EMAIL, RORY_ACCOUNT_ID);
3589+
expect(result.reportAction).toMatchObject(olderReportPreview);
3590+
expect(result.actionBadge).toBe(CONST.REPORT.ACTION_BADGE.APPROVE);
3591+
});
3592+
35033593
it('should return undefined actionBadge when report is settled', async () => {
35043594
const chatReportID = '400';
35053595
const iouReportID = '401';

0 commit comments

Comments
 (0)