diff --git a/src/controllers/OrganizationController.ts b/src/controllers/OrganizationController.ts index 766ab0b4..00b04eba 100644 --- a/src/controllers/OrganizationController.ts +++ b/src/controllers/OrganizationController.ts @@ -8291,6 +8291,7 @@ export class OrganizationController extends Controller { if (posMasterDraft.length <= 0) { // Fetch current positions const posMasterCurrent = await this.posMasterRepository.find({ + relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"], where: [ { orgRevisionId: currentRevisionId, orgRootId: In(currentOrgIds.orgRoot) }, { orgRevisionId: currentRevisionId, orgChild1Id: In(currentOrgIds.orgChild1) }, @@ -8313,7 +8314,34 @@ export class OrganizationController extends Controller { const deleteHistoryOps = posMasterCurrent.map((pos) => ({ posMasterDnaId: pos.ancestorDNA, profileId: null, - pm: null, + pm: { + prefix: null, + firstName: null, + lastName: null, + position: null, + posType: null, + posLevel: null, + posExecutive: null, + profileId: null, + shortName: pos + ? [ + pos.orgChild4?.orgChild4ShortName, + pos.orgChild3?.orgChild3ShortName, + pos.orgChild2?.orgChild2ShortName, + pos.orgChild1?.orgChild1ShortName, + pos.orgRoot?.orgRootShortName, + ].find((s: string | undefined) => typeof s === "string" && s.trim().length > 0) ?? + null + : null, + posMasterNoPrefix: pos.posMasterNoPrefix ?? null, + posMasterNo: pos.posMasterNo != null ? String(pos.posMasterNo) : null, + posMasterNoSuffix: pos.posMasterNoSuffix ?? null, + rootDnaId: pos?.orgRoot?.ancestorDNA ?? null, + child1DnaId: pos?.orgChild1?.ancestorDNA ?? null, + child2DnaId: pos?.orgChild2?.ancestorDNA ?? null, + child3DnaId: pos?.orgChild3?.ancestorDNA ?? null, + child4DnaId: pos?.orgChild4?.ancestorDNA ?? null, + } as SavePosMasterHistory, })); await BatchSavePosMasterHistoryOfficer(queryRunner, deleteHistoryOps); } @@ -8348,6 +8376,7 @@ export class OrganizationController extends Controller { if (nextHolderIds.length > 0) { // FIX: Fetch positions first before updating (to avoid race condition) const posMastersToUpdate = await queryRunner.manager.find(PosMaster, { + relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"], where: { orgRevisionId: currentRevisionId, current_holderId: In(nextHolderIds), @@ -8360,7 +8389,34 @@ export class OrganizationController extends Controller { .map((pos) => ({ posMasterDnaId: pos.ancestorDNA, profileId: null, - pm: null, + pm: { + prefix: null, + firstName: null, + lastName: null, + position: null, + posType: null, + posLevel: null, + posExecutive: null, + profileId: null, + shortName: pos + ? [ + pos.orgChild4?.orgChild4ShortName, + pos.orgChild3?.orgChild3ShortName, + pos.orgChild2?.orgChild2ShortName, + pos.orgChild1?.orgChild1ShortName, + pos.orgRoot?.orgRootShortName, + ].find((s: string | undefined) => typeof s === "string" && s.trim().length > 0) ?? + null + : null, + posMasterNoPrefix: pos.posMasterNoPrefix ?? null, + posMasterNo: pos.posMasterNo != null ? String(pos.posMasterNo) : null, + posMasterNoSuffix: pos.posMasterNoSuffix ?? null, + rootDnaId: pos?.orgRoot?.ancestorDNA ?? null, + child1DnaId: pos?.orgChild1?.ancestorDNA ?? null, + child2DnaId: pos?.orgChild2?.ancestorDNA ?? null, + child3DnaId: pos?.orgChild3?.ancestorDNA ?? null, + child4DnaId: pos?.orgChild4?.ancestorDNA ?? null, + } as SavePosMasterHistory, })); await BatchSavePosMasterHistoryOfficer(queryRunner, historyOps); @@ -8377,6 +8433,7 @@ export class OrganizationController extends Controller { // 2.2 Fetch current positions for comparison const posMasterCurrent = await this.posMasterRepository.find({ + relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"], where: [ { orgRevisionId: currentRevisionId, orgRootId: In(currentOrgIds.orgRoot) }, { orgRevisionId: currentRevisionId, orgChild1Id: In(currentOrgIds.orgChild1) }, @@ -8406,7 +8463,34 @@ export class OrganizationController extends Controller { const deleteHistoryOps = toDelete.map((pos) => ({ posMasterDnaId: pos.ancestorDNA, profileId: null, - pm: null, + pm: { + prefix: null, + firstName: null, + lastName: null, + position: null, + posType: null, + posLevel: null, + posExecutive: null, + profileId: null, + shortName: pos + ? [ + pos.orgChild4?.orgChild4ShortName, + pos.orgChild3?.orgChild3ShortName, + pos.orgChild2?.orgChild2ShortName, + pos.orgChild1?.orgChild1ShortName, + pos.orgRoot?.orgRootShortName, + ].find((s: string | undefined) => typeof s === "string" && s.trim().length > 0) ?? + null + : null, + posMasterNoPrefix: pos.posMasterNoPrefix ?? null, + posMasterNo: pos.posMasterNo != null ? String(pos.posMasterNo) : null, + posMasterNoSuffix: pos.posMasterNoSuffix ?? null, + rootDnaId: pos?.orgRoot?.ancestorDNA ?? null, + child1DnaId: pos?.orgChild1?.ancestorDNA ?? null, + child2DnaId: pos?.orgChild2?.ancestorDNA ?? null, + child3DnaId: pos?.orgChild3?.ancestorDNA ?? null, + child4DnaId: pos?.orgChild4?.ancestorDNA ?? null, + } as SavePosMasterHistory, })); await BatchSavePosMasterHistoryOfficer(queryRunner, deleteHistoryOps); } @@ -8900,6 +8984,7 @@ export class OrganizationController extends Controller { where: { posMasterId: In(currentPosMasterIds), }, + relations: ["posType", "posLevel", "posExecutive"], }), ]); @@ -8927,6 +9012,12 @@ export class OrganizationController extends Controller { const allToInsert: Array = []; const profileUpdates: Map = new Map(); + // Collect position and posMaster data for delete history tracking + const deleteHistoryData: Array<{ + position: any; + posMaster: PosMaster; + }> = []; + // Create a map for quick lookup of draft PosMasters with relations const draftPosMasterMap = new Map(draftPosMasters.map((pm: PosMaster) => [pm.id, pm])); @@ -8946,6 +9037,11 @@ export class OrganizationController extends Controller { if (draftPositions.length === 0) { allToDelete.push(...currentPositions.map((p: any) => p.id)); allToDeleteHistory.push(...currentPositions.map((p: any) => p.ancestorDNA)); + // Collect data for history tracking + const pm = draftPosMasterMap.get(draftPosMasterId) as PosMaster; + for (const pos of currentPositions) { + deleteHistoryData.push({ position: pos, posMaster: pm }); + } continue; } @@ -8954,10 +9050,13 @@ export class OrganizationController extends Controller { const draftOrderNos = new Set(draftPositions.map((p: any) => p.orderNo)); // Mark for deletion: current positions not in draft (by orderNo) + const pm = draftPosMasterMap.get(draftPosMasterId) as PosMaster; for (const currentPos of currentPositions) { if (!draftOrderNos.has(currentPos.orderNo)) { allToDelete.push(currentPos.id); allToDeleteHistory.push(currentPos.ancestorDNA); + // Collect data for history tracking + deleteHistoryData.push({ position: currentPos, posMaster: pm }); } } @@ -9063,10 +9162,36 @@ export class OrganizationController extends Controller { // Bulk DELETE if (allToDelete.length > 0) { await queryRunner.manager.delete(Position, allToDelete); - const deleteOps = allToDeleteHistory.map((ancestorDNA) => ({ - posMasterDnaId: ancestorDNA, + const deleteOps = deleteHistoryData.map(({ position, posMaster }) => ({ + posMasterDnaId: position.ancestorDNA, profileId: null, - pm: null, + pm: { + prefix: null, + firstName: null, + lastName: null, + position: null, + posType: null, + posLevel: null, + posExecutive: null, + profileId: null, + rootDnaId: posMaster?.orgRoot?.ancestorDNA ?? null, + child1DnaId: posMaster?.orgChild1?.ancestorDNA ?? null, + child2DnaId: posMaster?.orgChild2?.ancestorDNA ?? null, + child3DnaId: posMaster?.orgChild3?.ancestorDNA ?? null, + child4DnaId: posMaster?.orgChild4?.ancestorDNA ?? null, + shortName: posMaster + ? [ + posMaster.orgChild4?.orgChild4ShortName, + posMaster.orgChild3?.orgChild3ShortName, + posMaster.orgChild2?.orgChild2ShortName, + posMaster.orgChild1?.orgChild1ShortName, + posMaster.orgRoot?.orgRootShortName, + ].find((s) => typeof s === "string" && s.trim().length > 0) ?? null + : null, + posMasterNoPrefix: posMaster?.posMasterNoPrefix ?? null, + posMasterNo: posMaster?.posMasterNo != null ? String(posMaster.posMasterNo) : null, + posMasterNoSuffix: posMaster?.posMasterNoSuffix ?? null, + }, })); await BatchSavePosMasterHistoryOfficer(queryRunner, deleteOps); deletedCount = allToDelete.length;