From ae3a63459578220b120dc1da29574eb87aa2b26f Mon Sep 17 00:00:00 2001 From: harid Date: Wed, 21 Jan 2026 13:53:29 +0700 Subject: [PATCH 01/14] =?UTF-8?q?Task=20#2208=20=E0=B8=81=E0=B8=A3?= =?UTF-8?q?=E0=B8=93=E0=B8=B5=E0=B8=82=E0=B8=AD=E0=B9=81=E0=B8=81=E0=B9=89?= =?UTF-8?q?=E0=B9=84=E0=B8=82=E0=B8=82=E0=B9=89=E0=B8=AD=E0=B8=A1=E0=B8=B9?= =?UTF-8?q?=E0=B8=A5=E0=B8=97=E0=B8=B0=E0=B9=80=E0=B8=9A=E0=B8=B5=E0=B8=A2?= =?UTF-8?q?=E0=B8=99=E0=B8=9B=E0=B8=A3=E0=B8=B0=E0=B8=A7=E0=B8=B1=E0=B8=95?= =?UTF-8?q?=E0=B8=B4=20=E0=B9=81=E0=B8=A5=E0=B8=B0=20IDP=20=E0=B9=81?= =?UTF-8?q?=E0=B8=A5=E0=B8=B0=E0=B8=84=E0=B8=99=E0=B8=82=E0=B8=AD=E0=B8=AD?= =?UTF-8?q?=E0=B8=A2=E0=B8=B9=E0=B9=88=E0=B9=83=E0=B8=99=E0=B8=AA=E0=B8=B3?= =?UTF-8?q?=E0=B8=99=E0=B8=B1=E0=B8=81=E0=B8=9B=E0=B8=A5=E0=B8=B1=E0=B8=94?= =?UTF-8?q?=E0=B8=81=E0=B8=A3=E0=B8=B8=E0=B8=87=E0=B9=80=E0=B8=97=E0=B8=9E?= =?UTF-8?q?=E0=B8=A1=E0=B8=AB=E0=B8=B2=E0=B8=99=E0=B8=84=E0=B8=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DevelopmentRequestController.ts | 27 ++++++++++++++++-- src/controllers/ProfileEditController.ts | 28 +++++++++++++++++-- src/controllers/WorkflowController.ts | 22 +++++++++++---- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/controllers/DevelopmentRequestController.ts b/src/controllers/DevelopmentRequestController.ts index 16288640..f02b3049 100644 --- a/src/controllers/DevelopmentRequestController.ts +++ b/src/controllers/DevelopmentRequestController.ts @@ -27,6 +27,7 @@ import { ProfileDevelopmentHistory } from "../entities/ProfileDevelopmentHistory import { setLogDataDiff } from "../interfaces/utils"; import CallAPI from "../interfaces/call-api"; import { OrgRevision } from "../entities/OrgRevision"; +import { OrgRoot } from "../entities/OrgRoot"; @Route("api/v1/org/profile/development-request") @Tags("DevelopmentRequest") @Security("bearerAuth") @@ -37,6 +38,7 @@ export class DevelopmentRequestController extends Controller { private developmentProjectRepository = AppDataSource.getRepository(DevelopmentProject); private developmentHistoryRepository = AppDataSource.getRepository(ProfileDevelopmentHistory); private orgRevisionRepository = AppDataSource.getRepository(OrgRevision); + private orgRootRepo = AppDataSource.getRepository(OrgRoot); @Get("user") public async getDevelopmentRequestUser( @@ -298,12 +300,32 @@ export class DevelopmentRequestController extends Controller { @Body() body: CreateDevelopmentRequest, ) { const profile = await this.profileRepository.findOne({ - where: { keycloak: req.user.sub }, - relations: ["posLevel", "posType"], + relations: { + posLevel: true, + posType: true, + current_holders: true + }, + where: { + keycloak: req.user.sub, + current_holders: { + orgRevision: { + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false + } + } + } }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } + const orgRoot = await this.orgRootRepo.findOne({ + select: { + isDeputy: true + }, + where: { + id: profile.current_holders.find(x => x.orgRootId)!.orgRootId ?? "" + } + }) const before = null; const data = new DevelopmentRequest(); @@ -346,6 +368,7 @@ export class DevelopmentRequestController extends Controller { posLevelName: profile.posLevel.posLevelName, posTypeName: profile.posType.posTypeName, fullName: `${profile.prefix}${profile.firstName} ${profile.lastName}`, + isDeputy: orgRoot?.isDeputy ?? false }) .catch((error) => { console.error("Error calling API:", error); diff --git a/src/controllers/ProfileEditController.ts b/src/controllers/ProfileEditController.ts index 4c4fc6b8..013a2e9d 100644 --- a/src/controllers/ProfileEditController.ts +++ b/src/controllers/ProfileEditController.ts @@ -23,7 +23,7 @@ import { Brackets } from "typeorm"; import CallAPI from "../interfaces/call-api"; import permission from "../interfaces/permission"; import { OrgRevision } from "../entities/OrgRevision"; - +import { OrgRoot } from "../entities/OrgRoot"; @Route("api/v1/org/profile/edit") @Tags("ProfileEdit") @Security("bearerAuth") @@ -31,6 +31,7 @@ export class ProfileEditController extends Controller { private profileRepo = AppDataSource.getRepository(Profile); private profileEditRepo = AppDataSource.getRepository(ProfileEdit); private orgRevisionRepository = AppDataSource.getRepository(OrgRevision); + private orgRootRepo = AppDataSource.getRepository(OrgRoot); @Get("user") public async detailProfileEditUser( @@ -294,12 +295,32 @@ export class ProfileEditController extends Controller { @Post() public async newProfileEdit(@Request() req: RequestWithUser, @Body() body: CreateProfileEdit) { const profile = await this.profileRepo.findOne({ - where: { keycloak: req.user.sub }, - relations: ["posLevel", "posType"], + relations: { + posLevel: true, + posType: true, + current_holders: true + }, + where: { + keycloak: req.user.sub, + current_holders: { + orgRevision: { + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false + } + } + } }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } + const orgRoot = await this.orgRootRepo.findOne({ + select: { + isDeputy: true + }, + where: { + id: profile.current_holders.find(x => x.orgRootId)!.orgRootId ?? "" + } + }) const data = new ProfileEdit(); const meta = { @@ -322,6 +343,7 @@ export class ProfileEditController extends Controller { posLevelName: profile.posLevel.posLevelName, posTypeName: profile.posType.posTypeName, fullName: `${profile.prefix}${profile.firstName} ${profile.lastName}`, + isDeputy: orgRoot?.isDeputy ?? false }) .catch((error) => { console.error("Error calling API:", error); diff --git a/src/controllers/WorkflowController.ts b/src/controllers/WorkflowController.ts index 12688f80..f02aaf4b 100644 --- a/src/controllers/WorkflowController.ts +++ b/src/controllers/WorkflowController.ts @@ -145,12 +145,22 @@ export class WorkflowController extends Controller { metaStates.find((metaState) => metaState.id === metaStateOp.metaStateId)?.order === state.order, ); - // Task #2207 กรณีคนขอโอนอยู่ในสำนักปลัดกรุงเทพมหานคร - if (body.isDeputy && metaStateOp.operator == "PersonnelOfficer" && correspondingState?.order == 1) { - return; - } - else if (body.isDeputy && metaStateOp.operator == "Officer" && [1, 2].includes(correspondingState?.order as number)) { - metaStateOp.operator = "PersonnelOfficer" + if (body.isDeputy) { + // Task #2207 กรณีคนขอโอนอยู่ในสำนักปลัดกรุงเทพมหานคร + if (body.sysName == "SYS_TRANSFER_REQ") { + if (metaStateOp.operator == "PersonnelOfficer" && correspondingState?.order == 1) { + return; + } + else if (metaStateOp.operator == "Officer" && [1, 2].includes(correspondingState?.order as number)) { + metaStateOp.operator = "PersonnelOfficer" + } + } + // Task #2208 กรณีขอแก้ไขข้อมูลทะเบียนประวัติ และ IDP และคนขออยู่ในสำนักปลัดกรุงเทพมหานคร + if (metaStateOp.operator == "Officer" && + (["REGISTRY_PROFILE", "REGISTRY_PROFILE_EMP", "REGISTRY_IDP"].includes(body.sysName)) + ) { + metaStateOp.operator = "PersonnelOfficer" + } } if (correspondingState) { const stateOperator = new StateOperator(); From 0203a9105f622bcf5b51f72ea646f9b547216917 Mon Sep 17 00:00:00 2001 From: harid Date: Wed, 21 Jan 2026 16:09:03 +0700 Subject: [PATCH 02/14] =?UTF-8?q?fix=20=E0=B8=81=E0=B8=88.=20=E0=B9=84?= =?UTF-8?q?=E0=B8=A1=E0=B9=88=E0=B9=80=E0=B8=AB=E0=B9=87=E0=B8=99=E0=B8=A3?= =?UTF-8?q?=E0=B8=B2=E0=B8=A2=E0=B8=8A=E0=B8=B7=E0=B9=88=E0=B8=AD=E0=B8=9C?= =?UTF-8?q?=E0=B8=B9=E0=B9=89=E0=B8=AA=E0=B8=AD=E0=B8=9A=E0=B8=9C=E0=B9=88?= =?UTF-8?q?=E0=B8=B2=E0=B8=99=E0=B8=AB=E0=B8=A5=E0=B8=B1=E0=B8=87=E0=B8=88?= =?UTF-8?q?=E0=B8=B2=E0=B8=81=E0=B9=80=E0=B8=9C=E0=B8=A2=E0=B9=81=E0=B8=9E?= =?UTF-8?q?=E0=B8=A3=E0=B9=88=E0=B9=82=E0=B8=84=E0=B8=A3=E0=B8=87=E0=B8=AA?= =?UTF-8?q?=E0=B8=A3=E0=B9=89=E0=B8=B2=E0=B8=87=20Task=20#2219?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/ProfileController.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controllers/ProfileController.ts b/src/controllers/ProfileController.ts index e084d6ed..18a74e5c 100644 --- a/src/controllers/ProfileController.ts +++ b/src/controllers/ProfileController.ts @@ -7658,7 +7658,7 @@ export class ProfileController extends Controller { }, orgRevisionId: revisionId, }, - relations: ["orgChild1"], + relations: ["orgRoot", "orgChild1"], }); if (posMasters == null) { return new HttpSuccess({ @@ -7668,6 +7668,7 @@ export class ProfileController extends Controller { child2Id: null, child3Id: null, child4Id: null, + rootDnaId: null }); } return new HttpSuccess({ @@ -7677,6 +7678,7 @@ export class ProfileController extends Controller { child2Id: posMasters?.orgChild2Id || null, child3Id: posMasters?.orgChild3Id || null, child4Id: posMasters?.orgChild4Id || null, + rootDnaId: posMasters?.orgRoot?.ancestorDNA || null }); } From 38e2ec6586162eb4ca4e973b70aad84bf1cd2ad0 Mon Sep 17 00:00:00 2001 From: harid Date: Thu, 22 Jan 2026 11:15:09 +0700 Subject: [PATCH 03/14] =?UTF-8?q?api=20getKeycloak=20=E0=B8=97=E0=B8=B3?= =?UTF-8?q?=E0=B9=84=E0=B8=A7=E0=B9=89=E0=B9=83=E0=B8=8A=E0=B9=89=E0=B8=AA?= =?UTF-8?q?=E0=B8=B3=E0=B8=AB=E0=B8=A3=E0=B8=B1=E0=B8=9A=E0=B8=A3=E0=B8=B0?= =?UTF-8?q?=E0=B8=9A=E0=B8=9A=E0=B8=A5=E0=B8=87=E0=B9=80=E0=B8=A7=E0=B8=A5?= =?UTF-8?q?=E0=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OrganizationDotnetController.ts | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index c5da0819..688a593c 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -1639,6 +1639,241 @@ export class OrganizationDotnetController extends Controller { return new HttpSuccess(mapProfile); } + + @Get("by-keycloak/{keycloakId}") + async NewGetProfileByKeycloakIdAsync(@Path() keycloakId: string) { + /* ========================= + * 1. Load profile + * ========================= */ + const profile = await this.profileRepo.findOne({ + where: { keycloak: keycloakId }, + relations: { + posLevel: true, + posType: true, + current_holders: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, + }, + }); + + // Employee + if (!profile) { + const profile = await this.profileEmpRepo.findOne({ + where: { keycloak: keycloakId }, + relations: { + posLevel: true, + posType: true, + current_holders: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, + }, + }); + if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); + const currentHolder = profile.current_holders?.find( + x => + x.orgRevision?.orgRevisionIsDraft === false && + x.orgRevision?.orgRevisionIsCurrent === true, + ); + + let oc = ""; + if (currentHolder) { + if (!currentHolder.orgChild1Id) { + oc = currentHolder.orgRoot?.orgRootName; + } else if (!currentHolder.orgChild2Id) { + oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild3Id) { + oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild4Id) { + oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else { + oc = currentHolder.orgChild4?.orgChild4Name; + } + } + + const mapProfile = { + profileType: "EMPLOYEE", + id: profile.id, + keycloak: profile.keycloak, + prefix: profile.prefix, + firstName: profile.firstName, + lastName: profile.lastName, + citizenId: profile.citizenId, + position: profile.position, + email: profile.email, + phone: profile.phone, + isProbation: profile.isProbation, + isLeave: profile.isLeave, + dateRetire: profile.dateRetire, + dateAppoint: profile.dateAppoint, + dateRetireLaw: profile.dateRetireLaw, + dateStart: profile.dateStart, + govAgeAbsent: profile.govAgeAbsent, + govAgePlus: profile.govAgePlus, + birthDate: profile.birthDate ?? new Date(), + reasonSameDate: profile.reasonSameDate, + telephoneNumber: profile.phone, + nationality: profile.nationality, + gender: profile.gender, + relationship: profile.relationship, + religion: profile.religion, + bloodGroup: profile.bloodGroup, + dutyTimeId: profile.dutyTimeId, + dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate, + amount: profile.amount, + positionSalaryAmount: profile.positionSalaryAmount, + mouthSalaryAmount: profile.mouthSalaryAmount, + + posType: profile.posType?.posTypeName ?? null, + posLevel: profile.posType?.posTypeShortName == null && profile.posLevel?.posLevelName == null + ? null + : `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`, + oc, + + root: currentHolder?.orgRoot?.orgRootName ?? null, + rootId: currentHolder?.orgRootId ?? null, + rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null, + child1: currentHolder?.orgChild1?.orgChild1Name ?? null, + child1Id: currentHolder?.orgChild1Id ?? null, + child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null, + child2: currentHolder?.orgChild2?.orgChild2Name ?? null, + child2Id: currentHolder?.orgChild2Id ?? null, + child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null, + child3: currentHolder?.orgChild3?.orgChild3Name ?? null, + child3Id: currentHolder?.orgChild3Id ?? null, + child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null, + child4: currentHolder?.orgChild4?.orgChild4Name ?? null, + child4Id: currentHolder?.orgChild4Id ?? null, + child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null, + }; + + return new HttpSuccess(mapProfile); + } + + /* ========================================= + * 2. current holder + * ========================================= */ + const currentHolder = profile.current_holders?.find( + x => + x.orgRevision?.orgRevisionIsDraft === false && + x.orgRevision?.orgRevisionIsCurrent === true, + ); + + /* ========================================= + * 5. position executive + * ========================================= */ + const position = await this.positionRepository.findOne({ + where: { + positionIsSelected: true, + posMaster: { + orgRevisionId: currentHolder?.orgRevisionId, + current_holderId: profile.id, + }, + }, + order: { createdAt: "DESC" }, + relations: { posExecutive: true }, + }); + + /* ========================================= + * 6. OC name + * ========================================= */ + let oc = ""; + if (currentHolder) { + if (!currentHolder.orgChild1Id) { + oc = currentHolder.orgRoot?.orgRootName; + } else if (!currentHolder.orgChild2Id) { + oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild3Id) { + oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild4Id) { + oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else { + oc = currentHolder.orgChild4?.orgChild4Name; + } + } + + /* ========================================= + * 7. position level name + * ========================================= */ + const positionLeaveName = + profile.posType && + profile.posLevel && + (profile.posType.posTypeName === "บริหาร" || + profile.posType.posTypeName === "อำนวยการ") + ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}` + : profile.posLevel?.posLevelName ?? null; + + /* ========================================= + * 8. map response + * ========================================= */ + const mapProfile = { + profileType: "OFFICER", + id: profile.id, + keycloak: profile.keycloak, + prefix: profile.prefix, + firstName: profile.firstName, + lastName: profile.lastName, + citizenId: profile.citizenId, + position: profile.position, + email: profile.email, + phone: profile.phone, + isProbation: profile.isProbation, + isLeave: profile.isLeave, + dateRetire: profile.dateRetire, + dateAppoint: profile.dateAppoint, + dateRetireLaw: profile.dateRetireLaw, + dateStart: profile.dateStart, + govAgeAbsent: profile.govAgeAbsent, + govAgePlus: profile.govAgePlus, + birthDate: profile.birthDate ?? new Date(), + reasonSameDate: profile.reasonSameDate, + telephoneNumber: profile.phone, + nationality: profile.nationality, + gender: profile.gender, + relationship: profile.relationship, + religion: profile.religion, + bloodGroup: profile.bloodGroup, + dutyTimeId: profile.dutyTimeId, + dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate, + amount: profile.amount, + positionSalaryAmount: profile.positionSalaryAmount, + mouthSalaryAmount: profile.mouthSalaryAmount, + + posLevel: profile.posLevel?.posLevelName ?? null, + posType: profile.posType?.posTypeName ?? null, + posExecutiveName: position?.posExecutive?.posExecutiveName ?? null, + positionLeaveName, + oc, + + root: currentHolder?.orgRoot?.orgRootName ?? null, + rootId: currentHolder?.orgRootId ?? null, + rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null, + child1: currentHolder?.orgChild1?.orgChild1Name ?? null, + child1Id: currentHolder?.orgChild1Id ?? null, + child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null, + child2: currentHolder?.orgChild2?.orgChild2Name ?? null, + child2Id: currentHolder?.orgChild2Id ?? null, + child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null, + child3: currentHolder?.orgChild3?.orgChild3Name ?? null, + child3Id: currentHolder?.orgChild3Id ?? null, + child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null, + child4: currentHolder?.orgChild4?.orgChild4Name ?? null, + child4Id: currentHolder?.orgChild4Id ?? null, + child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null, + }; + + return new HttpSuccess(mapProfile); + } + /** * 3. API Get Profile จาก profile id * From 78778e0eb03fdfade34577218259980fc4fb2103 Mon Sep 17 00:00:00 2001 From: harid Date: Fri, 23 Jan 2026 17:32:11 +0700 Subject: [PATCH 04/14] =?UTF-8?q?test=20=E0=B9=80=E0=B8=9E=E0=B8=B4?= =?UTF-8?q?=E0=B9=88=E0=B8=A1=E0=B8=9F=E0=B8=B1=E0=B8=87=E0=B8=81=E0=B9=8C?= =?UTF-8?q?=E0=B8=8A=E0=B8=B1=E0=B9=88=E0=B8=99=E0=B9=83=E0=B8=AB=E0=B9=89?= =?UTF-8?q?=E0=B8=A2=E0=B8=B4=E0=B8=87=E0=B9=84=E0=B8=9B=E0=B8=A3=E0=B8=B0?= =?UTF-8?q?=E0=B8=9A=E0=B8=9A=20exprofile=20#2190?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/CommandController.ts | 534 +++++++++++++----- src/controllers/ProfileController.ts | 39 +- src/controllers/ProfileEmployeeController.ts | 38 +- .../ProfileEmployeeTempController.ts | 36 ++ src/interfaces/utils.ts | 13 +- src/services/rabbitmq.ts | 2 +- 6 files changed, 510 insertions(+), 152 deletions(-) diff --git a/src/controllers/CommandController.ts b/src/controllers/CommandController.ts index a682932d..905c77ea 100644 --- a/src/controllers/CommandController.ts +++ b/src/controllers/CommandController.ts @@ -97,6 +97,7 @@ import { CreatePosMasterHistoryEmployeeTemp, CreatePosMasterHistoryOfficer, } from "../services/PositionService"; +import { PostRetireToExprofile } from "./ExRetirementController"; @Route("api/v1/org/command") @Tags("Command") @Security("bearerAuth") @@ -3798,7 +3799,12 @@ export class CommandController extends Controller { body.data.map(async (item) => { const profile = await this.profileRepository.findOne({ where: { id: item.profileId }, - relations: ["roleKeycloaks"], + // relations: ["roleKeycloaks"], + relations: { + roleKeycloaks: true, + posType: true , + posLevel: true + } }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้"); @@ -3866,14 +3872,30 @@ export class CommandController extends Controller { const curRevision = await this.orgRevisionRepo.findOne({ where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false }, }); - + let orgRootRef = null; + let orgChild1Ref = null; + let orgChild2Ref = null; + let orgChild3Ref = null; + let orgChild4Ref = null; if (curRevision) { const curPosMaster = await this.posMasterRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: curRevision.id, }, + relations:{ + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + } }); + orgRootRef = curPosMaster?.orgRoot ?? null; + orgChild1Ref = curPosMaster?.orgChild1 ?? null; + orgChild2Ref = curPosMaster?.orgChild2 ?? null; + orgChild3Ref = curPosMaster?.orgChild3 ?? null; + orgChild4Ref = curPosMaster?.orgChild4 ?? null; if (curPosMaster && clearProfile.LeaveType != "RETIRE_OUT_EMP") { await CreatePosMasterHistoryOfficer(curPosMaster.id, req, "DELETE"); } @@ -4045,6 +4067,44 @@ export class CommandController extends Controller { profile.isActive = true; } await this.profileRepository.save(profile); + // Task #2190 + if (code && ["C-PM-17", "C-PM-18"].includes(code)) { + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // item.commandDateAffect?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // profile.posLevel?.posLevelName ?? "", + // item.commandDateAffect ?? new Date(), + // organizeName, + // clearProfile.retireTypeName ?? "", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); + } }), ); @@ -4138,7 +4198,12 @@ export class CommandController extends Controller { body.data.map(async (item) => { const profile = await this.profileEmployeeRepository.findOne({ where: { id: item.profileId }, - relations: ["roleKeycloaks"], + // relations: ["roleKeycloaks"], + relations: { + roleKeycloaks: true, + posType: true , + posLevel: true + } }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); @@ -4204,6 +4269,35 @@ export class CommandController extends Controller { await removeProfileInOrganize(profile.id, "EMPLOYEE"); } const clearProfile = await checkCommandType(String(item.commandId)); + const curRevision = await this.orgRevisionRepo.findOne({ + where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false }, + }); + let orgRootRef = null; + let orgChild1Ref = null; + let orgChild2Ref = null; + let orgChild3Ref = null; + let orgChild4Ref = null; + if (curRevision) { + const curPosMaster = await this.employeePosMasterRepository.findOne({ + where: { + current_holderId: profile.id, + orgRevisionId: curRevision.id, + }, + relations:{ + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + } + }); + orgRootRef = curPosMaster?.orgRoot ?? null; + orgChild1Ref = curPosMaster?.orgChild1 ?? null; + orgChild2Ref = curPosMaster?.orgChild2 ?? null; + orgChild3Ref = curPosMaster?.orgChild3 ?? null; + orgChild4Ref = curPosMaster?.orgChild4 ?? null; + } + if (clearProfile.status) { if (profile.keycloak != null) { const delUserKeycloak = await deleteUser(profile.keycloak); @@ -4224,6 +4318,44 @@ export class CommandController extends Controller { // profile.posLevelId = _null; } await this.profileEmployeeRepository.save(profile); + // Task #2190 + if (code && ["C-PM-23", "C-PM-43"].includes(code)) { + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // item.commandDateAffect?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`, + // item.commandDateAffect ?? new Date(), + // organizeName, + // clearProfile.retireTypeName ?? "", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); + } }), ); @@ -4320,7 +4452,12 @@ export class CommandController extends Controller { body.data.map(async (item) => { const profile: any = await this.profileRepository.findOne({ where: { id: item.profileId }, - relations: ["roleKeycloaks"], + // relations: ["roleKeycloaks"], + relations: { + roleKeycloaks: true, + posType: true, + posLevel: true + } }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้"); @@ -4333,10 +4470,22 @@ export class CommandController extends Controller { orgRevisionIsDraft: false, }, }, - relations: ["orgRevision"], + relations: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, }); const orgRevisionRef = posMaster ? posMaster.id : null; + const orgRootRef = orgRevisionRef?.orgRoot ?? null; + const orgChild1Ref = orgRevisionRef?.orgChild1 ?? null; + const orgChild2Ref = orgRevisionRef?.orgChild2 ?? null; + const orgChild3Ref = orgRevisionRef?.orgChild3 ?? null; + const orgChild4Ref = orgRevisionRef?.orgChild4 ?? null; //ลบตำแหน่งที่รักษาการแทน const code = _command?.commandType?.code; @@ -4405,15 +4554,14 @@ export class CommandController extends Controller { history.profileSalaryId = data.id; await this.salaryHistoryRepo.save(history, { data: req }); - if (item.commandId) { + if (_command) { + /* const command = await this.commandRepository.findOne({ where: { id: item.commandId }, relations: ["commandType"], }); - if ( - command != null && - (command.commandType.code == "C-PM-15" || command.commandType.code == "C-PM-16") - ) { + */ + if (["C-PM-15", "C-PM-16"].includes(_command.commandType.code)) { // ประวัติคำสั่งให้ช่วยราชการ const dataAssis = new ProfileAssistance(); @@ -4433,7 +4581,7 @@ export class CommandController extends Controller { lastUpdateFullName: req.user.name, createdAt: new Date(), lastUpdatedAt: new Date(), - status: command.commandType.code == "C-PM-15" ? "PENDING" : "DONE", + status: _command.commandType.code == "C-PM-15" ? "PENDING" : "DONE", }; Object.assign(dataAssis, metaAssis); @@ -4444,6 +4592,44 @@ export class CommandController extends Controller { historyAssis.profileAssistanceId = dataAssis.id; await this.assistanceHistoryRepository.save(historyAssis); } + // Task #2190 + else if (_command.commandType.code == "C-PM-13") { + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // item.commandDateAffect?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // profile.posLevel?.posLevelName ?? "", + // item.commandDateAffect ?? new Date(), + // organizeName, + // clearProfile.retireTypeName ?? "", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); + } } }), ); @@ -4656,10 +4842,25 @@ export class CommandController extends Controller { if (item.commandYear) { _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543; } + const orgRevision = await this.orgRevisionRepo.findOne({ + where: { + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false, + }, + }); + let orgRootRef = null; + let orgChild1Ref = null; + let orgChild2Ref = null; + let orgChild3Ref = null; + let orgChild4Ref = null; + let profile; + let isEmployee:boolean = false; + let retireTypeName:string = ""; + // ขรก. if (item.profileType && item.profileType.trim().toUpperCase() == "OFFICER") { - const profile = await this.profileRepository.findOne({ + profile = await this.profileRepository.findOne({ relations: [ - "profileSalary", + // "profileSalary", "posLevel", "posType", "current_holders", @@ -4673,63 +4874,35 @@ export class CommandController extends Controller { "roleKeycloaks", ], where: { id: item.profileId }, - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้"); } - + const lastSalary = await this.salaryRepo.findOne({ + where: { profileId: item.profileId }, + select: ["order"], + order: { order: "DESC" }, + }); + const nextOrder = lastSalary ? lastSalary.order + 1 : 1; //ลบตำแหน่งที่รักษาการแทน const code = _command?.commandType?.code; if (code && ["C-PM-19", "C-PM-20"].includes(code)) { removePostMasterAct(profile.id); } - const orgRevision = await this.orgRevisionRepo.findOne({ - where: { - orgRevisionIsCurrent: true, - orgRevisionIsDraft: false, - }, - }); const orgRevisionRef = profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null; - // const orgRootRef = orgRevisionRef?.orgRoot ?? null; - // const orgChild1Ref = orgRevisionRef?.orgChild1 ?? null; - // const orgChild2Ref = orgRevisionRef?.orgChild2 ?? null; - // const orgChild3Ref = orgRevisionRef?.orgChild3 ?? null; - // const orgChild4Ref = orgRevisionRef?.orgChild4 ?? null; - // const shortName = - // !profile.current_holders || profile.current_holders.length == 0 - // ? null - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild4 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4.orgChild4ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild3 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3.orgChild3ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != - // null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild2 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2.orgChild2ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != - // null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild1 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1.orgChild1ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != - // null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgRoot != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot.orgRootShortName}` - // : null; - // const posNo = `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`; + orgRootRef = orgRevisionRef?.orgRoot ?? null; + orgChild1Ref = orgRevisionRef?.orgChild1 ?? null; + orgChild2Ref = orgRevisionRef?.orgChild2 ?? null; + orgChild3Ref = orgRevisionRef?.orgChild3 ?? null; + orgChild4Ref = orgRevisionRef?.orgChild4 ?? null; + let position = profile.current_holders .filter((x) => x.orgRevisionId == orgRevision?.id)[0] @@ -4750,12 +4923,13 @@ export class CommandController extends Controller { positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null, amountSpecial: item.amountSpecial ? item.amountSpecial : null, mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null, - order: - profile.profileSalary.length >= 0 - ? profile.profileSalary.length > 0 - ? profile.profileSalary[0].order + 1 - : 1 - : null, + // order: + // profile.profileSalary.length >= 0 + // ? profile.profileSalary.length > 0 + // ? profile.profileSalary[0].order + 1 + // : 1 + // : null, + order: nextOrder, orgRoot: item.orgRoot, orgChild1: item.orgChild1, orgChild2: item.orgChild2, @@ -4845,6 +5019,7 @@ export class CommandController extends Controller { } const clearProfile = await checkCommandType(String(item.commandId)); if (clearProfile.status) { + retireTypeName = clearProfile.retireTypeName ?? ""; if (_profile.keycloak != null) { const delUserKeycloak = await deleteUser(_profile.keycloak); if (delUserKeycloak) { @@ -4865,10 +5040,13 @@ export class CommandController extends Controller { } await this.profileRepository.save(_profile); } - } else { - const profile = await this.profileEmployeeRepository.findOne({ + } + // ลูกจ้าง + else { + isEmployee = true; + profile = await this.profileEmployeeRepository.findOne({ relations: [ - "profileSalary", + // "profileSalary", "posLevel", "posType", "current_holders", @@ -4880,60 +5058,29 @@ export class CommandController extends Controller { "roleKeycloaks", ], where: { id: item.profileId }, - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้"); } - // const orgRevision = await this.orgRevisionRepo.findOne({ - // where: { - // orgRevisionIsCurrent: true, - // orgRevisionIsDraft: false, - // }, - // }); - // const orgRevisionRef = - // profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null; - // const orgRootRef = orgRevisionRef?.orgRoot ?? null; - // const orgChild1Ref = orgRevisionRef?.orgChild1 ?? null; - // const orgChild2Ref = orgRevisionRef?.orgChild2 ?? null; - // const orgChild3Ref = orgRevisionRef?.orgChild3 ?? null; - // const orgChild4Ref = orgRevisionRef?.orgChild4 ?? null; - // const shortName = - // !profile.current_holders || profile.current_holders.length == 0 - // ? null - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild4 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4.orgChild4ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild3 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3.orgChild3ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != - // null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild2 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2.orgChild2ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != - // null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgChild1 != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1.orgChild1ShortName}` - // : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != - // null && - // profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) - // ?.orgRoot != null - // ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot.orgRootShortName}` - // : null; - // const posNo = `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`; - // let position = - // profile.current_holders - // .filter((x) => x.orgRevisionId == orgRevision?.id)[0] - // ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null; + const lastSalary = await this.salaryRepo.findOne({ + where: { profileEmployeeId: item.profileId }, + select: ["order"], + order: { order: "DESC" }, + }); + const nextOrder = lastSalary ? lastSalary.order + 1 : 1; + const orgRevisionRef = + profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null; + orgRootRef = orgRevisionRef?.orgRoot ?? null; + orgChild1Ref = orgRevisionRef?.orgChild1 ?? null; + orgChild2Ref = orgRevisionRef?.orgChild2 ?? null; + orgChild3Ref = orgRevisionRef?.orgChild3 ?? null; + orgChild4Ref = orgRevisionRef?.orgChild4 ?? null; + // ประวัติตำแหน่ง const data = new ProfileSalary(); data.posNumCodeSit = _posNumCodeSit; @@ -4951,12 +5098,13 @@ export class CommandController extends Controller { amount: item.amount ? item.amount : null, positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null, mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null, - order: - profile.profileSalary.length >= 0 - ? profile.profileSalary.length > 0 - ? profile.profileSalary[0].order + 1 - : 1 - : null, + // order: + // profile.profileSalary.length >= 0 + // ? profile.profileSalary.length > 0 + // ? profile.profileSalary[0].order + 1 + // : 1 + // : null, + order: nextOrder, orgRoot: item.orgRoot, orgChild1: item.orgChild1, orgChild2: item.orgChild2, @@ -5048,6 +5196,7 @@ export class CommandController extends Controller { } const clearProfile = await checkCommandType(String(item.commandId)); if (clearProfile.status) { + retireTypeName = clearProfile.retireTypeName ?? ""; if (_profile.keycloak != null) { const delUserKeycloak = await deleteUser(_profile.keycloak); if (delUserKeycloak) { @@ -5069,6 +5218,47 @@ export class CommandController extends Controller { await this.profileEmployeeRepository.save(_profile); } } + // Task #2190 + if (_command && ["C-PM-19", "C-PM-20"].includes(_command.commandType.code)) { + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + let _posLevelName: string = !isEmployee + ? `${profile.posLevel?.posLevelName}` + : `${profile.posType?.posTypeName} ${profile.posLevel?.posLevelName}`; + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // item.commandDateAffect?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // _posLevelName, + // item.commandDateAffect ?? new Date(), + // organizeName, + // retireTypeName, + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); + } }), ); @@ -5158,7 +5348,7 @@ export class CommandController extends Controller { body.data.map(async (item) => { const profile = await this.profileEmployeeRepository.findOne({ relations: [ - "profileSalary", + // "profileSalary", "posLevel", "posType", "current_holders", @@ -5170,15 +5360,21 @@ export class CommandController extends Controller { "roleKeycloaks", ], where: { id: item.profileId }, - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้"); } + const lastSalary = await this.salaryRepo.findOne({ + where: { profileEmployeeId: item.profileId }, + select: ["order"], + order: { order: "DESC" }, + }); + const nextOrder = lastSalary ? lastSalary.order + 1 : 1; let _commandYear = item.commandYear; if (item.commandYear) { _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543; @@ -5244,12 +5440,13 @@ export class CommandController extends Controller { amountSpecial: item.amountSpecial ? item.amountSpecial : null, positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null, mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null, - order: - profile.profileSalary.length >= 0 - ? profile.profileSalary.length > 0 - ? profile.profileSalary[0].order + 1 - : 1 - : null, + // order: + // profile.profileSalary.length >= 0 + // ? profile.profileSalary.length > 0 + // ? profile.profileSalary[0].order + 1 + // : 1 + // : null, + order: nextOrder, orgRoot: item.orgRoot, orgChild1: item.orgChild1, orgChild2: item.orgChild2, @@ -5643,7 +5840,7 @@ export class CommandController extends Controller { body.data.map(async (item) => { const profile = await this.profileRepository.findOne({ relations: [ - "profileSalary", + // "profileSalary", "posType", "posLevel", "current_holders", @@ -5656,15 +5853,21 @@ export class CommandController extends Controller { "current_holders.positions.posExecutive", ], where: { id: item.profileId }, - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์"); } + const lastSalary = await this.salaryRepo.findOne({ + where: { profileId: item.profileId }, + select: ["order"], + order: { order: "DESC" }, + }); + const nextOrder = lastSalary ? lastSalary.order + 1 : 1; let _commandYear = item.commandYear; if (item.commandYear) { _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543; @@ -5740,12 +5943,13 @@ export class CommandController extends Controller { amountSpecial: item.amountSpecial ? item.amountSpecial : null, positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null, mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null, - order: - profile.profileSalary.length >= 0 - ? profile.profileSalary.length > 0 - ? profile.profileSalary[0].order + 1 - : 1 - : null, + // order: + // profile.profileSalary.length >= 0 + // ? profile.profileSalary.length > 0 + // ? profile.profileSalary[0].order + 1 + // : 1 + // : null, + order: nextOrder, orgRoot: orgRootRef?.orgRootName ?? null, orgChild1: orgChild1Ref?.orgChild1Name ?? null, orgChild2: orgChild2Ref?.orgChild2Name ?? null, @@ -5804,6 +6008,42 @@ export class CommandController extends Controller { Object.assign(history, { ...profileSalary, id: undefined }); history.profileSalaryId = profileSalary.id; await this.salaryHistoryRepo.save(history); + // Task #2190 + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // item.commandDateAffect?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // profile.posLevel?.posLevelName ?? "", + // item.commandDateAffect ?? new Date(), + // organizeName, + // clearProfile.retireTypeName ?? "", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); }), ); diff --git a/src/controllers/ProfileController.ts b/src/controllers/ProfileController.ts index 18a74e5c..15ae7694 100644 --- a/src/controllers/ProfileController.ts +++ b/src/controllers/ProfileController.ts @@ -89,7 +89,7 @@ import { CommandRecive } from "../entities/CommandRecive"; import { EmployeePosMaster } from "../entities/EmployeePosMaster"; import { CreatePosMasterHistoryOfficer, getTopDegrees } from "../services/PositionService"; import { ProfileLeaveService } from "../services/ProfileLeaveService"; - +import { PostRetireToExprofile } from "./ExRetirementController"; @Route("api/v1/org/profile") @Tags("Profile") @Security("bearerAuth") @@ -8194,7 +8194,7 @@ export class ProfileController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", "profileEducations", "profileActpositions", ], @@ -10858,6 +10858,41 @@ export class ProfileController extends Controller { } await removeProfileInOrganize(profile.id, "OFFICER"); } + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // requestBody.dateLeave?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // profile.posLevel?.posLevelName ?? "", + // requestBody.dateLeave ?? new Date(), + // organizeName, + // "ถึงแก่กรรม", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); return new HttpSuccess(); } diff --git a/src/controllers/ProfileEmployeeController.ts b/src/controllers/ProfileEmployeeController.ts index b37e115f..ed993152 100644 --- a/src/controllers/ProfileEmployeeController.ts +++ b/src/controllers/ProfileEmployeeController.ts @@ -82,6 +82,7 @@ import { ProfileChildren } from "../entities/ProfileChildren"; import { ProfileDuty } from "../entities/ProfileDuty"; import { getTopDegrees } from "../services/PositionService"; import { ProfileLeaveService } from "../services/ProfileLeaveService"; +import { PostRetireToExprofile } from "./ExRetirementController"; @Route("api/v1/org/profile-employee") @Tags("ProfileEmployee") @Security("bearerAuth") @@ -5333,6 +5334,41 @@ export class ProfileEmployeeController extends Controller { if (requestBody.isLeave == true) { await removeProfileInOrganize(profile.id, "EMPLOYEE"); } + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // requestBody.dateLeave?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`, + // requestBody.dateLeave ?? new Date(), + // organizeName, + // "ถึงแก่กรรม", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); return new HttpSuccess(); } @@ -5936,7 +5972,7 @@ export class ProfileEmployeeController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", "profileEducations", ], order: { diff --git a/src/controllers/ProfileEmployeeTempController.ts b/src/controllers/ProfileEmployeeTempController.ts index ce66c221..9fdfd581 100644 --- a/src/controllers/ProfileEmployeeTempController.ts +++ b/src/controllers/ProfileEmployeeTempController.ts @@ -70,6 +70,7 @@ import { deleteUser } from "../keycloak"; import { ProfileSalaryHistory } from "../entities/ProfileSalaryHistory"; import { getTopDegrees } from "../services/PositionService"; import HttpStatusCode from "../interfaces/http-status"; +import { PostRetireToExprofile } from "./ExRetirementController"; @Route("api/v1/org/profile-temp") @Tags("ProfileEmployee") @Security("bearerAuth") @@ -3547,6 +3548,41 @@ export class ProfileEmployeeTempController extends Controller { if (requestBody.isLeave == true) { await removeProfileInOrganize(profile.id, "EMPLOYEE"); } + let organizeName = ""; + if (orgRootRef) { + const names = [ + orgChild4Ref?.orgChild4Name, + orgChild3Ref?.orgChild3Name, + orgChild2Ref?.orgChild2Name, + orgChild1Ref?.orgChild1Name, + orgRootRef?.orgRootName, + ].filter(Boolean); + organizeName = names.join(" "); + } + await PostRetireToExprofile( + // profile.citizenId ?? "", + // profile.prefix ?? "", + // profile.firstName ?? "", + // profile.lastName ?? "", + // requestBody.dateLeave?.getFullYear().toString() ?? "", + // profile.position, + // profile.posType?.posTypeName ?? "", + // `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`, + // requestBody.dateLeave ?? new Date(), + // organizeName, + // "ถึงแก่กรรม", + "310190004095X", + "จ.ส.อ.", + "dev", + "hrms", + "2026", + "เจ้าหน้าที่จัดเก็บรายได้", + "อื่นๆ", + "C 3", + new Date(2026, 0, 1), + "สำนักงานเขตบางกอกใหญ่", + "เกษียณ" + ); return new HttpSuccess(); } diff --git a/src/interfaces/utils.ts b/src/interfaces/utils.ts index 12636a36..abe4bd4a 100644 --- a/src/interfaces/utils.ts +++ b/src/interfaces/utils.ts @@ -453,7 +453,7 @@ export async function checkCommandType(commandId: string) { ].includes(String(_type?.commandType.code)) ) { // return false; - return { status: false, LeaveType: null, leaveRemark: null }; + return { status: false, LeaveType: null, leaveRemark: null, retireTypeName: null }; } // return true; const _commandRecive = await commandReciveRepository.findOne({ @@ -461,47 +461,58 @@ export async function checkCommandType(commandId: string) { }); let _leaveType: string = ""; + let _retireTypeName: string = ""; //อิงตามเหตุผลการพ้นจากราชการ ข้อมูลทะเบียนประวัติผู้พ้นจากราชการ switch (String(_type?.commandType.code)) { case "C-PM-12": { _leaveType = "PROBATION_REPORT"; + _retireTypeName = "ผลการทดลองฯ ต่ำกว่ามาตรฐานที่กำหนด" break; } case "C-PM-13": { _leaveType = "PLACEMENT_TRANSFER"; + _retireTypeName = "โอนออก"; break; } case "C-PM-17": { _leaveType = "RETIRE_RESIGN"; + _retireTypeName = "ลาออกจากราชการ"; break; } case "C-PM-18": { _leaveType = "RETIRE_OUT"; + _retireTypeName = "ให้ออกจากราชการ"; break; } case "C-PM-19": { _leaveType = "DISCIPLINE_RESULT_REMOVE"; + _retireTypeName = "ปลดออกจากราชการ"; break; } case "C-PM-20": { _leaveType = "DISCIPLINE_RESULT_DISMISS"; + _retireTypeName = "ไล่ออกจากราชการ"; break; } case "C-PM-23": { _leaveType = "RETIRE_RESIGN_EMP"; + _retireTypeName = "ลาออกจากราชการ"; break; } case "C-PM-43": { _leaveType = "RETIRE_OUT_EMP"; + _retireTypeName = "ให้ออกจากราชการ"; break; } default: { _leaveType = ""; + _retireTypeName = ""; } } return { status: true, LeaveType: _leaveType, leaveRemark: _commandRecive ? _commandRecive.remarkVertical : null, + retireTypeName: _retireTypeName ? _retireTypeName : null }; } diff --git a/src/services/rabbitmq.ts b/src/services/rabbitmq.ts index aa02f882..326cb9a1 100644 --- a/src/services/rabbitmq.ts +++ b/src/services/rabbitmq.ts @@ -85,7 +85,7 @@ export async function init() { console.log("[AMQ] Listening for message..."); createConsumer(queue, channel, handler), //----> (3) Process Consumer - createConsumer(queue_org, channel, handler_org); + createConsumer(queue_org, channel, handler_org); createConsumer(queue_org_draft, channel, handler_org_draft); createConsumer(queue_command_noti, channel, handler_command_noti); // createConsumer(queue2, channel, handler2); From 6e6253887f4b3fabe1bc07ea7e344fc61add00d5 Mon Sep 17 00:00:00 2001 From: Adisak Date: Mon, 26 Jan 2026 14:14:58 +0700 Subject: [PATCH 05/14] #2231 --- src/controllers/UserController.ts | 46 +++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 5d7d4910..ecfef0ca 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -472,9 +472,9 @@ export class KeycloakController extends Controller { @Post("user/admin") async listUserKeycloak( - @Request() req: RequestWithUser, - @Body() - body:{ + @Request() req: RequestWithUser, + @Body() + body: { page: number, pageSize: number, keyword: string | null, @@ -507,9 +507,9 @@ export class KeycloakController extends Controller { let typeCondition = ""; let checkChildConditions = ""; - let conditions:any = {}; + let conditions: any = {}; - if(body.nodeId !== null && body.nodeId !== "" && body.nodeId !== undefined){ + if (body.nodeId !== null && body.nodeId !== "" && body.nodeId !== undefined) { if (body.node === 0) { typeCondition = `current_holders.orgRootId = '${body.nodeId}'`; if (!body.isAll) { @@ -533,9 +533,9 @@ export class KeycloakController extends Controller { } else if (body.node === 4) { typeCondition = `current_holders.orgChild4Id = '${body.nodeId}'`; } - + conditions = typeCondition; - if(checkChildConditions){ + if (checkChildConditions) { conditions += checkChildConditions; } } @@ -547,6 +547,11 @@ export class KeycloakController extends Controller { .createQueryBuilder("profile") .leftJoinAndSelect("profile.roleKeycloaks", "roleKeycloaks") .leftJoinAndSelect("profile.current_holders", "current_holders") + .leftJoinAndSelect("current_holders.orgRoot", "orgRoot") + .leftJoinAndSelect("current_holders.orgChild1", "orgChild1") + .leftJoinAndSelect("current_holders.orgChild2", "orgChild2") + .leftJoinAndSelect("current_holders.orgChild3", "orgChild3") + .leftJoinAndSelect("current_holders.orgChild4", "orgChild4") .where("profile.keycloak IS NOT NULL AND profile.keycloak != ''") .andWhere(checkChildFromRole) .andWhere(conditions) @@ -566,6 +571,13 @@ export class KeycloakController extends Controller { }), ) .orderBy("profile.citizenId", "ASC") + .orderBy("orgRoot.orgRootOrder", "ASC") + .addOrderBy("orgChild1.orgChild1Order", "ASC") + .addOrderBy("orgChild2.orgChild2Order", "ASC") + .addOrderBy("orgChild3.orgChild3Order", "ASC") + .addOrderBy("orgChild4.orgChild4Order", "ASC") + .addOrderBy("current_holders.posMasterOrder", "ASC") + .addOrderBy("current_holders.posMasterCreatedAt", "ASC") .skip((body.page - 1) * body.pageSize) .take(body.pageSize) .getManyAndCount(); @@ -574,6 +586,11 @@ export class KeycloakController extends Controller { .createQueryBuilder("profileEmployee") .leftJoinAndSelect("profileEmployee.roleKeycloaks", "roleKeycloaks") .leftJoinAndSelect("profileEmployee.current_holders", "current_holders") + .leftJoinAndSelect("current_holders.orgRoot", "orgRoot") + .leftJoinAndSelect("current_holders.orgChild1", "orgChild1") + .leftJoinAndSelect("current_holders.orgChild2", "orgChild2") + .leftJoinAndSelect("current_holders.orgChild3", "orgChild3") + .leftJoinAndSelect("current_holders.orgChild4", "orgChild4") .where("profileEmployee.keycloak IS NOT NULL AND profileEmployee.keycloak != ''") .andWhere(checkChildFromRole) .andWhere(conditions) @@ -598,6 +615,13 @@ export class KeycloakController extends Controller { }), ) .orderBy("profileEmployee.citizenId", "ASC") + .orderBy("orgRoot.orgRootOrder", "ASC") + .addOrderBy("orgChild1.orgChild1Order", "ASC") + .addOrderBy("orgChild2.orgChild2Order", "ASC") + .addOrderBy("orgChild3.orgChild3Order", "ASC") + .addOrderBy("orgChild4.orgChild4Order", "ASC") + .addOrderBy("current_holders.posMasterOrder", "ASC") + .addOrderBy("current_holders.posMasterCreatedAt", "ASC") .skip((body.page - 1) * body.pageSize) .take(body.pageSize) .getManyAndCount(); @@ -758,17 +782,17 @@ export class KeycloakController extends Controller { } @Get("user/role/{id}") - async getRoleUser(@Request() req: RequestWithUser,@Path("id") id: string) { - + async getRoleUser(@Request() req: RequestWithUser, @Path("id") id: string) { + const profile = await this.profileRepo.findOne({ where: { keycloak: id }, relations: ["roleKeycloaks"], }); - + if ( req.user.sub === id && req.user.role.some(x => x === 'ADMIN') && - !req.user.role.some(x => x === 'SUPER_ADMIN') + !req.user.role.some(x => x === 'SUPER_ADMIN') ) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่มีสิทธิ์เข้าถึงข้อมูลนี้"); } From 1ade81a0481562475693824854344a73ab134c94 Mon Sep 17 00:00:00 2001 From: harid Date: Mon, 26 Jan 2026 15:42:56 +0700 Subject: [PATCH 06/14] =?UTF-8?q?Fix=20=E0=B9=80=E0=B8=A5=E0=B8=82?= =?UTF-8?q?=E0=B8=97=E0=B8=B5=E0=B9=88=E0=B8=95=E0=B8=B3=E0=B9=81=E0=B8=AB?= =?UTF-8?q?=E0=B8=99=E0=B9=88=E0=B8=87=E0=B9=84=E0=B8=A1=E0=B9=88=E0=B9=81?= =?UTF-8?q?=E0=B8=AA=E0=B8=94=E0=B8=87=20#2230=20=20+=20Add=20api=20?= =?UTF-8?q?=E0=B8=AA=E0=B8=B3=E0=B8=AB=E0=B8=A3=E0=B8=B1=E0=B8=9A=E0=B9=83?= =?UTF-8?q?=E0=B8=9A=E0=B8=A5=E0=B8=B2=20#2233?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OrganizationDotnetController.ts | 306 +++++++++++++++++- 1 file changed, 305 insertions(+), 1 deletion(-) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index 688a593c..448bc6cb 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -39,6 +39,7 @@ import { PosMasterEmployeeHistory } from "../entities/PosMasterEmployeeHistory"; import { PosMasterAssign } from "../entities/PosMasterAssign"; import { Assign } from "../entities/Assign"; import { ProfileSalary } from "../entities/ProfileSalary"; +import { ProfileEducation } from "../entities/ProfileEducation"; @Route("api/v1/org/dotnet") @Tags("Dotnet") @Security("bearerAuth") @@ -67,6 +68,7 @@ export class OrganizationDotnetController extends Controller { private posMasterAssignRepo = AppDataSource.getRepository(PosMasterAssign); private assignRepository = AppDataSource.getRepository(Assign); private salaryRepo = AppDataSource.getRepository(ProfileSalary); + private educationRepo = AppDataSource.getRepository(ProfileEducation); /** * ทำไว้ให้ service อื่นๆ ภายในระบบ call มาตรวจสอบเลขบัตรประจำตัวประชาชน @@ -6788,6 +6790,308 @@ export class OrganizationDotnetController extends Controller { return new HttpSuccess(mapProfile); } + @Post("profile-leave/keycloak") + async GetProfileLeaveReportByKeycloakIdAsync( + @Body() body: { + keycloakId: string, + report?: string + } + ) { + const profile = await this.profileRepo.findOne({ + relations: { + currentProvince: true, + currentDistrict: true, + currentSubDistrict: true, + posLevel: true, + posType: true, + current_holders: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, + }, + where: { + keycloak: body.keycloakId, + }, + }); + + // ลูกจ้างประจำ + if (!profile) { + const profile = await this.profileEmpRepo.findOne({ + relations: { + currentProvince: true, + currentDistrict: true, + currentSubDistrict: true, + posLevel: true, + posType: true, + current_holders: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, + }, + where: { + keycloak: body.keycloakId, + } + }); + if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); + /* ========================================= + * current holder + * ========================================= */ + const currentHolder = profile.current_holders?.find( + x => + x.orgRevision?.orgRevisionIsDraft === false && + x.orgRevision?.orgRevisionIsCurrent === true, + ); + + let oc = ""; + if (currentHolder) { + if (!currentHolder.orgChild1Id) { + oc = currentHolder.orgRoot?.orgRootName; + } else if (!currentHolder.orgChild2Id) { + oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild3Id) { + oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild4Id) { + oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else { + oc = currentHolder.orgChild4?.orgChild4Name; + } + } + let _positions: any[] = []; + let _educations: any[] = []; + if (body.report && ["LEAVE16"].includes(body.report.trim().toUpperCase())) { + + const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today"); + let _currentDate = CURRENT_DATE[0].today; + if (profile && profile?.isLeave) { + _currentDate = + profile && profile.leaveDate ? Extension.toDateOnlyString(profile.leaveDate) : _currentDate; + } + const positions = await AppDataSource.query("CALL GetProfileEmployeeSalaryPosition(?, ?)", [ + profile!.id, + _currentDate, + ]); + _positions = positions[0].length > 0 + ? _positions.slice(0, -1).map((x: any, idx: number) => ({ + positionName: x.positionName, + dateStart: x.commandDateAffect ?? null, + dateEnd: _positions[idx + 1]?.commandDateAffect ?? null, + })) + : []; + + const profileEducations = await this.educationRepo.find({ + where: { profileEmployeeId: profile!.id }, + order: { level: "ASC" }, + }); + _educations = profileEducations.length > 0 + ? profileEducations.map((x) => ({ + educationLevel: x.educationLevel, + institute: x.institute ?? "-", + country: x.country ?? "-", + finishDate: x.finishDate, + })) + : []; + } + + const mapProfile = { + prefix: profile.prefix, + firstName: profile.firstName, + lastName: profile.lastName, + citizenId: profile.citizenId, + birthDate: profile.birthDate, + retireDate: profile.birthDate + ? calculateRetireLaw(profile.birthDate) + : null, + govAge: profile.dateAppoint + ? `${Extension.CalculateGovAge(profile.dateAppoint, 0, 0)} ปี` + : null, + age: profile.birthDate + ? Extension.CalculateAgeStrV2(profile.birthDate, 0, 0, "GET") + : null, + dateAppoint: profile.dateAppoint, + dateCurrent: new Date(), + amount: profile.amount, + telephoneNumber: profile.telephoneNumber, + currentAddress: + profile && profile.currentAddress + ? profile.currentAddress + + (profile.currentSubDistrict && profile.currentSubDistrict.name + ? " ตำบล/แขวง " + profile.currentSubDistrict.name + : "") + + (profile.currentDistrict && profile.currentDistrict.name + ? " อำเภอ/เขต " + profile.currentDistrict.name + : "") + + (profile.currentProvince && profile.currentProvince.name + ? " จังหวัด " + profile.currentProvince.name + " " + : "") + + profile.currentZipCode + : "-", + position: profile.position, + posType: profile.posType?.posTypeName, + posLevel: `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`, + positionLeaveName: null, + posExecutiveName: null, + + isCommission: currentHolder?.orgRoot?.isCommission ?? false, + root: currentHolder?.orgRoot?.orgRootName ?? null, + child1: currentHolder?.orgChild1?.orgChild1Name ?? null, + child2: currentHolder?.orgChild2?.orgChild2Name ?? null, + child3: currentHolder?.orgChild3?.orgChild3Name ?? null, + child4: currentHolder?.orgChild4?.orgChild4Name ?? null, + oc: oc, + + positions: _positions, + educations: _educations, + }; + return new HttpSuccess(mapProfile); + } + + /* ========================================= + * current holder + * ========================================= */ + const currentHolder = profile.current_holders?.find( + x => + x.orgRevision?.orgRevisionIsDraft === false && + x.orgRevision?.orgRevisionIsCurrent === true, + ); + + let oc = ""; + if (currentHolder) { + if (!currentHolder.orgChild1Id) { + oc = currentHolder.orgRoot?.orgRootName; + } else if (!currentHolder.orgChild2Id) { + oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild3Id) { + oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else if (!currentHolder.orgChild4Id) { + oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`; + } else { + oc = currentHolder.orgChild4?.orgChild4Name; + } + } + + /* ========================================= + * posType + posLevel + * ========================================= */ + const positionLeaveName = + profile.posType && + profile.posLevel && + (profile.posType.posTypeName === "บริหาร" || + profile.posType.posTypeName === "อำนวยการ") + ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}` + : profile.posLevel?.posLevelName ?? null; + + /* ========================================= + * position executive + * ========================================= */ + const _posExec = await this.positionRepository.findOne({ + where: { + positionIsSelected: true, + posMaster: { + orgRevisionId: currentHolder?.orgRevisionId, + current_holderId: profile.id, + }, + }, + order: { createdAt: "DESC" }, + relations: { posExecutive: true }, + }); + + let _positions: any[] = []; + let _educations: any[] = []; + if (body.report && ["LEAVE16"].includes(body.report.trim().toUpperCase())) { + + const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today"); + let _currentDate = CURRENT_DATE[0].today; + if (profile && profile?.isLeave) { + _currentDate = + profile && profile.leaveDate ? Extension.toDateOnlyString(profile.leaveDate) : _currentDate; + } + const positions = await AppDataSource.query("CALL GetProfileSalaryPosition(?, ?)", [ + profile!.id, + _currentDate, + ]); + _positions = positions[0].length > 0 + ? _positions.slice(0, -1).map((x: any, idx: number) => ({ + positionName: x.positionName, + dateStart: x.commandDateAffect ?? null, + dateEnd: _positions[idx + 1]?.commandDateAffect ?? null, + })) + : []; + + const profileEducations = await this.educationRepo.find({ + where: { profileId: profile!.id }, + order: { level: "ASC" }, + }); + _educations = profileEducations.length > 0 + ? profileEducations.map((x) => ({ + educationLevel: x.educationLevel, + institute: x.institute ?? "-", + country: x.country ?? "-", + finishDate: x.finishDate, + })) + : []; + } + + const mapProfile = { + prefix: profile.prefix, + firstName: profile.firstName, + lastName: profile.lastName, + citizenId: profile.citizenId, + birthDate: profile.birthDate, + retireDate: profile.birthDate + ? calculateRetireLaw(profile.birthDate) + : null, + govAge: profile.dateAppoint + ? `${Extension.CalculateGovAge(profile.dateAppoint, 0, 0)} ปี` + : null, + age: profile.birthDate + ? Extension.CalculateAgeStrV2(profile.birthDate, 0, 0, "GET") + : null, + dateAppoint: profile.dateAppoint, + dateCurrent: new Date(), + amount: profile.amount, + telephoneNumber: profile.telephoneNumber, + currentAddress: + profile && profile.currentAddress + ? profile.currentAddress + + (profile.currentSubDistrict && profile.currentSubDistrict.name + ? " ตำบล/แขวง " + profile.currentSubDistrict.name + : "") + + (profile.currentDistrict && profile.currentDistrict.name + ? " อำเภอ/เขต " + profile.currentDistrict.name + : "") + + (profile.currentProvince && profile.currentProvince.name + ? " จังหวัด " + profile.currentProvince.name + " " + : "") + + profile.currentZipCode + : "-", + position: profile.position ?? "-", + posLevel: profile.posLevel?.posLevelName ?? "-", + posType: profile.posType?.posTypeName ?? "-", + positionLeaveName, + posExecutiveName: _posExec?.posExecutive?.posExecutiveName ?? null, + + isCommission: currentHolder?.orgRoot?.isCommission ?? false, + root: currentHolder?.orgRoot?.orgRootName ?? null, + child1: currentHolder?.orgChild1?.orgChild1Name ?? null, + child2: currentHolder?.orgChild2?.orgChild2Name ?? null, + child3: currentHolder?.orgChild3?.orgChild3Name ?? null, + child4: currentHolder?.orgChild4?.orgChild4Name ?? null, + oc: oc, + + positions: _positions, + educations: _educations, + }; + return new HttpSuccess(mapProfile); + } + /** * API Get Profile ใช้อัพเดทสถานะ Mark ในระบบเครื่องราช * @@ -7723,7 +8027,7 @@ export class OrganizationDotnetController extends Controller { dateStart: profile?.dateStart ?? null, dateAppoint: profile?.dateAppoint ?? null, keycloak: profile?.keycloak ?? null, - posNo: item.shortName, + posNo: `${item.shortName} ${item.posMasterNo}`, position: item.position, positionLevel: item.posLevel, positionType: item.posType, From 64a7010d0a0f3dcb893e695755f1d9d6cebe5ff8 Mon Sep 17 00:00:00 2001 From: harid Date: Mon, 26 Jan 2026 17:07:00 +0700 Subject: [PATCH 07/14] Update #2233 --- src/controllers/OrganizationDotnetController.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index 448bc6cb..bcb35079 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -6866,7 +6866,7 @@ export class OrganizationDotnetController extends Controller { } let _positions: any[] = []; let _educations: any[] = []; - if (body.report && ["LEAVE16"].includes(body.report.trim().toUpperCase())) { + if (body.report && ["LEAVE16", "LEAVE18"].includes(body.report.trim().toUpperCase())) { const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today"); let _currentDate = CURRENT_DATE[0].today; @@ -6901,6 +6901,7 @@ export class OrganizationDotnetController extends Controller { } const mapProfile = { + profileType: "EMPLOYEE", prefix: profile.prefix, firstName: profile.firstName, lastName: profile.lastName, @@ -7005,7 +7006,7 @@ export class OrganizationDotnetController extends Controller { let _positions: any[] = []; let _educations: any[] = []; - if (body.report && ["LEAVE16"].includes(body.report.trim().toUpperCase())) { + if (body.report && ["LEAVE16", "LEAVE18"].includes(body.report.trim().toUpperCase())) { const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today"); let _currentDate = CURRENT_DATE[0].today; @@ -7040,6 +7041,7 @@ export class OrganizationDotnetController extends Controller { } const mapProfile = { + profileType: "OFFICER", prefix: profile.prefix, firstName: profile.firstName, lastName: profile.lastName, From 217ec1d7f6cbbe6b159a6739445c6b36dc86a760 Mon Sep 17 00:00:00 2001 From: harid Date: Tue, 27 Jan 2026 13:14:05 +0700 Subject: [PATCH 08/14] Fix Error Task #2248 --- src/controllers/ProfileController.ts | 95 ++++++++++++++------ src/controllers/ProfileEmployeeController.ts | 95 ++++++++++++++------ 2 files changed, 136 insertions(+), 54 deletions(-) diff --git a/src/controllers/ProfileController.ts b/src/controllers/ProfileController.ts index 15ae7694..cf74a0d0 100644 --- a/src/controllers/ProfileController.ts +++ b/src/controllers/ProfileController.ts @@ -1053,7 +1053,7 @@ export class ProfileController extends Controller { const cert_raw = await this.certificateRepository.find({ where: { profileId: id }, - select: ["certificateType", "issuer", "certificateNo", "issueDate"], + select: ["certificateType", "issuer", "certificateNo", "issueDate", "expireDate"], order: { createdAt: "ASC" }, }); const certs = @@ -1064,15 +1064,17 @@ export class ProfileController extends Controller { certificateNo: item.certificateNo ? Extension.ToThaiNumber(item.certificateNo) : null, issueDate: item.issueDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) - : null, + : "", expireDate: item.expireDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.expireDate)) - : null, + : "", issueToExpireDate: item.issueDate - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) - : "" + item.expireDate - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.expireDate)) - : null, + ? item.expireDate + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.issueDate)} - ${Extension.ToThaiFullDate2(item.expireDate)}`) + : Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) + : item.expireDate + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.expireDate)) + : "" })) : [ { @@ -1153,6 +1155,21 @@ export class ProfileController extends Controller { }, ]; const salary_raw = await this.salaryRepo.find({ + select: [ + "commandName", + "commandDateAffect", + "positionName", + "posNoAbb", + "posNo", + "amount", + "amountSpecial", + "positionLevel", + "positionCee", + "remark", + "positionType", + "positionSalaryAmount", + "order", + ], where: { profileId: id, commandCode: In(["5", "6"]), @@ -1218,6 +1235,17 @@ export class ProfileController extends Controller { ]; const insignia_raw = await this.profileInsigniaRepo.find({ + select: [ + "receiveDate", + "no", + "issue", + "volumeNo", + "volume", + "section", + "page", + "refCommandDate", + "note", + ], relations: { insignia: { insigniaType: true, @@ -1232,9 +1260,9 @@ export class ProfileController extends Controller { receiveDate: item.receiveDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.receiveDate)) : "", - insigniaName: item.insignia.name, - insigniaShortName: item.insignia.shortName, - insigniaTypeName: item.insignia.insigniaType.name, + insigniaName: item.insignia?.name ?? "", + insigniaShortName: item.insignia?.shortName ?? "", + insigniaTypeName: item.insignia?.insigniaType?.name ?? "", no: item.no ? Extension.ToThaiNumber(item.no) : "", issue: item.issue ? Extension.ToThaiNumber(item.issue) : "", volumeNo: item.volumeNo ? Extension.ToThaiNumber(item.volumeNo) : "", @@ -1293,7 +1321,9 @@ export class ProfileController extends Controller { const totalLeaveDaysKey = `totalLeaveDaysLv${lvIndex}`; const leaveTypeNameKey = `leaveTypeNameLv${lvIndex}`; - const leaveDate = new Date(item.maxDateLeaveStart); + const leaveDate = item.maxDateLeaveStart + ? new Date(item.maxDateLeaveStart) + : null; const year = leaveDate ? Extension.ToThaiNumber(Extension.ToThaiShortYear(leaveDate)) : ""; @@ -1487,11 +1517,14 @@ export class ProfileController extends Controller { const _actposition = actposition_raw.length > 0 ? actposition_raw.map((item) => ({ - date: item.dateStart - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) - : "" + item.dateEnd - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) - : "", + date: + item.dateStart && item.dateEnd + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.dateStart)} - ${Extension.ToThaiFullDate2(item.dateEnd)}`) + : item.dateStart + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) + : item.dateEnd + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) + : "", position: item.position ? Extension.ToThaiNumber(item.position) : "", commandName: "รักษาการในตำแหน่ง", agency: "", @@ -1509,11 +1542,14 @@ export class ProfileController extends Controller { const _assistance = assistance_raw.length > 0 ? assistance_raw.map((item) => ({ - date: item.dateStart - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) - : "" + item.dateEnd - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) - : "", + date: + item.dateStart && item.dateEnd + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.dateStart)} - ${Extension.ToThaiFullDate2(item.dateEnd)}`) + : item.dateStart + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) + : item.dateEnd + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) + : "", position: "", commandName: item.commandName ? Extension.ToThaiNumber(item.commandName) : "", agency: item.agency ? Extension.ToThaiNumber(item.agency) : "", @@ -1536,11 +1572,14 @@ export class ProfileController extends Controller { const duty = duty_raw.length > 0 ? duty_raw.map((item) => ({ - date: item.dateStart - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) - : "" + item.dateEnd - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) - : "", + date: + item.dateStart && item.dateEnd + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.dateStart)} - ${Extension.ToThaiFullDate2(item.dateEnd)}`) + : item.dateStart + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) + : item.dateEnd + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) + : "", refCommandDate: item.refCommandDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.refCommandDate)) : "", @@ -1813,7 +1852,9 @@ export class ProfileController extends Controller { ? Extension.ToThaiNumber(profiles.registrationZipCode) : "", fullRegistrationAddress: fullRegistrationAddress, - updateAt: Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.lastUpdatedAt)), + updateAt: profiles.lastUpdatedAt + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.lastUpdatedAt)) + : "", telephone: profiles.phone != null ? Extension.ToThaiNumber(profiles.phone) : "", url: ImgUrl ? ImgUrl : `${process.env.VITE_URL_MGT}`, url1: _ImgUrl[0] ? _ImgUrl[0] : null, diff --git a/src/controllers/ProfileEmployeeController.ts b/src/controllers/ProfileEmployeeController.ts index ed993152..0206bf36 100644 --- a/src/controllers/ProfileEmployeeController.ts +++ b/src/controllers/ProfileEmployeeController.ts @@ -1049,7 +1049,7 @@ export class ProfileEmployeeController extends Controller { const cert_raw = await this.certificateRepository.find({ where: { profileEmployeeId: id }, - select: ["certificateType", "issuer", "certificateNo", "issueDate"], + select: ["certificateType", "issuer", "certificateNo", "issueDate", "expireDate"], order: { createdAt: "ASC" }, }); const certs = @@ -1060,15 +1060,17 @@ export class ProfileEmployeeController extends Controller { certificateNo: item.certificateNo ? Extension.ToThaiNumber(item.certificateNo) : null, issueDate: item.issueDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) - : null, + : "", expireDate: item.expireDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.expireDate)) - : null, + : "", issueToExpireDate: item.issueDate - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) - : "" + item.expireDate - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.expireDate)) - : null, + ? item.expireDate + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.issueDate)} - ${Extension.ToThaiFullDate2(item.expireDate)}`) + : Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) + : item.expireDate + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.expireDate)) + : "" })) : [ { @@ -1149,6 +1151,21 @@ export class ProfileEmployeeController extends Controller { }, ]; const salary_raw = await this.salaryRepo.find({ + select: [ + "commandName", + "commandDateAffect", + "positionName", + "posNoAbb", + "posNo", + "amount", + "amountSpecial", + "positionLevel", + "positionCee", + "remark", + "positionType", + "positionSalaryAmount", + "order", + ], where: { profileEmployeeId: id, commandCode: In(["5", "6"]), @@ -1214,6 +1231,17 @@ export class ProfileEmployeeController extends Controller { ]; const insignia_raw = await this.profileInsigniaRepo.find({ + select: [ + "receiveDate", + "no", + "issue", + "volumeNo", + "volume", + "section", + "page", + "refCommandDate", + "note", + ], relations: { insignia: { insigniaType: true, @@ -1228,9 +1256,9 @@ export class ProfileEmployeeController extends Controller { receiveDate: item.receiveDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.receiveDate)) : "", - insigniaName: item.insignia.name, - insigniaShortName: item.insignia.shortName, - insigniaTypeName: item.insignia.insigniaType.name, + insigniaName: item.insignia?.name ?? "", + insigniaShortName: item.insignia?.shortName ?? "", + insigniaTypeName: item.insignia?.insigniaType?.name ?? "", no: item.no ? Extension.ToThaiNumber(item.no) : "", issue: item.issue ? Extension.ToThaiNumber(item.issue) : "", volumeNo: item.volumeNo ? Extension.ToThaiNumber(item.volumeNo) : "", @@ -1289,7 +1317,9 @@ export class ProfileEmployeeController extends Controller { const totalLeaveDaysKey = `totalLeaveDaysLv${lvIndex}`; const leaveTypeNameKey = `leaveTypeNameLv${lvIndex}`; - const leaveDate = new Date(item.maxDateLeaveStart); + const leaveDate = item.maxDateLeaveStart + ? new Date(item.maxDateLeaveStart) + : null; const year = leaveDate ? Extension.ToThaiNumber(Extension.ToThaiShortYear(leaveDate)) : ""; @@ -1483,11 +1513,14 @@ export class ProfileEmployeeController extends Controller { const _actposition = actposition_raw.length > 0 ? actposition_raw.map((item) => ({ - date: item.dateStart - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) - : "" + item.dateEnd - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) - : "", + date: + item.dateStart && item.dateEnd + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.dateStart)} - ${Extension.ToThaiFullDate2(item.dateEnd)}`) + : item.dateStart + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) + : item.dateEnd + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) + : "", position: item.position ? Extension.ToThaiNumber(item.position) : "", commandName: "รักษาการในตำแหน่ง", agency: "", @@ -1505,11 +1538,14 @@ export class ProfileEmployeeController extends Controller { const _assistance = assistance_raw.length > 0 ? assistance_raw.map((item) => ({ - date: item.dateStart - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) - : "" + item.dateEnd - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) - : "", + date: + item.dateStart && item.dateEnd + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.dateStart)} - ${Extension.ToThaiFullDate2(item.dateEnd)}`) + : item.dateStart + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) + : item.dateEnd + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) + : "", position: "", commandName: item.commandName ? Extension.ToThaiNumber(item.commandName) : "", agency: item.agency ? Extension.ToThaiNumber(item.agency) : "", @@ -1532,11 +1568,14 @@ export class ProfileEmployeeController extends Controller { const duty = duty_raw.length > 0 ? duty_raw.map((item) => ({ - date: item.dateStart - ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) - : "" + item.dateEnd - ? " - " + Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) - : "", + date: + item.dateStart && item.dateEnd + ? Extension.ToThaiNumber(`${Extension.ToThaiFullDate2(item.dateStart)} - ${Extension.ToThaiFullDate2(item.dateEnd)}`) + : item.dateStart + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateStart)) + : item.dateEnd + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateEnd)) + : "", refCommandDate: item.refCommandDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.refCommandDate)) : "", @@ -1791,7 +1830,9 @@ export class ProfileEmployeeController extends Controller { ? Extension.ToThaiNumber(profiles.registrationZipCode) : "", fullRegistrationAddress: fullRegistrationAddress, - updateAt: Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.lastUpdatedAt)), + updateAt: profiles.lastUpdatedAt + ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.lastUpdatedAt)) + : "", telephone: profiles.phone != null ? Extension.ToThaiNumber(profiles.phone) : "", url: ImgUrl ? ImgUrl : `${process.env.VITE_URL_MGT}`, url1: _ImgUrl[0] ? _ImgUrl[0] : null, From 2a2635ad8334df65955b1dfadccc0fdecd8b18e7 Mon Sep 17 00:00:00 2001 From: harid Date: Tue, 27 Jan 2026 18:09:31 +0700 Subject: [PATCH 09/14] =?UTF-8?q?Add=20workflow=20=E0=B8=82=E0=B8=AD?= =?UTF-8?q?=E0=B9=81=E0=B8=81=E0=B9=89=E0=B9=84=E0=B8=82=E0=B8=82=E0=B9=89?= =?UTF-8?q?=E0=B8=AD=E0=B8=A1=E0=B8=B9=E0=B8=A5=E0=B8=97=E0=B8=B0=E0=B9=80?= =?UTF-8?q?=E0=B8=9A=E0=B8=B5=E0=B8=A2=E0=B8=99=E0=B8=9B=E0=B8=A3=E0=B8=B0?= =?UTF-8?q?=E0=B8=A7=E0=B8=B1=E0=B8=95=E0=B8=B4=20(=E0=B8=A5=E0=B8=B9?= =?UTF-8?q?=E0=B8=81=E0=B8=88=E0=B9=89=E0=B8=B2=E0=B8=87=E0=B8=9B=E0=B8=A3?= =?UTF-8?q?=E0=B8=B0=E0=B8=88=E0=B8=B3)=20#2222=20Fix=20=E0=B9=80=E0=B8=9E?= =?UTF-8?q?=E0=B8=B4=E0=B9=88=E0=B8=A1=E0=B8=A3=E0=B8=B2=E0=B8=A2=E0=B8=81?= =?UTF-8?q?=E0=B8=B2=E0=B8=A3=E0=B9=81=E0=B8=95=E0=B9=88=E0=B9=84=E0=B8=A1?= =?UTF-8?q?=E0=B9=88=E0=B9=81=E0=B8=AA=E0=B8=94=E0=B8=87=E0=B9=83=E0=B8=99?= =?UTF-8?q?=20Tab=20=E0=B8=A3=E0=B8=B2=E0=B8=A2=E0=B8=81=E0=B8=B2=E0=B8=A3?= =?UTF-8?q?=E0=B8=95=E0=B8=B3=E0=B9=81=E0=B8=AB=E0=B8=99=E0=B9=88=E0=B8=87?= =?UTF-8?q?/=E0=B9=80=E0=B8=87=E0=B8=B4=E0=B8=99=E0=B9=80=E0=B8=94?= =?UTF-8?q?=E0=B8=B7=E0=B8=AD=E0=B8=99=E0=B8=AB=E0=B8=A5=E0=B8=B1=E0=B8=87?= =?UTF-8?q?=E0=B8=88=E0=B8=B2=E0=B8=81=E0=B9=81=E0=B8=81=E0=B9=89=E0=B9=84?= =?UTF-8?q?=E0=B8=82=E0=B9=81=E0=B8=A5=E0=B9=89=E0=B8=A7=20#2243?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProfileEditEmployeeController.ts | 41 ++++++++++++++++++- .../ProfileSalaryTempController.ts | 1 + 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/controllers/ProfileEditEmployeeController.ts b/src/controllers/ProfileEditEmployeeController.ts index 8abc6d8b..86c364d5 100644 --- a/src/controllers/ProfileEditEmployeeController.ts +++ b/src/controllers/ProfileEditEmployeeController.ts @@ -26,7 +26,8 @@ import { RequestWithUser } from "../middlewares/user"; import { Brackets } from "typeorm"; import permission from "../interfaces/permission"; import { OrgRevision } from "../entities/OrgRevision"; - +import { OrgRoot } from "../entities/OrgRoot"; +import CallAPI from "../interfaces/call-api"; @Route("api/v1/org/profile-employee/edit") @Tags("ProfileEmployeeEdit") @Security("bearerAuth") @@ -34,6 +35,7 @@ export class ProfileEditEmployeeController extends Controller { private profileEmployeeRepo = AppDataSource.getRepository(ProfileEmployee); private profileEditRepository = AppDataSource.getRepository(ProfileEdit); private orgRevisionRepository = AppDataSource.getRepository(OrgRevision); + private orgRootRepo = AppDataSource.getRepository(OrgRoot); @Get("user") public async detailProfileEditUserEmp( @@ -294,10 +296,32 @@ export class ProfileEditEmployeeController extends Controller { @Request() req: RequestWithUser, @Body() body: CreateProfileEmployeeEdit, ) { - const profile = await this.profileEmployeeRepo.findOneBy({ keycloak: req.user.sub }); + // const profile = await this.profileEmployeeRepo.findOneBy({ keycloak: req.user.sub }); + const profile = await this.profileEmployeeRepo.findOne({ + relations: { + current_holders: true + }, + where: { + keycloak: req.user.sub, + current_holders: { + orgRevision: { + orgRevisionIsCurrent: true, + orgRevisionIsDraft: false + } + } + } + }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } + const orgRoot = await this.orgRootRepo.findOne({ + select: { + isDeputy: true + }, + where: { + id: profile.current_holders.find(x => x.orgRootId)!.orgRootId ?? "" + } + }); const data = new ProfileEdit(); const meta = { @@ -312,6 +336,19 @@ export class ProfileEditEmployeeController extends Controller { data.status = "PENDING"; await this.profileEditRepository.save(data); + await new CallAPI() + .PostData(req, "/org/workflow/add-workflow", { + refId: data.id, + sysName: "REGISTRY_PROFILE_EMP", + posLevelName: "EMP", + posTypeName: "EMP", + fullName: `${profile.prefix}${profile.firstName} ${profile.lastName}`, + isDeputy: orgRoot?.isDeputy ?? false + }) + .catch((error) => { + console.error("Error calling API:", error); + }); + return new HttpSuccess(data.id); } diff --git a/src/controllers/ProfileSalaryTempController.ts b/src/controllers/ProfileSalaryTempController.ts index 8b49622a..cbdcf50a 100644 --- a/src/controllers/ProfileSalaryTempController.ts +++ b/src/controllers/ProfileSalaryTempController.ts @@ -1212,6 +1212,7 @@ export class ProfileSalaryTempController extends Controller { createdAt: new Date(), lastUpdatedAt: new Date(), isEdit: true, + isDelete: false, }; Object.assign(data, { ...body, ...meta }); await this.salaryRepo.save(data, { data: req }); From dd01e2a79df82e88abc5598a834275ebda6f92c4 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 28 Jan 2026 09:22:52 +0700 Subject: [PATCH 10/14] #migrate add ssues --- src/controllers/IssuesController.ts | 60 ++++++++++++ src/entities/Issues.ts | 93 +++++++++++++++++++ .../1769509622176-create_table_issues.ts | 33 +++++++ 3 files changed, 186 insertions(+) create mode 100644 src/controllers/IssuesController.ts create mode 100644 src/entities/Issues.ts create mode 100644 src/migration/1769509622176-create_table_issues.ts diff --git a/src/controllers/IssuesController.ts b/src/controllers/IssuesController.ts new file mode 100644 index 00000000..7514d1b9 --- /dev/null +++ b/src/controllers/IssuesController.ts @@ -0,0 +1,60 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Route, + Security, + Tags, + Body, + Path, + Request, + Response, +} from "tsoa"; +import HttpStatusCode from "../interfaces/http-status"; +import { AppDataSource } from "../database/data-source"; +import { Issues, CreateIssueRequest, UpdateIssueRequest } from "../entities/Issues"; +import HttpSuccess from "../interfaces/http-success"; + +@Route("api/v1/org/issues") +@Tags("issues") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +export class IssuesController extends Controller { + private issuesRepository = AppDataSource.getRepository(Issues); + + @Get("lists") + async getIssues() { + const issues = await this.issuesRepository.find({ + order: { + createdAt: "DESC", + }, + }); + return new HttpSuccess(issues); + } + + @Post("") + async createIssue(@Body() requestBody: CreateIssueRequest) { + let issue = this.issuesRepository.create(requestBody); + + await this.issuesRepository.save(issue); + + return new HttpSuccess(issue); + } + + @Put("{id}") + async updateIssue(@Path("id") id: string, @Body() requestBody: Partial) { + let issue = await this.issuesRepository.findOneBy({ id }); + if (!issue) { + this.setStatus(HttpStatusCode.NOT_FOUND); + return { message: "ไม่พบข้อมูลที่ต้องการแก้ไข" }; + } + Object.assign(issue, requestBody); + await this.issuesRepository.save(issue); + return new HttpSuccess(issue); + } +} diff --git a/src/entities/Issues.ts b/src/entities/Issues.ts new file mode 100644 index 00000000..8bf3143e --- /dev/null +++ b/src/entities/Issues.ts @@ -0,0 +1,93 @@ +import { Entity, Column, BeforeInsert } from "typeorm"; +import { AppDataSource } from "../database/data-source"; +import { EntityBase } from "./base/Base"; + +@Entity("issues") +export class Issues extends EntityBase { + @Column({ + type: "varchar", + nullable: false, + length: 20, + comment: "รหัส issue เช่น ISS20260127001", + }) + codeIssue: string; + + @Column({ type: "varchar", nullable: false, length: 255, comment: "หัวข้อ" }) + title: string; + + @Column({ type: "text", nullable: false, comment: "รายละเอียดของปัญหา" }) + description: string | null; + + @Column({ type: "varchar", nullable: false, length: 50, comment: "ระบบ" }) + system: string; + + @Column({ type: "varchar", nullable: false, length: 255, comment: "เมนู" }) + menu: string | null; + + @Column({ type: "varchar", nullable: true, length: 500, comment: "สังกัด" }) + org: string | null; + + @Column({ type: "text", nullable: true, comment: "หมายเหตุ" }) + remark: string | null; + + @Column({ + type: "enum", + enum: ["NEW", "IN_PROGRESS", "RESOLVED", "CLOSED"], + default: "NEW", + comment: "สถานะการแก้ไขปัญหา", + }) + status: "NEW" | "IN_PROGRESS" | "RESOLVED" | "CLOSED"; + + @BeforeInsert() + async generateCodeIssue() { + const today = new Date(); + const dateStr = today.toISOString().slice(0, 10).replace(/-/g, ""); + const prefix = `ISS${dateStr}`; + + const repository = AppDataSource.getRepository(Issues); + const lastIssue = await repository + .createQueryBuilder("issue") + .where("issue.codeIssue LIKE :prefix", { prefix: `${prefix}%` }) + .orderBy("issue.codeIssue", "DESC") + .getOne(); + + let runningNumber = 1; + if (lastIssue) { + const lastNumber = parseInt(lastIssue.codeIssue.slice(-3), 10); + runningNumber = lastNumber + 1; + } + + this.codeIssue = `${prefix}${runningNumber.toString().padStart(3, "0")}`; + } +} + +// Interface สำหรับ TSOA Response +export interface IssueResponse { + id: string; + codeIssue: string; + title: string; + description: string | null; + system: string; + menu: string | null; + org: string | null; + remark: string | null; + status: "NEW" | "IN_PROGRESS" | "RESOLVED" | "CLOSED"; + createdAt: Date; + lastUpdatedAt: Date; + createdFullName: string; + lastUpdateFullName: string; +} + +export interface CreateIssueRequest { + title: string; + description?: string; + system: string; + status?: "NEW" | "IN_PROGRESS" | "RESOLVED" | "CLOSED"; + menu?: string; + org?: string; +} + +export interface UpdateIssueRequest { + status?: "NEW" | "IN_PROGRESS" | "RESOLVED" | "CLOSED"; + remark?: string; +} diff --git a/src/migration/1769509622176-create_table_issues.ts b/src/migration/1769509622176-create_table_issues.ts new file mode 100644 index 00000000..493ab458 --- /dev/null +++ b/src/migration/1769509622176-create_table_issues.ts @@ -0,0 +1,33 @@ +import { MigrationInterface, QueryRunner, Table } from "typeorm"; + +export class CreateTableIssues1769509622176 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable(new Table({ + name: "issues", + columns: [ + { name: "id", type: "char", length: "36", isPrimary: true, isGenerated: true, generationStrategy: "uuid" }, + { name: "codeIssue", type: "varchar", length: "20", isNullable: false, comment: "รหัส issue เช่น ISS20260127001" }, + { name: "title", type: "varchar", length: "255", isNullable: false, comment: "หัวข้อ" }, + { name: "description", type: "text", isNullable: false, comment: "รายละเอียดของปัญหา" }, + { name: "system", type: "varchar", length: "50", isNullable: false, comment: "ระบบ" }, + { name: "menu", type: "varchar", length: "255", isNullable: true, comment: "เมนู" }, + { name: "org", type: "varchar", length: "500", isNullable: true, comment: "สังกัด" }, + { name: "remark", type: "text", isNullable: true, comment: "หมายเหตุ" }, + { name: "status", type: "enum", enum: ["NEW", "IN_PROGRESS", "RESOLVED", "CLOSED"], default: "'NEW'", comment: "สถานะการแก้ไขปัญหา" }, + { name: "createdUserId", type: "char", length: "40", isNullable: false, default: "'00000000-0000-0000-0000-000000000000'", comment: "User Id ที่สร้างข้อมูล" }, + { name: "createdFullName", type: "varchar", length: "200", isNullable: false, default: "'System Administrator'", comment: "ชื่อ User ที่สร้างข้อมูล" }, + { name: "createdAt", type: "timestamp", default: "CURRENT_TIMESTAMP", comment: "สร้างข้อมูลเมื่อ" }, + { name: "lastUpdateUserId", type: "char", length: "40", isNullable: false, default: "'00000000-0000-0000-0000-000000000000'", comment: "User Id ที่แก้ไขข้อมูล" }, + { name: "lastUpdateFullName", type: "varchar", length: "200", isNullable: false, default: "'System Administrator'", comment: "ชื่อ User ที่แก้ไขข้อมูลล่าสุด" }, + { name: "lastUpdatedAt", type: "timestamp", default: "CURRENT_TIMESTAMP", comment: "แก้ไขข้อมูลล่าสุดเมื่อ" }, + + ], + }), true); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable("issues"); + } + +} From ca433d571174cf7588a68ef4c98d5dba79f361fd Mon Sep 17 00:00:00 2001 From: Adisak Date: Wed, 28 Jan 2026 09:36:30 +0700 Subject: [PATCH 11/14] =?UTF-8?q?=E0=B8=9B=E0=B8=A3=E0=B8=B1=E0=B8=9A=20in?= =?UTF-8?q?sert=20DNA=20=E0=B9=83=E0=B8=99=20createPosMasterHistory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/PositionService.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/PositionService.ts b/src/services/PositionService.ts index 1b30f980..67cbecef 100644 --- a/src/services/PositionService.ts +++ b/src/services/PositionService.ts @@ -60,11 +60,6 @@ export async function CreatePosMasterHistoryOfficer( h.firstName = pm.current_holder?.firstName || _null; h.lastName = pm.current_holder?.lastName || _null; h.profileId = pm.current_holder?.id || _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; } else { h.prefix = pm.next_holder?.prefix || _null; h.firstName = pm.next_holder?.firstName || _null; @@ -74,6 +69,11 @@ export async function CreatePosMasterHistoryOfficer( 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; From 987f8ef81a4dcf3850c8c2cfbb222b761ee6c566 Mon Sep 17 00:00:00 2001 From: harid Date: Wed, 28 Jan 2026 10:45:38 +0700 Subject: [PATCH 12/14] =?UTF-8?q?tuning=20api=20(=E0=B8=95=E0=B8=B1?= =?UTF-8?q?=E0=B8=94=20profileSalary=20=E0=B9=80=E0=B8=AA=E0=B9=89?= =?UTF-8?q?=E0=B8=99=E0=B8=97=E0=B8=B5=E0=B9=88=E0=B9=84=E0=B8=A1=E0=B9=88?= =?UTF-8?q?=E0=B9=84=E0=B8=94=E0=B9=89=E0=B9=83=E0=B8=8A=E0=B9=89=E0=B8=87?= =?UTF-8?q?=E0=B8=B2=E0=B8=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OrganizationDotnetController.ts | 327 +++++++++++------- 1 file changed, 211 insertions(+), 116 deletions(-) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index bcb35079..0c8e4d9f 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -4122,16 +4122,28 @@ export class OrganizationDotnetController extends Controller { async getAllProfileByKeycloak(@Path() keycloakId: string) { const profile = await this.profileRepo.findOne({ where: { keycloak: keycloakId }, - relations: [ - "profileSalary", - "profileEducations", - "current_holders", - "current_holders.orgRoot", - "current_holders.orgChild1", - "current_holders.orgChild2", - "current_holders.orgChild3", - "current_holders.orgChild4", - ], + // relations: [ + // "profileSalary", + // "profileEducations", + // "current_holders", + // "current_holders.orgRoot", + // "current_holders.orgChild1", + // "current_holders.orgChild2", + // "current_holders.orgChild3", + // "current_holders.orgChild4", + // ], + relations:{ + posType: true, + posLevel: true, + current_holders: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + } + } }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); @@ -4292,7 +4304,7 @@ export class OrganizationDotnetController extends Controller { @Get("keycloak") async GetProfileWithKeycloak() { const profile = await this.profileRepo.find({ - where: { keycloak: Not(IsNull()) || Not("") }, + where: { keycloak: Not(IsNull()) }, relations: [ "posType", "posLevel", @@ -4302,111 +4314,194 @@ export class OrganizationDotnetController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", ], - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); const findRevision = await this.orgRevisionRepo.findOne({ where: { orgRevisionIsCurrent: true }, }); - const profile_ = await Promise.all( - profile.map((item: Profile) => { - const rootName = - item.current_holders.length == 0 - ? null - : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot - ?.orgRootName; - 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 profile_ = await Promise.all( + // profile.map((item: Profile) => { + // const rootName = + // item.current_holders.length == 0 + // ? null + // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot + // ?.orgRootName; + // 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; - return { - oc: rootName, - id: item.id, - createdAt: item.createdAt, - createdUserId: item.createdUserId, - lastUpdatedAt: item.lastUpdatedAt, - lastUpdateUserId: item.lastUpdateUserId, - createdFullName: item.createdFullName, - lastUpdateFullName: item.lastUpdateFullName, - avatar: item.avatar, - avatarName: item.avatarName, - rank: item.rank, - prefix: item.prefix, - firstName: item.firstName, - lastName: item.lastName, - citizenId: item.citizenId, - position: item.position, - posLevelId: item.posLevelId, - posTypeId: item.posTypeId, - email: item.email, - phone: item.phone, - keycloak: item.keycloak, - isProbation: item.isProbation, - isLeave: item.isLeave, - leaveReason: item.leaveReason, - dateLeave: item.dateLeave, - dateRetire: item.dateRetire, - dateAppoint: item.dateAppoint, - dateRetireLaw: item.dateRetireLaw, - dateStart: item.dateStart, - govAgeAbsent: item.govAgeAbsent, - govAgePlus: item.govAgePlus, - birthDate: item.birthDate ?? new Date(), - reasonSameDate: item.reasonSameDate, - ethnicity: item.ethnicity, - telephoneNumber: item.phone, - nationality: item.nationality, - gender: item.gender, - relationship: item.relationship, - religion: item.religion, - bloodGroup: item.bloodGroup, - registrationAddress: item.registrationAddress, - registrationProvinceId: item.registrationProvinceId, - registrationDistrictId: item.registrationDistrictId, - registrationSubDistrictId: item.registrationSubDistrictId, - registrationZipCode: item.registrationZipCode, - currentAddress: item.currentAddress, - currentProvinceId: item.currentProvinceId, - currentDistrictId: item.currentDistrictId, - currentSubDistrictId: item.currentSubDistrictId, - currentZipCode: item.currentZipCode, - dutyTimeId: item.dutyTimeId, - dutyTimeEffectiveDate: item.dutyTimeEffectiveDate, - positionLevel: item.posLevel?.posLevelName ?? null, - positionType: item.posType?.posTypeName ?? null, - posNo: shortName, - }; - }), - ); + // return { + // oc: rootName, + // id: item.id, + // createdAt: item.createdAt, + // createdUserId: item.createdUserId, + // lastUpdatedAt: item.lastUpdatedAt, + // lastUpdateUserId: item.lastUpdateUserId, + // createdFullName: item.createdFullName, + // lastUpdateFullName: item.lastUpdateFullName, + // avatar: item.avatar, + // avatarName: item.avatarName, + // rank: item.rank, + // prefix: item.prefix, + // firstName: item.firstName, + // lastName: item.lastName, + // citizenId: item.citizenId, + // position: item.position, + // posLevelId: item.posLevelId, + // posTypeId: item.posTypeId, + // email: item.email, + // phone: item.phone, + // keycloak: item.keycloak, + // isProbation: item.isProbation, + // isLeave: item.isLeave, + // leaveReason: item.leaveReason, + // dateLeave: item.dateLeave, + // dateRetire: item.dateRetire, + // dateAppoint: item.dateAppoint, + // dateRetireLaw: item.dateRetireLaw, + // dateStart: item.dateStart, + // govAgeAbsent: item.govAgeAbsent, + // govAgePlus: item.govAgePlus, + // birthDate: item.birthDate ?? new Date(), + // reasonSameDate: item.reasonSameDate, + // ethnicity: item.ethnicity, + // telephoneNumber: item.phone, + // nationality: item.nationality, + // gender: item.gender, + // relationship: item.relationship, + // religion: item.religion, + // bloodGroup: item.bloodGroup, + // registrationAddress: item.registrationAddress, + // registrationProvinceId: item.registrationProvinceId, + // registrationDistrictId: item.registrationDistrictId, + // registrationSubDistrictId: item.registrationSubDistrictId, + // registrationZipCode: item.registrationZipCode, + // currentAddress: item.currentAddress, + // currentProvinceId: item.currentProvinceId, + // currentDistrictId: item.currentDistrictId, + // currentSubDistrictId: item.currentSubDistrictId, + // currentZipCode: item.currentZipCode, + // dutyTimeId: item.dutyTimeId, + // dutyTimeEffectiveDate: item.dutyTimeEffectiveDate, + // positionLevel: item.posLevel?.posLevelName ?? null, + // positionType: item.posType?.posTypeName ?? null, + // posNo: shortName, + // }; + // }), + // ); + const profile_ = profile.map((item: Profile) => { + const holder = item.current_holders?.find( + (x) => x.orgRevisionId === findRevision?.id, + ); + + const rootName = holder?.orgRoot?.orgRootName ?? null; + + let shortName: string | null = null; + + if (holder) { + const posNo = holder.posMasterNo; + + if (holder.orgChild4) { + shortName = `${holder.orgChild4.orgChild4ShortName} ${posNo}`; + } else if (holder.orgChild3) { + shortName = `${holder.orgChild3.orgChild3ShortName} ${posNo}`; + } else if (holder.orgChild2) { + shortName = `${holder.orgChild2.orgChild2ShortName} ${posNo}`; + } else if (holder.orgChild1) { + shortName = `${holder.orgChild1.orgChild1ShortName} ${posNo}`; + } else if (holder.orgRoot) { + shortName = `${holder.orgRoot.orgRootShortName} ${posNo}`; + } + } + + return { + oc: rootName, + id: item.id, + createdAt: item.createdAt, + createdUserId: item.createdUserId, + lastUpdatedAt: item.lastUpdatedAt, + lastUpdateUserId: item.lastUpdateUserId, + createdFullName: item.createdFullName, + lastUpdateFullName: item.lastUpdateFullName, + avatar: item.avatar, + avatarName: item.avatarName, + rank: item.rank, + prefix: item.prefix, + firstName: item.firstName, + lastName: item.lastName, + citizenId: item.citizenId, + position: item.position, + posLevelId: item.posLevelId, + posTypeId: item.posTypeId, + email: item.email, + phone: item.phone, + keycloak: item.keycloak, + isProbation: item.isProbation, + isLeave: item.isLeave, + leaveReason: item.leaveReason, + dateLeave: item.dateLeave, + dateRetire: item.dateRetire, + dateAppoint: item.dateAppoint, + dateRetireLaw: item.dateRetireLaw, + dateStart: item.dateStart, + govAgeAbsent: item.govAgeAbsent, + govAgePlus: item.govAgePlus, + birthDate: item.birthDate ?? new Date(), + reasonSameDate: item.reasonSameDate, + ethnicity: item.ethnicity, + telephoneNumber: item.phone, + nationality: item.nationality, + gender: item.gender, + relationship: item.relationship, + religion: item.religion, + bloodGroup: item.bloodGroup, + registrationAddress: item.registrationAddress, + registrationProvinceId: item.registrationProvinceId, + registrationDistrictId: item.registrationDistrictId, + registrationSubDistrictId: item.registrationSubDistrictId, + registrationZipCode: item.registrationZipCode, + currentAddress: item.currentAddress, + currentProvinceId: item.currentProvinceId, + currentDistrictId: item.currentDistrictId, + currentSubDistrictId: item.currentSubDistrictId, + currentZipCode: item.currentZipCode, + dutyTimeId: item.dutyTimeId, + dutyTimeEffectiveDate: item.dutyTimeEffectiveDate, + positionLevel: item.posLevel?.posLevelName ?? null, + positionType: item.posType?.posTypeName ?? null, + posNo: shortName, + }; + }); return new HttpSuccess(profile_); } @@ -4430,13 +4525,13 @@ export class OrganizationDotnetController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", ], - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); const findRevision = await this.orgRevisionRepo.findOne({ @@ -7114,7 +7209,7 @@ export class OrganizationDotnetController extends Controller { if (type.trim().toLocaleUpperCase() == "OFFICER") { profile = await this.profileRepo.find({ relations: [ - "profileSalary", + // "profileSalary", "profileInsignias", "profileDisciplines", "profileAssessments", @@ -7124,7 +7219,7 @@ export class OrganizationDotnetController extends Controller { } else { profile = await this.profileEmpRepo.find({ relations: [ - "profileSalary", + // "profileSalary", "profileInsignias", "profileDisciplines", "profileAssessments", From 042dba505f14e3f79ab4a88f1da154287e5cb932 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Wed, 28 Jan 2026 10:57:25 +0700 Subject: [PATCH 13/14] fix(issue):save_created_Update_user --- src/controllers/IssuesController.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/controllers/IssuesController.ts b/src/controllers/IssuesController.ts index 7514d1b9..aeb849e5 100644 --- a/src/controllers/IssuesController.ts +++ b/src/controllers/IssuesController.ts @@ -16,6 +16,7 @@ import HttpStatusCode from "../interfaces/http-status"; import { AppDataSource } from "../database/data-source"; import { Issues, CreateIssueRequest, UpdateIssueRequest } from "../entities/Issues"; import HttpSuccess from "../interfaces/http-success"; +import { RequestWithUser } from "../middlewares/user"; @Route("api/v1/org/issues") @Tags("issues") @@ -38,22 +39,33 @@ export class IssuesController extends Controller { } @Post("") - async createIssue(@Body() requestBody: CreateIssueRequest) { + async createIssue(@Body() requestBody: CreateIssueRequest, @Request() request: RequestWithUser) { let issue = this.issuesRepository.create(requestBody); - + issue.createdUserId = request.user.sub; + issue.createdFullName = request.user.name; + issue.createdAt = new Date(); + issue.lastUpdateUserId = ""; + issue.lastUpdateFullName = ""; await this.issuesRepository.save(issue); return new HttpSuccess(issue); } @Put("{id}") - async updateIssue(@Path("id") id: string, @Body() requestBody: Partial) { + async updateIssue( + @Path("id") id: string, + @Body() requestBody: Partial, + @Request() request: RequestWithUser, + ) { let issue = await this.issuesRepository.findOneBy({ id }); if (!issue) { this.setStatus(HttpStatusCode.NOT_FOUND); return { message: "ไม่พบข้อมูลที่ต้องการแก้ไข" }; } Object.assign(issue, requestBody); + issue.lastUpdateUserId = request.user.sub; + issue.lastUpdateFullName = request.user.name; + issue.lastUpdatedAt = new Date(); await this.issuesRepository.save(issue); return new HttpSuccess(issue); } From 43ae825ac0ef5b17be08df2410efa1ec3b57c433 Mon Sep 17 00:00:00 2001 From: harid Date: Wed, 28 Jan 2026 11:02:11 +0700 Subject: [PATCH 14/14] =?UTF-8?q?tuning=20api=20(=E0=B8=95=E0=B8=B1?= =?UTF-8?q?=E0=B8=94=20profileSalary=20=E0=B9=80=E0=B8=AA=E0=B9=89?= =?UTF-8?q?=E0=B8=99=E0=B8=97=E0=B8=B5=E0=B9=88=E0=B9=84=E0=B8=A1=E0=B9=88?= =?UTF-8?q?=E0=B9=84=E0=B8=94=E0=B9=89=E0=B9=83=E0=B8=8A=E0=B9=89=E0=B8=87?= =?UTF-8?q?=E0=B8=B2=E0=B8=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/ProfileController.ts | 24 +++++++++---------- src/controllers/ProfileEmployeeController.ts | 12 +++++----- .../ProfileEmployeeTempController.ts | 12 +++++----- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/controllers/ProfileController.ts b/src/controllers/ProfileController.ts index cf74a0d0..4fe44943 100644 --- a/src/controllers/ProfileController.ts +++ b/src/controllers/ProfileController.ts @@ -7281,13 +7281,13 @@ export class ProfileController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", ], - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { const profile = await this.profileEmpRepo.findOne({ @@ -7301,13 +7301,13 @@ export class ProfileController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", ], - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { if (request.user.role.includes("SUPER_ADMIN")) { diff --git a/src/controllers/ProfileEmployeeController.ts b/src/controllers/ProfileEmployeeController.ts index 0206bf36..008f0c67 100644 --- a/src/controllers/ProfileEmployeeController.ts +++ b/src/controllers/ProfileEmployeeController.ts @@ -3494,13 +3494,13 @@ export class ProfileEmployeeController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", ], - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { if (request.user.role.includes("SUPER_ADMIN")) { diff --git a/src/controllers/ProfileEmployeeTempController.ts b/src/controllers/ProfileEmployeeTempController.ts index 9fdfd581..efe59ca2 100644 --- a/src/controllers/ProfileEmployeeTempController.ts +++ b/src/controllers/ProfileEmployeeTempController.ts @@ -2071,13 +2071,13 @@ export class ProfileEmployeeTempController extends Controller { "current_holders.orgChild2", "current_holders.orgChild3", "current_holders.orgChild4", - "profileSalary", + // "profileSalary", ], - order: { - profileSalary: { - order: "DESC", - }, - }, + // order: { + // profileSalary: { + // order: "DESC", + // }, + // }, }); if (!profile) { if (request.user.role.includes("SUPER_ADMIN")) {