From 780aa24bc139d3c1e5da4f0ddf7e9fc399d72db6 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 4 Mar 2025 17:52:30 +0800 Subject: [PATCH 1/2] optimistically remove violation when deleting workspace --- src/libs/actions/Policy/Policy.ts | 91 +++++++++++++++++++------------ tests/actions/PolicyTest.ts | 39 ++++++++++++- 2 files changed, 95 insertions(+), 35 deletions(-) diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 23aa853e71839..0552896b94a37 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -94,6 +94,7 @@ import type { Request, TaxRatesWithDefault, Transaction, + TransactionViolations, } from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {Attributes, CompanyAddress, CustomUnit, NetSuiteCustomList, NetSuiteCustomSegment, Rate, TaxRate} from '@src/types/onyx/Policy'; @@ -228,6 +229,13 @@ Onyx.connect({ callback: (value) => (activePolicyID = value), }); +let allTransactionViolations: OnyxCollection = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, + waitForCollectionCallback: true, + callback: (value) => (allTransactionViolations = value), +}); + /** * Stores in Onyx the policy ID of the last workspace that was accessed by the user */ @@ -330,13 +338,33 @@ function deleteWorkspace(policyID: string, policyName: string) { : []), ]; + const policy = getPolicy(policyID); + // Restore the old report stateNum and statusNum + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + errors: reimbursementAccount?.errors ?? null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + avatarURL: policy?.avatarURL, + pendingAction: null, + }, + }, + ]; + const reportsToArchive = Object.values(allReports ?? {}).filter( (report) => ReportUtils.isPolicyRelatedReport(report, policyID) && (ReportUtils.isChatRoom(report) || ReportUtils.isPolicyExpenseChat(report) || ReportUtils.isTaskReport(report)), ); const finallyData: OnyxUpdate[] = []; const currentTime = DateUtils.getDBTime(); reportsToArchive.forEach((report) => { - const {reportID, ownerAccountID} = report ?? {}; + const {reportID, ownerAccountID, oldPolicyName} = report ?? {}; const isInvoiceReceiverReport = report?.invoiceReceiver && 'policyID' in report.invoiceReceiver && report.invoiceReceiver.policyID === policyID; optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -379,39 +407,6 @@ function deleteWorkspace(policyID: string, policyName: string) { }, }); - // We are temporarily adding this workaround because 'DeleteWorkspace' doesn't - // support receiving the optimistic reportActions' ids for the moment. - finallyData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: { - [optimisticClosedReportAction.reportActionID]: null, - }, - }); - }); - - const policy = getPolicy(policyID); - // Restore the old report stateNum and statusNum - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - value: { - errors: reimbursementAccount?.errors ?? null, - }, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - avatarURL: policy?.avatarURL, - pendingAction: null, - }, - }, - ]; - - reportsToArchive.forEach((report) => { - const {reportID, oldPolicyName} = report ?? {}; failureData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, @@ -421,6 +416,7 @@ function deleteWorkspace(policyID: string, policyName: string) { isPinned: report?.isPinned, }, }); + failureData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`, @@ -428,6 +424,33 @@ function deleteWorkspace(policyID: string, policyName: string) { private_isArchived: null, }, }); + + // We are temporarily adding this workaround because 'DeleteWorkspace' doesn't + // support receiving the optimistic reportActions' ids for the moment. + finallyData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticClosedReportAction.reportActionID]: null, + }, + }); + + if (report?.iouReportID) { + const reportTransactions = ReportUtils.getReportTransactions(report.iouReportID); + for (const transaction of reportTransactions) { + const violations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`]; + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`, + value: violations?.filter((violation) => violation.type !== CONST.VIOLATION_TYPES.VIOLATION), + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, + value: violations, + }); + } + } }); const params: DeleteWorkspaceParams = {policyID}; diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index a188df3779f42..8b0889fb0b539 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -4,7 +4,7 @@ import CONST from '@src/CONST'; import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager'; import * as Policy from '@src/libs/actions/Policy/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Policy as PolicyType, Report, ReportAction, ReportActions} from '@src/types/onyx'; +import {type Policy as PolicyType, type Report, type ReportAction, type ReportActions, TransactionViolations} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/Report'; import createRandomPolicy from '../utils/collections/policies'; import createRandomReport from '../utils/collections/reports'; @@ -444,6 +444,43 @@ describe('actions/Policy', () => { }); }); }); + + it('should remove violation from expense report', async () => { + const policyID = '123'; + const expenseChatReportID = '1'; + const expenseReportID = '2'; + const transactionID = '3'; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, { + ...createRandomReport(Number(expenseChatReportID)), + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + policyID, + iouReportID: expenseReportID, + }); + + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { + reportID: expenseReportID, + transactionID, + }); + + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`, [ + {name: 'cashExpenseWithNoReceipt', type: CONST.VIOLATION_TYPES.VIOLATION}, + {name: 'hold', type: CONST.VIOLATION_TYPES.WARNING}, + ]); + + Policy.deleteWorkspace(policyID, 'test'); + + await waitForBatchedUpdates(); + + const violations = await new Promise>((resolve) => { + Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`, + callback: resolve, + }); + }); + + expect(violations?.every((violation) => violation.type !== CONST.VIOLATION_TYPES.VIOLATION)).toBe(true); + }); }); describe('enablePolicyWorkflows', () => { From 4ee219f3d7ebff4549815db08958108fe70d7940 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 4 Mar 2025 18:04:34 +0800 Subject: [PATCH 2/2] lint --- tests/actions/PolicyTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index 8b0889fb0b539..7da8c62f77991 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -4,7 +4,7 @@ import CONST from '@src/CONST'; import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager'; import * as Policy from '@src/libs/actions/Policy/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; -import {type Policy as PolicyType, type Report, type ReportAction, type ReportActions, TransactionViolations} from '@src/types/onyx'; +import type {Policy as PolicyType, Report, ReportAction, ReportActions, TransactionViolations} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/Report'; import createRandomPolicy from '../utils/collections/policies'; import createRandomReport from '../utils/collections/reports';