diff --git a/src/controllers/OrganizationController.ts b/src/controllers/OrganizationController.ts index 813e268c..b0a007f5 100644 --- a/src/controllers/OrganizationController.ts +++ b/src/controllers/OrganizationController.ts @@ -8167,6 +8167,10 @@ export class OrganizationController extends Controller { }); toUpdate.push(current); + if (draftPos.next_holderId === null) { + await SavePosMasterHistoryOfficer(queryRunner, draftPos.ancestorDNA, null, null); + } + // Track mapping for position sync posMasterMapping.set(draftPos.id, [current.id, draftPos.next_holderId]); } else { @@ -8512,107 +8516,6 @@ export class OrganizationController extends Controller { }; } - /** - * Helper function: Sync positions for a PosMaster - * Handles DELETE/UPDATE/INSERT for positions associated with a posMaster - * - * @deprecated Kept as fallback - use syncAllPositionsBatch for better performance - */ - private async syncPositionsForPosMaster( - queryRunner: any, - draftPosMasterId: string, - currentPosMasterId: string, - _draftRevisionId: string, - _currentRevisionId: string, - nextHolderId: string | null | undefined, - ): Promise<{ deleted: number; updated: number; inserted: number }> { - // Fetch draft and current positions for this posMaster - const [draftPositions, currentPositions] = await Promise.all([ - queryRunner.manager.find(Position, { - where: { - posMasterId: draftPosMasterId, - }, - order: { orderNo: "ASC" }, - }), - queryRunner.manager.find(Position, { - where: { - posMasterId: currentPosMasterId, - }, - }), - ]); - - // If no draft positions, delete all current positions - if (draftPositions.length === 0) { - if (currentPositions.length > 0) { - await queryRunner.manager.delete( - Position, - currentPositions.map((p: any) => p.id), - ); - } - return { deleted: currentPositions.length, updated: 0, inserted: 0 }; - } - - // Build maps for tracking - const currentByOrderNo = new Map(currentPositions.map((p: any) => [p.orderNo, p])); - - // DELETE: Current positions not in draft (by orderNo) - const draftOrderNos = new Set(draftPositions.map((p: any) => p.orderNo)); - const toDelete = currentPositions.filter((p: any) => !draftOrderNos.has(p.orderNo)); - - if (toDelete.length > 0) { - await queryRunner.manager.delete( - Position, - toDelete.map((p: any) => p.id), - ); - } - - // UPDATE and INSERT - let updatedCount = 0; - let insertedCount = 0; - for (const draftPos of draftPositions) { - const current: any = currentByOrderNo.get(draftPos.orderNo); - - if (current) { - // UPDATE existing position - await queryRunner.manager.update(Position, current.id, { - positionName: draftPos.positionName, - positionField: draftPos.positionField, - posTypeId: draftPos.posTypeId, - posLevelId: draftPos.posLevelId, - posExecutiveId: draftPos.posExecutiveId, - positionExecutiveField: draftPos.positionExecutiveField, - positionArea: draftPos.positionArea, - isSpecial: draftPos.isSpecial, - orderNo: draftPos.orderNo, - positionIsSelected: draftPos.positionIsSelected, - lastUpdateFullName: draftPos.lastUpdateFullName, - lastUpdatedAt: new Date(), - }); - updatedCount++; - } else { - // INSERT new position - const newPosition = queryRunner.manager.create(Position, { - ...draftPos, - id: undefined, - posMasterId: currentPosMasterId, - }); - await queryRunner.manager.save(newPosition); - insertedCount++; - } - - // update profile - if (nextHolderId != null && draftPos.positionIsSelected) { - await queryRunner.manager.update(Profile, nextHolderId, { - position: draftPos.positionName, - posTypeId: draftPos.posTypeId, - posLevelId: draftPos.posLevelId, - }); - } - } - - return { deleted: toDelete.length, updated: updatedCount, inserted: insertedCount }; - } - /** * Batch version: Sync positions for ALL posMasters in a single operation * This significantly reduces database round trips for large organizations @@ -8674,6 +8577,7 @@ export class OrganizationController extends Controller { // Collect all operations const allToDelete: string[] = []; + const allToDeleteHistory: string[] = []; const allToUpdate: Array<{ id: string; data: any }> = []; const allToInsert: Array = []; const profileUpdates: Map = new Map(); @@ -8696,6 +8600,7 @@ export class OrganizationController extends Controller { // If no draft positions, mark all current positions for deletion if (draftPositions.length === 0) { allToDelete.push(...currentPositions.map((p: any) => p.id)); + allToDeleteHistory.push(...currentPositions.map((p: any) => p.ancestorDNA)); continue; } @@ -8707,6 +8612,7 @@ export class OrganizationController extends Controller { for (const currentPos of currentPositions) { if (!draftOrderNos.has(currentPos.orderNo)) { allToDelete.push(currentPos.id); + allToDeleteHistory.push(currentPos.ancestorDNA); } } @@ -8742,10 +8648,6 @@ export class OrganizationController extends Controller { }); } - if (nextHolderId === null) { - await SavePosMasterHistoryOfficer(queryRunner, draftPos.ancestorDNA, null, null); - } - // Collect profile update for the selected position if (nextHolderId != null && draftPos.positionIsSelected) { profileUpdates.set(nextHolderId, { @@ -8753,10 +8655,8 @@ export class OrganizationController extends Controller { posTypeId: draftPos.posTypeId, posLevelId: draftPos.posLevelId, }); - } - // Collect history data for the selected position - if (nextHolderId != null && draftPos.positionIsSelected) { + // Collect history data for the selected position const draftPosMaster = draftPosMasterMap.get(draftPosMasterId) as any; if (draftPosMaster && draftPosMaster.ancestorDNA) { // Find the selected position from draft positions @@ -8805,6 +8705,11 @@ export class OrganizationController extends Controller { // Bulk DELETE if (allToDelete.length > 0) { await queryRunner.manager.delete(Position, allToDelete); + await Promise.all( + allToDeleteHistory.map(async (ancestorDNA) => { + await SavePosMasterHistoryOfficer(queryRunner, ancestorDNA, null, null); + }), + ); deletedCount = allToDelete.length; }