import { SavePosMasterHistory } from "./../interfaces/OrgMapping"; import { AppDataSource } from "../database/data-source"; import { EmployeePosMaster } from "../entities/EmployeePosMaster"; import { EmployeeTempPosMaster } from "../entities/EmployeeTempPosMaster"; import { OrgRevision } from "../entities/OrgRevision"; import { PosMaster } from "../entities/PosMaster"; import { PosMasterEmployeeHistory } from "../entities/PosMasterEmployeeHistory"; import { PosMasterEmployeeTempHistory } from "../entities/PosMasterEmployeeTempHistory"; import { PosMasterHistory } from "../entities/PosMasterHistory"; import { ProfileEducation } from "../entities/ProfileEducation"; import { RequestWithUser } from "../middlewares/user"; export async function CreatePosMasterHistoryOfficer( posMasterId: string, request: RequestWithUser | null, type?: string | null, ): Promise { try { await AppDataSource.transaction(async (manager) => { const repoPosmaster = manager.getRepository(PosMaster); const repoHistory = manager.getRepository(PosMasterHistory); const repoOrgRevision = manager.getRepository(OrgRevision); const pm = await repoPosmaster.findOne({ where: { id: posMasterId }, relations: [ "positions", "positions.posLevel", "positions.posType", "positions.posExecutive", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4", "current_holder", "next_holder", ], }); if (!pm) return false; if (!pm.ancestorDNA) return false; const checkCurrentRevision = await repoOrgRevision.findOne({ where: { id: pm.orgRevisionId, orgRevisionIsCurrent: true, orgRevisionIsDraft: false, }, }); const _null: any = null; const h = new PosMasterHistory(); const selectedPosition = pm.positions.length > 0 ? pm.positions.find((p) => p.positionIsSelected === true) ?? null : null; h.ancestorDNA = pm.ancestorDNA ? pm.ancestorDNA : _null; if (!type || type != "DELETE") { if (checkCurrentRevision) { h.prefix = pm.current_holder?.prefix || _null; h.firstName = pm.current_holder?.firstName || _null; h.lastName = pm.current_holder?.lastName || _null; h.profileId = pm.current_holder?.id || _null; } else { h.prefix = pm.next_holder?.prefix || _null; h.firstName = pm.next_holder?.firstName || _null; h.lastName = pm.next_holder?.lastName || _null; } h.position = selectedPosition?.positionName ?? _null; h.posType = selectedPosition?.posType?.posTypeName ?? _null; h.posLevel = selectedPosition?.posLevel?.posLevelName ?? _null; } h.rootDnaId = pm.orgRoot?.ancestorDNA || _null; h.child1DnaId = pm.orgChild1?.ancestorDNA || _null; h.child2DnaId = pm.orgChild2?.ancestorDNA || _null; h.child3DnaId = pm.orgChild3?.ancestorDNA || _null; h.child4DnaId = pm.orgChild4?.ancestorDNA || _null; h.posMasterNoPrefix = pm.posMasterNoPrefix ?? _null; h.posMasterNo = pm.posMasterNo ?? _null; h.posMasterNoSuffix = pm.posMasterNoSuffix ?? _null; h.posExecutive = selectedPosition?.posExecutive?.posExecutiveName ?? _null; h.shortName = [ pm.orgChild4?.orgChild4ShortName, pm.orgChild3?.orgChild3ShortName, pm.orgChild2?.orgChild2ShortName, pm.orgChild1?.orgChild1ShortName, pm.orgRoot?.orgRootShortName, ].find((s) => typeof s === "string" && s.trim().length > 0) ?? _null; const userId = request?.user?.sub ?? ""; const userName = request?.user?.name ?? "system"; h.createdUserId = userId; h.createdFullName = userName; h.lastUpdateUserId = userId; h.lastUpdateFullName = userName; h.createdAt = new Date(); h.lastUpdatedAt = new Date(); await repoHistory.save(h); }); return true; } catch (err) { console.error("CreatePosMasterHistoryOfficer transaction error:", err); return false; } } export async function CreatePosMasterHistoryEmployee( posMasterId: string, request: RequestWithUser | null, ): Promise { try { await AppDataSource.transaction(async (manager) => { const repoPosmaster = manager.getRepository(EmployeePosMaster); const repoHistory = manager.getRepository(PosMasterEmployeeHistory); const pm = await repoPosmaster.findOne({ where: { id: posMasterId }, relations: [ "positions", "positions.posLevel", "positions.posType", "positions.posExecutive", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4", "current_holder", ], }); if (!pm) return false; if (!pm.ancestorDNA) return false; const _null: any = null; const h = new PosMasterEmployeeHistory(); const selectedPosition = pm.positions.length > 0 ? pm.positions.find((p) => p.positionIsSelected === true) ?? null : null; h.ancestorDNA = pm.ancestorDNA; h.prefix = pm.current_holder?.prefix || _null; h.firstName = pm.current_holder?.firstName || _null; h.lastName = pm.current_holder?.lastName || _null; h.posMasterNoPrefix = pm.posMasterNoPrefix ?? _null; h.posMasterNo = pm.posMasterNo ?? _null; h.posMasterNoSuffix = pm.posMasterNoSuffix ?? _null; h.position = selectedPosition?.positionName ?? _null; h.posType = selectedPosition?.posType?.posTypeName ?? _null; h.posLevel = selectedPosition?.posLevel?.posLevelName ?? _null; h.shortName = [ pm.orgChild4?.orgChild4ShortName, pm.orgChild3?.orgChild3ShortName, pm.orgChild2?.orgChild2ShortName, pm.orgChild1?.orgChild1ShortName, pm.orgRoot?.orgRootShortName, ].find((s) => typeof s === "string" && s.trim().length > 0) ?? _null; const userId = request?.user?.sub ?? ""; const userName = request?.user?.name ?? "system"; h.createdUserId = userId; h.createdFullName = userName; h.lastUpdateUserId = userId; h.lastUpdateFullName = userName; h.createdAt = new Date(); h.lastUpdatedAt = new Date(); await repoHistory.save(h); }); return true; } catch (err) { console.error("CreatePosMasterHistoryEmployee transaction error:", err); return false; } } export async function CreatePosMasterHistoryEmployeeTemp( posMasterId: string, request: RequestWithUser | null, ): Promise { try { await AppDataSource.transaction(async (manager) => { const repoPosmaster = manager.getRepository(EmployeeTempPosMaster); const repoHistory = manager.getRepository(PosMasterEmployeeTempHistory); const pm = await repoPosmaster.findOne({ where: { id: posMasterId }, relations: [ "positions", "positions.posLevel", "positions.posType", "positions.posExecutive", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4", "current_holder", ], }); if (!pm) return false; if (!pm.ancestorDNA) return false; const _null: any = null; const h = new PosMasterEmployeeTempHistory(); const selectedPosition = pm.positions.length > 0 ? pm.positions.find((p) => p.positionIsSelected === true) ?? null : null; h.ancestorDNA = pm.ancestorDNA; h.prefix = pm.current_holder?.prefix || _null; h.firstName = pm.current_holder?.firstName || _null; h.lastName = pm.current_holder?.lastName || _null; h.posMasterNoPrefix = pm.posMasterNoPrefix ?? _null; h.posMasterNo = pm.posMasterNo ?? _null; h.posMasterNoSuffix = pm.posMasterNoSuffix ?? _null; h.position = selectedPosition?.positionName ?? _null; h.posType = selectedPosition?.posType?.posTypeName ?? _null; h.posLevel = selectedPosition?.posLevel?.posLevelName ?? _null; h.shortName = [ pm.orgChild4?.orgChild4ShortName, pm.orgChild3?.orgChild3ShortName, pm.orgChild2?.orgChild2ShortName, pm.orgChild1?.orgChild1ShortName, pm.orgRoot?.orgRootShortName, ].find((s) => typeof s === "string" && s.trim().length > 0) ?? _null; const userId = request?.user?.sub ?? ""; const userName = request?.user?.name ?? "system"; h.createdUserId = userId; h.createdFullName = userName; h.lastUpdateUserId = userId; h.lastUpdateFullName = userName; h.createdAt = new Date(); h.lastUpdatedAt = new Date(); await repoHistory.save(h); }); return true; } catch (err) { console.error("CreatePosMasterHistoryEmployeeTemp transaction error:", err); return false; } } export async function getTopDegrees(educations: ProfileEducation[]): Promise { // filter เฉพาะ isUse==true หรือ isEducation==true const filtered = educations.filter((e) => e.isUse === true || e.isEducation === true); // sort: isEducation==true ก่อน, ถ้าเท่ากัน sort ด้วย level น้อยสุด const sorted = filtered.sort((a, b) => { const aEdu = !!a.isEducation ? 0 : 1; const bEdu = !!b.isEducation ? 0 : 1; if (aEdu !== bEdu) return aEdu - bEdu; const aLevel = typeof a.level === "number" ? a.level : Number.MAX_SAFE_INTEGER; const bLevel = typeof b.level === "number" ? b.level : Number.MAX_SAFE_INTEGER; return aLevel - bLevel; }); return sorted .map((e) => [e.degree, e.field].filter(Boolean).join(" ")) .filter(Boolean) .join("\n"); } export async function SavePosMasterHistoryOfficer( queryRunner: any, posMasterDnaId: string, profileId: string | null, pm: SavePosMasterHistory | null, ): Promise { 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; } }