Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix - Sage Intacct - Preferred exporter remains the same after changing the role of admin to member #57430

139 changes: 138 additions & 1 deletion src/libs/actions/Policy/Member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -529,7 +658,7 @@ function removeMembers(accountIDs: number[], policyID: string) {
}

function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newRole: ValueOf<typeof CONST.POLICY.ROLE>) {
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;
Expand Down Expand Up @@ -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<number, Participant | null> = {...adminRoom.participants};
Expand Down
93 changes: 48 additions & 45 deletions src/types/onyx/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof CONST.QUICKBOOKS_EXPORT_DATE>;
/** Export date type */
exportDate: ValueOf<typeof CONST.QUICKBOOKS_EXPORT_DATE>;

/** 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'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain these changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As u can see here

pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_DESKTOP_CONFIG.EXPORTER], qbdConfig?.pendingFields)}

we are using pendingField.exporter for QBD but the type doesn't have it, so I am adding it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To align with other connections' config type, let's extract the QBDExportConfig and use it as keys for pending action. For example:

SageIntacctOfflineStateKeys | keyof SageIntacctSyncConfig | keyof SageIntacctAutoSyncConfig | keyof SageIntacctExportConfig

>;

/** State of integration connection */
type Connection<ConnectionData, ConnectionConfig> = {
Expand Down
Loading