complete script move draf to current

This commit is contained in:
Warunee Tamkoo 2026-02-10 16:23:52 +07:00
parent 1cab2b3afc
commit 3b97e52bd6

View file

@ -7865,7 +7865,6 @@ export class OrganizationController extends Controller {
]);
if (!orgRootDraft) return new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้างร่าง");
// Part 1: Differential sync of organization structure (bottom-up)
// Build mapping incrementally as we process each level
const allMappings: AllOrgMappings = {
@ -7876,60 +7875,80 @@ export class OrganizationController extends Controller {
orgChild4: { byAncestorDNA: new Map(), byDraftId: new Map() },
};
// Process from bottom (Child4) to top (Root) to handle foreign key constraints
// Child4 (leaf nodes - no children depending on them)
allMappings.orgChild4 = await this.syncOrgLevel(
queryRunner,
OrgChild4,
this.child4Repository,
drafRevisionId,
currentRevisionId,
rootDnaId,
allMappings,
);
// Track sync statistics for organization nodes
const orgSyncStats: Record<string, { deleted: number; updated: number; inserted: number }> =
{};
// Child3
allMappings.orgChild3 = await this.syncOrgLevel(
queryRunner,
OrgChild3,
this.child3Repository,
drafRevisionId,
currentRevisionId,
rootDnaId,
allMappings,
);
// Child2
allMappings.orgChild2 = await this.syncOrgLevel(
queryRunner,
OrgChild2,
this.child2Repository,
drafRevisionId,
currentRevisionId,
rootDnaId,
allMappings,
);
// Child1
allMappings.orgChild1 = await this.syncOrgLevel(
queryRunner,
OrgChild1,
this.child1Repository,
drafRevisionId,
currentRevisionId,
rootDnaId,
allMappings,
);
// OrgRoot (root level - no parent mapping needed)
allMappings.orgRoot = await this.syncOrgLevel(
// Process from top (Root) to bottom (Child4) to handle foreign key constraints
// OrgRoot (sync first - no parent dependencies)
const orgRootResult = await this.syncOrgLevel(
queryRunner,
OrgRoot,
this.orgRootRepository,
drafRevisionId,
currentRevisionId,
rootDnaId,
allMappings,
orgRootDraft?.id,
orgRootCurrent?.id,
);
allMappings.orgRoot = orgRootResult.mapping;
orgSyncStats.orgRoot = orgRootResult.counts;
// Child1 (parent OrgRoot already synced)
const child1Result = await this.syncOrgLevel(
queryRunner,
OrgChild1,
this.child1Repository,
drafRevisionId,
currentRevisionId,
allMappings,
orgRootDraft?.id,
orgRootCurrent?.id,
);
allMappings.orgChild1 = child1Result.mapping;
orgSyncStats.orgChild1 = child1Result.counts;
// Child2 (parents OrgRoot and Child1 already synced)
const child2Result = await this.syncOrgLevel(
queryRunner,
OrgChild2,
this.child2Repository,
drafRevisionId,
currentRevisionId,
allMappings,
orgRootDraft?.id,
orgRootCurrent?.id,
);
allMappings.orgChild2 = child2Result.mapping;
orgSyncStats.orgChild2 = child2Result.counts;
// Child3 (parents OrgRoot, Child1, Child2 already synced)
const child3Result = await this.syncOrgLevel(
queryRunner,
OrgChild3,
this.child3Repository,
drafRevisionId,
currentRevisionId,
allMappings,
orgRootDraft?.id,
orgRootCurrent?.id,
);
allMappings.orgChild3 = child3Result.mapping;
orgSyncStats.orgChild3 = child3Result.counts;
// Child4 (parents OrgRoot, Child1, Child2, Child3 already synced)
const child4Result = await this.syncOrgLevel(
queryRunner,
OrgChild4,
this.child4Repository,
drafRevisionId,
currentRevisionId,
allMappings,
orgRootDraft?.id,
orgRootCurrent?.id,
);
allMappings.orgChild4 = child4Result.mapping;
orgSyncStats.orgChild4 = child4Result.counts;
// Part 2: Sync position data using new org IDs from Part 1
// 2.1 Clear current_holderId for affected positions (keep existing logic)
@ -8097,17 +8116,44 @@ export class OrganizationController extends Controller {
}
// 2.5 Sync positions table for all affected posMasters
const positionSyncStats: { deleted: number; updated: number; inserted: number } = {
deleted: 0,
updated: 0,
inserted: 0,
};
for (const [draftPosMasterId, currentPosMasterId] of posMasterMapping) {
await this.syncPositionsForPosMaster(
const stats = await this.syncPositionsForPosMaster(
queryRunner,
draftPosMasterId,
currentPosMasterId,
drafRevisionId,
currentRevisionId,
);
positionSyncStats.deleted += stats.deleted;
positionSyncStats.updated += stats.updated;
positionSyncStats.inserted += stats.inserted;
}
// Build comprehensive summary
const summary = {
message: "ย้ายโครงสร้างสำเร็จ",
organization: {
orgRoot: orgSyncStats.orgRoot,
orgChild1: orgSyncStats.orgChild1,
orgChild2: orgSyncStats.orgChild2,
orgChild3: orgSyncStats.orgChild3,
orgChild4: orgSyncStats.orgChild4,
},
positionMaster: {
deleted: toDelete.length,
updated: toUpdate.length,
inserted: toInsert.length,
},
position: positionSyncStats,
};
await queryRunner.commitTransaction();
return new HttpSuccess(summary);
} catch (error) {
console.error("Error moving draft to current:", error);
await queryRunner.rollbackTransaction();
@ -8161,23 +8207,49 @@ export class OrganizationController extends Controller {
repository: any,
draftRevisionId: string,
currentRevisionId: string,
rootDnaId: string,
parentMappings?: AllOrgMappings,
): Promise<OrgIdMapping> {
draftOrgRootId?: string,
currentOrgRootId?: string,
): Promise<{
mapping: OrgIdMapping;
counts: { deleted: number; updated: number; inserted: number };
}> {
// 1. Fetch draft and current nodes under the given rootDnaId
// Build WHERE condition for draft nodes
const draftWhere: any = {
orgRevisionId: draftRevisionId,
};
if (
draftOrgRootId &&
(entityClass === OrgChild1 ||
entityClass === OrgChild2 ||
entityClass === OrgChild3 ||
entityClass === OrgChild4)
) {
draftWhere.orgRootId = draftOrgRootId;
} else if (entityClass === OrgRoot) {
draftWhere.id = draftOrgRootId;
}
// Build WHERE condition for current nodes
const currentWhere: any = {
orgRevisionId: currentRevisionId,
};
if (
currentOrgRootId &&
(entityClass === OrgChild1 ||
entityClass === OrgChild2 ||
entityClass === OrgChild3 ||
entityClass === OrgChild4)
) {
currentWhere.orgRootId = currentOrgRootId;
} else if (entityClass === OrgRoot) {
currentWhere.id = currentOrgRootId;
}
const [draftNodes, currentNodes] = await Promise.all([
repository.find({
where: {
orgRevisionId: draftRevisionId,
ancestorDNA: Like(`${rootDnaId}%`),
},
}),
repository.find({
where: {
orgRevisionId: currentRevisionId,
ancestorDNA: Like(`${rootDnaId}%`),
},
}),
repository.find({ where: draftWhere }),
repository.find({ where: currentWhere }),
]);
// 2. Build lookup maps for efficient matching by ancestorDNA
@ -8270,37 +8342,71 @@ export class OrganizationController extends Controller {
});
// Map parent IDs based on entity level
if (entityClass === OrgChild1 && draft.orgRootId && parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
} else if (entityClass === OrgChild2) {
if (draft.orgRootId && parentMappings) {
if (entityClass === OrgChild1 && draft.orgRootId) {
if (draft.orgRootId === draftOrgRootId) {
newNode.orgRootId = currentOrgRootId;
} else if (parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
}
} else if (entityClass === OrgChild2) {
if (draft.orgRootId) {
if (draft.orgRootId === draftOrgRootId) {
newNode.orgRootId = currentOrgRootId;
} else if (parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
}
}
if (draft.orgChild1Id && parentMappings) {
newNode.orgChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
const mappedChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
if (mappedChild1Id) {
newNode.orgChild1Id = mappedChild1Id;
}
}
} else if (entityClass === OrgChild3) {
if (draft.orgRootId && parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
if (draft.orgRootId) {
if (draft.orgRootId === draftOrgRootId) {
newNode.orgRootId = currentOrgRootId;
} else if (parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
}
}
if (draft.orgChild1Id && parentMappings) {
newNode.orgChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
const mappedChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
if (mappedChild1Id) {
newNode.orgChild1Id = mappedChild1Id;
}
}
if (draft.orgChild2Id && parentMappings) {
newNode.orgChild2Id = parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id);
const mappedChild2Id = parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id);
if (mappedChild2Id) {
newNode.orgChild2Id = mappedChild2Id;
}
}
} else if (entityClass === OrgChild4) {
if (draft.orgRootId && parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
if (draft.orgRootId) {
if (draft.orgRootId === draftOrgRootId) {
newNode.orgRootId = currentOrgRootId;
} else if (parentMappings) {
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
}
}
if (draft.orgChild1Id && parentMappings) {
newNode.orgChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
const mappedChild1Id = parentMappings.orgChild1.byDraftId.get(draft.orgChild1Id);
if (mappedChild1Id) {
newNode.orgChild1Id = mappedChild1Id;
}
}
if (draft.orgChild2Id && parentMappings) {
newNode.orgChild2Id = parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id);
const mappedChild2Id = parentMappings.orgChild2.byDraftId.get(draft.orgChild2Id);
if (mappedChild2Id) {
newNode.orgChild2Id = mappedChild2Id;
}
}
if (draft.orgChild3Id && parentMappings) {
newNode.orgChild3Id = parentMappings.orgChild3.byDraftId.get(draft.orgChild3Id);
const mappedChild3Id = parentMappings.orgChild3.byDraftId.get(draft.orgChild3Id);
if (mappedChild3Id) {
newNode.orgChild3Id = mappedChild3Id;
}
}
}
@ -8310,7 +8416,14 @@ export class OrganizationController extends Controller {
mapping.byDraftId.set(draft.id, saved.id);
}
return mapping;
return {
mapping,
counts: {
deleted: toDelete.length,
updated: toUpdate.length,
inserted: toInsert.length,
},
};
}
/**
@ -8323,7 +8436,7 @@ export class OrganizationController extends Controller {
currentPosMasterId: string,
draftRevisionId: string,
currentRevisionId: string,
): Promise<void> {
): 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, {
@ -8347,7 +8460,7 @@ export class OrganizationController extends Controller {
currentPositions.map((p: any) => p.id),
);
}
return;
return { deleted: currentPositions.length, updated: 0, inserted: 0 };
}
// Build maps for tracking
@ -8365,6 +8478,8 @@ export class OrganizationController extends Controller {
}
// UPDATE and INSERT
let updatedCount = 0;
let insertedCount = 0;
for (const draftPos of draftPositions) {
const current: any = currentByOrderNo.get(draftPos.orderNo);
@ -8380,6 +8495,7 @@ export class OrganizationController extends Controller {
positionArea: draftPos.positionArea,
isSpecial: draftPos.isSpecial,
});
updatedCount++;
} else {
// INSERT new position
const newPosition = queryRunner.manager.create(Position, {
@ -8388,7 +8504,10 @@ export class OrganizationController extends Controller {
posMasterId: currentPosMasterId,
});
await queryRunner.manager.save(newPosition);
insertedCount++;
}
}
return { deleted: toDelete.length, updated: updatedCount, inserted: insertedCount };
}
}