From e04d1ad7d3c44aa9b59f1cf478d55403b4aeaafa Mon Sep 17 00:00:00 2001 From: harid Date: Wed, 20 May 2026 10:57:18 +0700 Subject: [PATCH] =?UTF-8?q?Migrate=20+=20API=20=E0=B8=94=E0=B8=B6=E0=B8=87?= =?UTF-8?q?=E0=B8=A3=E0=B8=B2=E0=B8=A2=E0=B8=8A=E0=B8=B7=E0=B9=88=E0=B8=AD?= =?UTF-8?q?=E0=B8=A5=E0=B8=B9=E0=B8=81=E0=B8=88=E0=B9=89=E0=B8=B2=E0=B8=87?= =?UTF-8?q?=E0=B8=9B=E0=B8=A3=E0=B8=B0=E0=B8=88=E0=B8=B3=E0=B8=95=E0=B8=B2?= =?UTF-8?q?=E0=B8=A1=E0=B8=9B=E0=B8=A3=E0=B8=B0=E0=B8=A7=E0=B8=B1=E0=B8=95?= =?UTF-8?q?=E0=B8=B4=E0=B8=95=E0=B8=B3=E0=B9=81=E0=B8=AB=E0=B8=99=E0=B9=88?= =?UTF-8?q?=E0=B8=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OrganizationDotnetController.ts | 427 +++++++++--------- src/entities/PosMasterEmployeeHistory.ts | 84 ++-- ...44154610-update_posMasterEmpHis_add_dna.ts | 23 + src/services/PositionService.ts | 6 + 4 files changed, 280 insertions(+), 260 deletions(-) create mode 100644 src/migration/1779244154610-update_posMasterEmpHis_add_dna.ts diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index b26cf73c..91e5c9d2 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -26,6 +26,7 @@ import { OrgRoot } from "../entities/OrgRoot"; import { Position } from "../entities/Position"; import { PosMaster } from "../entities/PosMaster"; import { PosMasterHistory } from "../entities/PosMasterHistory"; +import { PosMasterEmployeeHistory } from "../entities/PosMasterEmployeeHistory"; import { Profile } from "../entities/Profile"; import { ProfileEducation } from "../entities/ProfileEducation"; import { ProfileEmployee } from "../entities/ProfileEmployee"; @@ -57,6 +58,7 @@ export class OrganizationDotnetController extends Controller { private positionRepository = AppDataSource.getRepository(Position); private posMasterRepository = AppDataSource.getRepository(PosMaster); private posMasterHistoryRepository = AppDataSource.getRepository(PosMasterHistory); + private posMasterEmployeeHistoryRepository = AppDataSource.getRepository(PosMasterEmployeeHistory); private empPosMasterRepository = AppDataSource.getRepository(EmployeePosMaster); private insigniaRepo = AppDataSource.getRepository(ProfileInsignia); private employeePosDictRepository = AppDataSource.getRepository(EmployeePosDict); @@ -6922,229 +6924,218 @@ export class OrganizationDotnetController extends Controller { return new HttpSuccess(profile_); } - // /** - // * รายชื่อขรก. ตามสิทธิ์ admin - // * - // * @summary รายชื่อขรก. ตามสิทธิ์ admin - // * - // */ - // @Post("employee-by-admin-rolev2") - // async GetEmployeesByAdminRoleV2( - // @Request() req: RequestWithUser, - // @Body() - // body: { - // node: number; - // nodeId: string; - // role: string; - // isRetirement?: boolean; - // reqNode?: number; - // reqNodeId?: string; - // date?: Date; - // }, - // ) { - // let typeCondition: any = {}; - // if (body.role === "CHILD" || body.role === "PARENT" || body.role === "BROTHER") { - // if (body.role === "CHILD") { - // switch (body.node) { - // case 0: - // typeCondition = { - // rootDnaId: body.nodeId, - // }; - // break; - // case 1: - // typeCondition = { - // child1DnaId: body.nodeId, - // }; - // break; - // case 2: - // typeCondition = { - // child2DnaId: body.nodeId, - // }; - // break; - // case 3: - // typeCondition = { - // child3DnaId: body.nodeId, - // }; - // break; - // case 4: - // typeCondition = { - // child4DnaId: body.nodeId, - // }; - // break; - // default: - // typeCondition = {}; - // break; - // } - // } else if (body.role === "BROTHER") { - // switch (body.node) { - // case 0: - // typeCondition = { - // rootDnaId: body.nodeId, - // }; - // break; - // case 1: - // typeCondition = { - // rootDnaId: body.nodeId, - // }; - // break; - // case 2: - // typeCondition = { - // child1DnaId: body.nodeId, - // }; - // break; - // case 3: - // typeCondition = { - // child2DnaId: body.nodeId, - // }; - // break; - // case 4: - // typeCondition = { - // child3DnaId: body.nodeId, - // }; - // break; - // default: - // typeCondition = {}; - // break; - // } - // } else if (body.role === "PARENT") { - // typeCondition = { - // rootDnaId: body.nodeId, - // child1DnaId: Not(IsNull()), - // }; - // } - // } else if (body.role === "OWNER" || body.role === "ROOT") { - // switch (body.reqNode) { - // case 0: - // typeCondition = { - // rootDnaId: body.reqNodeId, - // }; - // break; - // case 1: - // typeCondition = { - // child1DnaId: body.reqNodeId, - // }; - // break; - // case 2: - // typeCondition = { - // child2DnaId: body.reqNodeId, - // }; - // break; - // case 3: - // typeCondition = { - // child3DnaId: body.reqNodeId, - // }; - // break; - // case 4: - // typeCondition = { - // child4DnaId: body.reqNodeId, - // }; - // break; - // default: - // typeCondition = {}; - // break; - // } - // } else if (body.role === "NORMAL") { - // switch (body.node) { - // case 0: - // typeCondition = { - // rootDnaId: body.nodeId, - // child1DnaId: IsNull(), - // }; - // break; - // case 1: - // typeCondition = { - // child1DnaId: body.nodeId, - // child2DnaId: IsNull(), - // }; - // break; - // case 2: - // typeCondition = { - // child2DnaId: body.nodeId, - // child3DnaId: IsNull(), - // }; - // break; - // case 3: - // typeCondition = { - // child3DnaId: body.nodeId, - // child4DnaId: IsNull(), - // }; - // break; - // case 4: - // typeCondition = { - // child4DnaId: body.nodeId, - // }; - // break; - // default: - // typeCondition = {}; - // break; - // } - // } - // const date = body.date ? new Date(body.date) : new Date(); - // // set เวลาเป็น 23:59:59 ของวันนั้น - // date.setHours(23, 59, 59, 999); + /** + * รายชื่อลูกจ้างประจำ ตามสิทธิ์ admin + * @summary รายชื่อลูกจ้างประจำ ตามสิทธิ์ admin + */ + @Post("employee-by-admin-rolev2") + async GetEmployeesByAdminRoleV2( + @Request() req: RequestWithUser, + @Body() + body: { + node: number; + nodeId: string; + role: string; + isRetirement?: boolean; + reqNode?: number; + reqNodeId?: string; + date: Date; + }, + ) { + let typeCondition: any = {}; + if (body.role === "CHILD" || body.role === "BROTHER") { + if (body.role === "CHILD") { + switch (body.node) { + case 0: + typeCondition = { + rootDnaId: body.nodeId, + }; + break; + case 1: + typeCondition = { + child1DnaId: body.nodeId, + }; + break; + case 2: + typeCondition = { + child2DnaId: body.nodeId, + }; + break; + case 3: + typeCondition = { + child3DnaId: body.nodeId, + }; + break; + case 4: + typeCondition = { + child4DnaId: body.nodeId, + }; + break; + default: + typeCondition = {}; + break; + } + } else if (body.role === "BROTHER") { + switch (body.node) { + case 0: + typeCondition = { + rootDnaId: body.nodeId, + }; + break; + case 1: + typeCondition = { + rootDnaId: body.nodeId, + }; + break; + case 2: + typeCondition = { + child1DnaId: body.nodeId, + }; + break; + case 3: + typeCondition = { + child2DnaId: body.nodeId, + }; + break; + case 4: + typeCondition = { + child3DnaId: body.nodeId, + }; + break; + default: + typeCondition = {}; + break; + } + } + } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") { + switch (body.reqNode) { + case 0: + typeCondition = { + rootDnaId: body.reqNodeId, + }; + break; + case 1: + typeCondition = { + child1DnaId: body.reqNodeId, + }; + break; + case 2: + typeCondition = { + child2DnaId: body.reqNodeId, + }; + break; + case 3: + typeCondition = { + child3DnaId: body.reqNodeId, + }; + break; + case 4: + typeCondition = { + child4DnaId: body.reqNodeId, + }; + break; + default: + typeCondition = {}; + break; + } + } else if (body.role === "NORMAL") { + switch (body.node) { + case 0: + typeCondition = { + rootDnaId: body.nodeId, + child1DnaId: IsNull(), + }; + break; + case 1: + typeCondition = { + child1DnaId: body.nodeId, + child2DnaId: IsNull(), + }; + break; + case 2: + typeCondition = { + child2DnaId: body.nodeId, + child3DnaId: IsNull(), + }; + break; + case 3: + typeCondition = { + child3DnaId: body.nodeId, + child4DnaId: IsNull(), + }; + break; + case 4: + typeCondition = { + child4DnaId: body.nodeId, + }; + break; + default: + typeCondition = {}; + break; + } + } + // set เวลาเป็น 23:59:59 ของวันนั้น + const date = body.date.setHours(23, 59, 59, 999); - // let profile = await this.posMasterEmployeeHistoryRepository.find({ - // where: { - // ...typeCondition, - // createdAt: LessThanOrEqual(date), - // // firstName: Not("") && Not(IsNull()), - // // lastName: Not("") && Not(IsNull()), - // }, - // order: { - // firstName: "ASC", - // lastName: "ASC", - // createdAt: "DESC", // ให้ createdAt ล่าสุดอยู่ข้างบน - // }, - // }); + let posEmpHis = await this.posMasterEmployeeHistoryRepository.find({ + where: { + ...typeCondition, + createdAt: LessThanOrEqual(date), + }, + order: { + firstName: "ASC", + lastName: "ASC", + createdAt: "DESC", // ให้ createdAt ล่าสุดอยู่ข้างบน + }, + }); - // // group by ancestorDNA แล้วเลือก create_at ล่าสุด - // const grouped = new Map(); - // for (const item of profile) { - // const key = `${item.shortName}-${item.posMasterNo}`; - // if (!grouped.has(key)) { - // grouped.set(key, item); - // } else { - // // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด - // const exist = grouped.get(key); - // if (exist && item.createdAt > exist.createdAt) { - // grouped.set(key, item); - // } - // } - // } + // group by ancestorDNA แล้วเลือก create_at ล่าสุด + const grouped = new Map(); + for (const item of posEmpHis) { + const key = `${item.shortName}-${item.posMasterNo}`; + if (!grouped.has(key)) { + grouped.set(key, item); + } else { + // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด + const exist = grouped.get(key); + if (exist && item.createdAt > exist.createdAt) { + grouped.set(key, item); + } + } + } - // const profile_ = await Promise.all( - // Array.from(grouped.values()) - // .filter((x) => x.profileId != null) - // .map(async (item: PosMasterEmployeeHistory) => { - // let profile = await this.profileRepo.findOne({ - // where: { id: item.profileId }, - // }); + const profile_ = await Promise.all( + Array.from(grouped.values()) + .filter((x) => x.profileEmployeeId != null) + .map(async (item: PosMasterEmployeeHistory) => { + let profileEmp = await this.profileEmpRepo.findOne({ + where: { id: item.profileEmployeeId }, + }); - // return { - // id: item.profileId, - // prefix: item.prefix, - // firstName: item.firstName, - // lastName: item.lastName, - // citizenId: profile?.citizenId ?? null, - // dateStart: profile?.dateStart ?? null, - // dateAppoint: profile?.dateAppoint ?? null, - // keycloak: profile?.keycloak ?? null, - // posNo: item.shortName, - // position: item.position, - // positionLevel: item.posLevel, - // positionType: item.posType, - // // oc: Oc, - // orgRootId: item.rootDnaId, - // orgChild1Id: item.child1DnaId, - // orgChild2Id: item.child2DnaId, - // orgChild3Id: item.child3DnaId, - // orgChild4Id: item.child4DnaId, - // }; - // }), - // ); + return { + id: profileEmp?.id, + prefix: profileEmp?.prefix, + firstName: profileEmp?.firstName, + lastName: profileEmp?.lastName, + citizenId: profileEmp?.citizenId ?? null, + dateStart: profileEmp?.dateStart ?? null, + dateAppoint: profileEmp?.dateAppoint ?? null, + keycloak: profileEmp?.keycloak ?? null, + posNo: item.shortName, + position: item.position, + positionLevel: item.posLevel, + positionType: item.posType, + orgRootId: item.rootDnaId, + orgChild1Id: item.child1DnaId, + orgChild2Id: item.child2DnaId, + orgChild3Id: item.child3DnaId, + orgChild4Id: item.child4DnaId, + }; + }), + ); - // return new HttpSuccess(profile_); - // } + return new HttpSuccess(profile_); + } /** * 4. API Update รอบการลงเวลา ในตาราง profile diff --git a/src/entities/PosMasterEmployeeHistory.ts b/src/entities/PosMasterEmployeeHistory.ts index b0418644..e0aa7853 100644 --- a/src/entities/PosMasterEmployeeHistory.ts +++ b/src/entities/PosMasterEmployeeHistory.ts @@ -99,51 +99,51 @@ export class PosMasterEmployeeHistory extends EntityBase { }) ancestorDNA: string; - // @Column({ - // nullable: true, - // length: 40, - // comment: "คีย์นอก(FK)ของตาราง profile", - // default: null, - // }) - // profileId: string; + @Column({ + nullable: true, + length: 40, + comment: "คีย์นอก(FK)ของตาราง profileEmployee", + default: null, + }) + profileEmployeeId: string; - // @Column({ - // nullable: true, - // length: 40, - // comment: "dna ของตาราง orgRoot", - // default: null, - // }) - // rootDnaId: string; + @Column({ + nullable: true, + length: 40, + comment: "dna ของตาราง orgRoot", + default: null, + }) + rootDnaId: string; - // @Column({ - // nullable: true, - // length: 40, - // comment: "dna ของตาราง orgChild1", - // default: null, - // }) - // child1DnaId: string; + @Column({ + nullable: true, + length: 40, + comment: "dna ของตาราง orgChild1", + default: null, + }) + child1DnaId: string; - // @Column({ - // nullable: true, - // length: 40, - // comment: "dna ของตาราง orgChild2", - // default: null, - // }) - // child2DnaId: string; + @Column({ + nullable: true, + length: 40, + comment: "dna ของตาราง orgChild2", + default: null, + }) + child2DnaId: string; - // @Column({ - // nullable: true, - // length: 40, - // comment: "dna ของตาราง orgChild3", - // default: null, - // }) - // child3DnaId: string; + @Column({ + nullable: true, + length: 40, + comment: "dna ของตาราง orgChild3", + default: null, + }) + child3DnaId: string; - // @Column({ - // nullable: true, - // length: 40, - // comment: "dna ของตาราง orgChild4", - // default: null, - // }) - // child4DnaId: string; + @Column({ + nullable: true, + length: 40, + comment: "dna ของตาราง orgChild4", + default: null, + }) + child4DnaId: string; } diff --git a/src/migration/1779244154610-update_posMasterEmpHis_add_dna.ts b/src/migration/1779244154610-update_posMasterEmpHis_add_dna.ts new file mode 100644 index 00000000..5b7a4a1d --- /dev/null +++ b/src/migration/1779244154610-update_posMasterEmpHis_add_dna.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdatePosMasterEmpHisAddDna1779244154610 implements MigrationInterface { + name = 'UpdatePosMasterEmpHisAddDna1779244154610' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` ADD \`profileEmployeeId\` varchar(40) NULL COMMENT 'คีย์นอก(FK)ของตาราง profileEmployee'`); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` ADD \`rootDnaId\` varchar(40) NULL COMMENT 'dna ของตาราง orgRoot'`); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` ADD \`child1DnaId\` varchar(40) NULL COMMENT 'dna ของตาราง orgChild1'`); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` ADD \`child2DnaId\` varchar(40) NULL COMMENT 'dna ของตาราง orgChild2'`); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` ADD \`child3DnaId\` varchar(40) NULL COMMENT 'dna ของตาราง orgChild3'`); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` ADD \`child4DnaId\` varchar(40) NULL COMMENT 'dna ของตาราง orgChild4'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` DROP COLUMN \`child4DnaId\``); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` DROP COLUMN \`child3DnaId\``); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` DROP COLUMN \`child2DnaId\``); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` DROP COLUMN \`child1DnaId\``); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` DROP COLUMN \`rootDnaId\``); + await queryRunner.query(`ALTER TABLE \`posMasterEmployeeHistory\` DROP COLUMN \`profileEmployeeId\``); + } +} diff --git a/src/services/PositionService.ts b/src/services/PositionService.ts index b1837b99..29bb168a 100644 --- a/src/services/PositionService.ts +++ b/src/services/PositionService.ts @@ -230,6 +230,7 @@ export async function CreatePosMasterHistoryEmployee( : null; h.ancestorDNA = pm.ancestorDNA; if (!type || type != "DELETE") { + h.profileEmployeeId = pm.current_holder?.id || _null; h.prefix = pm.current_holder?.prefix || _null; h.firstName = pm.current_holder?.firstName || _null; h.lastName = pm.current_holder?.lastName || _null; @@ -237,6 +238,11 @@ export async function CreatePosMasterHistoryEmployee( 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;