From 0c0664a895dfc31038807790df09467fe06de44a Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 22 Jul 2025 23:53:02 +0300 Subject: [PATCH] disallow updating archived invoice --- .../ReportActionItem/MoneyRequestView.tsx | 18 +++++---- src/libs/ReportUtils.ts | 17 ++++++-- tests/unit/ReportUtilsTest.ts | 40 +++++++++++++++++++ 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 94af45e12ea9..9c1139dbea3f 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -17,6 +17,7 @@ import useActiveRoute from '@hooks/useActiveRoute'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import useTransactionViolations from '@hooks/useTransactionViolations'; @@ -198,20 +199,21 @@ function MoneyRequestView({allReports, report, policy, shouldShowAnimatedBackgro const isSettled = isSettledReportUtils(moneyRequestReport?.reportID); const isCancelled = moneyRequestReport && moneyRequestReport?.isCancelledIOU; + const isChatReportArchived = useReportIsArchived(moneyRequestReport?.chatReportID); // Flags for allowing or disallowing editing an expense // Used for non-restricted fields such as: description, category, tag, billable, etc... const canUserPerformWriteAction = !!canUserPerformWriteActionReportUtils(report) && !readonly; - const canEdit = isMoneyRequestAction(parentReportAction) && canEditMoneyRequest(parentReportAction, transaction) && canUserPerformWriteAction; + const canEdit = isMoneyRequestAction(parentReportAction) && canEditMoneyRequest(parentReportAction, transaction, isChatReportArchived) && canUserPerformWriteAction; const canEditTaxFields = canEdit && !isDistanceRequest; - const canEditAmount = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.AMOUNT); - const canEditMerchant = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.MERCHANT); - const canEditDate = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE); - const canEditReceipt = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT); - const canEditDistance = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE); - const canEditDistanceRate = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE_RATE); - const canEditReport = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.REPORT); + const canEditAmount = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.AMOUNT, undefined, isChatReportArchived); + const canEditMerchant = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.MERCHANT, undefined, isChatReportArchived); + const canEditDate = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE, undefined, isChatReportArchived); + const canEditReceipt = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT, undefined, isChatReportArchived); + const canEditDistance = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE, undefined, isChatReportArchived); + const canEditDistanceRate = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE_RATE, undefined, isChatReportArchived); + const canEditReport = canUserPerformWriteAction && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.REPORT, undefined, isChatReportArchived); // A flag for verifying that the current report is a sub-report of a expense chat // if the policy of the report is either Collect or Control, then this report must be tied to expense chat diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f0d06064ff38..bd7d3ac14e85 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4031,7 +4031,11 @@ function isWorkspacePayer(memberLogin: string, policy: OnyxEntry): boole * This is used in conjunction with canEditRestrictedField to control editing of specific fields like amount, currency, created, receipt, and distance. * On its own, it only controls allowing/disallowing navigating to the editing pages or showing/hiding the 'Edit' icon on report actions */ -function canEditMoneyRequest(reportAction: OnyxInputOrEntry>, linkedTransaction?: OnyxEntry): boolean { +function canEditMoneyRequest( + reportAction: OnyxInputOrEntry>, + linkedTransaction?: OnyxEntry, + isChatReportArchived = false, +): boolean { const isDeleted = isDeletedAction(reportAction); if (isDeleted) { @@ -4072,7 +4076,7 @@ function canEditMoneyRequest(reportAction: OnyxInputOrEntry, reportPolicy: OnyxEntry< * Checks if the current user can edit the provided property of an expense * */ -function canEditFieldOfMoneyRequest(reportAction: OnyxInputOrEntry, fieldToEdit: ValueOf, isDeleteAction?: boolean): boolean { +function canEditFieldOfMoneyRequest( + reportAction: OnyxInputOrEntry, + fieldToEdit: ValueOf, + isDeleteAction?: boolean, + isChatReportArchived = false, +): boolean { // A list of fields that cannot be edited by anyone, once an expense has been settled const restrictedFields: string[] = [ CONST.EDIT_REQUEST_FIELD.AMOUNT, @@ -4168,7 +4177,7 @@ function canEditFieldOfMoneyRequest(reportAction: OnyxInputOrEntry CONST.EDIT_REQUEST_FIELD.REPORT, ]; - if (!isMoneyRequestAction(reportAction) || !canEditMoneyRequest(reportAction)) { + if (!isMoneyRequestAction(reportAction) || !canEditMoneyRequest(reportAction, undefined, isChatReportArchived)) { return false; } diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 1afbddde788e..759f3b775f0b 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -22,6 +22,7 @@ import { canAddTransaction, canDeleteReportAction, canDeleteTransaction, + canEditMoneyRequest, canEditReportDescription, canEditRoomVisibility, canEditWriteCapability, @@ -1820,6 +1821,45 @@ describe('ReportUtils', () => { }); }); + describe('canEditMoneyRequest', () => { + it('it should return false for archived invoice', async () => { + const invoiceReport: Report = { + reportID: '1', + type: CONST.REPORT.TYPE.INVOICE, + }; + const transaction = createRandomTransaction(22); + const moneyRequestAction: ReportAction = { + reportActionID: '22', + actorAccountID: currentUserAccountID, + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + originalMessage: { + IOUReportID: invoiceReport.reportID, + IOUTransactionID: transaction.transactionID, + amount: 530, + currency: CONST.CURRENCY.USD, + type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, + }, + message: [ + { + type: 'COMMENT', + html: 'USD 5.30 expense', + text: 'USD 5.30 expense', + isEdited: false, + whisperedTo: [], + isDeletedParentAction: false, + deleted: '', + }, + ], + created: '2025-03-05 16:34:27', + }; + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${invoiceReport.reportID}`, invoiceReport); + + const canEditRequest = canEditMoneyRequest(moneyRequestAction, transaction, true); + + expect(canEditRequest).toEqual(false); + }); + }); + describe('getChatByParticipants', () => { const userAccountID = 1; const userAccountID2 = 2;