From dae771882c6d08ed8c4e9b08aa64bfd416ebb1e4 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 25 Feb 2025 22:55:54 +0300 Subject: [PATCH] reset preferred exporter when admin is removed --- src/libs/actions/Policy/Member.ts | 139 +++++++++++++++++++++++++++++- src/types/onyx/Policy.ts | 93 ++++++++++---------- 2 files changed, 186 insertions(+), 46 deletions(-) diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index f9bb9a1e14ed..a4a51af107c3 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -315,6 +315,127 @@ function removeOptimisticRoomMembers( return roomMembers; } +/** This function will reset the preferred exporter to the owner of the workspace + * if the current preferred exporter is removed from the admin role. + */ +function resetAccountingPreferredExporter(policyID: string, loginList: string[]) { + const policy = getPolicy(policyID); + const owner = ReportUtils.getPersonalDetailsForAccountID(policy?.ownerAccountID).login ?? ''; + const optimisticData: OnyxUpdate[] = []; + const successData: OnyxUpdate[] = []; + const failureData: OnyxUpdate[] = []; + const policyKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const; + + if (policy?.connections?.xero?.config.export.exporter && loginList.includes(policy?.connections?.xero?.config.export.exporter)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {xero: {config: {export: {exporter: owner}, pendingFields: {exporter: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}}, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {xero: {config: {pendingFields: {exporter: null}}}}, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: {connections: {xero: {config: {export: {exporter: policy?.connections?.xero?.config.export.exporter}, pendingFields: {exporter: null}}}}}, + }); + } else if (policy?.connections?.netsuite?.options.config.exporter && loginList.includes(policy?.connections?.netsuite?.options.config.exporter)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {netsuite: {options: {config: {exporter: owner, pendingFields: {exporter: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}}}, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {netsuite: {options: {config: {pendingFields: {exporter: null}}}}}, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: {connections: {netsuite: {options: {config: {exporter: policy?.connections?.netsuite?.options.config.exporter, pendingFields: {exporter: null}}}}}}, + }); + } else if (policy?.connections?.quickbooksOnline?.config.export.exporter && loginList.includes(policy?.connections?.quickbooksOnline?.config.export.exporter)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {quickbooksOnline: {config: {export: {exporter: owner}, pendingFields: {export: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}}, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {quickbooksOnline: {config: {pendingFields: {export: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}}, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: { + quickbooksOnline: { + config: {export: {exporter: policy?.connections?.quickbooksOnline?.config.export.exporter}, pendingFields: {export: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}, + }, + }, + }, + }); + } else if (policy?.connections?.intacct?.config.export.exporter && loginList.includes(policy?.connections?.intacct?.config.export.exporter)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {intacct: {config: {export: {exporter: owner}, pendingFields: {exporter: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}}, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {intacct: {config: {pendingFields: {exporter: null}}}}, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: {connections: {intacct: {config: {export: {exporter: policy?.connections?.intacct?.config.export.exporter}, pendingFields: {exporter: null}}}}}, + }); + } else if (policy?.connections?.quickbooksDesktop?.config.export.exporter && loginList.includes(policy?.connections?.quickbooksDesktop?.config.export.exporter)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {quickbooksDesktop: {config: {export: {exporter: owner}, pendingFields: {exporter: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}}, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + connections: {quickbooksDesktop: {config: {pendingFields: {exporter: null}}}}, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: {connections: {quickbooksDesktop: {config: {export: {exporter: policy?.connections?.quickbooksDesktop?.config.export.exporter}, pendingFields: {exporter: null}}}}}, + }); + } + + return {optimisticData, successData, failureData}; +} /** * Remove the passed members from the policy employeeList @@ -430,6 +551,14 @@ function removeMembers(accountIDs: number[], policyID: string) { ]; failureData.push(...announceRoomMembers.onyxFailureData, ...adminRoomMembers.onyxFailureData); + const previousAdminLogins = emailList.filter((login) => policy?.employeeList?.[login]?.role === CONST.POLICY.ROLE.ADMIN); + if (previousAdminLogins.length) { + const preferredExporterOnyxData = resetAccountingPreferredExporter(policyID, previousAdminLogins); + optimisticData.push(...preferredExporterOnyxData.optimisticData); + successData.push(...preferredExporterOnyxData.successData); + failureData.push(...preferredExporterOnyxData.failureData); + } + const pendingChatMembers = ReportUtils.getPendingChatMembers(accountIDs, [], CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); workspaceChats.forEach((report) => { @@ -529,7 +658,7 @@ function removeMembers(accountIDs: number[], policyID: string) { } function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newRole: ValueOf) { - const previousEmployeeList = {...allPolicies?.[policyID]?.employeeList}; + const previousEmployeeList = {...allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]?.employeeList}; const memberRoles: WorkspaceMembersRoleData[] = accountIDs.reduce((result: WorkspaceMembersRoleData[], accountID: number) => { if (!allPersonalDetails?.[accountID]?.login) { return result; @@ -589,6 +718,14 @@ function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newR }, ]; + if (newRole !== CONST.POLICY.ROLE.ADMIN) { + const previousAdminLogins = memberRoles.filter((member) => previousEmployeeList[member.email]?.role === CONST.POLICY.ROLE.ADMIN).map((member) => member.email); + const preferredExporterOnyxData = resetAccountingPreferredExporter(policyID, previousAdminLogins); + optimisticData.push(...preferredExporterOnyxData.optimisticData); + successData.push(...preferredExporterOnyxData.successData); + failureData.push(...preferredExporterOnyxData.failureData); + } + const adminRoom = ReportUtils.getAllPolicyReports(policyID).find(ReportUtils.isAdminRoom); if (adminRoom) { const failureDataParticipants: Record = {...adminRoom.participants}; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 465b744deb0c..10315235ce8f 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1373,67 +1373,70 @@ type QBDConnectionData = { /** * User configuration for the QuickBooks Desktop accounting integration. */ -type QBDConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ - /** API provider */ - apiProvider: string; +type QBDConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< + { + /** API provider */ + apiProvider: string; - /** Configuration of automatic synchronization from QuickBooks Desktop to the app */ - autoSync: { - /** Job ID of the synchronization */ - jobID: string; + /** Configuration of automatic synchronization from QuickBooks Desktop to the app */ + autoSync: { + /** Job ID of the synchronization */ + jobID: string; - /** Whether changes made in QuickBooks Desktop should be reflected into the app automatically */ - enabled: boolean; - }; + /** Whether changes made in QuickBooks Desktop should be reflected into the app automatically */ + enabled: boolean; + }; - /** Whether a check to be printed */ - markChecksToBePrinted: boolean; + /** Whether a check to be printed */ + markChecksToBePrinted: boolean; - /** Determines if a vendor should be automatically created */ - shouldAutoCreateVendor: boolean; + /** Determines if a vendor should be automatically created */ + shouldAutoCreateVendor: boolean; - /** Whether items is imported */ - importItems: boolean; + /** Whether items is imported */ + importItems: boolean; - /** Configuration of the export */ - export: { - /** E-mail of the exporter */ - exporter: string; + /** Configuration of the export */ + export: { + /** E-mail of the exporter */ + exporter: string; - /** Defines how reimbursable expenses are exported */ - reimbursable: QBDReimbursableExportAccountType; + /** Defines how reimbursable expenses are exported */ + reimbursable: QBDReimbursableExportAccountType; - /** Account that receives the reimbursable expenses */ - reimbursableAccount: string; + /** Account that receives the reimbursable expenses */ + reimbursableAccount: string; - /** Export date type */ - exportDate: ValueOf; + /** Export date type */ + exportDate: ValueOf; - /** Defines how non-reimbursable expenses are exported */ - nonReimbursable: QBDNonReimbursableExportAccountType; + /** Defines how non-reimbursable expenses are exported */ + nonReimbursable: QBDNonReimbursableExportAccountType; - /** Account that receives the non reimbursable expenses */ - nonReimbursableAccount: string; + /** Account that receives the non reimbursable expenses */ + nonReimbursableAccount: string; - /** Default vendor of non reimbursable bill */ - nonReimbursableBillDefaultVendor: string; - }; + /** Default vendor of non reimbursable bill */ + nonReimbursableBillDefaultVendor: string; + }; - /** Configuration of import settings from QuickBooks Desktop to the app */ - mappings: { - /** How QuickBooks Desktop classes displayed as */ - classes: IntegrationEntityMap; + /** Configuration of import settings from QuickBooks Desktop to the app */ + mappings: { + /** How QuickBooks Desktop classes displayed as */ + classes: IntegrationEntityMap; - /** How QuickBooks Desktop customers displayed as */ - customers: IntegrationEntityMap; - }; + /** How QuickBooks Desktop customers displayed as */ + customers: IntegrationEntityMap; + }; - /** Whether new categories are enabled in chart of accounts */ - enableNewCategories: boolean; + /** Whether new categories are enabled in chart of accounts */ + enableNewCategories: boolean; - /** Collections of form field errors */ - errorFields?: OnyxCommon.ErrorFields; -}>; + /** Collections of form field errors */ + errorFields?: OnyxCommon.ErrorFields; + }, + 'exporter' +>; /** State of integration connection */ type Connection = {