diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e2b6a14e2e08..05e2db66d629 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2306,7 +2306,6 @@ function getReportPreviewMessage( isPreviewMessageForParentChatReport = false, policy: OnyxEntry = null, isForListPreview = false, - shouldHidePayer = false, ): string { const reportActionMessage = reportAction?.message?.[0].html ?? ''; @@ -2371,9 +2370,7 @@ function getReportPreviewMessage( 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: TranslationPaths = 'iou.paidElsewhereWithAmount'; - if (isPreviewMessageForParentChatReport) { - translatePhraseKey = 'iou.payerPaidAmount'; - } else if ( + if ( [CONST.IOU.PAYMENT_TYPE.VBBA, CONST.IOU.PAYMENT_TYPE.EXPENSIFY].some((paymentType) => paymentType === originalMessage?.paymentType) || !!reportActionMessage.match(/ (with Expensify|using Expensify)$/) || report.isWaitingOnBankAccount @@ -2381,7 +2378,7 @@ function getReportPreviewMessage( translatePhraseKey = 'iou.paidWithExpensifyWithAmount'; } - let actualPayerName = report.managerID === currentUserAccountID || shouldHidePayer ? '' : getDisplayNameForParticipant(report.managerID, true); + let actualPayerName = report.managerID === currentUserAccountID ? '' : getDisplayNameForParticipant(report.managerID, true); actualPayerName = actualPayerName && isForListPreview && !isPreviewMessageForParentChatReport ? `${actualPayerName}:` : actualPayerName; const payerDisplayName = isPreviewMessageForParentChatReport ? payerName : actualPayerName; @@ -4690,6 +4687,62 @@ function getVisibleMemberIDs(report: OnyxEntry): number[] { return visibleChatMemberAccountIDs; } +/** + * Return iou report action display message + */ +function getIOUReportActionDisplayMessage(reportAction: OnyxEntry): string { + if (reportAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU) { + return ''; + } + const originalMessage = reportAction.originalMessage; + const {IOUReportID} = originalMessage; + const iouReport = getReport(IOUReportID); + let translationKey: TranslationPaths; + if (originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.PAY) { + // The `REPORT_ACTION_TYPE.PAY` action type is used for both fulfilling existing requests and sending money. To + // differentiate between these two scenarios, we check if the `originalMessage` contains the `IOUDetails` + // property. If it does, it indicates that this is a 'Send money' action. + const {amount, currency} = originalMessage.IOUDetails ?? originalMessage; + const formattedAmount = CurrencyUtils.convertToDisplayString(Math.abs(amount), currency) ?? ''; + const payerName = isExpenseReport(iouReport) ? getPolicyName(iouReport) : getDisplayNameForParticipant(iouReport?.managerID, true); + + switch (originalMessage.paymentType) { + case CONST.IOU.PAYMENT_TYPE.ELSEWHERE: + translationKey = 'iou.paidElsewhereWithAmount'; + break; + case CONST.IOU.PAYMENT_TYPE.EXPENSIFY: + case CONST.IOU.PAYMENT_TYPE.VBBA: + translationKey = 'iou.paidWithExpensifyWithAmount'; + break; + default: + translationKey = 'iou.payerPaidAmount'; + break; + } + return Localize.translateLocal(translationKey, {amount: formattedAmount, payer: payerName ?? ''}); + } + + const transaction = TransactionUtils.getTransaction(originalMessage.IOUTransactionID ?? ''); + const transactionDetails = getTransactionDetails(!isEmptyObject(transaction) ? transaction : null); + const formattedAmount = CurrencyUtils.convertToDisplayString(transactionDetails?.amount ?? 0, transactionDetails?.currency); + const isRequestSettled = isSettled(originalMessage.IOUReportID); + const isApproved = isReportApproved(iouReport); + if (isRequestSettled) { + return Localize.translateLocal('iou.payerSettled', { + amount: formattedAmount, + }); + } + if (isApproved) { + return Localize.translateLocal('iou.approvedAmount', { + amount: formattedAmount, + }); + } + translationKey = ReportActionsUtils.isSplitBillAction(reportAction) ? 'iou.didSplitAmount' : 'iou.requestedAmount'; + return Localize.translateLocal(translationKey, { + formattedAmount, + comment: transactionDetails?.comment ?? '', + }); +} + /** * Checks if a report is a group chat. * @@ -5127,6 +5180,7 @@ export { hasOnlyTransactionsWithPendingRoutes, hasNonReimbursableTransactions, hasMissingSmartscanFields, + getIOUReportActionDisplayMessage, isWaitingForAssigneeToCompleteTask, isGroupChat, isDraftExpenseReport, diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index abd9d2a09fdf..51e6b25f1314 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -359,15 +359,7 @@ const ContextMenuActions: ContextMenuAction[] = [ const displayMessage = ReportUtils.getReimbursementDeQueuedActionMessage(reportAction, expenseReport); Clipboard.setString(displayMessage); } else if (ReportActionsUtils.isMoneyRequestAction(reportAction)) { - const displayMessage = ReportUtils.getReportPreviewMessage( - ReportUtils.getReport(ReportUtils.getOriginalReportID(reportID, reportAction)), - reportAction, - false, - false, - null, - false, - true, - ); + const displayMessage = ReportUtils.getIOUReportActionDisplayMessage(reportAction); Clipboard.setString(displayMessage); } else if (ReportActionsUtils.isCreatedTaskReportAction(reportAction)) { const taskPreviewMessage = TaskUtils.getTaskCreatedMessage(reportAction); diff --git a/src/pages/home/report/ReportActionItemMessage.tsx b/src/pages/home/report/ReportActionItemMessage.tsx index becc8e094c97..0ec23e9aaf79 100644 --- a/src/pages/home/report/ReportActionItemMessage.tsx +++ b/src/pages/home/report/ReportActionItemMessage.tsx @@ -58,7 +58,7 @@ function ReportActionItemMessage({action, displayAsGroup, reportID, style, isHid const originalMessage = action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? action.originalMessage : null; const iouReportID = originalMessage?.IOUReportID; if (iouReportID) { - iouMessage = ReportUtils.getReportPreviewMessage(ReportUtils.getReport(iouReportID), action, false, false, null, false, true); + iouMessage = ReportUtils.getIOUReportActionDisplayMessage(action); } } diff --git a/tests/perf-test/ReportUtils.perf-test.ts b/tests/perf-test/ReportUtils.perf-test.ts index ee3c54608436..ae3429bb9c01 100644 --- a/tests/perf-test/ReportUtils.perf-test.ts +++ b/tests/perf-test/ReportUtils.perf-test.ts @@ -184,4 +184,23 @@ describe('ReportUtils', () => { await waitForBatchedUpdates(); await measureFunction(() => ReportUtils.getTransactionDetails(transaction, 'yyyy-MM-dd')); }); + + test('[ReportUtils] getIOUReportActionDisplayMessage on 1k policies', async () => { + const reportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + originalMessage: { + IOUReportID: '1', + IOUTransactionID: '1', + amount: 100, + participantAccountID: 1, + currency: CONST.CURRENCY.USD, + type: CONST.IOU.REPORT_ACTION_TYPE.PAY, + paymentType: CONST.IOU.PAYMENT_TYPE.EXPENSIFY, + }, + }; + + await waitForBatchedUpdates(); + await measureFunction(() => ReportUtils.getIOUReportActionDisplayMessage(reportAction)); + }); });