diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 454c25a0b6d1..4f8b93e7dcfe 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5281,7 +5281,7 @@ function buildOptimisticExpenseReport( return expenseReport; } -function getFormattedAmount(reportAction: ReportAction) { +function getFormattedAmount(reportAction: ReportAction, report?: Report | null) { if ( !isSubmittedAction(reportAction) && !isForwardedAction(reportAction) && @@ -5292,30 +5292,38 @@ function getFormattedAmount(reportAction: ReportAction) { return ''; } const originalMessage = getOriginalMessage(reportAction); - const formattedAmount = convertToDisplayString(Math.abs(originalMessage?.amount ?? 0), originalMessage?.currency); + + // Expense reports can have a negative amount and we need to display it as negative in the UI + // the amount found in originalMessage does not accurately track this so we need to use the total from the report instead + const amount = report && isExpenseReport(report) ? (report?.total ?? 0) * -1 : Math.abs(originalMessage?.amount ?? 0); + const formattedAmount = convertToDisplayString(amount, originalMessage?.currency); return formattedAmount; } function getReportAutomaticallySubmittedMessage( reportAction: ReportAction | ReportAction, + report?: Report, ) { - return translateLocal('iou.automaticallySubmittedAmount', {formattedAmount: getFormattedAmount(reportAction)}); + return translateLocal('iou.automaticallySubmittedAmount', {formattedAmount: getFormattedAmount(reportAction, report)}); } -function getIOUSubmittedMessage(reportAction: ReportAction | ReportAction) { - return translateLocal('iou.submittedAmount', {formattedAmount: getFormattedAmount(reportAction)}); +function getIOUSubmittedMessage( + reportAction: ReportAction | ReportAction, + report?: Report, +) { + return translateLocal('iou.submittedAmount', {formattedAmount: getFormattedAmount(reportAction, report)}); } -function getReportAutomaticallyApprovedMessage(reportAction: ReportAction) { - return translateLocal('iou.automaticallyApprovedAmount', {amount: getFormattedAmount(reportAction)}); +function getReportAutomaticallyApprovedMessage(reportAction: ReportAction, report?: Report) { + return translateLocal('iou.automaticallyApprovedAmount', {amount: getFormattedAmount(reportAction, report)}); } -function getIOUUnapprovedMessage(reportAction: ReportAction) { - return translateLocal('iou.unapprovedAmount', {amount: getFormattedAmount(reportAction)}); +function getIOUUnapprovedMessage(reportAction: ReportAction, report?: Report) { + return translateLocal('iou.unapprovedAmount', {amount: getFormattedAmount(reportAction, report)}); } -function getIOUApprovedMessage(reportAction: ReportAction) { - return translateLocal('iou.approvedAmount', {amount: getFormattedAmount(reportAction)}); +function getIOUApprovedMessage(reportAction: ReportAction, report?: Report) { + return translateLocal('iou.approvedAmount', {amount: getFormattedAmount(reportAction, report)}); } /** @@ -5329,7 +5337,7 @@ function getReportAutomaticallyForwardedMessage(reportAction: ReportAction 0 && !isChatReportArchived && !isAutoReimbursable && (!shouldBeApproved || !shouldCheckApprovedState) && diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx index de098395987f..4208aa96f066 100644 --- a/src/pages/home/report/PureReportActionItem.tsx +++ b/src/pages/home/report/PureReportActionItem.tsx @@ -835,25 +835,25 @@ function PureReportActionItem({ if (wasSubmittedViaHarvesting) { children = ( - ${getReportAutomaticallySubmittedMessage(action)}`} /> + ${getReportAutomaticallySubmittedMessage(action, report)}`} /> ); } else { - children = ; + children = ; } } else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED)) { const wasAutoApproved = getOriginalMessage(action)?.automaticAction ?? false; if (wasAutoApproved) { children = ( - ${getReportAutomaticallyApprovedMessage(action)}`} /> + ${getReportAutomaticallyApprovedMessage(action, report)}`} /> ); } else { - children = ; + children = ; } } else if (isUnapprovedAction(action)) { - children = ; + children = ; } else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.FORWARDED)) { const wasAutoForwarded = getOriginalMessage(action)?.automaticAction ?? false; if (wasAutoForwarded) { diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 51e621909f60..82b8db884cd5 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -6,6 +6,7 @@ import { canApproveIOU, canCancelPayment, cancelPayment, + canIOUBePaid, canUnapproveIOU, deleteMoneyRequest, payMoneyRequest, @@ -4768,4 +4769,26 @@ describe('actions/IOU', () => { expect(canCancelPayment(fakeReport, {accountID: RORY_ACCOUNT_ID})).toBeTruthy(); }); }); + + describe('canIOUBePaid', () => { + it('should return false if the report has negative total', () => { + const policyChat = createRandomReport(1); + const fakePolicy: Policy = { + ...createRandomPolicy(Number('AA')), + type: CONST.POLICY.TYPE.TEAM, + approvalMode: CONST.POLICY.APPROVAL_MODE.BASIC, + }; + + const fakeReport: Report = { + ...createRandomReport(1), + type: CONST.REPORT.TYPE.EXPENSE, + policyID: 'AA', + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.APPROVED, + managerID: RORY_ACCOUNT_ID, + total: 100, // positive amount in the DB means negative amount in the UI + }; + expect(canIOUBePaid(fakeReport, policyChat, fakePolicy)).toBeFalsy(); + }); + }); });