From 4c495efea62558d148aeabf911d4f326a2164d5c Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Thu, 13 Nov 2025 22:26:01 +0700 Subject: [PATCH 1/5] 74211 allow delete invoice in offline mode --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 48a7854514b06..82677145b934f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6528,7 +6528,7 @@ function buildOptimisticInvoiceReport( currency, // We don't translate reportName because the server response is always in English reportName: `${receiverName} owes ${formattedTotal}`, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + stateNum: CONST.REPORT.STATE_NUM.OPEN, statusNum: CONST.REPORT.STATUS_NUM.OPEN, total: total * -1, participants: { From b0826dd28eed2fd9bdceca9d5c8f9f58369b3c65 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Thu, 13 Nov 2025 22:36:31 +0700 Subject: [PATCH 2/5] update status number same backend response --- src/libs/ReportUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 82677145b934f..49f00ef2e249d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6528,8 +6528,8 @@ function buildOptimisticInvoiceReport( currency, // We don't translate reportName because the server response is always in English reportName: `${receiverName} owes ${formattedTotal}`, - stateNum: CONST.REPORT.STATE_NUM.OPEN, - statusNum: CONST.REPORT.STATUS_NUM.OPEN, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, total: total * -1, participants: { [receiverAccountID]: { From 74d1f2d39f36d960fdef85714f0c34fb526f98b4 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Sat, 15 Nov 2025 16:51:58 +0700 Subject: [PATCH 3/5] add unit test for create an invoice report --- tests/unit/ReportUtilsTest.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 8dc007167ee81..bb6142959b8ef 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -24,6 +24,7 @@ import { buildOptimisticChatReport, buildOptimisticCreatedReportAction, buildOptimisticExpenseReport, + buildOptimisticInvoiceReport, buildOptimisticIOUReportAction, buildOptimisticReportPreview, buildParticipantsFromAccountIDs, @@ -9259,4 +9260,17 @@ describe('ReportUtils', () => { expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.DEFAULT); await Onyx.clear(); }); + + it('should create an invoice report with SUBMITTED status the same BE response', () => { + const mockChatReportID = 'chat-report-123'; + const mockPolicyID = 'policy-456'; + const mockReceiverAccountID = 789; + const mockReceiverName = 'John Doe'; + const mockTotal = 100; + const mockCurrency = 'USD'; + const optimisticInvoiceReport = buildOptimisticInvoiceReport(mockChatReportID, mockPolicyID, mockReceiverAccountID, mockReceiverName, mockTotal, mockCurrency); + + expect(optimisticInvoiceReport.statusNum).toBe(CONST.REPORT.STATUS_NUM.SUBMITTED); + expect(optimisticInvoiceReport.stateNum).toBe(CONST.REPORT.STATE_NUM.SUBMITTED); + }); }); From ea3c5b2a11a982ccac6efad7bbc145fd8e893e09 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Thu, 20 Nov 2025 22:18:56 +0700 Subject: [PATCH 4/5] disable deprecated eslint --- src/libs/ReportUtils.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e9652e72ecb93..415c73295961c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -75,6 +75,7 @@ import type {NotificationPreference, Participants, Participant as ReportParticip import type {Message, OldDotReportAction, ReportActions} from '@src/types/onyx/ReportAction'; import type {PendingChatMember} from '@src/types/onyx/ReportMetadata'; import type {OnyxData} from '@src/types/onyx/Request'; +// eslint-disable-next-line @typescript-eslint/no-deprecated import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type {Comment, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import type {FileObject} from '@src/types/utils/Attachment'; @@ -925,6 +926,7 @@ type GetReportNameParams = { parentReportActionParam?: OnyxInputOrEntry; personalDetails?: Partial; invoiceReceiverPolicy?: OnyxEntry; + // eslint-disable-next-line @typescript-eslint/no-deprecated transactions?: SearchTransaction[]; reports?: Report[]; policies?: Policy[]; @@ -2247,6 +2249,7 @@ function findLastAccessedReport(ignoreDomainRooms: boolean, openOnAdminRoom = fa /** * Whether the provided report has expenses */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function hasExpenses(reportID?: string, transactions?: SearchTransaction[] | Array>): boolean { if (transactions) { return !!transactions?.find((transaction) => transaction?.reportID === reportID); @@ -2257,6 +2260,7 @@ function hasExpenses(reportID?: string, transactions?: SearchTransaction[] | Arr /** * Whether the provided report is a closed expense report with no expenses */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function isClosedExpenseReportWithNoExpenses(report: OnyxEntry, transactions?: SearchTransaction[] | Array>): boolean { if (!report?.statusNum || report.statusNum !== CONST.REPORT.STATUS_NUM.CLOSED || !isExpenseReport(report)) { return false; @@ -4483,6 +4487,7 @@ function canEditMoneyRequest( isChatReportArchived = false, report?: OnyxInputOrEntry, policy?: OnyxEntry, + // eslint-disable-next-line @typescript-eslint/no-deprecated linkedTransaction?: OnyxEntry | SearchTransaction, ): boolean { const isDeleted = isDeletedAction(reportAction); @@ -4625,6 +4630,7 @@ function canEditFieldOfMoneyRequest( isDeleteAction?: boolean, isChatReportArchived = false, outstandingReportsByPolicyID?: OutstandingReportsByPolicyIDDerivedValue, + // eslint-disable-next-line @typescript-eslint/no-deprecated linkedTransaction?: OnyxEntry | SearchTransaction, report?: OnyxInputOrEntry, policy?: OnyxEntry, @@ -4907,6 +4913,7 @@ function areAllRequestsBeingSmartScanned(iouReportID: string | undefined, report * * NOTE: This method is only meant to be used inside this action file. Do not export and use it elsewhere. Use useOnyx instead. */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function getLinkedTransaction(reportAction: OnyxEntry, transactions?: SearchTransaction[]): OnyxEntry | SearchTransaction { let transactionID: string | undefined; @@ -4962,6 +4969,7 @@ function getTransactionReportName({ reports, }: { reportAction: OnyxEntry; + // eslint-disable-next-line @typescript-eslint/no-deprecated transactions?: SearchTransaction[]; reports?: Report[]; }): string { @@ -5595,6 +5603,7 @@ function getReportName( personalDetails?: Partial, invoiceReceiverPolicy?: OnyxEntry, reportAttributes?: ReportAttributesDerivedValue['reports'], + // eslint-disable-next-line @typescript-eslint/no-deprecated transactions?: SearchTransaction[], isReportArchived?: boolean, reports?: Report[], @@ -8904,6 +8913,7 @@ function hasViolations( reportID: string | undefined, transactionViolations: OnyxCollection, shouldShowInReview?: boolean, + // eslint-disable-next-line @typescript-eslint/no-deprecated reportTransactions?: SearchTransaction[], ): boolean { const transactions = reportTransactions ?? getReportTransactions(reportID); @@ -8917,6 +8927,7 @@ function hasWarningTypeViolations( reportID: string | undefined, transactionViolations: OnyxCollection, shouldShowInReview?: boolean, + // eslint-disable-next-line @typescript-eslint/no-deprecated reportTransactions?: SearchTransaction[], ): boolean { const transactions = reportTransactions ?? getReportTransactions(reportID); @@ -8959,6 +8970,7 @@ function hasNoticeTypeViolations( /** * Checks to see if a report contains any type of violation */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function hasAnyViolations(reportID: string | undefined, transactionViolations: OnyxCollection, reportTransactions?: SearchTransaction[]) { return ( hasViolations(reportID, transactionViolations, undefined, reportTransactions) || @@ -8983,11 +8995,13 @@ function shouldBlockSubmitDueToStrictPolicyRules( reportID: string | undefined, transactionViolations: OnyxCollection, areStrictPolicyRulesEnabled: boolean, + // eslint-disable-next-line @typescript-eslint/no-deprecated reportTransactions?: Transaction[] | SearchTransaction[], ) { if (!areStrictPolicyRulesEnabled) { return false; } + // eslint-disable-next-line @typescript-eslint/no-deprecated return hasAnyViolations(reportID, transactionViolations, reportTransactions as SearchTransaction[]); } @@ -10341,6 +10355,7 @@ function getAllHeldTransactions(iouReportID?: string): Transaction[] { /** * Check if Report has any held expenses */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function hasHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTransaction[]): boolean { const iouReportTransactions = getReportTransactions(iouReportID); const transactions = allReportTransactions ?? iouReportTransactions; @@ -10350,6 +10365,7 @@ function hasHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTra /** * Check if all expenses in the Report are on hold */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function hasOnlyHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTransaction[]): boolean { const transactionsByIouReportID = getReportTransactions(iouReportID); const reportTransactions = allReportTransactions ?? transactionsByIouReportID; From 8dfbe5f7244154ea9a71b4058884fffdfa1bf6eb Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Thu, 20 Nov 2025 22:41:43 +0700 Subject: [PATCH 5/5] disable deprecated eslint in unit test --- src/libs/ReportUtils.ts | 2 +- tests/unit/ReportUtilsTest.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 415c73295961c..1aa8d3717086e 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -75,7 +75,6 @@ import type {NotificationPreference, Participants, Participant as ReportParticip import type {Message, OldDotReportAction, ReportActions} from '@src/types/onyx/ReportAction'; import type {PendingChatMember} from '@src/types/onyx/ReportMetadata'; import type {OnyxData} from '@src/types/onyx/Request'; -// eslint-disable-next-line @typescript-eslint/no-deprecated import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type {Comment, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import type {FileObject} from '@src/types/utils/Attachment'; @@ -8961,6 +8960,7 @@ function hasNoticeTypeViolations( reportID: string | undefined, transactionViolations: OnyxCollection, shouldShowInReview?: boolean, + // eslint-disable-next-line @typescript-eslint/no-deprecated reportTransactions?: SearchTransaction[], ): boolean { const transactions = reportTransactions ?? getReportTransactions(reportID); diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 0353d2a361474..25fe39149f70c 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -1663,7 +1663,7 @@ describe('ReportUtils', () => { currency: 'USD', }, }; - + // eslint-disable-next-line @typescript-eslint/no-deprecated const transaction: SearchTransaction = { transactionID: 'txn1', reportID: '2', @@ -1672,6 +1672,7 @@ describe('ReportUtils', () => { merchant: 'Test Merchant', created: testDate, modifiedMerchant: 'Test Merchant', + // eslint-disable-next-line @typescript-eslint/no-deprecated } as SearchTransaction; const reportName = getSearchReportName({