complete script move draf to current
This commit is contained in:
parent
1cab2b3afc
commit
3b97e52bd6
1 changed files with 199 additions and 80 deletions
|
|
@ -7865,7 +7865,6 @@ export class OrganizationController extends Controller {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!orgRootDraft) return new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้างร่าง");
|
if (!orgRootDraft) return new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลโครงสร้างร่าง");
|
||||||
|
|
||||||
// Part 1: Differential sync of organization structure (bottom-up)
|
// Part 1: Differential sync of organization structure (bottom-up)
|
||||||
// Build mapping incrementally as we process each level
|
// Build mapping incrementally as we process each level
|
||||||
const allMappings: AllOrgMappings = {
|
const allMappings: AllOrgMappings = {
|
||||||
|
|
@ -7876,60 +7875,80 @@ export class OrganizationController extends Controller {
|
||||||
orgChild4: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
orgChild4: { byAncestorDNA: new Map(), byDraftId: new Map() },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Process from bottom (Child4) to top (Root) to handle foreign key constraints
|
// Track sync statistics for organization nodes
|
||||||
// Child4 (leaf nodes - no children depending on them)
|
const orgSyncStats: Record<string, { deleted: number; updated: number; inserted: number }> =
|
||||||
allMappings.orgChild4 = await this.syncOrgLevel(
|
{};
|
||||||
queryRunner,
|
|
||||||
OrgChild4,
|
|
||||||
this.child4Repository,
|
|
||||||
drafRevisionId,
|
|
||||||
currentRevisionId,
|
|
||||||
rootDnaId,
|
|
||||||
allMappings,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Child3
|
// Process from top (Root) to bottom (Child4) to handle foreign key constraints
|
||||||
allMappings.orgChild3 = await this.syncOrgLevel(
|
// OrgRoot (sync first - no parent dependencies)
|
||||||
queryRunner,
|
const orgRootResult = await this.syncOrgLevel(
|
||||||
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(
|
|
||||||
queryRunner,
|
queryRunner,
|
||||||
OrgRoot,
|
OrgRoot,
|
||||||
this.orgRootRepository,
|
this.orgRootRepository,
|
||||||
drafRevisionId,
|
drafRevisionId,
|
||||||
currentRevisionId,
|
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
|
// Part 2: Sync position data using new org IDs from Part 1
|
||||||
// 2.1 Clear current_holderId for affected positions (keep existing logic)
|
// 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
|
// 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) {
|
for (const [draftPosMasterId, currentPosMasterId] of posMasterMapping) {
|
||||||
await this.syncPositionsForPosMaster(
|
const stats = await this.syncPositionsForPosMaster(
|
||||||
queryRunner,
|
queryRunner,
|
||||||
draftPosMasterId,
|
draftPosMasterId,
|
||||||
currentPosMasterId,
|
currentPosMasterId,
|
||||||
drafRevisionId,
|
drafRevisionId,
|
||||||
currentRevisionId,
|
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();
|
await queryRunner.commitTransaction();
|
||||||
|
return new HttpSuccess(summary);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error moving draft to current:", error);
|
console.error("Error moving draft to current:", error);
|
||||||
await queryRunner.rollbackTransaction();
|
await queryRunner.rollbackTransaction();
|
||||||
|
|
@ -8161,23 +8207,49 @@ export class OrganizationController extends Controller {
|
||||||
repository: any,
|
repository: any,
|
||||||
draftRevisionId: string,
|
draftRevisionId: string,
|
||||||
currentRevisionId: string,
|
currentRevisionId: string,
|
||||||
rootDnaId: string,
|
|
||||||
parentMappings?: AllOrgMappings,
|
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
|
// 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([
|
const [draftNodes, currentNodes] = await Promise.all([
|
||||||
repository.find({
|
repository.find({ where: draftWhere }),
|
||||||
where: {
|
repository.find({ where: currentWhere }),
|
||||||
orgRevisionId: draftRevisionId,
|
|
||||||
ancestorDNA: Like(`${rootDnaId}%`),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
repository.find({
|
|
||||||
where: {
|
|
||||||
orgRevisionId: currentRevisionId,
|
|
||||||
ancestorDNA: Like(`${rootDnaId}%`),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 2. Build lookup maps for efficient matching by ancestorDNA
|
// 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
|
// Map parent IDs based on entity level
|
||||||
if (entityClass === OrgChild1 && draft.orgRootId && parentMappings) {
|
if (entityClass === OrgChild1 && draft.orgRootId) {
|
||||||
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
if (draft.orgRootId === draftOrgRootId) {
|
||||||
} else if (entityClass === OrgChild2) {
|
newNode.orgRootId = currentOrgRootId;
|
||||||
if (draft.orgRootId && parentMappings) {
|
} else if (parentMappings) {
|
||||||
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
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) {
|
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) {
|
} else if (entityClass === OrgChild3) {
|
||||||
if (draft.orgRootId && parentMappings) {
|
if (draft.orgRootId) {
|
||||||
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
if (draft.orgRootId === draftOrgRootId) {
|
||||||
|
newNode.orgRootId = currentOrgRootId;
|
||||||
|
} else if (parentMappings) {
|
||||||
|
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (draft.orgChild1Id && parentMappings) {
|
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) {
|
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) {
|
} else if (entityClass === OrgChild4) {
|
||||||
if (draft.orgRootId && parentMappings) {
|
if (draft.orgRootId) {
|
||||||
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
if (draft.orgRootId === draftOrgRootId) {
|
||||||
|
newNode.orgRootId = currentOrgRootId;
|
||||||
|
} else if (parentMappings) {
|
||||||
|
newNode.orgRootId = parentMappings.orgRoot.byDraftId.get(draft.orgRootId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (draft.orgChild1Id && parentMappings) {
|
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) {
|
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) {
|
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);
|
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,
|
currentPosMasterId: string,
|
||||||
draftRevisionId: string,
|
draftRevisionId: string,
|
||||||
currentRevisionId: string,
|
currentRevisionId: string,
|
||||||
): Promise<void> {
|
): Promise<{ deleted: number; updated: number; inserted: number }> {
|
||||||
// Fetch draft and current positions for this posMaster
|
// Fetch draft and current positions for this posMaster
|
||||||
const [draftPositions, currentPositions] = await Promise.all([
|
const [draftPositions, currentPositions] = await Promise.all([
|
||||||
queryRunner.manager.find(Position, {
|
queryRunner.manager.find(Position, {
|
||||||
|
|
@ -8347,7 +8460,7 @@ export class OrganizationController extends Controller {
|
||||||
currentPositions.map((p: any) => p.id),
|
currentPositions.map((p: any) => p.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return { deleted: currentPositions.length, updated: 0, inserted: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build maps for tracking
|
// Build maps for tracking
|
||||||
|
|
@ -8365,6 +8478,8 @@ export class OrganizationController extends Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UPDATE and INSERT
|
// UPDATE and INSERT
|
||||||
|
let updatedCount = 0;
|
||||||
|
let insertedCount = 0;
|
||||||
for (const draftPos of draftPositions) {
|
for (const draftPos of draftPositions) {
|
||||||
const current: any = currentByOrderNo.get(draftPos.orderNo);
|
const current: any = currentByOrderNo.get(draftPos.orderNo);
|
||||||
|
|
||||||
|
|
@ -8380,6 +8495,7 @@ export class OrganizationController extends Controller {
|
||||||
positionArea: draftPos.positionArea,
|
positionArea: draftPos.positionArea,
|
||||||
isSpecial: draftPos.isSpecial,
|
isSpecial: draftPos.isSpecial,
|
||||||
});
|
});
|
||||||
|
updatedCount++;
|
||||||
} else {
|
} else {
|
||||||
// INSERT new position
|
// INSERT new position
|
||||||
const newPosition = queryRunner.manager.create(Position, {
|
const newPosition = queryRunner.manager.create(Position, {
|
||||||
|
|
@ -8388,7 +8504,10 @@ export class OrganizationController extends Controller {
|
||||||
posMasterId: currentPosMasterId,
|
posMasterId: currentPosMasterId,
|
||||||
});
|
});
|
||||||
await queryRunner.manager.save(newPosition);
|
await queryRunner.manager.save(newPosition);
|
||||||
|
insertedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return { deleted: toDelete.length, updated: updatedCount, inserted: insertedCount };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue