import { EntityManager, EntityTarget, In } from "typeorm"; import { AppDataSource } from "../database/data-source"; import { OrgRevision } from "../entities/OrgRevision"; import { PosMaster } from "../entities/PosMaster"; import { Position } from "../entities/Position"; import { OrgRoot } from "../entities/OrgRoot"; import { OrgChild1 } from "../entities/OrgChild1"; import { OrgChild2 } from "../entities/OrgChild2"; import { OrgChild3 } from "../entities/OrgChild3"; import { OrgChild4 } from "../entities/OrgChild4"; import { PosMasterAct } from "../entities/PosMasterAct"; import { PosMasterAssign } from "../entities/PosMasterAssign"; import { PermissionOrg } from "../entities/PermissionOrg"; import { PermissionProfile } from "../entities/PermissionProfile"; import { EmployeePosMaster } from "../entities/EmployeePosMaster"; import { EmployeeTempPosMaster } from "../entities/EmployeeTempPosMaster"; import { EmployeePosition } from "../entities/EmployeePosition"; import { orgStructureCache } from "../utils/OrgStructureCache"; export interface ClearOldOrgRevisionSummary { orgRevisionId: string; orgRevisionName: string; deleted: { positions: number; employeePositionsByPosMaster: number; employeePositionsByTempPosMaster: number; posMasterActsByParent: number; posMasterActsByChild: number; posMasterAssigns: number; posMasters: number; employeePosMasters: number; employeeTempPosMasters: number; permissionOrgs: number; permissionProfiles: number; orgChild4s: number; orgChild3s: number; orgChild2s: number; orgChild1s: number; orgRoots: number; orgRevisions: number; }; } interface OrgRevisionSnapshot { id: string; orgRevisionName: string; orgRevisionIsCurrent: boolean; orgRevisionIsDraft: boolean; } export async function clearOldOrgRevisionData( orgRevisionId: string, ): Promise { const result = await AppDataSource.transaction(async (manager) => { const orgRevision = await manager.findOne(OrgRevision, { where: { id: orgRevisionId }, select: ["id", "orgRevisionName", "orgRevisionIsCurrent", "orgRevisionIsDraft"], }); if (!orgRevision) { throw new Error(`ไม่พบ orgRevision ที่ต้องการล้างข้อมูล: ${orgRevisionId}`); } validateOrgRevisionForDeletion(orgRevision); const [posMasters, orgRoots, employeePosMasters, employeeTempPosMasters] = await Promise.all([ manager.find(PosMaster, { where: { orgRevisionId }, select: ["id"], }), manager.find(OrgRoot, { where: { orgRevisionId }, select: ["id"], }), manager.find(EmployeePosMaster, { where: { orgRevisionId }, select: ["id"], }), manager.find(EmployeeTempPosMaster, { where: { orgRevisionId }, select: ["id"], }), ]); const posMasterIds = posMasters.map((item) => item.id); const orgRootIds = orgRoots.map((item) => item.id); const employeePosMasterIds = employeePosMasters.map((item) => item.id); const employeeTempPosMasterIds = employeeTempPosMasters.map((item) => item.id); const [ positionsCount, employeePositionsByPosMasterCount, employeePositionsByTempPosMasterCount, posMasterActsByParentCount, posMasterActsByChildCount, posMasterAssignsCount, permissionOrgsCount, permissionProfilesCount, orgChild4sCount, orgChild3sCount, orgChild2sCount, orgChild1sCount, ] = await Promise.all([ countByIds(manager, Position, "posMasterId", posMasterIds), countByIds(manager, EmployeePosition, "posMasterId", employeePosMasterIds), countByIds(manager, EmployeePosition, "posMasterTempId", employeeTempPosMasterIds), countByIds(manager, PosMasterAct, "posMasterId", posMasterIds), countByIds(manager, PosMasterAct, "posMasterChildId", posMasterIds), countByIds(manager, PosMasterAssign, "posMasterId", posMasterIds), countByIds(manager, PermissionOrg, "orgRootId", orgRootIds), countByIds(manager, PermissionProfile, "orgRootId", orgRootIds), manager.count(OrgChild4, { where: { orgRevisionId } }), manager.count(OrgChild3, { where: { orgRevisionId } }), manager.count(OrgChild2, { where: { orgRevisionId } }), manager.count(OrgChild1, { where: { orgRevisionId } }), ]); if (positionsCount > 0) { await manager.delete(Position, { posMasterId: In(posMasterIds) }); } if (employeePositionsByPosMasterCount > 0) { await manager.delete(EmployeePosition, { posMasterId: In(employeePosMasterIds) }); } if (employeePositionsByTempPosMasterCount > 0) { await manager.delete(EmployeePosition, { posMasterTempId: In(employeeTempPosMasterIds) }); } if (posMasterActsByParentCount > 0) { await manager.delete(PosMasterAct, { posMasterId: In(posMasterIds) }); } if (posMasterActsByChildCount > 0) { await manager.delete(PosMasterAct, { posMasterChildId: In(posMasterIds) }); } if (posMasterAssignsCount > 0) { await manager.delete(PosMasterAssign, { posMasterId: In(posMasterIds) }); } const posMastersCount = posMasterIds.length; const employeePosMastersCount = employeePosMasterIds.length; const employeeTempPosMastersCount = employeeTempPosMasterIds.length; if (posMastersCount > 0) { await manager.delete(PosMaster, { orgRevisionId }); } if (employeePosMastersCount > 0) { await manager.delete(EmployeePosMaster, { orgRevisionId }); } if (employeeTempPosMastersCount > 0) { await manager.delete(EmployeeTempPosMaster, { orgRevisionId }); } if (permissionOrgsCount > 0) { await manager.delete(PermissionOrg, { orgRootId: In(orgRootIds) }); } if (permissionProfilesCount > 0) { await manager.delete(PermissionProfile, { orgRootId: In(orgRootIds) }); } if (orgChild4sCount > 0) { await manager.delete(OrgChild4, { orgRevisionId }); } if (orgChild3sCount > 0) { await manager.delete(OrgChild3, { orgRevisionId }); } if (orgChild2sCount > 0) { await manager.delete(OrgChild2, { orgRevisionId }); } if (orgChild1sCount > 0) { await manager.delete(OrgChild1, { orgRevisionId }); } const orgRootsCount = orgRootIds.length; if (orgRootsCount > 0) { await manager.delete(OrgRoot, { orgRevisionId }); } await manager.delete(OrgRevision, { id: orgRevisionId }); return { orgRevisionId: orgRevision.id, orgRevisionName: orgRevision.orgRevisionName, deleted: { positions: positionsCount, employeePositionsByPosMaster: employeePositionsByPosMasterCount, employeePositionsByTempPosMaster: employeePositionsByTempPosMasterCount, posMasterActsByParent: posMasterActsByParentCount, posMasterActsByChild: posMasterActsByChildCount, posMasterAssigns: posMasterAssignsCount, posMasters: posMastersCount, employeePosMasters: employeePosMastersCount, employeeTempPosMasters: employeeTempPosMastersCount, permissionOrgs: permissionOrgsCount, permissionProfiles: permissionProfilesCount, orgChild4s: orgChild4sCount, orgChild3s: orgChild3sCount, orgChild2s: orgChild2sCount, orgChild1s: orgChild1sCount, orgRoots: orgRootsCount, orgRevisions: 1, }, }; }); orgStructureCache.invalidate(orgRevisionId); return result; } function validateOrgRevisionForDeletion(orgRevision: OrgRevisionSnapshot): void { if (orgRevision.orgRevisionIsCurrent) { throw new Error(`ไม่สามารถลบ orgRevision ปัจจุบันได้: ${orgRevision.id}`); } if (orgRevision.orgRevisionIsDraft) { throw new Error(`ไม่สามารถลบ orgRevision แบบร่างได้ด้วยสคริปต์นี้: ${orgRevision.id}`); } } async function countByIds( manager: EntityManager, entity: EntityTarget, field: keyof Entity, ids: string[], ): Promise { if (ids.length === 0) { return 0; } const alias = "entity"; return manager .createQueryBuilder(entity, alias) .where(`${alias}.${String(field)} IN (:...ids)`, { ids }) .getCount(); }