diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 75806077daca..e909f0d86453 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -398,7 +398,9 @@ function getLastMessageTextForReport(report) { reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && ReportActionUtils.isMoneyRequestAction(reportAction), ); - lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastIOUMoneyReport, true); + lastMessageTextFromReport = ReportUtils.getReportPreviewMessage(iouReport, lastIOUMoneyReport, true, ReportUtils.isChatReport(report)); + } else if (ReportActionUtils.isReimbursementQueuedAction(lastReportAction)) { + lastMessageTextFromReport = ReportUtils.getReimbursementQueuedActionMessage(lastReportAction, report); } else if (ReportActionUtils.isDeletedParentAction(lastReportAction) && ReportUtils.isChatReport(report)) { lastMessageTextFromReport = ReportUtils.getDeletedParentActionMessageForChatReport(lastReportAction); } else if (ReportActionUtils.isModifiedExpenseAction(lastReportAction)) { diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index d016e220e147..b17b403ee8ef 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -91,6 +91,10 @@ function isWhisperAction(reportAction: OnyxEntry): boolean { return (reportAction?.whisperedToAccountIDs ?? []).length > 0; } +function isReimbursementQueuedAction(reportAction: OnyxEntry) { + return reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED; +} + /** * Returns whether the comment is a thread parent message/the first message in a thread */ @@ -636,6 +640,7 @@ export { isThreadParentMessage, isTransactionThread, isWhisperAction, + isReimbursementQueuedAction, shouldReportActionBeVisible, shouldReportActionBeVisibleAsLastAction, }; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index b974c1cef700..5122a8177421 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -283,6 +283,12 @@ function isSettled(reportID) { return false; } + // In case the payment is scheduled and we are waiting for the payee to set up their wallet, + // consider the report as paid as well. + if (report.isWaitingOnBankAccount && report.statusNum === CONST.REPORT.STATUS.APPROVED) { + return true; + } + return report.statusNum === CONST.REPORT.STATUS.REIMBURSED; } @@ -1240,6 +1246,25 @@ function getDeletedParentActionMessageForChatReport(reportAction) { return deletedMessageText; } +/** + * Returns the preview message for `REIMBURSEMENTQUEUED` action + * + * @param {Object} reportAction + * @param {Object} report + * @returns {String} + */ +function getReimbursementQueuedActionMessage(reportAction, report) { + const submitterDisplayName = getDisplayNameForParticipant(report.ownerAccountID, true); + let messageKey; + if (lodashGet(reportAction, 'originalMessage.paymentType', '') === CONST.IOU.PAYMENT_TYPE.EXPENSIFY) { + messageKey = 'iou.waitingOnEnabledWallet'; + } else { + messageKey = 'iou.waitingOnBankAccount'; + } + + return Localize.translateLocal(messageKey, {submitterDisplayName}); +} + /** * Returns the last visible message for a given report after considering the given optimistic actions * @@ -1295,7 +1320,8 @@ function isWaitingForIOUActionFromCurrentUser(report) { } // Money request waiting for current user to add their credit bank account - if (report.hasOutstandingIOU && report.ownerAccountID === currentUserAccountID && report.isWaitingOnBankAccount) { + // hasOutstandingIOU will be false if the user paid, but isWaitingOnBankAccount will be true if user don't have a wallet or bank account setup + if (!report.hasOutstandingIOU && report.isWaitingOnBankAccount && report.ownerAccountID === currentUserAccountID) { return true; } @@ -1657,9 +1683,10 @@ function getTransactionReportName(reportAction) { * @param {Object} report * @param {Object} [reportAction={}] This can be either a report preview action or the IOU action * @param {Boolean} [shouldConsiderReceiptBeingScanned=false] + * @param {Boolean} isPreviewMessageForParentChatReport * @returns {String} */ -function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceiptBeingScanned = false) { +function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceiptBeingScanned = false, isPreviewMessageForParentChatReport = false) { const reportActionMessage = lodashGet(reportAction, 'message[0].html', ''); if (_.isEmpty(report) || !report.reportID) { @@ -1698,12 +1725,14 @@ function getReportPreviewMessage(report, reportAction = {}, shouldConsiderReceip } } - if (isSettled(report.reportID)) { + // Show Paid preview message if it's settled or if the amount is paid & stuck at receivers end for only chat reports. + if (isSettled(report.reportID) || (report.isWaitingOnBankAccount && isPreviewMessageForParentChatReport)) { // A settled report preview message can come in three formats "paid ... elsewhere" or "paid ... with Expensify" let translatePhraseKey = 'iou.paidElsewhereWithAmount'; if ( _.contains([CONST.IOU.PAYMENT_TYPE.VBBA, CONST.IOU.PAYMENT_TYPE.EXPENSIFY], lodashGet(reportAction, 'originalMessage.paymentType')) || - reportActionMessage.match(/ (with Expensify|using Expensify)$/) + reportActionMessage.match(/ (with Expensify|using Expensify)$/) || + report.isWaitingOnBankAccount ) { translatePhraseKey = 'iou.paidWithExpensifyWithAmount'; } @@ -4178,4 +4207,5 @@ export { isReportDraft, shouldUseFullTitleToDisplay, parseReportRouteParams, + getReimbursementQueuedActionMessage, }; diff --git a/tests/unit/ReportUtilsTest.js b/tests/unit/ReportUtilsTest.js index 6d3aba1fd9ad..25f093cbd711 100644 --- a/tests/unit/ReportUtilsTest.js +++ b/tests/unit/ReportUtilsTest.js @@ -271,23 +271,23 @@ describe('ReportUtils', () => { expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); }); - it('returns false when the report has no oustanding IOU but is waiting for a bank account and the logged user is the report owner', () => { + it('returns true when the report has no outstanding IOU but is waiting for a bank account and the logged user is the report owner', () => { const report = { ...LHNTestUtils.getFakeReport(), hasOutstandingIOU: false, ownerAccountID: currentUserAccountID, isWaitingOnBankAccount: true, }; - expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(true); }); - it('returns true when the report has oustanding IOU and is waiting for a bank account and the logged user is the report owner', () => { + it('returns false when the report has outstanding IOU and is not waiting for a bank account and the logged user is the report owner', () => { const report = { ...LHNTestUtils.getFakeReport(), hasOutstandingIOU: true, ownerAccountID: currentUserAccountID, - isWaitingOnBankAccount: true, + isWaitingOnBankAccount: false, }; - expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(true); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); it('returns false when the report has no oustanding IOU but is waiting for a bank account and the logged user is not the report owner', () => { const report = {