diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f0d06064ff38..5c4b2886a32e 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4229,6 +4229,17 @@ function canEditFieldOfMoneyRequest(reportAction: OnyxInputOrEntry if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.REPORT) { // Unreported transaction from OldDot can have the reportID as an empty string const isUnreportedExpense = !transaction?.reportID || transaction?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID; + + if (isInvoiceReport(moneyRequestReport) && !isUnreportedExpense) { + return ( + getOutstandingReportsForUser( + moneyRequestReport?.policyID, + moneyRequestReport?.ownerAccountID, + reportsByPolicyID?.[moneyRequestReport?.policyID ?? CONST.DEFAULT_NUMBER_ID] ?? {}, + ).length > 0 + ); + } + return isUnreportedExpense ? Object.values(allPolicies ?? {}).flatMap((currentPolicy) => getOutstandingReportsForUser(currentPolicy?.id, currentUserAccountID, reportsByPolicyID?.[currentPolicy?.id ?? CONST.DEFAULT_NUMBER_ID] ?? {}), diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 1afbddde788e..d1af7ba17922 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -22,6 +22,7 @@ import { canAddTransaction, canDeleteReportAction, canDeleteTransaction, + canEditFieldOfMoneyRequest, canEditReportDescription, canEditRoomVisibility, canEditWriteCapability, @@ -295,6 +296,71 @@ describe('ReportUtils', () => { }); beforeEach(() => IntlStore.load(CONST.LOCALES.DEFAULT).then(waitForBatchedUpdates)); + describe('canEditFieldOfMoneyRequest', () => { + const reportActionID = 2; + const IOUReportID = '1234'; + const IOUTransactionID = '123'; + const randomReportAction = createRandomReportAction(reportActionID); + const policyID = '2424'; + const amount = 39; + + const policy1 = {...createRandomPolicy(Number(policyID), CONST.POLICY.TYPE.TEAM), areInvoicesEnabled: true, role: CONST.POLICY.ROLE.ADMIN}; + + // Given that there is at least one outstanding expense report in a policy + const outstandingExpenseReport = { + ...createExpenseReport(483), + policyID, + stateNum: CONST.REPORT.STATE_NUM.OPEN, + statusNum: CONST.REPORT.STATUS_NUM.OPEN, + ownerAccountID: currentUserAccountID, + }; + + // When a user creates an invoice in the same policy + + const reportAction = { + ...randomReportAction, + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + actorAccountID: currentUserAccountID, + childStateNum: CONST.REPORT.STATE_NUM.OPEN, + childStatusNum: CONST.REPORT.STATUS_NUM.OPEN, + originalMessage: { + // eslint-disable-next-line deprecation/deprecation + ...randomReportAction.originalMessage, + IOUReportID, + IOUTransactionID, + type: CONST.IOU.ACTION.CREATE, + amount, + currency: CONST.CURRENCY.USD, + }, + }; + + const moneyRequestTransaction = {...createRandomTransaction(Number(IOUTransactionID)), reportID: IOUReportID, transactionID: IOUTransactionID, amount}; + + const invoiceReport = { + ...createInvoiceReport(Number(IOUReportID)), + policyID, + ownerAccountID: currentUserAccountID, + state: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: 8723, + }; + + beforeAll(() => { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${IOUTransactionID}`, moneyRequestTransaction); + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${IOUReportID}`, invoiceReport); + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${483}`, outstandingExpenseReport); + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, policy1); + return waitForBatchedUpdates(); + }); + + // Then the user should be able to move the invoice to the outstanding expense report + it('should return true for invoice report action given that there is a minimum of one outstanding report', () => { + const canEditReportField = canEditFieldOfMoneyRequest(reportAction, CONST.EDIT_REQUEST_FIELD.REPORT); + expect(canEditReportField).toBe(true); + }); + }); + describe('prepareOnboardingOnyxData', () => { it('provides test drive url to task title', () => { const title = jest.fn();