diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 4b9763517983..b09506c8c3bd 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6307,6 +6307,11 @@ function canRequestMoney(report: OnyxEntry, policy: OnyxEntry, o return false; } + // Current user must be a manager or owner of this IOU + if (isIOUReport(report) && currentUserAccountID !== report?.managerID && currentUserAccountID !== report?.ownerAccountID) { + return false; + } + // User can submit expenses in any IOU report, unless paid, but the user can only submit expenses in an expense report // which is tied to their workspace chat. if (isMoneyRequestReport(report)) { diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 12bcabc92b19..6161fa57f75c 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -561,6 +561,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.IOU, stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(1); @@ -573,6 +574,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.IOU, stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(1); @@ -591,6 +593,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), parentReportID: '102', type: CONST.REPORT.TYPE.EXPENSE, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(2); @@ -611,6 +614,7 @@ describe('ReportUtils', () => { stateNum: CONST.REPORT.STATE_NUM.OPEN, statusNum: CONST.REPORT.STATUS_NUM.OPEN, parentReportID: '103', + managerID: currentUserAccountID, }; const paidPolicy = { type: CONST.POLICY.TYPE.TEAM, @@ -634,6 +638,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.IOU, stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(1); @@ -646,6 +651,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.IOU, stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(1); @@ -679,6 +685,7 @@ describe('ReportUtils', () => { statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, parentReportID: '101', policyID: paidPolicy.id, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, paidPolicy, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(2); @@ -706,6 +713,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, isOwnPolicyExpenseChat: true, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID, ...participantsAccountIDs]); expect(moneyRequestOptions.length).toBe(3);