feature/IO-3255-simplified-parts-management Deprovision route can now remove jobs, joblines, and audit trail
This commit is contained in:
@@ -1,71 +1,20 @@
|
|||||||
const admin = require("firebase-admin");
|
const admin = require("firebase-admin");
|
||||||
const client = require("../../../graphql-client/graphql-client").client;
|
const client = require("../../../graphql-client/graphql-client").client;
|
||||||
|
|
||||||
const { DELETE_SHOP } = require("../partsManagement.queries");
|
const {
|
||||||
|
DELETE_SHOP,
|
||||||
// Define corrected DELETE_VENDORS_BY_SHOP locally
|
DELETE_VENDORS_BY_SHOP,
|
||||||
const DELETE_VENDORS_BY_SHOP = `
|
GET_BODYSHOP,
|
||||||
mutation DELETE_VENDORS_BY_SHOP($shopId: uuid!) {
|
GET_ASSOCIATED_USERS,
|
||||||
delete_vendors(where: {bodyshopid: {_eq: $shopId}}) {
|
DELETE_ASSOCIATIONS_BY_SHOP,
|
||||||
affected_rows
|
GET_USER_ASSOCIATIONS_COUNT,
|
||||||
}
|
DELETE_USER,
|
||||||
}
|
GET_VENDORS,
|
||||||
`;
|
GET_JOBS_BY_SHOP,
|
||||||
|
DELETE_JOBLINES_BY_JOB_IDS,
|
||||||
// New queries for deprovisioning
|
DELETE_JOBS_BY_IDS,
|
||||||
const GET_BODYSHOP = `
|
DELETE_AUDIT_TRAIL_BY_SHOP
|
||||||
query GetBodyshop($id: uuid!) {
|
} = require("../partsManagement.queries");
|
||||||
bodyshops_by_pk(id: $id) {
|
|
||||||
external_shop_id
|
|
||||||
shopname
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const GET_ASSOCIATED_USERS = `
|
|
||||||
query GetAssociatedUsers($shopId: uuid!) {
|
|
||||||
associations(where: {shopid: {_eq: $shopId}}) {
|
|
||||||
user {
|
|
||||||
authid
|
|
||||||
email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const DELETE_ASSOCIATIONS_BY_SHOP = `
|
|
||||||
mutation DeleteAssociationsByShop($shopId: uuid!) {
|
|
||||||
delete_associations(where: {shopid: {_eq: $shopId}}) {
|
|
||||||
affected_rows
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const GET_USER_ASSOCIATIONS_COUNT = `
|
|
||||||
query GetUserAssociationsCount($userEmail: String!) {
|
|
||||||
associations_aggregate(where: {useremail: {_eq: $userEmail}}) {
|
|
||||||
aggregate {
|
|
||||||
count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const DELETE_USER = `
|
|
||||||
mutation DeleteUser($email: String!) {
|
|
||||||
delete_users(where: {email: {_eq: $email}}) {
|
|
||||||
affected_rows
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const GET_VENDORS = `
|
|
||||||
query GetVendors($shopId: uuid!) {
|
|
||||||
vendors(where: {bodyshopid: {_eq: $shopId}}) {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a Firebase user by UID.
|
* Deletes a Firebase user by UID.
|
||||||
@@ -94,6 +43,38 @@ const deleteBodyshop = async (shopId) => {
|
|||||||
await client.request(DELETE_SHOP, { id: shopId });
|
await client.request(DELETE_SHOP, { id: shopId });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch job ids for a given shop
|
||||||
|
* @param shopId
|
||||||
|
* @returns {Promise<string[]>}
|
||||||
|
*/
|
||||||
|
const getJobIdsForShop = async (shopId) => {
|
||||||
|
const resp = await client.request(GET_JOBS_BY_SHOP, { shopId });
|
||||||
|
return resp.jobs.map((j) => j.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete joblines for the given job ids
|
||||||
|
* @param jobIds {string[]}
|
||||||
|
* @returns {Promise<number>} affected rows
|
||||||
|
*/
|
||||||
|
const deleteJoblinesForJobs = async (jobIds) => {
|
||||||
|
if (!jobIds.length) return 0;
|
||||||
|
const resp = await client.request(DELETE_JOBLINES_BY_JOB_IDS, { jobIds });
|
||||||
|
return resp.delete_joblines.affected_rows;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete jobs for the given job ids
|
||||||
|
* @param jobIds {string[]}
|
||||||
|
* @returns {Promise<number>} affected rows
|
||||||
|
*/
|
||||||
|
const deleteJobsByIds = async (jobIds) => {
|
||||||
|
if (!jobIds.length) return 0;
|
||||||
|
const resp = await client.request(DELETE_JOBS_BY_IDS, { jobIds });
|
||||||
|
return resp.delete_jobs.affected_rows;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles deprovisioning a shop for parts management.
|
* Handles deprovisioning a shop for parts management.
|
||||||
* @param req
|
* @param req
|
||||||
@@ -156,6 +137,15 @@ const partsManagementDeprovisioning = async (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all job ids for this shop, then delete joblines and jobs (joblines first)
|
||||||
|
const jobIds = await getJobIdsForShop(p.shopId);
|
||||||
|
const joblinesDeleted = await deleteJoblinesForJobs(jobIds);
|
||||||
|
const jobsDeleted = await deleteJobsByIds(jobIds);
|
||||||
|
|
||||||
|
// Delete any audit trail entries tied to this bodyshop to avoid FK violations
|
||||||
|
const auditResp = await client.request(DELETE_AUDIT_TRAIL_BY_SHOP, { shopId: p.shopId });
|
||||||
|
const auditDeleted = auditResp.delete_audit_trail.affected_rows;
|
||||||
|
|
||||||
// Delete vendors
|
// Delete vendors
|
||||||
await deleteVendorsByShop(p.shopId);
|
await deleteVendorsByShop(p.shopId);
|
||||||
|
|
||||||
@@ -163,16 +153,26 @@ const partsManagementDeprovisioning = async (req, res) => {
|
|||||||
await deleteBodyshop(p.shopId);
|
await deleteBodyshop(p.shopId);
|
||||||
|
|
||||||
// Summary log
|
// Summary log
|
||||||
console.log(
|
logger.log("admin-delete-shop-summary", "info", null, null, {
|
||||||
`Deleted bodyshop ${p.shopId} (${shop.shopname}), ${associationsDeleted} associations, ${deletedUsers.length} users (${deletedUsers.join(", ") || "none"}), ${deletedVendors.length} vendors (${deletedVendors.join(", ") || "none"}).`
|
shopId: p.shopId,
|
||||||
);
|
shopname: shop.shopname,
|
||||||
|
associationsDeleted,
|
||||||
|
deletedUsers,
|
||||||
|
deletedVendors,
|
||||||
|
joblinesDeleted,
|
||||||
|
jobsDeleted,
|
||||||
|
auditDeleted
|
||||||
|
});
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
message: `Bodyshop ${p.shopId} and associated resources deleted successfully.`,
|
message: `Bodyshop ${p.shopId} and associated resources deleted successfully.`,
|
||||||
deletedShop: { id: p.shopId, name: shop.shopname },
|
deletedShop: { id: p.shopId, name: shop.shopname },
|
||||||
deletedAssociationsCount: associationsDeleted,
|
deletedAssociationsCount: associationsDeleted,
|
||||||
deletedUsers: deletedUsers,
|
deletedUsers: deletedUsers,
|
||||||
deletedVendors: deletedVendors
|
deletedVendors: deletedVendors,
|
||||||
|
deletedJoblinesCount: joblinesDeleted,
|
||||||
|
deletedJobsCount: jobsDeleted,
|
||||||
|
deletedAuditTrailCount: auditDeleted
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.log("admin-delete-shop-error", "error", null, null, {
|
logger.log("admin-delete-shop-error", "error", null, null, {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ const CREATE_SHOP = `
|
|||||||
|
|
||||||
const DELETE_VENDORS_BY_SHOP = `
|
const DELETE_VENDORS_BY_SHOP = `
|
||||||
mutation DELETE_VENDORS($shopId: uuid!) {
|
mutation DELETE_VENDORS($shopId: uuid!) {
|
||||||
delete_vendors(where: { shopid: { _eq: $shopId } }) {
|
delete_vendors(where: { bodyshopid: { _eq: $shopId } }) {
|
||||||
affected_rows
|
affected_rows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,6 +147,92 @@ const CREATE_USER = `
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const GET_BODYSHOP = `
|
||||||
|
query GetBodyshop($id: uuid!) {
|
||||||
|
bodyshops_by_pk(id: $id) {
|
||||||
|
external_shop_id
|
||||||
|
shopname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_ASSOCIATED_USERS = `
|
||||||
|
query GetAssociatedUsers($shopId: uuid!) {
|
||||||
|
associations(where: {shopid: {_eq: $shopId}}) {
|
||||||
|
user {
|
||||||
|
authid
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_ASSOCIATIONS_BY_SHOP = `
|
||||||
|
mutation DeleteAssociationsByShop($shopId: uuid!) {
|
||||||
|
delete_associations(where: {shopid: {_eq: $shopId}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_USER_ASSOCIATIONS_COUNT = `
|
||||||
|
query GetUserAssociationsCount($userEmail: String!) {
|
||||||
|
associations_aggregate(where: {useremail: {_eq: $userEmail}}) {
|
||||||
|
aggregate {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_USER = `
|
||||||
|
mutation DeleteUser($email: String!) {
|
||||||
|
delete_users(where: {email: {_eq: $email}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_VENDORS = `
|
||||||
|
query GetVendors($shopId: uuid!) {
|
||||||
|
vendors(where: {bodyshopid: {_eq: $shopId}}) {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const GET_JOBS_BY_SHOP = `
|
||||||
|
query GetJobsByShop($shopId: uuid!) {
|
||||||
|
jobs(where: {shopid: {_eq: $shopId}}) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_JOBLINES_BY_JOB_IDS = `
|
||||||
|
mutation DeleteJoblinesByJobIds($jobIds: [uuid!]!) {
|
||||||
|
delete_joblines(where: {jobid: {_in: $jobIds}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_JOBS_BY_IDS = `
|
||||||
|
mutation DeleteJobsByIds($jobIds: [uuid!]!) {
|
||||||
|
delete_jobs(where: {id: {_in: $jobIds}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DELETE_AUDIT_TRAIL_BY_SHOP = `
|
||||||
|
mutation DeleteAuditTrailByShop($shopId: uuid!) {
|
||||||
|
delete_audit_trail(where: {bodyshopid: {_eq: $shopId}}) {
|
||||||
|
affected_rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
GET_BODYSHOP_STATUS,
|
GET_BODYSHOP_STATUS,
|
||||||
GET_VEHICLE_BY_SHOP_VIN,
|
GET_VEHICLE_BY_SHOP_VIN,
|
||||||
@@ -162,5 +248,15 @@ module.exports = {
|
|||||||
CREATE_SHOP,
|
CREATE_SHOP,
|
||||||
DELETE_VENDORS_BY_SHOP,
|
DELETE_VENDORS_BY_SHOP,
|
||||||
DELETE_SHOP,
|
DELETE_SHOP,
|
||||||
CREATE_USER
|
CREATE_USER,
|
||||||
|
GET_BODYSHOP,
|
||||||
|
GET_ASSOCIATED_USERS,
|
||||||
|
DELETE_ASSOCIATIONS_BY_SHOP,
|
||||||
|
GET_USER_ASSOCIATIONS_COUNT,
|
||||||
|
DELETE_USER,
|
||||||
|
GET_VENDORS,
|
||||||
|
GET_JOBS_BY_SHOP,
|
||||||
|
DELETE_JOBLINES_BY_JOB_IDS,
|
||||||
|
DELETE_JOBS_BY_IDS,
|
||||||
|
DELETE_AUDIT_TRAIL_BY_SHOP
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user