From 21bef607a1f56613324c0d18221c52b9848a93cc Mon Sep 17 00:00:00 2001 From: mamoss <> Date: Fri, 9 Jan 2026 19:00:21 +0700 Subject: [PATCH 1/3] export report leave --- .../OrganizationDotnetController.ts | 346 ++++++++++++++++++ 1 file changed, 346 insertions(+) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index 706cb318..38db4e88 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -6219,4 +6219,350 @@ export class OrganizationDotnetController extends Controller { return new HttpSuccess(profile_); } + + /** + * รายชื่อขรก. ตามสิทธิ์ admin + * + * @summary รายชื่อขรก. ตามสิทธิ์ admin + * + */ + @Post("officer-by-admin-rolev3") + async GetOfficersByAdminRoleV3( + @Request() req: RequestWithUser, + @Body() + body: { + node: number; + nodeId: string; + role: string; + // isRetirement?: boolean; + // revisionId?: string; + reqNode?: number; + reqNodeId?: string; + startDate: Date; + endDate: Date; + }, + ) { + let typeCondition: any = {}; + if (body.role === "CHILD" || body.role === "PARENT" || body.role === "BROTHER") { + if (body.role === "CHILD") { + switch (body.node) { + case 0: + typeCondition = { + orgRoot: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 1: + typeCondition = { + orgChild1: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 2: + typeCondition = { + orgChild2: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 3: + typeCondition = { + orgChild3: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 4: + typeCondition = { + orgChild4: { + ancestorDNA: body.nodeId, + }, + }; + break; + default: + typeCondition = {}; + break; + } + } else if (body.role === "BROTHER") { + switch (body.node) { + case 0: + typeCondition = { + orgRoot: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 1: + typeCondition = { + orgRoot: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 2: + typeCondition = { + orgChild1: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 3: + typeCondition = { + orgChild2: { + ancestorDNA: body.nodeId, + }, + }; + break; + case 4: + typeCondition = { + orgChild3: { + ancestorDNA: body.nodeId, + }, + }; + break; + default: + typeCondition = {}; + break; + } + } else if (body.role === "PARENT") { + typeCondition = { + orgRoot: { + ancestorDNA: body.nodeId, + }, + orgChild1: Not(IsNull()), + }; + } + } else if (body.role === "OWNER" || body.role === "ROOT") { + switch (body.reqNode) { + case 0: + typeCondition = { + orgRoot: { + id: body.reqNodeId, + }, + }; + break; + case 1: + typeCondition = { + orgChild1: { + id: body.reqNodeId, + }, + }; + break; + case 2: + typeCondition = { + orgChild2: { + id: body.reqNodeId, + }, + }; + break; + case 3: + typeCondition = { + orgChild3: { + id: body.reqNodeId, + }, + }; + break; + case 4: + typeCondition = { + orgChild4: { + id: body.reqNodeId, + }, + }; + break; + default: + typeCondition = {}; + break; + } + } else if (body.role === "NORMAL") { + switch (body.node) { + case 0: + typeCondition = { + orgRoot: { + ancestorDNA: body.nodeId, + }, + orgChild1: IsNull(), + }; + break; + case 1: + typeCondition = { + orgChild1: { + ancestorDNA: body.nodeId, + }, + orgChild2: IsNull(), + }; + break; + case 2: + typeCondition = { + orgChild2: { + ancestorDNA: body.nodeId, + }, + orgChild3: IsNull(), + }; + break; + case 3: + typeCondition = { + orgChild3: { + ancestorDNA: body.nodeId, + }, + orgChild4: IsNull(), + }; + break; + case 4: + typeCondition = { + orgChild4: { + ancestorDNA: body.nodeId, + }, + }; + break; + default: + typeCondition = {}; + break; + } + } + + let profile = await this.profileRepo.find({ + where: { isLeave: false, isRetirement: false, current_holders: typeCondition }, + relations: [ + "posType", + "posLevel", + "current_holders", + "current_holders.orgRoot", + "current_holders.orgChild1", + "current_holders.orgChild2", + "current_holders.orgChild3", + "current_holders.orgChild4", + ], + order: { + current_holders: { + orgRoot: { + orgRootOrder: "ASC", + }, + orgChild1: { + orgChild1Order: "ASC", + }, + orgChild2: { + orgChild2Order: "ASC", + }, + orgChild3: { + orgChild3Order: "ASC", + }, + orgChild4: { + orgChild4Order: "ASC", + }, + posMasterNo: "ASC", + }, + }, + }); + // if (body.isRetirement) { + // profile = await this.profileRepo.find({ + // where: { + // isLeave: false, + // current_holders: typeCondition, + // isRetirement: true, + // }, + // relations: [ + // "posType", + // "posLevel", + // "current_holders", + // "current_holders.orgRoot", + // "current_holders.orgChild1", + // "current_holders.orgChild2", + // "current_holders.orgChild3", + // "current_holders.orgChild4", + // ], + // }); + // } + // Filter only by date part, not time + const startDateOnly = new Date( + body.startDate.getFullYear(), + body.startDate.getMonth(), + body.startDate.getDate(), + ); + const endDateOnly = new Date( + body.endDate.getFullYear(), + body.endDate.getMonth(), + body.endDate.getDate(), + ); + let findRevision = await this.orgRevisionRepo.findOne({ + where: { + orgPublishDate: Between(startDateOnly, endDateOnly), + }, + }); + + const profile_ = await Promise.all( + profile.map(async (item: Profile) => { + const shortName = + item.current_holders.length == 0 + ? null + : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && + item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 != + null + ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` + : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && + item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) + ?.orgChild3 != null + ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` + : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && + item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) + ?.orgChild2 != null + ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` + : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && + item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) + ?.orgChild1 != null + ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` + : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != + null && + item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) + ?.orgRoot != null + ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` + : null; + const Oc = + item.current_holders.length == 0 + ? null + : item.current_holders[0].orgChild4 != null + ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}` + : item.current_holders[0].orgChild3 != null + ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}` + : item.current_holders[0].orgChild2 != null + ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}` + : item.current_holders[0].orgChild1 != null + ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}` + : item.current_holders[0].orgRoot != null + ? `${item.current_holders[0].orgRoot.orgRootName}` + : null; + + let _posMaster = await this.posMasterRepository.findOne({ + where: { + orgRevisionId: findRevision?.id, + current_holderId: item.id, + }, + }); + + return { + id: item.id, + prefix: item.prefix, + firstName: item.firstName, + lastName: item.lastName, + citizenId: item.citizenId, + dateStart: item.dateStart, + dateAppoint: item.dateAppoint, + keycloak: item.keycloak, + posNo: shortName, + position: item.position, + positionLevel: item.posLevel?.posLevelName ?? null, + positionType: item.posType?.posTypeName ?? null, + oc: Oc, + orgRootId: _posMaster?.orgRootId, + orgChild1Id: _posMaster?.orgChild1Id, + orgChild2Id: _posMaster?.orgChild2Id, + orgChild3Id: _posMaster?.orgChild3Id, + orgChild4Id: _posMaster?.orgChild4Id, + }; + }), + ); + + return new HttpSuccess(profile_); + } } From b1105751361cd79359f4d9c2d109f4c4e18cb029 Mon Sep 17 00:00:00 2001 From: mamoss <> Date: Sun, 11 Jan 2026 15:17:14 +0700 Subject: [PATCH 2/3] report leave --- src/controllers/OrganizationDotnetController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index 38db4e88..22b9952d 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -6174,7 +6174,7 @@ export class OrganizationDotnetController extends Controller { // group by ancestorDNA แล้วเลือก create_at ล่าสุด const grouped = new Map(); for (const item of profile) { - const key = `${item.ancestorDNA}`; + const key = `${item.shortName}-${item.posMasterNo}`; if (!grouped.has(key)) { grouped.set(key, item); } else { From e040409fa5c3d61ea21383e186130da6511287f1 Mon Sep 17 00:00:00 2001 From: mamoss <> Date: Sun, 11 Jan 2026 16:33:20 +0700 Subject: [PATCH 3/3] report group posno and dna --- .../OrganizationDotnetController.ts | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index 22b9952d..a1323d86 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -6565,4 +6565,242 @@ export class OrganizationDotnetController extends Controller { return new HttpSuccess(profile_); } + + /** + * รายชื่อขรก. ตามสิทธิ์ admin + * + * @summary รายชื่อขรก. ตามสิทธิ์ admin + * + */ + @Post("officer-by-admin-rolev4") + async GetOfficersByAdminRoleV4( + @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); + + let profile = await this.posMasterHistoryRepository.find({ + where: { + ...typeCondition, + createdAt: LessThanOrEqual(date), + // firstName: Not("") && Not(IsNull()), + // lastName: Not("") && Not(IsNull()), + }, + order: { + firstName: "ASC", + lastName: "ASC", + createdAt: "DESC", // ให้ createdAt ล่าสุดอยู่ข้างบน + }, + }); + + // group1: group by ancestorDNA แล้วเลือก create_at ล่าสุด + const grouped1 = new Map(); + for (const item of profile) { + const key = `${item.ancestorDNA}`; + if (!grouped1.has(key)) { + grouped1.set(key, item); + } else { + // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด + const exist = grouped1.get(key); + if (exist && item.createdAt > exist.createdAt) { + grouped1.set(key, item); + } + } + } + // group2: group by shortName-posMasterNo จากค่าที่ได้จาก group1 + const grouped2 = new Map(); + for (const item of Array.from(grouped1.values())) { + const key = `${item.shortName}-${item.posMasterNo}`; + if (!grouped2.has(key)) { + grouped2.set(key, item); + } else { + // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด + const exist = grouped2.get(key); + if (exist && item.createdAt > exist.createdAt) { + grouped2.set(key, item); + } + } + } + + const profile_ = await Promise.all( + Array.from(grouped2.values()) + .filter((x) => x.profileId != null) + .map(async (item: PosMasterHistory) => { + let profile = await this.profileRepo.findOne({ + where: { id: item.profileId }, + }); + + 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 new HttpSuccess(profile_); + } }