fix: script org move draf to current save posMasterHistory
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m57s
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m57s
This commit is contained in:
parent
7694a83d5a
commit
3c9e3a1bb6
3 changed files with 173 additions and 8 deletions
|
|
@ -55,9 +55,10 @@ import {
|
|||
import {
|
||||
CreatePosMasterHistoryEmployee,
|
||||
CreatePosMasterHistoryOfficer,
|
||||
SavePosMasterHistoryOfficer,
|
||||
} from "../services/PositionService";
|
||||
import { orgStructureCache } from "../utils/OrgStructureCache";
|
||||
import { OrgIdMapping, AllOrgMappings } from "../interfaces/OrgMapping";
|
||||
import { OrgIdMapping, AllOrgMappings, SavePosMasterHistory } from "../interfaces/OrgMapping";
|
||||
|
||||
@Route("api/v1/org")
|
||||
@Tags("Organization")
|
||||
|
|
@ -8110,6 +8111,12 @@ export class OrganizationController extends Controller {
|
|||
|
||||
// Then delete posMaster records
|
||||
await queryRunner.manager.delete(PosMaster, toDeleteIds);
|
||||
|
||||
await Promise.all(
|
||||
toDelete.map(async (pos) => {
|
||||
await SavePosMasterHistoryOfficer(queryRunner, pos.ancestorDNA, null, null);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// 2.4 Process draft positions (UPDATE or INSERT)
|
||||
|
|
@ -8176,6 +8183,7 @@ export class OrganizationController extends Controller {
|
|||
current_holderId: draftPos.next_holderId,
|
||||
statusReport: "DONE",
|
||||
});
|
||||
|
||||
toInsert.push(newPosMaster);
|
||||
}
|
||||
}
|
||||
|
|
@ -8231,6 +8239,11 @@ export class OrganizationController extends Controller {
|
|||
console.error("Error moving draft to current:", error);
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดในการย้ายโครงสร้าง");
|
||||
} finally {
|
||||
if (queryRunner.isTransactionActive) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
}
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8612,18 +8625,27 @@ export class OrganizationController extends Controller {
|
|||
): Promise<{ deleted: number; updated: number; inserted: number }> {
|
||||
// Extract draft and current posMaster IDs
|
||||
const draftPosMasterIds = Array.from(posMasterMapping.keys());
|
||||
const currentPosMasterIds = Array.from(posMasterMapping.values()).map(([currentId]) => currentId);
|
||||
const currentPosMasterIds = Array.from(posMasterMapping.values()).map(
|
||||
([currentId]) => currentId,
|
||||
);
|
||||
|
||||
if (draftPosMasterIds.length === 0) {
|
||||
return { deleted: 0, updated: 0, inserted: 0 };
|
||||
}
|
||||
|
||||
// Fetch draft PosMasters with relations for history tracking
|
||||
const draftPosMasters = await queryRunner.manager.find(PosMaster, {
|
||||
where: { id: In(draftPosMasterIds) },
|
||||
relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4", "next_holder"],
|
||||
});
|
||||
|
||||
// Fetch ALL positions for ALL posMasters in just 2 queries
|
||||
const [allDraftPositions, allCurrentPositions] = await Promise.all([
|
||||
queryRunner.manager.find(Position, {
|
||||
where: {
|
||||
posMasterId: In(draftPosMasterIds),
|
||||
},
|
||||
relations: ["posType", "posLevel", "posExecutive"],
|
||||
order: { orderNo: "ASC" },
|
||||
}),
|
||||
queryRunner.manager.find(Position, {
|
||||
|
|
@ -8656,6 +8678,16 @@ export class OrganizationController extends Controller {
|
|||
const allToInsert: Array<any> = [];
|
||||
const profileUpdates: Map<string, any> = new Map();
|
||||
|
||||
// Create a map for quick lookup of draft PosMasters with relations
|
||||
const draftPosMasterMap = new Map(draftPosMasters.map((pm: PosMaster) => [pm.id, pm]));
|
||||
|
||||
// Collect PosMasterHistory calls for selected positions
|
||||
const historyCalls: Array<{
|
||||
ancestorDNA: string;
|
||||
profileId: string | null;
|
||||
historyData: SavePosMasterHistory;
|
||||
}> = [];
|
||||
|
||||
// Process each posMaster mapping
|
||||
for (const [draftPosMasterId, [currentPosMasterId, nextHolderId]] of posMasterMapping) {
|
||||
const draftPositions = draftPositionsByMaster.get(draftPosMasterId) || [];
|
||||
|
|
@ -8710,6 +8742,10 @@ 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, {
|
||||
|
|
@ -8718,6 +8754,46 @@ export class OrganizationController extends Controller {
|
|||
posLevelId: draftPos.posLevelId,
|
||||
});
|
||||
}
|
||||
|
||||
// Collect history data for the selected position
|
||||
if (nextHolderId != null && draftPos.positionIsSelected) {
|
||||
const draftPosMaster = draftPosMasterMap.get(draftPosMasterId) as any;
|
||||
if (draftPosMaster && draftPosMaster.ancestorDNA) {
|
||||
// Find the selected position from draft positions
|
||||
const selectedPos =
|
||||
draftPositions.find((p) => p.positionIsSelected === true) || draftPos;
|
||||
historyCalls.push({
|
||||
ancestorDNA: draftPosMaster.ancestorDNA,
|
||||
profileId: nextHolderId,
|
||||
historyData: {
|
||||
prefix: draftPosMaster.next_holder?.prefix ?? null,
|
||||
firstName: draftPosMaster.next_holder?.firstName ?? null,
|
||||
lastName: draftPosMaster.next_holder?.lastName ?? null,
|
||||
position: selectedPos.positionName ?? null,
|
||||
posType: (selectedPos as any).posType?.posTypeName ?? null,
|
||||
posLevel: (selectedPos as any).posLevel?.posLevelName ?? null,
|
||||
posExecutive: (selectedPos as any).posExecutive?.posExecutiveName ?? null,
|
||||
profileId: nextHolderId,
|
||||
rootDnaId: draftPosMaster.orgRoot?.ancestorDNA ?? null,
|
||||
child1DnaId: draftPosMaster.orgChild1?.ancestorDNA ?? null,
|
||||
child2DnaId: draftPosMaster.orgChild2?.ancestorDNA ?? null,
|
||||
child3DnaId: draftPosMaster.orgChild3?.ancestorDNA ?? null,
|
||||
child4DnaId: draftPosMaster.orgChild4?.ancestorDNA ?? null,
|
||||
shortName:
|
||||
[
|
||||
draftPosMaster.orgChild4?.orgChild4ShortName,
|
||||
draftPosMaster.orgChild3?.orgChild3ShortName,
|
||||
draftPosMaster.orgChild2?.orgChild2ShortName,
|
||||
draftPosMaster.orgChild1?.orgChild1ShortName,
|
||||
draftPosMaster.orgRoot?.orgRootShortName,
|
||||
].find((s) => typeof s === "string" && s.trim().length > 0) ?? null,
|
||||
posMasterNoPrefix: draftPosMaster.posMasterNoPrefix ?? null,
|
||||
posMasterNo: draftPosMaster.posMasterNo ?? null,
|
||||
posMasterNoSuffix: draftPosMaster.posMasterNoSuffix ?? null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8738,7 +8814,7 @@ export class OrganizationController extends Controller {
|
|||
for (let i = 0; i < allToUpdate.length; i += batchSize) {
|
||||
const batch = allToUpdate.slice(i, i + batchSize);
|
||||
await Promise.all(
|
||||
batch.map(({ id, data }) => queryRunner.manager.update(Position, id, data))
|
||||
batch.map(({ id, data }) => queryRunner.manager.update(Position, id, data)),
|
||||
);
|
||||
}
|
||||
updatedCount = allToUpdate.length;
|
||||
|
|
@ -8759,8 +8835,17 @@ export class OrganizationController extends Controller {
|
|||
const profileUpdateEntries = Array.from(profileUpdates.entries());
|
||||
await Promise.all(
|
||||
profileUpdateEntries.map(([profileId, data]) =>
|
||||
queryRunner.manager.update(Profile, profileId, data)
|
||||
)
|
||||
queryRunner.manager.update(Profile, profileId, data),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Save PosMasterHistory for updated positions
|
||||
if (historyCalls.length > 0) {
|
||||
await Promise.all(
|
||||
historyCalls.map(({ ancestorDNA, profileId, historyData }) =>
|
||||
SavePosMasterHistoryOfficer(queryRunner, ancestorDNA, profileId, historyData),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,3 +22,23 @@ export interface AllOrgMappings {
|
|||
orgChild3: OrgIdMapping;
|
||||
orgChild4: OrgIdMapping;
|
||||
}
|
||||
|
||||
export interface SavePosMasterHistory {
|
||||
prefix: string | null;
|
||||
firstName: string | null;
|
||||
lastName: string | null;
|
||||
position: string | null;
|
||||
posType: string | null;
|
||||
posLevel: string | null;
|
||||
posExecutive: string | null;
|
||||
profileId: string | null;
|
||||
rootDnaId: string | null;
|
||||
child1DnaId: string | null;
|
||||
child2DnaId: string | null;
|
||||
child3DnaId: string | null;
|
||||
child4DnaId: string | null;
|
||||
shortName: string | null;
|
||||
posMasterNoPrefix: string | null;
|
||||
posMasterNo: string | null;
|
||||
posMasterNoSuffix: string | null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { SavePosMasterHistory } from "./../interfaces/OrgMapping";
|
||||
import { AppDataSource } from "../database/data-source";
|
||||
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
|
||||
import { EmployeeTempPosMaster } from "../entities/EmployeeTempPosMaster";
|
||||
|
|
@ -44,9 +45,9 @@ export async function CreatePosMasterHistoryOfficer(
|
|||
where: {
|
||||
id: pm.orgRevisionId,
|
||||
orgRevisionIsCurrent: true,
|
||||
orgRevisionIsDraft: false
|
||||
}
|
||||
})
|
||||
orgRevisionIsDraft: false,
|
||||
},
|
||||
});
|
||||
const _null: any = null;
|
||||
const h = new PosMasterHistory();
|
||||
const selectedPosition =
|
||||
|
|
@ -260,3 +261,62 @@ export async function getTopDegrees(educations: ProfileEducation[]): Promise<str
|
|||
.filter(Boolean)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
export async function SavePosMasterHistoryOfficer(
|
||||
queryRunner: any,
|
||||
posMasterDnaId: string,
|
||||
profileId: string | null,
|
||||
pm: SavePosMasterHistory | null,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
// Type workaround: entity columns are nullable but types don't reflect it
|
||||
const _null: any = null;
|
||||
const repoPosMasterHistory = queryRunner.manager.getRepository(PosMasterHistory);
|
||||
const pmh = await repoPosMasterHistory.findOne({
|
||||
where: {
|
||||
ancestorDNA: posMasterDnaId,
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
});
|
||||
|
||||
// Check if we need to insert a new history record
|
||||
const shouldInsert = !pmh && profileId && pm;
|
||||
const profileChanged = pmh && pmh.profileId !== profileId;
|
||||
|
||||
if (shouldInsert || profileChanged) {
|
||||
// insert new record
|
||||
const newPmh = new PosMasterHistory();
|
||||
newPmh.ancestorDNA = posMasterDnaId;
|
||||
newPmh.prefix = pm?.prefix ?? _null;
|
||||
newPmh.firstName = pm?.firstName ?? _null;
|
||||
newPmh.lastName = pm?.lastName ?? _null;
|
||||
newPmh.position = pm?.position ?? _null;
|
||||
newPmh.posType = pm?.posType ?? _null;
|
||||
newPmh.posLevel = pm?.posLevel ?? _null;
|
||||
newPmh.posExecutive = pm?.posExecutive ?? _null;
|
||||
newPmh.profileId = profileId ?? _null;
|
||||
newPmh.rootDnaId = pm?.rootDnaId ?? _null;
|
||||
newPmh.child1DnaId = pm?.child1DnaId ?? _null;
|
||||
newPmh.child2DnaId = pm?.child2DnaId ?? _null;
|
||||
newPmh.child3DnaId = pm?.child3DnaId ?? _null;
|
||||
newPmh.child4DnaId = pm?.child4DnaId ?? _null;
|
||||
newPmh.shortName = pm?.shortName ?? _null;
|
||||
newPmh.posMasterNoPrefix = pm?.posMasterNoPrefix ?? _null;
|
||||
newPmh.posMasterNo = pm?.posMasterNo ?? _null;
|
||||
newPmh.posMasterNoSuffix = pm?.posMasterNoSuffix ?? _null;
|
||||
// Add audit fields for data integrity
|
||||
newPmh.createdUserId = "system";
|
||||
newPmh.createdFullName = "system";
|
||||
newPmh.lastUpdateUserId = "system";
|
||||
newPmh.lastUpdateFullName = "system";
|
||||
newPmh.createdAt = new Date();
|
||||
newPmh.lastUpdatedAt = new Date();
|
||||
await queryRunner.manager.save(PosMasterHistory, newPmh);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error("SavePosMasterHistoryOfficer error:", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue