From 648fb33cc26603cfa19dfbde6a887461aa1c2c26 Mon Sep 17 00:00:00 2001 From: harid Date: Mon, 19 Jan 2026 16:49:24 +0700 Subject: [PATCH] tuning api Get org/dotnet/keycloak/{keycloakId} --- .../OrganizationDotnetController.ts | 440 +++++++++++++++++- 1 file changed, 438 insertions(+), 2 deletions(-) diff --git a/src/controllers/OrganizationDotnetController.ts b/src/controllers/OrganizationDotnetController.ts index 9357d8af..c5da0819 100644 --- a/src/controllers/OrganizationDotnetController.ts +++ b/src/controllers/OrganizationDotnetController.ts @@ -38,6 +38,7 @@ import { PosMasterHistory } from "../entities/PosMasterHistory"; import { PosMasterEmployeeHistory } from "../entities/PosMasterEmployeeHistory"; import { PosMasterAssign } from "../entities/PosMasterAssign"; import { Assign } from "../entities/Assign"; +import { ProfileSalary } from "../entities/ProfileSalary"; @Route("api/v1/org/dotnet") @Tags("Dotnet") @Security("bearerAuth") @@ -65,6 +66,8 @@ export class OrganizationDotnetController extends Controller { private employeePosDictRepository = AppDataSource.getRepository(EmployeePosDict); private posMasterAssignRepo = AppDataSource.getRepository(PosMasterAssign); private assignRepository = AppDataSource.getRepository(Assign); + private salaryRepo = AppDataSource.getRepository(ProfileSalary); + /** * ทำไว้ให้ service อื่นๆ ภายในระบบ call มาตรวจสอบเลขบัตรประจำตัวประชาชน * @@ -406,8 +409,8 @@ export class OrganizationDotnetController extends Controller { * * @param {string} keycloakId Id keycloak */ - @Get("keycloak/{keycloakId}") - async GetProfileByKeycloakIdAsync(@Path() keycloakId: string) { + @Get("keycloak-old/{keycloakId}") + async GetProfileByKeycloakIdAsyncOld(@Path() keycloakId: string) { const profile = await this.profileRepo.findOne({ relations: [ "registrationProvince", @@ -1203,6 +1206,439 @@ export class OrganizationDotnetController extends Controller { return new HttpSuccess(mapProfile); } + + @Get("keycloak/{keycloakId}") + async GetProfileByKeycloakIdAsync(@Path() keycloakId: string) { + /* ========================= + * 1. Load profile + * ========================= */ + const profile = await this.profileRepo.findOne({ + where: { keycloak: keycloakId }, + relations: { + registrationProvince: true, + registrationDistrict: true, + registrationSubDistrict: true, + currentProvince: true, + currentDistrict: true, + currentSubDistrict: true, + 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: { + registrationProvince: true, + registrationDistrict: true, + registrationSubDistrict: true, + currentProvince: true, + currentDistrict: true, + currentSubDistrict: true, + 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, + ); + + const org = { + root: currentHolder?.orgRootId ?? null, + child1: currentHolder?.orgChild1Id ?? null, + child2: currentHolder?.orgChild2Id ?? null, + child3: currentHolder?.orgChild3Id ?? null, + child4: currentHolder?.orgChild4Id ?? null, + }; + + let commanderFullname = ""; + let commanderPositionName = ""; + let commanderId = ""; + let commanderKeycloak = ""; + + const pos = await this.empPosMasterRepository + .createQueryBuilder("pos") + .leftJoinAndSelect("pos.current_holder", "holder") + .leftJoin("pos.orgRevision", "rev") + .where("rev.orgRevisionIsCurrent = true") + .andWhere("rev.orgRevisionIsDraft = false") + .andWhere("pos.isDirector = true") + .andWhere("pos.current_holderId IS NOT NULL") + .andWhere("pos.orgRootId = :root", { root: org.root }) + .andWhere( + `(pos.orgChild1Id = :c1 OR pos.orgChild1Id IS NULL) + AND (pos.orgChild2Id = :c2 OR pos.orgChild2Id IS NULL) + AND (pos.orgChild3Id = :c3 OR pos.orgChild3Id IS NULL) + AND (pos.orgChild4Id = :c4 OR pos.orgChild4Id IS NULL)`, + { + c1: org.child1, + c2: org.child2, + c3: org.child3, + c4: org.child4, + }, + ) + .orderBy( + `(CASE WHEN pos.orgChild4Id IS NULL THEN 1 ELSE 0 END) + + (CASE WHEN pos.orgChild3Id IS NULL THEN 1 ELSE 0 END) + + (CASE WHEN pos.orgChild2Id IS NULL THEN 1 ELSE 0 END) + + (CASE WHEN pos.orgChild1Id IS NULL THEN 1 ELSE 0 END)`, + "ASC", + ) + .getOne(); + + if (pos?.current_holder) { + commanderFullname = + `${pos.current_holder.prefix}${pos.current_holder.firstName} ${pos.current_holder.lastName}`; + commanderPositionName = pos.current_holder.position; + commanderId = pos.current_holder.id; + commanderKeycloak = pos.current_holder.keycloak; + } + + const [latestSalary, latestInsignia] = await Promise.all([ + this.salaryRepo.findOne({ + where: { profileEmployeeId: profile.id }, + order: { commandDateAffect: "DESC" }, + }), + this.insigniaRepo.findOne({ + where: { profileEmployeeId: profile.id }, + order: { receiveDate: "DESC" }, + }), + ]); + + 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 positionLeaveName = + profile.posType && + profile.posLevel && + (profile.posType.posTypeName === "บริหาร" || + profile.posType.posTypeName === "อำนวยการ") + ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}` + : profile.posLevel?.posLevelName ?? null; + + const mapProfile = { + id: profile.id, + avatar: profile.avatar, + avatarName: profile.avatarName, + rank: profile.rank, + prefix: profile.prefix, + firstName: profile.firstName, + lastName: profile.lastName, + citizenId: profile.citizenId, + position: profile.position, + posLevelId: profile.posLevelId, + email: profile.email, + phone: profile.phone, + keycloak: profile.keycloak, + isProbation: profile.isProbation, + isLeave: profile.isLeave, + leaveReason: profile.leaveReason, + 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, + registrationAddress: profile.registrationAddress, + registrationProvinceId: profile.registrationProvinceId, + registrationDistrictId: profile.registrationDistrictId, + registrationSubDistrictId: profile.registrationSubDistrictId, + registrationZipCode: profile.registrationZipCode, + registrationProvince: profile.registrationProvince?.name ?? null, + registrationDistrict: profile.registrationDistrict?.name ?? null, + registrationSubDistrict: profile.registrationSubDistrict?.name ?? null, + currentAddress: profile.currentAddress, + currentProvinceId: profile.currentProvinceId, + currentDistrictId: profile.currentDistrictId, + currentSubDistrictId: profile.currentSubDistrictId, + currentZipCode: profile.currentZipCode, + currentProvince: profile.currentProvince?.name ?? null, + currentDistrict: profile.currentDistrict?.name ?? null, + currentSubDistrict: profile.currentSubDistrict?.name ?? null, + dutyTimeId: profile.dutyTimeId, + dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate, + amount: profile.amount, + positionSalaryAmount: profile.positionSalaryAmount, + mouthSalaryAmount: profile.mouthSalaryAmount, + 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, + commander: commanderFullname, + commanderPositionName, + commanderId, + commanderKeycloak, + posLevel: profile.posLevel?.posLevelName ?? null, + posType: profile.posType?.posTypeName ?? null, + profileSalary: latestSalary ?? null, + profileInsignia: latestInsignia ?? null, + profileType: "EMPLOYEE", + positionLeaveName, + oc, + }; + + return new HttpSuccess(mapProfile); + } + + /* ========================================= + * 2. current holder + * ========================================= */ + const currentHolder = profile.current_holders?.find( + x => + x.orgRevision?.orgRevisionIsDraft === false && + x.orgRevision?.orgRevisionIsCurrent === true, + ); + + const org = { + root: currentHolder?.orgRootId ?? null, + child1: currentHolder?.orgChild1Id ?? null, + child2: currentHolder?.orgChild2Id ?? null, + child3: currentHolder?.orgChild3Id ?? null, + child4: currentHolder?.orgChild4Id ?? null, + }; + + /* ================================================= + * 3. หา commander + * ================================================= */ + let commanderFullname = ""; + let commanderPositionName = ""; + let commanderId = ""; + let commanderKeycloak = ""; + + const pos = await this.posMasterRepository + .createQueryBuilder("pos") + .leftJoinAndSelect("pos.current_holder", "holder") + .leftJoin("pos.orgRevision", "rev") + .where("rev.orgRevisionIsCurrent = true") + .andWhere("rev.orgRevisionIsDraft = false") + .andWhere("pos.isDirector = true") + .andWhere("pos.current_holderId IS NOT NULL") + .andWhere("pos.orgRootId = :root", { root: org.root }) + .andWhere( + `(pos.orgChild1Id = :c1 OR pos.orgChild1Id IS NULL) + AND (pos.orgChild2Id = :c2 OR pos.orgChild2Id IS NULL) + AND (pos.orgChild3Id = :c3 OR pos.orgChild3Id IS NULL) + AND (pos.orgChild4Id = :c4 OR pos.orgChild4Id IS NULL)`, + { + c1: org.child1, + c2: org.child2, + c3: org.child3, + c4: org.child4, + }, + ) + .orderBy( + `(CASE WHEN pos.orgChild4Id IS NULL THEN 1 ELSE 0 END) + + (CASE WHEN pos.orgChild3Id IS NULL THEN 1 ELSE 0 END) + + (CASE WHEN pos.orgChild2Id IS NULL THEN 1 ELSE 0 END) + + (CASE WHEN pos.orgChild1Id IS NULL THEN 1 ELSE 0 END)`, + "ASC", + ) + .getOne(); + + if (pos?.current_holder) { + commanderFullname = + `${pos.current_holder.prefix}${pos.current_holder.firstName} ${pos.current_holder.lastName}`; + commanderPositionName = pos.current_holder.position; + commanderId = pos.current_holder.id; + commanderKeycloak = pos.current_holder.keycloak; + } + + /* ========================================= + * 4. salary / insignia (เอาแค่ล่าสุด) + * ========================================= */ + const [latestSalary, latestInsignia] = await Promise.all([ + this.salaryRepo.findOne({ + where: { profileId: profile.id }, + order: { commandDateAffect: "DESC" }, + }), + this.insigniaRepo.findOne({ + where: { profileId: profile.id }, + order: { receiveDate: "DESC" }, + }), + ]); + + /* ========================================= + * 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 = { + id: profile.id, + avatar: profile.avatar, + avatarName: profile.avatarName, + rank: profile.rank, + prefix: profile.prefix, + firstName: profile.firstName, + lastName: profile.lastName, + citizenId: profile.citizenId, + position: profile.position, + posLevelId: profile.posLevelId, + email: profile.email, + phone: profile.phone, + keycloak: profile.keycloak, + isProbation: profile.isProbation, + isLeave: profile.isLeave, + leaveReason: profile.leaveReason, + 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, + registrationAddress: profile.registrationAddress, + registrationProvinceId: profile.registrationProvinceId, + registrationDistrictId: profile.registrationDistrictId, + registrationSubDistrictId: profile.registrationSubDistrictId, + registrationZipCode: profile.registrationZipCode, + registrationProvince: profile.registrationProvince?.name ?? null, + registrationDistrict: profile.registrationDistrict?.name ?? null, + registrationSubDistrict: profile.registrationSubDistrict?.name ?? null, + currentAddress: profile.currentAddress, + currentProvinceId: profile.currentProvinceId, + currentDistrictId: profile.currentDistrictId, + currentSubDistrictId: profile.currentSubDistrictId, + currentZipCode: profile.currentZipCode, + currentProvince: profile.currentProvince?.name ?? null, + currentDistrict: profile.currentDistrict?.name ?? null, + currentSubDistrict: profile.currentSubDistrict?.name ?? null, + dutyTimeId: profile.dutyTimeId, + dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate, + amount: profile.amount, + positionSalaryAmount: profile.positionSalaryAmount, + mouthSalaryAmount: profile.mouthSalaryAmount, + 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, + commander: commanderFullname, + commanderPositionName, + commanderId, + commanderKeycloak, + posLevel: profile.posLevel?.posLevelName ?? null, + posType: profile.posType?.posTypeName ?? null, + profileSalary: latestSalary ?? null, + profileInsignia: latestInsignia ?? null, + profileType: "OFFICER", + positionLeaveName, + posExecutiveName: position?.posExecutive?.posExecutiveName ?? null, + oc, + }; + + return new HttpSuccess(mapProfile); + } /** * 3. API Get Profile จาก profile id *