import {
  Controller,
  Post,
  Put,
  Delete,
  Route,
  Security,
  Tags,
  Body,
  Path,
  Request,
  SuccessResponse,
  Response,
  Get,
  Query,
  Example,
  Patch,
} from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatus from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import {
  Profile,
  CreateProfile,
  UpdateProfile,
  ProfileHistory,
  CreateProfileAllFields,
  UpdateProfileReqEdit,
  UpdateProfileFather,
  UpdateProfileMother,
  UpdateProfileCouple,
  UpdatePrivacyDto,
} from "../entities/Profile";
import { Brackets, In, IsNull, Like, Not, MoreThan } from "typeorm";
import { OrgRevision } from "../entities/OrgRevision";
import { PosMaster } from "../entities/PosMaster";
import { PosLevel } from "../entities/PosLevel";
import { PosType } from "../entities/PosType";
import {
  calculateAge,
  calculateRetireDate,
  calculateRetireLaw,
  removeProfileInOrganize,
  setLogDataDiff,
} from "../interfaces/utils";
import { RequestWithUser } from "../middlewares/user";
import { Position } from "../entities/Position";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import { Province } from "../entities/Province";
import { District } from "../entities/District";
import { SubDistrict } from "../entities/SubDistrict";
import { ProfileCertificate } from "../entities/ProfileCertificate";
import { ProfileTraining } from "../entities/ProfileTraining";
import { ProfileDiscipline } from "../entities/ProfileDiscipline";
import { ProfileEducation } from "../entities/ProfileEducation";
import { ProfileSalary } from "../entities/ProfileSalary";
import { ProfileFamilyCouple } from "../entities/ProfileFamilyCouple";
import { ProfileFamilyMother } from "../entities/ProfileFamilyMother";
import { ProfileFamilyFather } from "../entities/ProfileFamilyFather";
import Extension from "../interfaces/extension";
import { ProfileInsignia } from "../entities/ProfileInsignia";
import { ProfileLeave } from "../entities/ProfileLeave";
import { ProfileAbsentLate } from "../entities/ProfileAbsentLate";
import { updateName, deleteUser } from "../keycloak";
import permission from "../interfaces/permission";
import { PosMasterAct } from "../entities/PosMasterAct";
import axios from "axios";
import { ProfileFamilyFatherHistory } from "../entities/ProfileFamilyFatherHistory";
import { ProfileFamilyMotherHistory } from "../entities/ProfileFamilyMotherHistory";
import { ProfileFamilyCoupleHistory } from "../entities/ProfileFamilyCoupleHistory";
import { viewDirector } from "../entities/view/viewDirector";
import { viewDirectorActing } from "../entities/view/viewDirectorActing";
import CallAPI from "../interfaces/call-api";
import { OrgRoot } from "../entities/OrgRoot";
import { ProfileChildren } from "../entities/ProfileChildren";
import { ProfileChangeName } from "../entities/ProfileChangeName";
import { ProfileActposition } from "../entities/ProfileActposition";
import { ProfileDuty } from "../entities/ProfileDuty";
import { ProfileAssessment } from "../entities/ProfileAssessment";
import { ProfileAbility } from "../entities/ProfileAbility";
import { PermissionProfile } from "../entities/PermissionProfile";
import { OrgChild1 } from "../entities/OrgChild1";
import { OrgChild2 } from "../entities/OrgChild2";
import { OrgChild3 } from "../entities/OrgChild3";
import { OrgChild4 } from "../entities/OrgChild4";
import { ProfileSalaryHistory } from "../entities/ProfileSalaryHistory";
import { ProfileAssistance } from "../entities/ProfileAssistance";
import { CommandRecive } from "../entities/CommandRecive";
import { CommandCode } from "../entities/CommandCode";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { CreatePosMasterHistoryOfficer, getTopDegrees, getPosMasterPositions } from "../services/PositionService";
import { ProfileLeaveService } from "../services/ProfileLeaveService";
// import { PostRetireToExprofile } from "./ExRetirementController";
import { getPosNumCodeSit } from "../services/CommandService";
import { updateHolderProfileHistory } from "../services/PositionService";
@Route("api/v1/org/profile")
@Tags("Profile")
@Security("bearerAuth")
@Response(
  HttpStatus.INTERNAL_SERVER_ERROR,
  "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
@SuccessResponse(HttpStatus.OK, "สำเร็จ")
export class ProfileController extends Controller {
  private orgRevisionRepo = AppDataSource.getRepository(OrgRevision);
  private orgRootRepo = AppDataSource.getRepository(OrgRoot);
  private orgChild1Repo = AppDataSource.getRepository(OrgChild1);
  private orgChild2Repo = AppDataSource.getRepository(OrgChild2);
  private orgChild3Repo = AppDataSource.getRepository(OrgChild3);
  private orgChild4Repo = AppDataSource.getRepository(OrgChild4);
  private posMasterRepo = AppDataSource.getRepository(PosMaster);
  private employeePosMasterRepo = AppDataSource.getRepository(EmployeePosMaster);
  private profileRepo = AppDataSource.getRepository(Profile);
  private profileEmpRepo = AppDataSource.getRepository(ProfileEmployee);
  private profileHistoryRepo = AppDataSource.getRepository(ProfileHistory);
  private posLevelRepo = AppDataSource.getRepository(PosLevel);
  private posTypeRepo = AppDataSource.getRepository(PosType);
  private positionRepository = AppDataSource.getRepository(Position);
  private provinceRepository = AppDataSource.getRepository(Province);
  private districtRepository = AppDataSource.getRepository(District);
  private subDistrict = AppDataSource.getRepository(SubDistrict);
  private certificateRepository = AppDataSource.getRepository(ProfileCertificate);
  private profileFamilyCoupleRepository = AppDataSource.getRepository(ProfileFamilyCouple);
  private profileFamilyCoupleHistoryRepo = AppDataSource.getRepository(ProfileFamilyCoupleHistory);
  private profileFamilyMotherRepository = AppDataSource.getRepository(ProfileFamilyMother);
  private profileFamilyMotherHistoryRepo = AppDataSource.getRepository(ProfileFamilyMotherHistory);
  private profileFamilyFatherRepository = AppDataSource.getRepository(ProfileFamilyFather);
  private profileFamilyFatherHistoryRepo = AppDataSource.getRepository(ProfileFamilyFatherHistory);
  private trainingRepository = AppDataSource.getRepository(ProfileTraining);
  private disciplineRepository = AppDataSource.getRepository(ProfileDiscipline);
  private salaryRepo = AppDataSource.getRepository(ProfileSalary);
  private salaryHistoryRepo = AppDataSource.getRepository(ProfileSalaryHistory);
  private profileEducationRepo = AppDataSource.getRepository(ProfileEducation);
  private provinceRepo = AppDataSource.getRepository(Province);
  private districtRepo = AppDataSource.getRepository(District);
  private subDistrictRepo = AppDataSource.getRepository(SubDistrict);
  private profileInsigniaRepo = AppDataSource.getRepository(ProfileInsignia);
  private profileLeaveRepository = AppDataSource.getRepository(ProfileLeave);
  private profileAbsentLateRepo = AppDataSource.getRepository(ProfileAbsentLate);
  private posMasterActRepository = AppDataSource.getRepository(PosMasterAct);
  private profileChildrenRepository = AppDataSource.getRepository(ProfileChildren);
  private changeNameRepository = AppDataSource.getRepository(ProfileChangeName);
  private profileActpositionRepo = AppDataSource.getRepository(ProfileActposition);
  private dutyRepository = AppDataSource.getRepository(ProfileDuty);
  private profileAssessmentsRepository = AppDataSource.getRepository(ProfileAssessment);
  private profileAbilityRepo = AppDataSource.getRepository(ProfileAbility);
  private permissionProflileRepository = AppDataSource.getRepository(PermissionProfile);
  private profileAssistanceRepository = AppDataSource.getRepository(ProfileAssistance);
  private commandReciveRepository = AppDataSource.getRepository(CommandRecive);
  private commandCodeRepository = AppDataSource.getRepository(CommandCode);

  // Services
  private profileLeaveService = new ProfileLeaveService();

  /**
   * report ประวัติแบบย่อ ข้าราชการ
   *
   * @summary report ประวัติแบบย่อ ข้าราชการ
   *
   * @param {string} id  Id โปรไฟล์
   */
  @Get("kp7-short/{id}")
  async kp7ShortById(@Path() id: string, @Request() req: RequestWithUser) {
    const orgRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });

    const profile = await this.profileRepo.findOne({
      relations: [
        "profileSalary",
        "profileEducations",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { id: id },
      order: {
        profileSalary: {
          commandDateAffect: "DESC",
        },
      },
    });
    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    let ImgUrl: any;
    if (profile?.avatar != null && profile?.avatarName != null) {
      // await new CallAPI()
      //   .GetData(req, `/salary/file/${profile?.avatar}/${profile?.avatarName}`)
      //   .then(async (x) => {
      //     ImgUrl = x.downloadUrl;
      //   })
      //   .catch();
      let req_: any = req;
      const token_ = "Bearer " + req_.headers.authorization.replace("Bearer ", "");
      const url = process.env.API_URL + `/salary/file/${profile?.avatar}/${profile?.avatarName}`;
      try {
        const response_ = await axios.get(url, {
          headers: {
            Authorization: `${token_}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        });
        ImgUrl = response_.data.downloadUrl;
      } catch { }
    }
    const province = await this.provinceRepository.findOneBy({
      id: profile.registrationProvinceId,
    });
    const district = await this.districtRepository.findOneBy({
      id: profile.registrationDistrictId,
    });
    const subDistrict = await this.subDistrict.findOneBy({ id: profile.registrationSubDistrictId });

    const root =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot;

    const child1 =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1;

    const child2 =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2;

    const child3 =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3;

    const child4 =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4;

    let _regisAddres =
      profile && profile.registrationAddress != null ? profile.registrationAddress : "";
    let _subDistrict =
      subDistrict && subDistrict.name != null ? `\r\nตำบล/แขวง ${province?.name}` : "";
    let _district = district && district.name != null ? `\r\nเขต/อำเภอ ${district?.name}` : "";
    let _province = province && province.name != null ? `\r\nจังหวัด ${province?.name}` : "";
    let registrationZipCode =
      profile && profile.registrationZipCode != null
        ? ` รหัสไปรษณีย์ ${profile.registrationZipCode}`
        : "";
    let _root = root?.orgRootName;
    let _child1 = child1?.orgChild1Name;
    let _child2 = child2?.orgChild2Name;
    let _child3 = child3?.orgChild3Name;
    let _child4 = child4?.orgChild4Name;

    const salary_raw = await this.salaryRepo.find({
      //   select: [
      //     "commandDateAffect",
      //     "positionName",
      //     "posNo",
      //     "positionType",
      //     "positionLevel",
      //     "positionSalaryAmount",
      //     "commandNo",
      //     "amount",
      //     "remark",
      //     "orgRoot",
      //     "orgChild1",
      //     "orgChild2",
      //     "orgChild3",
      //     "orgChild4",
      //     "positionExecutive",
      //   ],
      where: {
        profileId: id,
        commandCode: In(["1", "2", "3", "4", "8", "10", "11", "12", "15", "16", "20"]),
      },
      order: { order: "ASC" },
    });

    const salarys =
      salary_raw.length > 1
        ? salary_raw.slice(1).map((item) => ({
          date: item.commandDateAffect
            ? Extension.ToThaiNumber(Extension.ToThaiShortDate(item.commandDateAffect))
            : null,
          position: Extension.ToThaiNumber(
            Extension.ToThaiNumber(
              `${item.positionName != null ? item.positionName : "-"} ${item.positionType == null ? item.positionCee ?? "" : (item.positionType == "อำนวยการ" || item.positionType == "บริหาร" ? item.positionType : "") + item.positionLevel}`,
            ),
          ),
          posNo: item.posNo != null ? Extension.ToThaiNumber(item.posNo) : "",
          orgRoot: item.orgRoot != null ? Extension.ToThaiNumber(item.orgRoot) : "",
          orgChild1: item.orgChild1 != null ? Extension.ToThaiNumber(item.orgChild1) : "",
          orgChild2: item.orgChild2 != null ? Extension.ToThaiNumber(item.orgChild2) : "",
          orgChild3: item.orgChild3 != null ? Extension.ToThaiNumber(item.orgChild3) : "",
          orgChild4: item.orgChild4 != null ? Extension.ToThaiNumber(item.orgChild4) : "",
          positionCee: item.positionCee != null ? Extension.ToThaiNumber(item.positionCee) : "",
          positionExecutive:
            item.positionExecutive != null ? Extension.ToThaiNumber(item.positionExecutive) : "",
        }))
        : [
          {
            date: "-",
            position: "-",
            posNo: "-",
            orgRoot: null,
            orgChild1: null,
            orgChild2: null,
            orgChild3: null,
            orgChild4: null,
            positionCee: null,
            positionExecutive: null,
          },
        ];

    const educations = await this.profileEducationRepo.find({
      select: [
        "startDate",
        "endDate",
        "educationLevel",
        "degree",
        "field",
        "institute",
        "isDeleted",
      ],
      where: { profileId: id, isDeleted: false },
      order: { level: "ASC" },
    });
    const Education =
      educations && educations.length > 0
        ? educations.map((item) => ({
          institute: item.institute ? item.institute : "-",
          date:
            item.startDate && item.endDate
              ? `${Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.startDate))} - ${Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.endDate))}`
              : "-",
          degree: item.degree ? item.degree : "-",
        }))
        : [
          {
            institute: "-",
            date: "-",
            degree: "-",
          },
        ];

    const mapData = {
      // Id: profile.id,
      fullName: `${profile?.prefix}${profile?.firstName} ${profile?.lastName}`,
      prefix: profile.prefix != null ? profile.prefix : null,
      firstName: profile.firstName != null ? profile.firstName : null,
      lastName: profile.lastName != null ? profile.lastName : null,
      citizenId: profile.citizenId != null ? Extension.ToThaiNumber(profile.citizenId) : "",
      dateOfBirth:
        profile.birthDate != null
          ? Extension.ToThaiNumber(Extension.ToThaiShortDate_monthYear2(profile.birthDate))
          : "",
      dateRetire:
        profile.dateRetire != null
          ? Extension.ToThaiNumber(Extension.ToThaiShortDate_monthYear2(profile.dateRetire))
          : "",
      salaryAmount:
        profile.amount != null ? Extension.ToThaiNumber(profile.amount.toLocaleString()) : "",
      registrationAddress: Extension.ToThaiNumber(
        `${_regisAddres}${_subDistrict}${_district}${_province}${registrationZipCode}`,
      ),
      date:
        salary_raw.length > 0 && salary_raw[0].commandDateAffect != null
          ? Extension.ToThaiNumber(Extension.ToThaiShortDate(salary_raw[0].commandDateAffect))
          : "",
      positionName: profile.position != null ? profile.position : "",
      appointText:
        profile.dateAppoint != null
          ? Extension.ToThaiNumber(Extension.ToThaiShortDate(profile.dateAppoint))
          : "",
      posNo:
        salary_raw.length > 0 && salary_raw[0].posNo != null
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].posNo))
          : "",
      position:
        salary_raw.length > 0 && salary_raw[0].positionName != null
          ? Extension.ToThaiNumber(
            Extension.ToThaiNumber(
              `${salary_raw[0].positionName != null ? salary_raw[0].positionName : "-"} ${salary_raw[0].positionType == null ? salary_raw[0].positionCee ?? "" : (salary_raw[0].positionType == "อำนวยการ" || salary_raw[0].positionType == "บริหาร" ? salary_raw[0].positionType : "") + salary_raw[0].positionLevel}`,
            ),
          )
          : "",
      positionCee:
        salary_raw.length > 0 && salary_raw[0].positionCee != null
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].positionCee))
          : "",
      positionExecutive:
        salary_raw.length > 0 && salary_raw[0].positionExecutive != null
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].positionExecutive))
          : "",
      org: `${salary_raw.length > 0 && salary_raw[0].orgChild4 && salary_raw[0].orgChild4 != "-"
        ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].orgChild4)) + " "
        : ""
        }${salary_raw.length > 0 && salary_raw[0].orgChild3 && salary_raw[0].orgChild3 != "-"
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].orgChild3)) + " "
          : ""
        }${salary_raw.length > 0 && salary_raw[0].orgChild2 && salary_raw[0].orgChild2 != "-"
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].orgChild2)) + " "
          : ""
        }${salary_raw.length > 0 && salary_raw[0].orgChild1 && salary_raw[0].orgChild1 != "-"
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].orgChild1)) + " "
          : ""
        }${salary_raw.length > 0 && salary_raw[0].orgRoot && salary_raw[0].orgRoot != "-"
          ? Extension.ToThaiNumber(Extension.ToThaiNumber(salary_raw[0].orgRoot))
          : ""
        }`,
      ocFullPath:
        (_child4 == null ? "" : _child4 + "\n") +
        (_child3 == null ? "" : _child3 + "\n") +
        (_child2 == null ? "" : _child2 + "\n") +
        (_child1 == null ? "" : _child1 + "\n") +
        (_root == null ? "" : _root),
      educations: Education,
      salarys: salarys.map((item) => {
        return {
          ...item,
          org: `${item.orgChild4 && item.orgChild4 != "-" ? item.orgChild4 + " " : ""}${item.orgChild3 && item.orgChild3 != "-" ? item.orgChild3 + " " : ""}${item.orgChild2 && item.orgChild2 != "-" ? item.orgChild2 + " " : ""}${item.orgChild1 && item.orgChild1 != "-" ? item.orgChild1 + " " : ""}${item.orgRoot && item.orgRoot != "-" ? item.orgRoot + " " : ""}`,
        };
      }),
      url: ImgUrl ? ImgUrl : `${process.env.VITE_URL_MGT}`,
    };

    return new HttpSuccess({
      template: "kp7",
      reportName: "docx-report",
      data: mapData,
    });
  }

  /**
   * รายงาน ก.ก.1 (ข้าราชการ)
   *
   * @summary รายงาน ก.ก.1 (ข้าราชการ)
   *
   * @param {string} id  Id โปรไฟล์
   */
  @Get("kk1old/{id}")
  public async getKk1(@Path() id: string, @Request() req: RequestWithUser) {
    const profiles = await this.profileRepo.findOne({
      relations: ["currentSubDistrict", "currentDistrict", "currentProvince", "profileAvatars"],
      order: {
        profileAvatars: { createdAt: "ASC" },
      },
      where: { id: id },
    });
    if (!profiles) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    let ImgUrl: any = null;
    let _ImgUrl: any = [];
    if (profiles?.avatar != null && profiles?.avatarName != null) {
      // await new CallAPI()
      //   .GetData(req, `/salary/file/${profiles?.avatar}/${profiles?.avatarName}`)
      //   .then(async (x) => {
      //     ImgUrl = x.downloadUrl;
      //   })
      //   .catch();

      let req_: any = req;
      const token_ = "Bearer " + req_.headers.authorization.replace("Bearer ", "");

      await Promise.all(
        await profiles.profileAvatars.slice(-7).map(async (x, i) => {
          if (x == null) {
            _ImgUrl[i] = null;
          } else {
            const url = process.env.API_URL + `/salary/file/${x?.avatar}/${x?.avatarName}`;
            try {
              const response_ = await axios.get(url, {
                headers: {
                  Authorization: `${token_}`,
                  "Content-Type": "application/json",
                  api_key: process.env.API_KEY,
                },
              });
              _ImgUrl[i] = response_.data.downloadUrl;
            } catch { }
          }
        }),
      );
      const url = process.env.API_URL + `/salary/file/${profiles?.avatar}/${profiles?.avatarName}`;
      try {
        const response_ = await axios.get(url, {
          headers: {
            Authorization: `${token_}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        });
        ImgUrl = response_.data.downloadUrl;
      } catch { }
    }
    const profileOc = await this.profileRepo.findOne({
      relations: [
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { id: id },
    });
    if (!profileOc) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    const orgRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });

    const profileFamilyCouple = await this.profileFamilyCoupleRepository.findOne({
      where: { profileId: id },
      select: ["couplePrefix", "coupleFirstName", "coupleLastName", "coupleLastNameOld"],
      order: { lastUpdatedAt: "DESC" },
    });

    const profileFamilyMother = await this.profileFamilyMotherRepository.findOne({
      where: { profileId: id },
      select: ["motherPrefix", "motherFirstName", "motherLastName"],
      order: { lastUpdatedAt: "DESC" },
    });

    const profileFamilyFather = await this.profileFamilyFatherRepository.findOne({
      where: { profileId: id },
      select: ["fatherPrefix", "fatherFirstName", "fatherLastName"],
      order: { lastUpdatedAt: "DESC" },
    });

    const root =
      profileOc.current_holders == null ||
        profileOc.current_holders.length == 0 ||
        profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot;

    const child1 =
      profileOc.current_holders == null ||
        profileOc.current_holders.length == 0 ||
        profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1;

    const child2 =
      profileOc.current_holders == null ||
        profileOc.current_holders.length == 0 ||
        profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2;

    const child3 =
      profileOc.current_holders == null ||
        profileOc.current_holders.length == 0 ||
        profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3;

    const child4 =
      profileOc.current_holders == null ||
        profileOc.current_holders.length == 0 ||
        profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profileOc.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4;

    // Construct org path
    let _root = root?.orgRootName;
    let _child1 = child1?.orgChild1Name;
    let _child2 = child2?.orgChild2Name;
    let _child3 = child3?.orgChild3Name;
    let _child4 = child4?.orgChild4Name;

    const cert_raw = await this.certificateRepository.find({
      select: ["certificateType", "issuer", "certificateNo", "issueDate", "isDeleted"],
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const certs =
      cert_raw.length > 0
        ? cert_raw.slice(-2).map((item) => ({
          certificateType: item.certificateType ?? null,
          issuer: item.issuer ?? null,
          certificateNo: Extension.ToThaiNumber(item.certificateNo) ?? null,
          issueDate: Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.issueDate)) ?? null,
        }))
        : [
          {
            certificateType: "-",
            issuer: "-",
            certificateNo: "-",
            issueDate: "-",
          },
        ];
    const training_raw = await this.trainingRepository.find({
      select: ["startDate", "endDate", "place", "department", "name", "isDeleted"],
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const trainings =
      training_raw.length > 0
        ? training_raw.slice(-2).map((item) => ({
          institute: item.department ?? "",
          start:
            item.startDate == null
              ? ""
              : Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.startDate)),
          end:
            item.endDate == null
              ? ""
              : Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.endDate)),
          date:
            item.startDate && item.endDate
              ? `${Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.startDate))} - ${Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.endDate))}`
              : "",
          level: "",
          degree: item.name,
          field: "",
        }))
        : [
          {
            institute: "-",
            start: "-",
            end: "-",
            date: "-",
            level: "-",
            degree: "-",
            field: "-",
          },
        ];

    const discipline_raw = await this.disciplineRepository.find({
      select: ["refCommandDate", "refCommandNo", "detail", "isDeleted"],
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const disciplines =
      discipline_raw.length > 0
        ? discipline_raw.slice(-2).map((item) => ({
          disciplineYear:
            Extension.ToThaiNumber(new Date(item.refCommandDate).getFullYear().toString()) ??
            null,
          disciplineDetail: item.detail ?? null,
          refNo: Extension.ToThaiNumber(item.refCommandNo) ?? null,
        }))
        : [
          {
            disciplineYear: "-",
            disciplineDetail: "-",
            refNo: "-",
          },
        ];

    const education_raw = await this.profileEducationRepo.find({
      select: [
        "startDate",
        "endDate",
        "educationLevel",
        "degree",
        "field",
        "institute",
        "isDeleted",
      ],
      where: { profileId: id, isDeleted: false },
      // order: { lastUpdatedAt: "DESC" },
      order: { level: "ASC" },
    });
    const educations =
      education_raw.length > 0
        ? education_raw.slice(-2).map((item) => ({
          institute: item.institute,
          start:
            item.startDate == null
              ? ""
              : Extension.ToThaiNumber(new Date(item.startDate).getFullYear().toString()),
          end:
            item.endDate == null
              ? ""
              : Extension.ToThaiNumber(new Date(item.endDate).getFullYear().toString()),
          date:
            item.startDate && item.endDate
              ? `${Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.startDate))} - ${Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.endDate))}`
              : "",
          level: item.educationLevel ?? "",
          degree: item.degree ? `${item.degree} ${item.field ? item.field : ""}` : "",
          field: item.field ?? "-",
        }))
        : [
          {
            institute: "-",
            start: "-",
            end: "-",
            date: "-",
            level: "-",
            degree: "-",
            field: "-",
          },
        ];
    const salary_raw = await this.salaryRepo.find({
      select: [
        "commandDateAffect",
        "positionName",
        "posNo",
        "positionType",
        "positionLevel",
        "positionSalaryAmount",
        "commandNo",
        "amount",
        "remark",
      ],
      where: { profileId: id },
      order: { order: "ASC" },
    });

    const salarys =
      salary_raw.length > 0
        ? salary_raw.map((item) => ({
          salaryDate: item.commandDateAffect
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateAffect))
            : null,
          position: item.positionName != null ? Extension.ToThaiNumber(item.positionName) : null,
          posNo: item.posNo != null ? Extension.ToThaiNumber(item.posNo) : null,
          salary:
            item.amount != null ? Extension.ToThaiNumber(item.amount.toLocaleString()) : null,
          rank: item.positionLevel != null ? Extension.ToThaiNumber(item.positionLevel) : null,
          refAll: item.remark ? Extension.ToThaiNumber(item.remark) : null,
          positionLevel:
            item.positionLevel != null ? Extension.ToThaiNumber(item.positionLevel) : null,
          positionType: item.positionType ?? null,
          positionAmount:
            item.positionSalaryAmount == null
              ? null
              : Extension.ToThaiNumber(item.positionSalaryAmount.toLocaleString()),
          fullName: `${profiles?.prefix}${profiles?.firstName} ${profiles?.lastName}`,
          ocFullPath:
            (_child4 == null ? "" : _child4 + "\n") +
            (_child3 == null ? "" : _child3 + "\n") +
            (_child2 == null ? "" : _child2 + "\n") +
            (_child1 == null ? "" : _child1 + "\n") +
            (_root == null ? "" : _root),
        }))
        : [
          {
            salaryDate: "-",
            position: "-",
            posNo: "-",
            salary: "-",
            rank: "-",
            refAll: "-",
            positionLevel: "-",
            positionType: "-",
            positionAmount: "-",
            fullName: "-",
            ocFullPath: "-",
          },
        ];

    const insignia_raw = await this.profileInsigniaRepo.find({
      relations: {
        insignia: {
          insigniaType: true,
        },
      },
      where: { profileId: id, isDeleted: false },
      order: { receiveDate: "ASC" },
    });
    const insignias =
      insignia_raw.length > 0
        ? insignia_raw.map((item) => ({
          receiveDate: item.receiveDate
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.receiveDate))
            : "",
          insigniaName: item.insignia.name,
          insigniaShortName: item.insignia.shortName,
          insigniaTypeName: item.insignia.insigniaType.name,
          no: item.no ? Extension.ToThaiNumber(item.no) : "",
          issue: item.issue ? item.issue : "",
          volumeNo: item.volumeNo ? Extension.ToThaiNumber(item.volumeNo) : "",
          volume: item.volume ? Extension.ToThaiNumber(item.volume) : "",
          section: item.section ? Extension.ToThaiNumber(item.section) : "",
          page: item.page ? Extension.ToThaiNumber(item.page) : "",
          refCommandDate: item.refCommandDate
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.refCommandDate))
            : "",
        }))
        : [
          {
            receiveDate: "-",
            insigniaName: "-",
            insigniaShortName: "-",
            insigniaTypeName: "-",
            no: "-",
            issue: "-",
            volumeNo: "-",
            volume: "-",
            section: "-",
            page: "-",
            refCommandDate: "-",
          },
        ];

    const leave_raw = await this.profileLeaveRepository.find({
      relations: { leaveType: true },
      where: { profileId: id, isDeleted: false },
      order: { dateLeaveStart: "ASC" },
    });
    const leaves =
      leave_raw.length > 0
        ? leave_raw.map((item) => ({
          leaveTypeName: item.leaveType.name,
          dateLeaveStart: item.dateLeaveStart
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveStart))
            : "",
          leaveDays: item.leaveDays ? Extension.ToThaiNumber(item.leaveDays.toString()) : "",
        }))
        : [
          {
            leaveTypeName: "-",
            dateLeaveStart: "-",
            leaveDays: "-",
          },
        ];

    const data = {
      fullName: `${profiles?.prefix}${profiles?.firstName} ${profiles?.lastName}`,
      prefix: profiles?.prefix != null ? profiles.prefix : "",
      firstName: profiles?.firstName != null ? profiles.firstName : "",
      lastName: profiles?.lastName != null ? profiles.lastName : "",
      ocFullPath:
        (_child4 == null ? "" : _child4 + "\n") +
        (_child3 == null ? "" : _child3 + "\n") +
        (_child2 == null ? "" : _child2 + "\n") +
        (_child1 == null ? "" : _child1 + "\n") +
        (_root == null ? "" : _root),
      birthDate: profiles?.birthDate
        ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.birthDate))
        : "",
      retireDate:
        profiles.dateRetireLaw != null
          ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.dateRetireLaw))
          : "",
      appointDate: profiles?.dateAppoint
        ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.dateAppoint))
        : "",
      citizenId:
        profiles.citizenId != null ? Extension.ToThaiNumber(profiles.citizenId.toString()) : "",
      fatherFullName:
        profileFamilyFather?.fatherPrefix ||
          profileFamilyFather?.fatherFirstName ||
          profileFamilyFather?.fatherLastName
          ? `${profileFamilyFather?.fatherPrefix ?? ""}${profileFamilyFather?.fatherFirstName ?? ""} ${profileFamilyFather?.fatherLastName ?? ""}`.trim()
          : null,
      motherFullName:
        profileFamilyMother?.motherPrefix ||
          profileFamilyMother?.motherFirstName ||
          profileFamilyMother?.motherLastName
          ? `${profileFamilyMother?.motherPrefix ?? ""}${profileFamilyMother?.motherFirstName ?? ""} ${profileFamilyMother?.motherLastName ?? ""}`.trim()
          : null,
      coupleFullName:
        profileFamilyCouple?.couplePrefix ||
          profileFamilyCouple?.coupleFirstName ||
          profileFamilyCouple?.coupleLastNameOld
          ? `${profileFamilyCouple?.couplePrefix ?? ""}${profileFamilyCouple?.coupleFirstName ?? ""} ${profileFamilyCouple?.coupleLastName ?? ""}`.trim()
          : null,
      coupleLastNameOld: profileFamilyCouple?.coupleLastNameOld ?? null,
      currentAddress:
        profiles.currentAddress != null ? Extension.ToThaiNumber(profiles.currentAddress) : "",
      currentSubDistrict:
        profiles.currentSubDistrict != null
          ? Extension.ToThaiNumber(profiles.currentSubDistrict.name)
          : "",
      currentDistrict:
        profiles.currentDistrict != null
          ? Extension.ToThaiNumber(profiles.currentDistrict.name)
          : "",
      currentProvince:
        profiles.currentProvince != null
          ? Extension.ToThaiNumber(profiles.currentProvince.name)
          : "",
      telephone: profiles.phone != null ? Extension.ToThaiNumber(profiles.phone) : "",
      url: ImgUrl ? ImgUrl : `${process.env.VITE_URL_MGT}`,
      url1: _ImgUrl[0] ? _ImgUrl[0] : null,
      yearUpload1: profiles.profileAvatars[0]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[0].createdAt))
        : null,
      url2: _ImgUrl[1] ? _ImgUrl[1] : null,
      yearUpload2: profiles.profileAvatars[1]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[1].createdAt))
        : null,
      url3: _ImgUrl[2] ? _ImgUrl[2] : null,
      yearUpload3: profiles.profileAvatars[2]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[2].createdAt))
        : null,
      url4: _ImgUrl[3] ? _ImgUrl[3] : null,
      yearUpload4: profiles.profileAvatars[3]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[3].createdAt))
        : null,
      url5: _ImgUrl[4] ? _ImgUrl[4] : null,
      yearUpload5: profiles.profileAvatars[4]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[4].createdAt))
        : null,
      url6: _ImgUrl[5] ? _ImgUrl[5] : null,
      yearUpload6: profiles.profileAvatars[5]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[5].createdAt))
        : null,
      url7: _ImgUrl[6] ? _ImgUrl[6] : null,
      yearUpload7: profiles.profileAvatars[6]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[6].createdAt))
        : null,
      insignias,
      leaves,
      certs,
      trainings,
      disciplines,
      educations,
      salarys,
    };

    return new HttpSuccess({
      template: "kk1",
      reportName: "docx-report",
      data: data,
    });
  }

  /**
   * รายงาน ก.ก.1 (ข้าราชการ) ใหม่
   *
   * @summary รายงาน ก.ก.1 (ข้าราชการ) ใหม่
   *
   * @param {string} id  Id โปรไฟล์
   */
  @Get("kk1/{id}")
  public async getKk1new(@Path() id: string, @Request() req: RequestWithUser) {
    const profiles = await this.profileRepo.findOne({
      relations: [
        "posLevel",
        "currentSubDistrict",
        "currentDistrict",
        "currentProvince",
        "registrationSubDistrict",
        "registrationDistrict",
        "registrationProvince",
        "profileAvatars",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      order: {
        profileAvatars: { createdAt: "ASC" },
      },
      where: { id: id },
    });
    if (!profiles) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    let ImgUrl: any = null;
    let _ImgUrl: any = [];
    if (profiles?.avatar != null && profiles?.avatarName != null) {
      let req_: any = req;
      const token_ = "Bearer " + req_.headers.authorization.replace("Bearer ", "");

      await Promise.all(
        await profiles.profileAvatars.slice(-7).map(async (x, i) => {
          if (x == null) {
            _ImgUrl[i] = null;
          } else {
            const url = process.env.API_URL + `/salary/file/${x?.avatar}/${x?.avatarName}`;
            try {
              const response_ = await axios.get(url, {
                headers: {
                  Authorization: `${token_}`,
                  "Content-Type": "application/json",
                  api_key: process.env.API_KEY,
                },
              });
              _ImgUrl[i] = response_.data.downloadUrl;
            } catch { }
          }
        }),
      );
      const url = process.env.API_URL + `/salary/file/${profiles?.avatar}/${profiles?.avatarName}`;
      try {
        const response_ = await axios.get(url, {
          headers: {
            Authorization: `${token_}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        });
        ImgUrl = response_.data.downloadUrl;
      } catch { }
    }

    const orgRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });

    const profileFamilyCouple = await this.profileFamilyCoupleRepository.findOne({
      where: { profileId: id },
      select: ["couplePrefix", "coupleFirstName", "coupleLastName", "coupleLastNameOld"],
      order: { lastUpdatedAt: "DESC" },
    });

    const profileFamilyMother = await this.profileFamilyMotherRepository.findOne({
      where: { profileId: id },
      select: ["motherPrefix", "motherFirstName", "motherLastName"],
      order: { lastUpdatedAt: "DESC" },
    });

    const profileFamilyFather = await this.profileFamilyFatherRepository.findOne({
      where: { profileId: id },
      select: ["fatherPrefix", "fatherFirstName", "fatherLastName"],
      order: { lastUpdatedAt: "DESC" },
    });

    const posMasterId =
      profiles.current_holders == null ||
        profiles.current_holders.length == 0 ||
        profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.id;

    const root =
      profiles.current_holders == null ||
        profiles.current_holders.length == 0 ||
        profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot;

    const child1 =
      profiles.current_holders == null ||
        profiles.current_holders.length == 0 ||
        profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1;

    const child2 =
      profiles.current_holders == null ||
        profiles.current_holders.length == 0 ||
        profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2;

    const child3 =
      profiles.current_holders == null ||
        profiles.current_holders.length == 0 ||
        profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3;

    const child4 =
      profiles.current_holders == null ||
        profiles.current_holders.length == 0 ||
        profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) == null
        ? null
        : profiles.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4;

    // Construct org path
    let _root = root?.orgRootName;
    let _child1 = child1?.orgChild1Name;
    let _child2 = child2?.orgChild2Name;
    let _child3 = child3?.orgChild3Name;
    let _child4 = child4?.orgChild4Name;

    const cert_raw = await this.certificateRepository.find({
      select: [
        "certificateType",
        "issuer",
        "certificateNo",
        "issueDate",
        "expireDate",
        "isDeleted",
      ],
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const certs =
      cert_raw.length > 0
        ? cert_raw.map((item) => ({
          certificateType: item.certificateType ?? null,
          issuer: item.issuer ?? null,
          certificateNo: item.certificateNo ? Extension.ToThaiNumber(item.certificateNo) : null,
          detail: Extension.ToThaiNumber(
            `${item.issuer ?? ""} ${item.certificateNo ?? ""}`.trim(),
          ),
          issueToExpireDate: item.issueDate
            ? 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))
              : "",
        }))
        : [
          {
            certificateType: "",
            issuer: "",
            certificateNo: "",
            detail: "",
            issueToExpireDate: "",
          },
        ];
    const training_raw = await this.trainingRepository.find({
      select: ["place", "department", "name", "duration", "isDeleted", "startDate", "endDate"],
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const trainings =
      training_raw.length > 0
        ? training_raw.map((item) => ({
          institute: item.department ?? "",
          degree: item.name ? Extension.ToThaiNumber(item.name) : "",
          place: item.place ? Extension.ToThaiNumber(item.place) : "",
          duration: item.duration ? Extension.ToThaiNumber(item.duration) : "",
          date: Extension.ToThaiNumber(
            `${Extension.ToThaiFullDate2(item.startDate)} - ${Extension.ToThaiFullDate2(item.endDate)}`,
          ),
        }))
        : [
          {
            institute: "",
            degree: "",
            place: "",
            duration: "",
            date: "",
          },
        ];

    const discipline_raw = await this.disciplineRepository.find({
      select: ["refCommandDate", "refCommandNo", "detail", "level", "isDeleted"],
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const disciplines =
      discipline_raw.length > 0
        ? discipline_raw.map((item) => ({
          disciplineYear: item.refCommandDate
            ? Extension.ToThaiNumber(Extension.ToThaiShortYear(new Date(item.refCommandDate)))
            : null,
          disciplineDetail: item.detail ?? null,
          refNo: Extension.ToThaiNumber(item.refCommandNo) ?? null,
          level: item.level ?? "",
        }))
        : [
          {
            disciplineYear: "",
            disciplineDetail: "",
            refNo: "",
            level: "",
          },
        ];

    const education_raw = await this.profileEducationRepo
      .createQueryBuilder("education")
      .where("education.profileId = :profileId", { profileId: id })
      .andWhere("education.isDeleted = :isDeleted", { isDeleted: false })
      .orderBy("CASE WHEN education.isEducation = true THEN 1 ELSE 2 END", "ASC")
      .addOrderBy("education.level", "ASC")
      .getMany();
    const educations =
      education_raw.length > 0
        ? education_raw.map((item) => ({
          institute: item.institute,
          date: item.isDate
            ? `${item.startDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.startDate)) : ""} - ${item.endDate ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.endDate)) : ""}`
            : `${item.startDate ? Extension.ToThaiNumber(Extension.ToThaiShortYear(new Date(item.startDate))) : ""} - ${item.endDate ? Extension.ToThaiNumber(Extension.ToThaiShortYear(new Date(item.endDate))) : ""}`,
          degree: `${item.degree ?? ""} ${item.field ?? ""}`.trim(),
          level: item.educationLevel,
        }))
        : [
          {
            institute: "",
            date: "",
            degree: "",
            level: "",
          },
        ];
    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"]),
        // isEntry: false,
      },
      order: { order: "ASC" },
    });

    const salarys =
      salary_raw.length > 0
        ? salary_raw.map((item) => ({
          commandName: item.commandName ?? "",
          salaryDate: item.commandDateAffect
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateAffect))
            : null,
          position: item.positionName != null ? Extension.ToThaiNumber(item.positionName) : null,
          posNo:
            item.posNoAbb && item.posNo
              ? Extension.ToThaiNumber(`${item.posNoAbb}${item.posNo}`)
              : null,
          salary:
            item.amount != null ? Extension.ToThaiNumber(item.amount.toLocaleString()) : null,
          special:
            item.amountSpecial != null
              ? Extension.ToThaiNumber(item.amountSpecial.toLocaleString())
              : null,
          rank: item.positionLevel != null ? Extension.ToThaiNumber(item.positionLevel) : null,
          refAll: item.remark ? Extension.ToThaiNumber(item.remark) : null,
          positionLevel: item.positionLevel
            ? Extension.ToThaiNumber(item.positionLevel)
            : item.positionCee
              ? Extension.ToThaiNumber(item.positionCee)
              : null,
          positionType: item.positionType ?? null,
          positionAmount:
            item.positionSalaryAmount == null
              ? null
              : Extension.ToThaiNumber(item.positionSalaryAmount.toLocaleString()),
          fullName: `${profiles?.prefix}${profiles?.firstName} ${profiles?.lastName}`,
          ocFullPath:
            (_child4 == null ? "" : _child4 + "\n") +
            (_child3 == null ? "" : _child3 + "\n") +
            (_child2 == null ? "" : _child2 + "\n") +
            (_child1 == null ? "" : _child1 + "\n") +
            (_root == null ? "" : _root),
        }))
        : [
          {
            commandName: "",
            salaryDate: "",
            position: "",
            posNo: "",
            salary: "",
            special: "",
            rank: "",
            refAll: "",
            positionLevel: "",
            positionType: "",
            positionAmount: "",
            fullName: "",
            ocFullPath: "",
          },
        ];

    const insignia_raw = await this.profileInsigniaRepo.find({
      select: [
        "receiveDate",
        "no",
        "issue",
        "volumeNo",
        "volume",
        "section",
        "page",
        "refCommandDate",
        "note",
        "isDeleted",
      ],
      relations: {
        insignia: {
          insigniaType: true,
        },
      },
      where: { profileId: id, isDeleted: false },
      order: { receiveDate: "ASC" },
    });
    const insignias =
      insignia_raw.length > 0
        ? insignia_raw.map((item) => ({
          receiveDate: item.receiveDate
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.receiveDate))
            : "",
          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) : "",
          volume: item.volume ? Extension.ToThaiNumber(item.volume) : "",
          section: item.section ? Extension.ToThaiNumber(item.section) : "",
          page: item.page ? Extension.ToThaiNumber(item.page) : "",
          refCommandDate: item.refCommandDate
            ? Extension.ToThaiNumber(
              `ราชกิจจานุเบกษา เล่มที่ ${item.volume ?? "-"} ตอนที่ ${item.section ?? "-"} ลว. ${Extension.ToThaiFullDate2(item.refCommandDate)}`,
            )
            : "-",
          note: item.note ? Extension.ToThaiNumber(item.note) : "",
        }))
        : [
          {
            receiveDate: "",
            insigniaName: "",
            insigniaShortName: "",
            insigniaTypeName: "",
            no: "",
            issue: "",
            volumeNo: "",
            volume: "",
            section: "",
            page: "",
            refCommandDate: "",
            note: "",
          },
        ];

    const leave_raw = await this.profileLeaveRepository
      .createQueryBuilder("profileLeave")
      .leftJoinAndSelect("profileLeave.leaveType", "leaveType")
      .select([
        "profileLeave.isDeleted",
        "profileLeave.leaveTypeId",
        "leaveType.name as name",
        "leaveType.code as code",
        "profileLeave.status",
        "profileLeave.profileId",
        "MAX(profileLeave.dateLeaveStart) as maxDateLeaveStart",
      ])
      .addSelect("SUM(profileLeave.leaveDays)", "totalLeaveDays")
      .where("profileLeave.profileId = :profileId", { profileId: id })
      .andWhere("profileLeave.isDeleted = :isDeleted", { isDeleted: false })
      .andWhere("profileLeave.status = :status", { status: "approve" })
      .groupBy("profileLeave.leaveTypeId")
      .orderBy("code", "ASC")
      .addOrderBy("maxDateLeaveStart", "ASC")
      .getRawMany();

    const leaves: any[] = [];

    leave_raw.forEach((item) => {
      const leaveTypeCode = item.code ? item.code.trim().toUpperCase() : "";
      if (leaveTypeCode.startsWith("LV-")) {
        const lvIndex = parseInt(leaveTypeCode.split("-")[1], 10);

        if (lvIndex >= 1 && lvIndex <= 11) {
          const leaveTypeCodeKey = `leaveTypeCodeLv${lvIndex}`;
          const totalLeaveDaysKey = `totalLeaveDaysLv${lvIndex}`;
          const leaveTypeNameKey = `leaveTypeNameLv${lvIndex}`;

          const leaveDate = item.maxDateLeaveStart ? new Date(item.maxDateLeaveStart) : null;
          const year = leaveDate
            ? Extension.ToThaiNumber(Extension.ToThaiShortYear(leaveDate))
            : "";

          let yearData = leaves.find((data) => data.year === year);
          if (!yearData) {
            yearData = { year };

            for (let i = 1; i <= 11; i++) {
              yearData[`leaveTypeCodeLv${i}`] = "";
              yearData[`totalLeaveDaysLv${i}`] = "";
              yearData[`leaveTypeNameLv${i}`] = "";
            }

            leaves.push(yearData);
          }

          yearData[leaveTypeCodeKey] = item.code ? item.code : "";
          yearData[totalLeaveDaysKey] = item.totalLeaveDays
            ? Extension.ToThaiNumber(item.totalLeaveDays.toString())
            : "-";
          yearData[leaveTypeNameKey] = item.name ? item.name : "";
        }
      }
    });

    // Query มาสาย/ขาดราชการ และ merge ตามปี
    const absentLate_raw = await this.profileAbsentLateRepo
      .createQueryBuilder("absentLate")
      .select([
        "YEAR(absentLate.stampDate) as year",
        "absentLate.status as status",
        "SUM(absentLate.stampAmount) as totalAmount",
      ])
      .where("absentLate.profileId = :profileId", { profileId: id })
      .andWhere("absentLate.isDeleted = :isDeleted", { isDeleted: false })
      .groupBy("YEAR(absentLate.stampDate), absentLate.status")
      .orderBy("year", "DESC")
      .getRawMany();

    // Merge มาสาย/ขาดราชการเข้า leaves array
    absentLate_raw.forEach((item) => {
      const year = item.year ? Extension.ToThaiNumber((item.year + 543).toString()) : "";

      let yearData = leaves.find((data) => data.year === year);

      // ถ้าไม่มีปีนั้นใน leaves ให้สร้างใหม่
      if (!yearData) {
        yearData = { year };
        for (let i = 1; i <= 11; i++) {
          yearData[`leaveTypeCodeLv${i}`] = "";
          yearData[`totalLeaveDaysLv${i}`] = "";
          yearData[`leaveTypeNameLv${i}`] = "";
        }
        leaves.push(yearData);
      }

      // เพิ่มข้อมูลมาสาย/ขาดราชการ
      if (item.status === "LATE") {
        yearData.late = item.totalAmount
          ? Extension.ToThaiNumber(parseFloat(item.totalAmount).toFixed(1))
          : "";
      } else if (item.status === "ABSENT") {
        yearData.absent = item.totalAmount
          ? Extension.ToThaiNumber(parseFloat(item.totalAmount).toFixed(1))
          : "";
      }
    });

    // // เติมค่า "" ถ้าไม่มีข้อมูลมาสาย/ขาดราชการ
    // leaves.forEach((yearData) => {
    //   if (!yearData.late) yearData.late = "";
    //   if (!yearData.absent) yearData.absent = "";
    // });

    if (leaves.length === 0) {
      leaves.push({ year: "" });
    }

    const leave2_raw = await this.profileLeaveRepository
      .createQueryBuilder("profileLeave")
      .leftJoinAndSelect("profileLeave.leaveType", "leaveType")
      .select([
        "profileLeave.leaveSubTypeName AS leaveSubTypeName",
        "profileLeave.coupleDayLevelCountry AS coupleDayLevelCountry",
        "profileLeave.isDeleted AS isDeleted",
        "profileLeave.dateLeaveStart AS dateLeaveStart",
        "profileLeave.dateLeaveEnd AS dateLeaveEnd",
        "profileLeave.leaveDays AS leaveDays",
        "profileLeave.reason AS reason",
        "leaveType.name as name",
        "leaveType.code as code",
      ])
      .where("profileLeave.profileId = :profileId", { profileId: id })
      .andWhere("profileLeave.isDeleted = :isDeleted", { isDeleted: false })
      .andWhere("leaveType.code IN (:...codes)", { codes: ["LV-008", "LV-009", "LV-010"] })
      .andWhere("profileLeave.status = :status", { status: "approve" })
      .orderBy("leaveType.code", "ASC")
      .getRawMany();
    const leaves2 =
      leave2_raw.length > 0
        ? leave2_raw.map((item) => {
          const leaveTypeCode = item.code ? item.code.trim().toUpperCase() : "";

          // ข้อที่ 1: LV-008 ให้ใช้ leaveSubTypeName (ประเภทย่อย) แทน name
          const displayType =
            leaveTypeCode === "LV-008" && item.leaveSubTypeName
              ? item.leaveSubTypeName
              : item.name || "-";

          // ข้อที่ 2: แสดง reason ก่อนเสมอ ถ้ามี coupleDayLevelCountry ค่อยแสดงประเทศ
          const displayReason = item.coupleDayLevelCountry
            ? `${item.reason || ""} ลาไปประเทศ ${item.coupleDayLevelCountry}`.trim()
            : item.reason || "-";

          return {
            date:
              item.dateLeaveStart && item.dateLeaveEnd
                ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveStart)) +
                " - " +
                Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.dateLeaveEnd))
                : "-",
            type: displayType,
            leaveDays: item.leaveDays ? Extension.ToThaiNumber(item.leaveDays.toString()) : "-",
            reason: displayReason,
          };
        })
        : [
          {
            date: "",
            type: "",
            leaveDays: "",
            reason: "",
          },
        ];
    const children_raw = await this.profileChildrenRepository.find({
      where: { profileId: id, isDeleted: false },
    });
    const children =
      children_raw.length > 0
        ? children_raw.map((item, index) => ({
          no: Extension.ToThaiNumber((index + 1).toString()),
          childrenPrefix: item.childrenPrefix,
          childrenFirstName: item.childrenFirstName,
          childrenLastName: item.childrenLastName,
          childrenFullName: `${item.childrenPrefix}${item.childrenFirstName} ${item.childrenLastName}`,
          childrenLive: item.childrenLive == false ? "ถึงแก่กรรม" : "มีชีวิต",
        }))
        : [
          {
            no: "",
            childrenPrefix: "",
            childrenFirstName: "",
            childrenLastName: "",
            childrenFullName: "",
            childrenLive: "",
          },
        ];
    const changeName_raw = await this.changeNameRepository.find({
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const changeName =
      changeName_raw.length > 0
        ? changeName_raw.map((item) => ({
          createdAt: item.createdAt
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.createdAt))
            : null,
          status: item.status,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
        }))
        : [
          {
            createdAt: "",
            status: "",
            prefix: "",
            firstName: "",
            lastName: "",
          },
        ];

    const profileHistory = await this.profileHistoryRepo.find({
      where: { profileId: id },
      order: { createdAt: "ASC" },
    });
    const history =
      profileHistory.length > 0
        ? profileHistory.map((item) => ({
          birthDateOld: item.birthDateOld
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.birthDateOld))
            : "",
          birthDate: item.birthDate
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.birthDate))
            : "",
        }))
        : [
          {
            birthDateOld: "",
            birthDate: "",
          },
        ];

    const position_raw = await this.salaryRepo.find({
      where: [
        {
          profileId: id,
          commandCode: In([
            "0",
            "1",
            "2",
            "3",
            "4",
            "8",
            "9",
            "10",
            "11",
            "12",
            "13",
            "14",
            "15",
            "16",
            "20",
          ]),
          // isEntry: false,
        },
        { profileId: id, commandCode: IsNull() },
      ],
      order: { order: "ASC" },
    });
    let _commandName: any = "";
    let _commandDateAffect: any = "";
    const positionList =
      position_raw.length > 0
        ? await Promise.all(
          position_raw.map(async (item, idx, arr) => {
            const isLast = idx === arr.length - 1;
            if (isLast) {
              _commandDateAffect = item.commandDateAffect
                ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateAffect))
                : "";
            }
            const _code = item.commandCode ? Number(item.commandCode) : null;
            if (_code != null) {
              _commandName = await this.commandCodeRepository.findOne({
                select: { name: true, code: true },
                where: { code: _code },
              });
            }
            const codeSitAbb = item.posNumCodeSitAbb ?? "-";
            const commandNo =
              item.commandNo && item.commandYear
                ? item.commandNo +
                "/" +
                (item.commandYear > 2500 ? item.commandYear : item.commandYear + 543)
                : "-";
            const dateAffect = item.commandDateAffect
              ? `${Extension.ToThaiFullDate2(item.commandDateAffect)}`
              : "-";
            return {
              commandName:
                _commandName && _commandName.name ? _commandName.name : item.commandName,
              commandDateAffect: item.commandDateAffect
                ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateAffect))
                : "",
              commandDateSign: item.commandDateSign
                ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateSign))
                : "",
              posNo:
                item.posNoAbb && item.posNo
                  ? Extension.ToThaiNumber(`${item.posNoAbb} ${item.posNo}`)
                  : "",
              position: item.positionName,
              posType: item.positionType,
              posLevel: item.positionLevel
                ? Extension.ToThaiNumber(item.positionLevel)
                : item.positionCee
                  ? Extension.ToThaiNumber(item.positionCee)
                  : null,
              amount: item.amount
                ? Extension.ToThaiNumber(Number(item.amount).toLocaleString())
                : "",
              positionSalaryAmount: item.positionSalaryAmount
                ? Extension.ToThaiNumber(Number(item.positionSalaryAmount).toLocaleString())
                : "",
              refDoc: Extension.ToThaiNumber(
                `คำสั่ง ${codeSitAbb} ที่ ${commandNo} ลว. ${dateAffect}`,
              ),
            };
          }),
        )
        : [
          {
            commandName: "",
            commandDateAffect: "",
            commandDateSign: "",
            posNo: "",
            position: "",
            posType: "",
            posLevel: "",
            amount: "",
            positionSalaryAmount: "",
            refDoc: "",
          },
        ];

    // ประวัติพ้นจากราชการ
    let retires = [];
    const currentDate = new Date();

    // commandCode ที่ถือว่าออกจากราชการ
    const retireCommandCodes = ["12", "15", "16"];

    // ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
    const salaries = await this.salaryRepo.find({
      where: { profileId: id },
      order: { order: "ASC" },
    });

    // มีคำสั่งพ้นราชการหรือไม่
    if (
      salaries.length > 0 &&
      salaries.some((s) => s.commandCode && retireCommandCodes.includes(s.commandCode))
    ) {
      // กรองข้อมูลซ้ำตาม commandDateAffect
      const uniqueSalaries = salaries.filter(
        (item, index, self) =>
          index ===
          self.findIndex(
            (t) => t.commandDateAffect?.getTime() === item.commandDateAffect?.getTime(),
          ),
      );

      // วนลูปหาคู่ของ "ออกราชการ" และ "กลับเข้าราชการ"
      for (let i = 0; i < uniqueSalaries.length; i++) {
        const current = uniqueSalaries[i];

        // เป็นคำสั่งออกจากราชการหรือไม่
        if (current.commandCode && retireCommandCodes.includes(current.commandCode)) {
          const startDate = current.commandDateAffect;
          let endDate: Date | null = null;
          let endRecord = null;

          // หาคำสั่งถัดไปที่ไม่ใช่การออกจากราชการ (ถือว่ากลับเข้าราชการ)
          for (let j = i + 1; j < uniqueSalaries.length; j++) {
            const next = uniqueSalaries[j];
            if (next.commandCode && !retireCommandCodes.includes(next.commandCode)) {
              endDate = next.commandDateAffect;
              endRecord = next;
              break;
            }
          }

          // ถ้าไม่เจอคำสั่งกลับเข้า ให้ใช้วันปัจจุบัน
          if (!endDate) {
            endDate = currentDate;
          }

          // คำนวณจำนวนวัน
          let daysCount = 0;
          if (startDate && endDate) {
            const start = new Date(startDate);
            const end = new Date(endDate);
            daysCount = Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
          }

          // สร้าง detail จาก commandName + remark
          const commandName = current.commandName || "";
          const remark = current.remark || "";
          const detail = `${commandName} ${remark}`.trim();

          // แปลงวันที่เป็น format ไทย
          const startDateStr = startDate
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
            : "-";
          const endDateStr = endDate
            ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(endDate))
            : "-";

          retires.push({
            date: `${startDateStr} - ${endDateStr}`,
            detail: detail || "-",
            day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-",
          });
        }
      }
    }

    // กรณีไม่มีข้อมูล
    if (retires.length === 0) {
      retires.push({ date: "", detail: "", day: "" });
    }

    // รักษาการ
    const actposition_raw = await this.profileActpositionRepo.find({
      select: ["dateStart", "profileId", "dateEnd", "position", "commandId", "isDeleted"],
      where: { profileId: id, status: true, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    let _actpositions = [];
    if (actposition_raw.length > 0) {
      for (const item of actposition_raw) {
        let _commandTypename: string = "รักษาการในตำแหน่ง";
        let _document: string = "-";
        let _org: string = "-";

        if (item.commandId) {
          const { posNumCodeSitAbb, commandTypeName, commandNo, commandYear, commandExcecuteDate } =
            await getPosNumCodeSit(item.commandId, "REPORTED");

          _document = Extension.ToThaiNumber(
            `คำสั่ง ${posNumCodeSitAbb ?? "-"} ที่ ${commandNo}/${commandYear > 2500 ? commandYear : commandYear + 543} ลว. ${Extension.ToThaiFullDate2(commandExcecuteDate)}`,
          );
          _commandTypename = commandTypeName;
        }
        // ค้นหาหน่วยงานที่รักษาการ
        const _posmasterAct = await this.posMasterActRepository.findOne({
          where: {
            posMasterChildId: posMasterId ?? "",
            statusReport: "DONE",
          },
        });
        if (_posmasterAct) {
          const _posMater = await this.posMasterRepo.findOne({
            where: {
              id: _posmasterAct.posMasterId,
            },
            relations: {
              orgRoot: true,
              orgChild1: true,
              orgChild2: true,
              orgChild3: true,
              orgChild4: true,
            },
          });
          let child4 = _posMater?.orgChild4?.orgChild4Name ?? "";
          let child3 = _posMater?.orgChild3?.orgChild3Name ?? "";
          let child2 = _posMater?.orgChild2?.orgChild2Name ?? "";
          let child1 = _posMater?.orgChild1?.orgChild1Name ?? "";
          let root = _posMater?.orgRoot?.orgRootName ?? "";
          _org = `${child4} ${child3} ${child2} ${child1} ${root}`.trim();
        }

        _actpositions.push({
          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: _commandTypename,
          agency: _org,
          note:
            _posmasterAct && _posmasterAct?.posMasterOrder
              ? Extension.ToThaiNumber(_posmasterAct?.posMasterOrder.toString())
              : "-",
          document: _document,
        });
      }
    } else {
      _actpositions.push({
        date: "",
        position: "",
        commandName: "",
        agency: "",
        note: "",
        document: "",
      });
    }
    // ช่วยราชการ
    const assistance_raw = await this.profileAssistanceRepository.find({
      select: ["dateStart", "dateEnd", "commandName", "agency", "document", "isDeleted"],
      where: { profileId: id, /*status: "PENDING",*/ isDeleted: false },
      order: { createdAt: "ASC" },
    });
    let _assistances = [];
    if (assistance_raw.length > 0) {
      for (const item of assistance_raw) {
        let _commandTypename: string = item.commandName ?? "ให้ช่วยราชการ";
        let _document: string = item.document ? Extension.ToThaiNumber(item.document) : "-";
        let _org: string = item.agency ? Extension.ToThaiNumber(item.agency) : "-";

        if (item.commandId) {
          const { posNumCodeSitAbb, commandTypeName, commandNo, commandYear, commandExcecuteDate } =
            await getPosNumCodeSit(item.commandId);

          _document = Extension.ToThaiNumber(
            `คำสั่ง ${posNumCodeSitAbb ?? "-"} ที่ ${commandNo}/${commandYear > 2500 ? commandYear : commandYear + 543} ลว. ${Extension.ToThaiFullDate2(commandExcecuteDate)}`,
          );
          _commandTypename = commandTypeName;
        }
        _assistances.push({
          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: _commandTypename,
          agency: _org,
          note: "-",
          document: _document,
        });
      }
    }
    // Merge รักษาการ และ ช่วยราชการ
    const actposition = [..._actpositions, ..._assistances];

    const duty_raw = await this.dutyRepository.find({
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const duty =
      duty_raw.length > 0
        ? duty_raw.map((item) => ({
          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))
                  : "",
          type: "-",
          detail: Extension.ToThaiNumber(item.detail),
          agency: "-",
          refCommandNo: item.refCommandNo
            ? item.refCommandDate
              ? Extension.ToThaiNumber(
                `${item.refCommandNo} ลว. ${Extension.ToThaiFullDate2(item.refCommandDate)}`,
              )
              : Extension.ToThaiNumber(item.refCommandNo)
            : "-",
        }))
        : [
          {
            date: "",
            type: "",
            detail: "",
            agency: "",
            refCommandNo: "",
          },
        ];
    const assessments_raw = await this.profileAssessmentsRepository.find({
      where: { profileId: id, isDeleted: false },
      order: { createdAt: "ASC" },
    });
    const assessments =
      assessments_raw.length > 0
        ? assessments_raw.map((item) => ({
          year: item.year ? Extension.ToThaiNumber((parseInt(item.year) + 543).toString()) : "",
          period:
            item.period && item.period == "APR"
              ? Extension.ToThaiNumber(
                `1 เม.ย. ${(parseInt(item.year) + 543 - 1).toString()} - 31 มี.ค. ${(parseInt(item.year) + 543).toString()}`,
              )
              : Extension.ToThaiNumber(
                `1 ต.ค. ${(parseInt(item.year) + 543 - 1).toString()} - 30 ก.ย. ${(parseInt(item.year) + 543).toString()}`,
              ),
          point1: item.point1 ? Extension.ToThaiNumber(item.point1.toString()) : "",
          point1Total: item.point1Total
            ? Extension.ToThaiNumber(item.point1Total.toString())
            : "",
          point2: item.point2 ? Extension.ToThaiNumber(item.point2.toString()) : "",
          point2Total: item.point2Total
            ? Extension.ToThaiNumber(item.point2Total.toString())
            : "",
          pointSum: item.pointSum
            ? Extension.ToThaiNumber(`ร้อยละ ${item.pointSum.toString()}`)
            : "",
          pointSumTh: item.pointSum ? Extension.textPoint(item.pointSum) : "",
          level:
            item.pointSum < 60.0
              ? "ต้องปรับปรุง"
              : item.pointSum <= 69.99 && item.pointSum >= 60.0
                ? "พอใช้"
                : item.pointSum <= 79.99 && item.pointSum >= 70.0
                  ? "ดี"
                  : item.pointSum <= 89.99 && item.pointSum >= 80.0
                    ? "ดีมาก"
                    : "ดีเด่น",
        }))
        : [
          {
            year: "",
            period: "",
            point1: "",
            point2: "",
            pointSum: "",
            pointSumTh: "",
            level: "",
          },
        ];
    const profileAbility_raw = await this.profileAbilityRepo.find({
      where: { profileId: id },
      order: { createdAt: "ASC" },
    });
    const profileAbility =
      profileAbility_raw.length > 0
        ? profileAbility_raw.map((item) => ({
          field: item.field ? item.field : "",
          detail: item.detail ? item.detail : "",
        }))
        : [
          {
            field: "",
            detail: "",
          },
        ];

    const otherIncome_raw = await this.salaryRepo.find({
      where: {
        profileId: id,
        commandCode: "7",
        // isEntry: false,
      },
      order: { order: "ASC" },
    });
    const otherIncome =
      otherIncome_raw.length > 0
        ? await Promise.all(
          otherIncome_raw.map(async (item) => {
            const codeSitAbb = item.posNumCodeSitAbb ?? "-";
            const commandNo =
              item.commandNo && item.commandYear
                ? item.commandNo +
                "/" +
                (item.commandYear > 2500 ? item.commandYear : item.commandYear + 543)
                : "-";
            const dateAffect = item.commandDateAffect
              ? `${Extension.ToThaiFullDate2(item.commandDateAffect)}`
              : "-";
            return {
              commandName: item.commandName ?? "",
              commandDateAffect: item.commandDateAffect
                ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateAffect))
                : "",
              commandDateSign: item.commandDateSign
                ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(item.commandDateSign))
                : "",
              commandNo: item.commandNo ? Extension.ToThaiNumber(item.commandNo) : "",
              position: item.positionName,
              posLevel: item.positionLevel
                ? Extension.ToThaiNumber(item.positionLevel)
                : item.positionCee
                  ? Extension.ToThaiNumber(item.positionCee)
                  : null,
              amount: item.amount
                ? Extension.ToThaiNumber(Number(item.amount).toLocaleString())
                : "",
              refDoc: Extension.ToThaiNumber(
                `คำสั่ง ${codeSitAbb} ที่ ${commandNo} ลว. ${dateAffect}`,
              ),
            };
          }),
        )
        : [
          {
            commandName: "",
            commandDateAffect: "",
            commandDateSign: "",
            commandNo: "",
            position: "",
            posLevel: "",
            amount: "",
            refDoc: "",
          },
        ];

    const sum = profiles
      ? Extension.ToThaiNumber(
        (
          Number(profiles.amount) +
          Number(profiles.positionSalaryAmount) +
          Number(profiles.mouthSalaryAmount) +
          Number(profiles.amountSpecial)
        ).toLocaleString(),
      )
      : "";
    const fullCurrentAddress =
      profiles && profiles.currentAddress
        ? Extension.ToThaiNumber(
          profiles.currentAddress +
          (profiles.currentSubDistrict && profiles.currentSubDistrict.name
            ? " ตำบล/แขวง " + profiles.currentSubDistrict.name
            : "") +
          (profiles.currentDistrict && profiles.currentDistrict.name
            ? " อำเภอ/เขต " + profiles.currentDistrict.name
            : "") +
          (profiles.currentProvince && profiles.currentProvince.name
            ? " จังหวัด " + profiles.currentProvince.name
            : "") +
          (profiles.currentZipCode ? " " + profiles.currentZipCode : ""),
        )
        : "";
    const fullRegistrationAddress =
      profiles && profiles.registrationAddress
        ? Extension.ToThaiNumber(
          profiles.registrationAddress +
          (profiles.registrationSubDistrict && profiles.registrationSubDistrict.name
            ? " ตำบล/แขวง " + profiles.registrationSubDistrict.name
            : "") +
          (profiles.registrationDistrict && profiles.registrationDistrict.name
            ? " อำเภอ/เขต " + profiles.registrationDistrict.name
            : "") +
          (profiles.registrationProvince && profiles.registrationProvince.name
            ? " จังหวัด " + profiles.registrationProvince.name
            : "") +
          (profiles.currentZipCode ? " " + profiles.currentZipCode : ""),
        )
        : "";

    let portfolios: any[] = [];
    await new CallAPI()
      .GetData(req, `/development/portfolio/kk1/${profiles?.keycloak}`)
      .then((x) => {
        portfolios = Array.isArray(x) ? x : [];
      })
      .catch(() => { });
    if (portfolios.length == 0) {
      portfolios = [{ name: "", year: "", position: "" }];
    } else {
      portfolios = portfolios.map((x: any) => ({
        name: x.name ? Extension.ToThaiNumber(x.name) : "-",
        year: x.year ? Extension.ToThaiNumber(x.year.toString()) : "-",
        position: `${x.position ?? "-"}`,
      }));
    }
    const org =
      (_child4 == null ? "" : _child4 + " ") +
      (_child3 == null ? "" : _child3 + " ") +
      (_child2 == null ? "" : _child2 + " ") +
      (_child1 == null ? "" : _child1 + " ") +
      (_root == null ? "" : _root).trim();
    const _position =
      profiles?.position != null
        ? profiles?.posLevel != null
          ? `${profiles.position}${profiles.posLevel.posLevelName}`
          : profiles.position
        : "";
    const ocAssistance = await this.profileAssistanceRepository.findOne({
      select: ["agency", "profileId", "commandName", "status", "isDeleted"],
      where: {
        profileId: id,
        commandName: "ให้ช่วยราชการ",
        status: "PENDING",
        isDeleted: false,
      },
      order: { createdAt: "ASC" },
    });
    const data = {
      currentDate: Extension.ToThaiNumber(Extension.ToThaiFullDate2(currentDate)),
      fullName: `${profiles?.prefix}${profiles?.firstName} ${profiles?.lastName}`,
      prefix: profiles?.prefix != null ? profiles.prefix : "",
      firstName: profiles?.firstName != null ? profiles.firstName : "",
      lastName: profiles?.lastName != null ? profiles.lastName : "",
      position: _position,
      posAssistance: ocAssistance ? "-" : _position, // ปัจจุบันช่วยราชการยังไม่มีเก็บฟิลด์ตำแหน่ง
      amount:
        profiles?.amount != null ? Extension.ToThaiNumber(profiles.amount.toLocaleString()) : "",
      positionSalaryAmount:
        profiles?.positionSalaryAmount != null
          ? Extension.ToThaiNumber(profiles.positionSalaryAmount.toLocaleString())
          : "",
      mouthSalaryAmount:
        profiles?.mouthSalaryAmount != null
          ? Extension.ToThaiNumber(profiles.mouthSalaryAmount.toLocaleString())
          : "",
      amountSpecial:
        profiles?.amountSpecial != null
          ? Extension.ToThaiNumber(profiles.amountSpecial.toLocaleString())
          : "",
      salarySum: sum,
      ocFullPath: org,
      ocAssistance: ocAssistance?.agency ?? org,
      root: _root == null ? "" : _root,
      agency:
        (_child4 == null ? "" : _child4 + " ") +
        (_child3 == null ? "" : _child3 + " ") +
        (_child2 == null ? "" : _child2 + " ") +
        (_child1 == null ? "" : _child1).trim(),
      birthDate: profiles?.birthDate
        ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.birthDate))
        : "",
      retireDate:
        profiles.dateRetireLaw != null
          ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.dateRetireLaw))
          : "",
      appointDate: profiles?.dateAppoint
        ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(profiles.dateAppoint))
        : "",
      positionDate: _commandDateAffect ?? "",
      citizenId:
        profiles.citizenId != null ? Extension.ToThaiNumber(profiles.citizenId.toString()) : "",
      fatherFullName:
        profileFamilyFather?.fatherPrefix ||
          profileFamilyFather?.fatherFirstName ||
          profileFamilyFather?.fatherLastName
          ? `${profileFamilyFather?.fatherPrefix ?? ""}${profileFamilyFather?.fatherFirstName ?? ""} ${profileFamilyFather?.fatherLastName ?? ""}`.trim()
          : null,
      fatherLive:
        profileFamilyFather && profileFamilyFather?.fatherLive == false ? "ถึงแก่กรรม" : "มีชีวิต",
      motherFullName:
        profileFamilyMother?.motherPrefix ||
          profileFamilyMother?.motherFirstName ||
          profileFamilyMother?.motherLastName
          ? `${profileFamilyMother?.motherPrefix ?? ""}${profileFamilyMother?.motherFirstName ?? ""} ${profileFamilyMother?.motherLastName ?? ""}`.trim()
          : null,
      motherLive:
        profileFamilyMother && profileFamilyMother?.motherLive == false ? "ถึงแก่กรรม" : "มีชีวิต",
      coupleFullName:
        profileFamilyCouple?.couplePrefix ||
          profileFamilyCouple?.coupleFirstName ||
          profileFamilyCouple?.coupleLastNameOld
          ? `${profileFamilyCouple?.couplePrefix ?? ""}${profileFamilyCouple?.coupleFirstName ?? ""} ${profileFamilyCouple?.coupleLastName ?? ""}`.trim()
          : null,
      coupleLastNameOld: profileFamilyCouple?.coupleLastNameOld ?? null,
      coupleLive:
        profileFamilyCouple && profileFamilyCouple?.coupleLive == false ? "ถึงแก่กรรม" : "มีชีวิต",
      currentAddress:
        profiles.currentAddress != null ? Extension.ToThaiNumber(profiles.currentAddress) : "",
      currentSubDistrict:
        profiles.currentSubDistrict != null
          ? Extension.ToThaiNumber(profiles.currentSubDistrict.name)
          : "",
      currentDistrict:
        profiles.currentDistrict != null
          ? Extension.ToThaiNumber(profiles.currentDistrict.name)
          : "",
      currentProvince:
        profiles.currentProvince != null
          ? Extension.ToThaiNumber(profiles.currentProvince.name)
          : "",
      currentZipcode:
        profiles.currentZipCode != null ? Extension.ToThaiNumber(profiles.currentZipCode) : "",
      fullCurrentAddress: fullCurrentAddress,
      registrationAddress:
        profiles.registrationAddress != null
          ? Extension.ToThaiNumber(profiles.registrationAddress)
          : "",
      registrationSubDistrict:
        profiles.registrationSubDistrict != null
          ? Extension.ToThaiNumber(profiles.registrationSubDistrict.name)
          : "",
      registrationDistrict:
        profiles.registrationDistrict != null
          ? Extension.ToThaiNumber(profiles.registrationDistrict.name)
          : "",
      registrationProvince:
        profiles.registrationProvince != null
          ? Extension.ToThaiNumber(profiles.registrationProvince.name)
          : "",
      registrationZipcode:
        profiles.registrationZipCode != null
          ? Extension.ToThaiNumber(profiles.registrationZipCode)
          : "",
      fullRegistrationAddress: fullRegistrationAddress,
      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,
      yearUpload1: profiles.profileAvatars[0]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[0].createdAt))
        : null,
      url2: _ImgUrl[1] ? _ImgUrl[1] : null,
      yearUpload2: profiles.profileAvatars[1]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[1].createdAt))
        : null,
      url3: _ImgUrl[2] ? _ImgUrl[2] : null,
      yearUpload3: profiles.profileAvatars[2]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[2].createdAt))
        : null,
      url4: _ImgUrl[3] ? _ImgUrl[3] : null,
      yearUpload4: profiles.profileAvatars[3]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[3].createdAt))
        : null,
      url5: _ImgUrl[4] ? _ImgUrl[4] : null,
      yearUpload5: profiles.profileAvatars[4]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[4].createdAt))
        : null,
      url6: _ImgUrl[5] ? _ImgUrl[5] : null,
      yearUpload6: profiles.profileAvatars[5]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[5].createdAt))
        : null,
      url7: _ImgUrl[6] ? _ImgUrl[6] : null,
      yearUpload7: profiles.profileAvatars[6]
        ? Extension.ToThaiNumber(Extension.ToThaiShortYear(profiles.profileAvatars[6].createdAt))
        : null,
      urlQRcode: "https://seis.ocsc.go.th",
      children,
      insignias,
      leaves,
      leaves2,
      certs,
      trainings,
      disciplines,
      educations,
      salarys,
      changeName,
      history,
      positionList,
      actposition,
      duty,
      assessments,
      profileAbility,
      otherIncome,
      portfolios,
      retires,
    };

    return new HttpSuccess({
      template: "new_kk1",
      reportName: "docx-report",
      data: data,
    });
  }

  /**
   *
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Get("placement/{id}")
  async getProfilePlacement(@Path() id: string) {
    const profile = await this.profileRepo.findOne({
      where: { id: id },
    });

    const posMaster = await this.posMasterRepo.findOne({
      where: { current_holderId: profile?.id },
    });
    if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
    const orgRoot = posMaster.orgRootId;
    const orgChild1 = posMaster.orgChild1Id;
    const orgChild2 = posMaster.orgChild2Id;
    const orgChild3 = posMaster.orgChild3Id;
    const orgChild4 = posMaster.orgChild4Id;

    const findChild4 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .getMany();
    const findChild3 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild3Id = :orgChild3Id", { orgChild3Id: orgChild3 })
      .andWhere("current_holders.orgChild4Id IS NULL")
      .getMany();
    const findChild2 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild2Id = :orgChild2Id", { orgChild2Id: orgChild2 })
      .andWhere("current_holders.orgChild3Id IS NULL")
      .getMany();
    const findChild1 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild1Id = :orgChild1Id", { orgChild1Id: orgChild1 })
      .andWhere("current_holders.orgChild2Id IS NULL")
      .getMany();
    const findRoot = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild1Id  IS NULL")
      .getMany();

    let _caregiver: any;
    let caregiver: any;
    let _commander: any;
    let commander: any;
    let _chairman: any;
    let chairman: any;
    if (posMaster) {
      if (orgChild4) {
        if (findChild4) {
          _caregiver = findChild4;
          _commander = findChild3;
          _chairman = findChild2;
        } else if (findChild3) {
          _caregiver = findChild3;
          _commander = findChild2;
          _chairman = findChild1;
        } else if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild3) {
        if (findChild3) {
          _caregiver = findChild3;
          _commander = findChild2;
          _chairman = findChild1;
        } else if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild2) {
        if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild1) {
        if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgRoot) {
        if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      }
      caregiver = _caregiver.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
      commander = _commander.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
      chairman = _chairman.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
    }

    return new HttpSuccess({ caregiver, commander, chairman });
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม profileId
   *
   * @summary ข้อมูลองค์กรของ Profile (ADMIN)
   *
   * @param {string} profileId  Profile ID
   */
  @Get("org-user/{profileId}")
  async getOrgUserByProfileId(@Path() profileId: string) {
    // 1. หาข้อมูล org hierarchy สำหรับ profile นี้
    const posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holderId: profileId,
        orgRevision: {
          orgRevisionIsCurrent: true,
          orgRevisionIsDraft: false,
        },
      },
      select: {
        id: true,
        orgRoot: {
          id: true,
          orgRootName: true,
        },
        orgChild1: {
          id: true,
          orgChild1Name: true,
        },
        orgChild2: {
          id: true,
          orgChild2Name: true,
        },
        orgChild3: {
          id: true,
          orgChild3Name: true,
        },
        orgChild4: {
          id: true,
          orgChild4Name: true,
        },
      },
      relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
    });

    // 2. ถ้าไม่พบใน PosMaster ให้ลองหาใน EmployeePosMaster
    if (!posMaster) {
      const employeePosMaster = await this.employeePosMasterRepo.findOne({
        where: {
          current_holderId: profileId,
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
        },
        select: {
          id: true,
          orgRoot: {
            id: true,
            orgRootName: true,
          },
          orgChild1: {
            id: true,
            orgChild1Name: true,
          },
          orgChild2: {
            id: true,
            orgChild2Name: true,
          },
          orgChild3: {
            id: true,
            orgChild3Name: true,
          },
          orgChild4: {
            id: true,
            orgChild4Name: true,
          },
        },
        relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
      });

      if (!employeePosMaster) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งสำหรับ Profile นี้");
      }

      return new HttpSuccess({
        root: employeePosMaster.orgRoot?.orgRootName ?? null,
        child1: employeePosMaster.orgChild1?.orgChild1Name ?? null,
        child2: employeePosMaster.orgChild2?.orgChild2Name ?? null,
        child3: employeePosMaster.orgChild3?.orgChild3Name ?? null,
        child4: employeePosMaster.orgChild4?.orgChild4Name ?? null,
      });
    }

    // 3. Return ข้อมูล org hierarchy
    return new HttpSuccess({
      root: posMaster.orgRoot?.orgRootName ?? null,
      child1: posMaster.orgChild1?.orgChild1Name ?? null,
      child2: posMaster.orgChild2?.orgChild2Name ?? null,
      child3: posMaster.orgChild3?.orgChild3Name ?? null,
      child4: posMaster.orgChild4?.orgChild4Name ?? null,
    });
  }

  /**
   * API
   *
   * @summary API
   *
   */
  @Get("admin-keycloak")
  async listProfileIdByorg(@Request() request: RequestWithUser) {
    let _data: any = {
      root: null,
      child1: null,
      child2: null,
      child3: null,
      child4: null,
    };
    if (!request.user.role.includes("SUPER_ADMIN")) {
      _data = await new permission().PermissionOrgList(request, "SYS_ORG");
    }
    const profiles = await this.profileRepo
      .createQueryBuilder("profile")
      .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")
      .andWhere(
        _data.root != undefined && _data.root != null
          ? _data.root[0] != null
            ? `current_holders.orgRootId IN (:...root)`
            : `current_holders.orgRootId is null`
          : "1=1",
        {
          root: _data.root,
        },
      )
      .andWhere(
        _data.child1 != undefined && _data.child1 != null
          ? _data.child1[0] != null
            ? `current_holders.orgChild1Id IN (:...child1)`
            : // : `current_holders.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
            `current_holders.orgChild1Id is null`
          : "1=1",
        {
          child1: _data.child1,
        },
      )
      .andWhere(
        _data.child2 != undefined && _data.child2 != null
          ? _data.child2[0] != null
            ? `current_holders.orgChild2Id IN (:...child2)`
            : `current_holders.orgChild2Id is null`
          : "1=1",
        {
          child2: _data.child2,
        },
      )
      .andWhere(
        _data.child3 != undefined && _data.child3 != null
          ? _data.child3[0] != null
            ? `current_holders.orgChild3Id IN (:...child3)`
            : `current_holders.orgChild3Id is null`
          : "1=1",
        {
          child3: _data.child3,
        },
      )
      .andWhere(
        _data.child4 != undefined && _data.child4 != null
          ? _data.child4[0] != null
            ? `current_holders.orgChild4Id IN (:...child4)`
            : `current_holders.orgChild4Id is null`
          : "1=1",
        {
          child4: _data.child4,
        },
      )
      .andWhere({ keycloak: Not(IsNull()) })
      .andWhere({ keycloak: Not("") })
      .select("profile.keycloak", "keycloak")
      .getRawMany();
    const keycloakArray = profiles.map((p) => p.keycloak);

    return new HttpSuccess(keycloakArray);
  }
  /**
   *
   *
   */
  @Get("commander")
  async getProfileCommander(@Request() request: RequestWithUser) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
    });
    const posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holderId: profile?.id,
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
    });
    if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
    const orgRoot = posMaster.orgRootId;
    const orgChild1 = posMaster.orgChild1Id;
    const orgChild2 = posMaster.orgChild2Id;
    const orgChild3 = posMaster.orgChild3Id;
    const orgChild4 = posMaster.orgChild4Id;

    const findChild4 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .getMany();
    const findChild3 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild3Id = :orgChild3Id", { orgChild3Id: orgChild3 })
      .andWhere("current_holders.orgChild4Id IS NULL")
      .getMany();
    const findChild2 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild2Id = :orgChild2Id", { orgChild2Id: orgChild2 })
      .andWhere("current_holders.orgChild3Id IS NULL")
      .getMany();
    const findChild1 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild1Id = :orgChild1Id", { orgChild1Id: orgChild1 })
      .andWhere("current_holders.orgChild2Id IS NULL")
      .getMany();
    const findRoot = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild1Id  IS NULL")
      .getMany();

    let _caregiver: any;
    let caregiver: any;
    let _commander: any;
    let commander: any;
    let _chairman: any;
    let chairman: any;
    if (posMaster) {
      if (orgChild4) {
        if (findChild4) {
          _caregiver = findChild4;
          _commander = findChild3;
          _chairman = findChild2;
        } else if (findChild3) {
          _caregiver = findChild3;
          _commander = findChild2;
          _chairman = findChild1;
        } else if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild3) {
        if (findChild3) {
          _caregiver = findChild3;
          _commander = findChild2;
          _chairman = findChild1;
        } else if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild2) {
        if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild1) {
        if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgRoot) {
        if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      }
      caregiver = _caregiver.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
      commander = _commander.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
      chairman = _chairman.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
    }

    return new HttpSuccess({ caregiver, commander, chairman });
  }
  /**
   *
   *
   */
  @Post("commander-director-act")
  async getProfileCommanderDirectorAct(
    @Request() request: RequestWithUser,
    @Body() body: { isDirector: boolean; keyword: string; page: number; pageSize: number },
  ) {
    const posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holder: { keycloak: request.user.sub },
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
    });
    if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");

    let condition: any = {
      orgRootId: posMaster.orgRootId,
      id: Not(posMaster.current_holderId || ""),
    };
    // let conditionNow: any = {
    //   orgRootId: posMaster.orgRootId,
    //   orgChild1Id: posMaster.orgChild1Id,
    //   orgChild2Id: posMaster.orgChild2Id,
    //   orgChild3Id: posMaster.orgChild3Id,
    //   orgChild4Id: posMaster.orgChild4Id,
    //   id: Not(posMaster.current_holderId),
    // };
    // if (posMaster.orgChild1Id == null) {
    // } else if (posMaster.orgChild2Id == null) {
    //   condition.orgChild1Id = null;
    // } else if (posMaster.orgChild3Id == null) {
    //   condition.orgChild2Id = null;
    // } else if (posMaster.orgChild4Id == null) {
    //   condition.orgChild3Id = null;
    // } else {
    //   condition.orgChild4Id = null;
    // }
    if (body.isDirector == true) {
      condition.isDirector = true;
      //   conditionNow.isDirector = true;
    }
    const [lists, total] = await AppDataSource.getRepository(viewDirectorActing)
      .createQueryBuilder("viewDirectorActing")
      .andWhere(condition)
      //   .andWhere(
      //     new Brackets((qb) => {
      //       qb.orWhere(condition).orWhere(conditionNow);
      //     }),
      //   )
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(
            body.keyword != null && body.keyword != ""
              ? "CONCAT(viewDirectorActing.prefix,viewDirectorActing.firstName,' ',viewDirectorActing.lastName) LIKE :keyword"
              : "1=1",
            {
              keyword: `%${body.keyword}%`,
            },
          )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "viewDirectorActing.citizenId LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "viewDirectorActing.position LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "viewDirectorActing.posLevel LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "viewDirectorActing.posType LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "viewDirectorActing.actFullName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            );
        }),
      )
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();
    return new HttpSuccess({ data: lists, total });
  }
  /**
   *
   *
   */
  @Post("commander-director")
  async getProfileCommanderDirector(
    @Request() request: RequestWithUser,
    @Body()
    body: {
      isAct: boolean;
      isDirector: boolean;
      keyword: string;
      page: number;
      pageSize: number;
      sortBy?: string;
      descending?: boolean;
    },
  ) {
    let posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holder: { keycloak: request.user.sub },
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
      relations: ["current_holder", "current_holder.posLevel"],
    });
    if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
    if ((posMaster?.current_holder?.posLevel?.posLevelAuthority ?? null) == "DEPUTY") {
      posMaster = await this.posMasterRepo.findOne({
        where: {
          orgRoot: { isDeputy: true },
          orgChild1Id: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
        },
      });
      return new HttpSuccess({ data: [], total: 0 });
    } else if ((posMaster?.current_holder?.posLevel?.posLevelAuthority ?? null) == "GOVERNOR") {
      return new HttpSuccess({ data: [], total: 0 });
    }
    let condition: any = {
      orgRootId: posMaster.orgRootId,
      id: Not(posMaster.current_holderId || ""),
    };
    let conditionNow: any = {
      orgRootId: posMaster.orgRootId ?? IsNull(),
      orgChild1Id: posMaster.orgChild1Id ?? IsNull(),
      orgChild2Id: posMaster.orgChild2Id ?? IsNull(),
      orgChild3Id: posMaster.orgChild3Id ?? IsNull(),
      orgChild4Id: posMaster.orgChild4Id ?? IsNull(),
      id: Not(posMaster.current_holderId),
    };
    if (
      posMaster.orgRootId == null ||
      posMaster.orgChild1Id == null ||
      posMaster.orgChild2Id == null
    ) {
      condition.orgChild1Id = IsNull();
    } else if (posMaster.orgChild3Id == null) {
      condition.orgChild2Id = IsNull();
    } else if (posMaster.orgChild4Id == null) {
      condition.orgChild3Id = IsNull();
    } else if (posMaster.orgChild4Id != null) {
      condition.orgChild4Id = IsNull();
    }
    if (body.isDirector == true) {
      condition.isDirector = true;
      conditionNow.isDirector = true;
    }
    if (body.isAct == true) {
      //   const posMaster = await this.posMasterRepo.findOne({
      //     where: {
      //       current_holder: { keycloak: request.user.sub },
      //       orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      //     },
      //   });
      //   if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");

      //   let condition: any = {
      //     orgRootId: posMaster.orgRootId,
      //     id: Not(posMaster.current_holderId || ""),
      //   };
      //   //   let conditionNow: any = {
      //   //     orgRootId: posMaster.orgRootId,
      //   //     orgChild1Id: posMaster.orgChild1Id,
      //   //     orgChild2Id: posMaster.orgChild2Id,
      //   //     orgChild3Id: posMaster.orgChild3Id,
      //   //     orgChild4Id: posMaster.orgChild4Id,
      //   //     id: Not(posMaster.current_holderId),
      //   //   };
      //   //   if (posMaster.orgChild1Id == null) {
      //   //     condition.orgRootId = null;
      //   //   } else if (posMaster.orgChild2Id == null) {
      //   //     condition.orgChild1Id = null;
      //   //   } else if (posMaster.orgChild3Id == null) {
      //   //     condition.orgChild2Id = null;
      //   //   } else if (posMaster.orgChild4Id == null) {
      //   //     condition.orgChild3Id = null;
      //   //   } else {
      //   //     condition.orgChild4Id = null;
      //   //   }
      //   if (body.isDirector == true) {
      //     condition.isDirector = true;
      //     // conditionNow.isDirector = true;
      //   }
      let query = await AppDataSource.getRepository(viewDirectorActing)
        .createQueryBuilder("viewDirectorActing")
        // .andWhere(condition)
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(condition).orWhere(conditionNow);
          }),
        )
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(viewDirectorActing.prefix,viewDirectorActing.firstName,' ',viewDirectorActing.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.position LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.actFullName LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "CONCAT(viewDirectorActing.posType, ' (', viewDirectorActing.posLevel, ')') LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.posNo LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              );
          }),
        );

      if (body.sortBy) {
        query = query.orderBy(
          `viewDirectorActing.${body.sortBy}`,
          body.descending ? "DESC" : "ASC",
        );
      }

      const [lists, total] = await query
        .skip((body.page - 1) * body.pageSize)
        .take(body.pageSize)
        .getManyAndCount();

      return new HttpSuccess({ data: lists, total });
    } else {
      //   const posMaster = await this.posMasterRepo.findOne({
      //     where: {
      //       current_holder: { keycloak: request.user.sub },
      //       orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      //     },
      //   });
      //   if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");

      //   let condition: any = {
      //     orgRootId: posMaster.orgRootId,
      //     id: Not(posMaster.current_holderId || ""),
      //   };
      //   let conditionNow: any = {
      //     orgRootId: posMaster.orgRootId,
      //     orgChild1Id: posMaster.orgChild1Id,
      //     orgChild2Id: posMaster.orgChild2Id,
      //     orgChild3Id: posMaster.orgChild3Id,
      //     orgChild4Id: posMaster.orgChild4Id,
      //     id: Not(posMaster.current_holderId),
      //   };
      //   if (posMaster.orgChild1Id == null) {
      //     condition.orgRootId = null;
      //   } else if (posMaster.orgChild2Id == null) {
      //     condition.orgChild1Id = null;
      //   } else if (posMaster.orgChild3Id == null) {
      //     condition.orgChild2Id = null;
      //   } else if (posMaster.orgChild4Id == null) {
      //     condition.orgChild3Id = null;
      //   } else {
      //     condition.orgChild4Id = null;
      //   }
      //   if (body.isDirector == true) {
      //     condition.isDirector = true;
      //     // conditionNow.isDirector = true;
      //   }
      let query = await AppDataSource.getRepository(viewDirector)
        .createQueryBuilder("viewDirector")
        // .andWhere(condition)
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(condition).orWhere(conditionNow);
          }),
        )
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(viewDirector.prefix,viewDirector.firstName,' ',viewDirector.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.position LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.actFullName LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "CONCAT(viewDirector.posType, ' (', viewDirector.posLevel, ')') LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.posNo LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              );
          }),
        );

      if (body.sortBy) {
        query = query.orderBy(`viewDirector.${body.sortBy}`, body.descending ? "DESC" : "ASC");
      }

      const [lists, total] = await query
        .skip((body.page - 1) * body.pageSize)
        .take(body.pageSize)
        .getManyAndCount();

      return new HttpSuccess({ data: lists, total });
    }
  }
  /**
   *
   *
   */
  @Post("commander-director-position")
  async getProfileCommanderDirectorPosition(
    @Request() request: RequestWithUser,
    @Body()
    body: {
      isAct: boolean;
      isDirector: boolean;
      keyword: string;
      page: number;
      pageSize: number;
      profileId: string;
    },
  ) {
    let posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holderId: body.profileId,
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
      relations: ["current_holder", "current_holder.posLevel"],
    });
    if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
    if ((posMaster?.current_holder?.posLevel?.posLevelAuthority ?? null) == "DEPUTY") {
      posMaster = await this.posMasterRepo.findOne({
        where: {
          orgRoot: { isDeputy: true },
          orgChild1Id: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
        },
      });
      if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
      posMaster.current_holderId = null;
      posMaster.lastUpdatedAt = new Date();
      //   return new HttpSuccess({ data: [], total: 0 });
    } else if ((posMaster?.current_holder?.posLevel?.posLevelAuthority ?? null) == "GOVERNOR") {
      return new HttpSuccess({ data: [], total: 0 });
    }
    // console.log(posMaster);
    // console.log(posMaster.id);
    let condition: any = {
      orgRootId: posMaster.orgRootId,
      id: Not(posMaster.current_holderId || ""),
    };
    let conditionNow: any = {
      orgRootId: posMaster.orgRootId ?? IsNull(),
      orgChild1Id: posMaster.orgChild1Id ?? IsNull(),
      orgChild2Id: posMaster.orgChild2Id ?? IsNull(),
      orgChild3Id: posMaster.orgChild3Id ?? IsNull(),
      orgChild4Id: posMaster.orgChild4Id ?? IsNull(),
      id: Not(posMaster.current_holderId),
    };
    if (
      posMaster.orgRootId == null ||
      posMaster.orgChild1Id == null ||
      posMaster.orgChild2Id == null
    ) {
      condition.orgChild1Id = IsNull();
    } else if (posMaster.orgChild3Id == null) {
      condition.orgChild2Id = IsNull();
    } else if (posMaster.orgChild4Id == null) {
      condition.orgChild3Id = IsNull();
    } else if (posMaster.orgChild4Id != null) {
      condition.orgChild4Id = IsNull();
    }
    if (body.isDirector == true) {
      condition.isDirector = true;
      conditionNow.isDirector = true;
    }
    // console.log(condition);
    // console.log("------------------");
    // console.log(conditionNow);

    // Task #2342 list ปลัด และรองปลัดใน popup ผู้บังคับบัญชา และผู้มีอำนาจเพิ่ม
    let conditionisDeputy: any = {
      isDeputy: true,
      isDirector: true,
      orgChild1Id: IsNull(),
      orgChild2Id: IsNull(),
      orgChild3Id: IsNull(),
      orgChild4Id: IsNull(),
      id: Not(posMaster.current_holderId),
    };
    const orgRoot = await this.orgRootRepo.findOne({
      select: { id: true, isDeputy: true },
      where: {
        id: Not(posMaster.orgRootId ?? ""),
        isDeputy: true,
        orgRevision: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
      },
    });

    if (body.isAct == true) {
      const [lists, total] = await AppDataSource.getRepository(viewDirectorActing)
        .createQueryBuilder("viewDirectorActing")
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(condition).orWhere(conditionNow);
            if (orgRoot && orgRoot.isDeputy) {
              qb.orWhere(conditionisDeputy);
            }
          }),
        )
        .andWhere("viewDirectorActing.isProbation = :isProbation", { isProbation: false })
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(viewDirectorActing.prefix,viewDirectorActing.firstName,' ',viewDirectorActing.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.position LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.actFullName LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "CONCAT(viewDirectorActing.posType, ' (', viewDirectorActing.posLevel, ')') LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.posNo LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirectorActing.citizenId LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              );
          }),
        )
        .skip((body.page - 1) * body.pageSize)
        .take(body.pageSize)
        .getManyAndCount();

      // ดึง posMasterId ทั้งหมด (36 ตัวแรกของ key) เพื่อ query positionName
      const posMasterIds = lists
        .map((x) => x.key?.substring(0, 36))
        .filter((id) => id && id.length === 36);
      const posMasterPositionMap = await getPosMasterPositions(posMasterIds);

      // ปรับ positionSign สำหรับกรณีรักษาการ
      const processedLists = lists.map((x: any) => {
        let newPositionSign = x.positionSign;

        // ตำแหน่งของคนที่เลือกไปรักษาการ
        let childPosition = "";
        if (x.posType === "อำนวยการ" || x.posType === "บริหาร") {
          childPosition = x.posExecutiveName || "";
          if (!childPosition) {
            childPosition = `${x.position || ""}ระดับ${x.posLevel || ""}`.trim();
          }
        } else {
          childPosition = `${x.position || ""}${x.posLevel || ""}`.trim();
        }

        // ตำแหน่งที่รักษาการแทน
        const posMasterId = x.key?.substring(0, 36);
        const targetPosition = x.positionSign
          ? x.positionSign
          : posMasterPositionMap.get(posMasterId) || "";

        // สร้าง positionSign ใหม่
        newPositionSign = `${childPosition} รักษาการในตำแหน่ง${targetPosition}`;

        return {
          ...x,
          positionSign: newPositionSign,
        };
      });

      return new HttpSuccess({ data: processedLists, total });
    } else {
      const [lists, total] = await AppDataSource.getRepository(viewDirector)
        .createQueryBuilder("viewDirector")
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(condition).orWhere(conditionNow);
            if (orgRoot && orgRoot.isDeputy) {
              qb.orWhere(conditionisDeputy);
            }
          }),
        )
        .andWhere("viewDirector.isProbation = :isProbation", { isProbation: false })
        .andWhere(
          new Brackets((qb) => {
            qb.orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(viewDirector.prefix,viewDirector.firstName,' ',viewDirector.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.position LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.actFullName LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "CONCAT(viewDirector.posType, ' (', viewDirector.posLevel, ')') LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.posNo LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              )
              .orWhere(
                body.keyword != null && body.keyword != ""
                  ? "viewDirector.citizenId LIKE :keyword"
                  : "1=1",
                {
                  keyword: `%${body.keyword}%`,
                },
              );
          }),
        )
        .skip((body.page - 1) * body.pageSize)
        .take(body.pageSize)
        .getManyAndCount();
      return new HttpSuccess({ data: lists, total });
    }
  }

  /**
   * API เลือกผู้ประเมินสำหรับ User (ADMIN)
   *
   * @summary เลือกผู้ประเมินสำหรับ User  (ADMIN)
   *
   * @param {string} profileId  Id ทะเบียนประวัติ User
   */
  @Get("commander/{profileId}")
  async getProfileCommanderUser(@Request() request: RequestWithUser, @Path() profileId: string) {
    //await new permission().PermissionOrgUserGet(request, "SYS_REGISTRY_OFFICER", profileId); //ไม่แน่ใจOFFปิดไว้ก่อน
    const profile = await this.profileRepo.findOne({
      where: { id: profileId },
    });

    const posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holderId: profile?.id,
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
    });
    if (!posMaster) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลการครองตำแหน่ง");
    const orgRoot = posMaster.orgRootId;
    const orgChild1 = posMaster.orgChild1Id;
    const orgChild2 = posMaster.orgChild2Id;
    const orgChild3 = posMaster.orgChild3Id;
    const orgChild4 = posMaster.orgChild4Id;

    const findChild4 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .getMany();
    const findChild3 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild3Id = :orgChild3Id", { orgChild3Id: orgChild3 })
      .andWhere("current_holders.orgChild4Id IS NULL")
      .getMany();
    const findChild2 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild2Id = :orgChild2Id", { orgChild2Id: orgChild2 })
      .andWhere("current_holders.orgChild3Id IS NULL")
      .getMany();
    const findChild1 = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild1Id = :orgChild1Id", { orgChild1Id: orgChild1 })
      .andWhere("current_holders.orgChild2Id IS NULL")
      .getMany();
    const findRoot = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .andWhere({ keycloak: Not(IsNull()) })
      .where("current_holders.current_holderId IS NOT NULL")
      .andWhere("current_holders.orgRootId = :orgRootId", { orgRootId: orgRoot })
      .andWhere("current_holders.current_holderId <> :current_holderId", {
        current_holderId: posMaster.current_holderId,
      })
      .andWhere("current_holders.orgChild1Id  IS NULL")
      .getMany();

    let _caregiver: any;
    let caregiver: any;
    let _commander: any;
    let commander: any;
    let _chairman: any;
    let chairman: any;
    if (posMaster) {
      if (orgChild4) {
        if (findChild4) {
          _caregiver = findChild4;
          _commander = findChild3;
          _chairman = findChild2;
        } else if (findChild3) {
          _caregiver = findChild3;
          _commander = findChild2;
          _chairman = findChild1;
        } else if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild3) {
        if (findChild3) {
          _caregiver = findChild3;
          _commander = findChild2;
          _chairman = findChild1;
        } else if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild2) {
        if (findChild2) {
          _caregiver = findChild2;
          _commander = findChild1;
          _chairman = findRoot;
        } else if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgChild1) {
        if (findChild1) {
          _caregiver = findChild1;
          _commander = findRoot;
          _chairman = findRoot;
        } else if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      } else if (orgRoot) {
        if (findRoot) {
          _caregiver = findRoot;
          _commander = findRoot;
          _chairman = findRoot;
        }
      }
      caregiver = _caregiver.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
      commander = _commander.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
      chairman = _chairman.map((_data: any) => ({
        id: _data.id,
        prefix: _data.prefix,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        position: _data.position,
        posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
        posType: _data.posType == null ? null : _data.posType.posTypeName,
        isDirector: true,
      }));
    }

    return new HttpSuccess({ caregiver, commander, chairman });
  }

  /**
   * API สร้างทะเบียนประวัติ
   *
   * @summary ORG_065 - สร้างทะเบียนประวัติ (ADMIN) #70
   *
   */
  @Post()
  async createProfile(@Request() request: RequestWithUser, @Body() body: CreateProfile) {
    if (await this.profileRepo.findOneBy({ citizenId: body.citizenId })) {
      throw new HttpError(
        HttpStatus.INTERNAL_SERVER_ERROR,
        "รหัสบัตรประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว",
      );
    }

    if (body.posLevelId === "") body.posLevelId = null;
    if (body.posTypeId === "") body.posTypeId = null;

    if (body.posLevelId && !(await this.posLevelRepo.findOneBy({ id: body.posLevelId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้");
    }

    if (body.citizenId) {
      const citizenIdDigits = body.citizenId.toString().split("").map(Number);
      const cal =
        citizenIdDigits[0] * 13 +
        citizenIdDigits[1] * 12 +
        citizenIdDigits[2] * 11 +
        citizenIdDigits[3] * 10 +
        citizenIdDigits[4] * 9 +
        citizenIdDigits[5] * 8 +
        citizenIdDigits[6] * 7 +
        citizenIdDigits[7] * 6 +
        citizenIdDigits[8] * 5 +
        citizenIdDigits[9] * 4 +
        citizenIdDigits[10] * 3 +
        citizenIdDigits[11] * 2;
      const calStp2 = cal % 11;
      const chkDigit = (11 - calStp2) % 10;

      if (citizenIdDigits[12] !== chkDigit) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ข้อมูลรหัสบัตรประจำตัวประชาชนไม่ถูกต้อง");
      }
    }
    if (body.posTypeId && !(await this.posTypeRepo.findOneBy({ id: body.posTypeId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
    }

    if (body.citizenId.length !== 13) {
      throw new HttpError(
        HttpStatus.NOT_FOUND,
        "กรุณากรอกข้อมูลรหัสบัตรประจำตัวประชาชนให้ครบ 13 หลัก",
      );
    }

    if (body.citizenId) {
      const citizenIdDigits = body.citizenId.toString().split("").map(Number);
      const cal =
        citizenIdDigits[0] * 13 +
        citizenIdDigits[1] * 12 +
        citizenIdDigits[2] * 11 +
        citizenIdDigits[3] * 10 +
        citizenIdDigits[4] * 9 +
        citizenIdDigits[5] * 8 +
        citizenIdDigits[6] * 7 +
        citizenIdDigits[7] * 6 +
        citizenIdDigits[8] * 5 +
        citizenIdDigits[9] * 4 +
        citizenIdDigits[10] * 3 +
        citizenIdDigits[11] * 2;
      const calStp2 = cal % 11;
      const chkDigit = (11 - calStp2) % 10;
      // else if(chkDigit === 11){
      //   chkDigit = cal % 10;
      // }

      if (citizenIdDigits[12] !== chkDigit) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ข้อมูลรหัสบัตรประจำตัวประชาชนไม่ถูกต้อง");
      }
    }

    // if (body.citizenId && (await this.profileRepo.findOneBy({ citizenId: body.citizenId }))) {
    //   throw new HttpError(HttpStatus.NOT_FOUND, "ข้อมูลรหัสบัตรประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว");
    // }

    const profile = Object.assign(new Profile(), body);
    profile.prefixMain = profile.prefix;
    profile.prefix = profile.rank && profile.rank.length > 0 ? profile.rank : profile.prefixMain;
    profile.isProbation = false;
    profile.isLeave = false;
    profile.createdUserId = request.user.sub;
    profile.createdFullName = request.user.name;
    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.createdAt = new Date();
    profile.lastUpdatedAt = new Date();
    profile.dateRetire = calculateRetireDate(profile.birthDate);
    profile.dateRetireLaw = calculateRetireLaw(profile.birthDate);
    await this.profileRepo.save(profile);

    return new HttpSuccess();
  }

  /**
   * API สร้างทะเบียนประวัติใหม่
   *
   * @summary ORG_065 - สร้างทะเบียนประวัติใหม่ (ADMIN) #XXX
   *
   */
  @Post("all")
  async createProfileAll(
    @Request() request: RequestWithUser,
    @Body() body: CreateProfileAllFields,
  ) {
    const profileExist = await this.profileRepo.findOneBy({ citizenId: body.citizenId });
    if (profileExist) {
      return new HttpSuccess(profileExist.id);
    }

    if (body.posLevelId === "") body.posLevelId = null;
    if (body.posTypeId === "") body.posTypeId = null;

    if (body.posLevelId && !(await this.posLevelRepo.findOneBy({ id: body.posLevelId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้");
    }

    if (body.posTypeId && !(await this.posTypeRepo.findOneBy({ id: body.posTypeId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
    }

    if (body.citizenId) {
      const citizenIdDigits = body.citizenId.toString().split("").map(Number);
      const cal =
        citizenIdDigits[0] * 13 +
        citizenIdDigits[1] * 12 +
        citizenIdDigits[2] * 11 +
        citizenIdDigits[3] * 10 +
        citizenIdDigits[4] * 9 +
        citizenIdDigits[5] * 8 +
        citizenIdDigits[6] * 7 +
        citizenIdDigits[7] * 6 +
        citizenIdDigits[8] * 5 +
        citizenIdDigits[9] * 4 +
        citizenIdDigits[10] * 3 +
        citizenIdDigits[11] * 2;
      const calStp2 = cal % 11;
      const chkDigit = (11 - calStp2) % 10;

      if (citizenIdDigits[12] !== chkDigit) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ข้อมูลรหัสบัตรประจำตัวประชาชนไม่ถูกต้อง");
      }
    }
    const profile: Profile = Object.assign(new Profile(), body);
    const _null: any = null;
    profile.prefixMain = profile.prefix;
    profile.prefix = profile.rank && profile.rank.length > 0 ? profile.rank : profile.prefixMain;
    profile.dateRetire = body.birthDate == null ? _null : calculateRetireDate(body.birthDate);
    profile.dateRetireLaw = body.birthDate == null ? _null : calculateRetireLaw(body.birthDate);
    profile.createdUserId = request.user.sub;
    profile.createdFullName = request.user.name;
    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.createdAt = new Date();
    profile.lastUpdatedAt = new Date();
    await this.profileRepo.save(profile);
    return new HttpSuccess(profile.id);
  }

  /**
   * API สร้างทะเบียนประวัติใหม่
   *
   * @summary ORG_065 - สร้างทะเบียนประวัติใหม่ (ADMIN) #XXX
   *
   */
  @Post("allv2")
  async createProfileAllV2(
    @Request() request: RequestWithUser,
    @Body() body: CreateProfileAllFields,
  ) {
    const profileExist = await this.profileRepo.findOneBy({ citizenId: body.citizenId });
    if (profileExist) {
      return new HttpSuccess(profileExist.id);
    }

    if (body.posLevelId === "") body.posLevelId = null;
    if (body.posTypeId === "") body.posTypeId = null;

    if (body.posLevelId && !(await this.posLevelRepo.findOneBy({ id: body.posLevelId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้");
    }

    if (body.posTypeId && !(await this.posTypeRepo.findOneBy({ id: body.posTypeId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
    }

    if (body.citizenId) {
      const citizenIdDigits = body.citizenId.toString().split("").map(Number);
      const cal =
        citizenIdDigits[0] * 13 +
        citizenIdDigits[1] * 12 +
        citizenIdDigits[2] * 11 +
        citizenIdDigits[3] * 10 +
        citizenIdDigits[4] * 9 +
        citizenIdDigits[5] * 8 +
        citizenIdDigits[6] * 7 +
        citizenIdDigits[7] * 6 +
        citizenIdDigits[8] * 5 +
        citizenIdDigits[9] * 4 +
        citizenIdDigits[10] * 3 +
        citizenIdDigits[11] * 2;
      const calStp2 = cal % 11;
      const chkDigit = (11 - calStp2) % 10;

      if (citizenIdDigits[12] !== chkDigit) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ข้อมูลรหัสบัตรประจำตัวประชาชนไม่ถูกต้อง");
      }
    }
    const profile: Profile = Object.assign(new Profile(), body);
    profile.prefixMain = profile.prefix;
    profile.prefix = profile.rank && profile.rank.length > 0 ? profile.rank : profile.prefixMain;
    profile.createdUserId = request.user.sub;
    profile.createdFullName = request.user.name;
    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.createdAt = new Date();
    profile.lastUpdatedAt = new Date();
    await this.profileRepo.save(profile);
    return new HttpSuccess(profile.id);
  }

  async sendVerifyEmail(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      email: string;
      subject: string;
    },
  ) {
    const jwt = require("jsonwebtoken");
    const token = jwt.sign(
      { email_id: body.email, profileId: body.profileId },
      process.env.AUTH_ACCOUNT_SECRET,
      { expiresIn: "15m" },
    );
    const link = process.env.VITE_URL_USER + "/verifyemail?upn=" + token;

    await new CallAPI()
      .PostData(req, "/placement/noti/send-mail", {
        subject: body.subject,
        body: link,
        Email: body.email,
      })
      .catch((error) => {
        console.error("Error calling API:", error);
      });
    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งให้ข้าราชการที่มีผลการทดลองปฏิบัติหน้าที่ราชการไม่ต่ำกว่ามาตรฐานที่กำหนดรับราชการต่อไป
   *
   * @summary API ออกคำสั่ง คำสั่งให้ข้าราชการที่มีผลการทดลองปฏิบัติหน้าที่ราชการไม่ต่ำกว่ามาตรฐานที่กำหนดรับราชการต่อไป (ADMIN)
   *
   */
  @Post("command11/{profileId}")
  async ExecuteCommand11Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    // const posType = await this.posTypeRepo.findOneBy({ id: String(profile.posTypeId) })
    // const posLevel = await this.posLevelRepo.findOneBy({ id: String(profile.posLevelId) })
    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    if (profile.isProbation != false) {
      profile.isProbation = false;
      profile.lastUpdateUserId = req.user.sub;
      profile.lastUpdateFullName = req.user.name;
      profile.lastUpdatedAt = new Date();
      const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
        profileId: body.profileId,
        positionType: profile.posType.posTypeName,
        positionLevel: profile.posLevel.posLevelName,
        positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        order:
          profile.profileSalary.length >= 0
            ? profile.profileSalary.length > 0
              ? profile.profileSalary[0].order + 1
              : 1
            : null,
        orgRoot: orgRootRef?.orgRootName ?? null,
        orgChild1: orgChild1Ref?.orgChild1Name ?? null,
        orgChild2: orgChild2Ref?.orgChild2Name ?? null,
        orgChild3: orgChild3Ref?.orgChild3Name ?? null,
        orgChild4: orgChild4Ref?.orgChild4Name ?? null,
        createdUserId: req.user.sub,
        createdFullName: req.user.name,
        lastUpdateUserId: req.user.sub,
        lastUpdateFullName: req.user.name,
        createdAt: new Date(),
        lastUpdatedAt: new Date(),
        positionName: profile.position,
        commandNo: body.commandNo,
        commandYear: body.commandYear,
        posNo: shortName,
        posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
          ?.posMasterNo,
        commandDateAffect: body.commandDateAffect,
        commandDateSign: body.commandDateSign,
        commandCode: body.commandCode,
        commandName: body.commandName,
        remark: body.remark,
      });
      await Promise.all([this.salaryRepo.save(profileSalary)]);
    }
    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งให้ข้าราชการออกจากราชการเพราะผลการทดลองปฏิบัติหน้าที่ราชการต่ำกว่ามาตรฐานที่กำหนด
   *
   * @summary API ออกคำสั่ง คำสั่งให้ข้าราชการออกจากราชการเพราะผลการทดลองปฏิบัติหน้าที่ราชการต่ำกว่ามาตรฐานที่กำหนด (ADMIN)
   *
   */
  @Post("command12/{profileId}")
  async ExecuteCommand12Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    const _profile = await this.profileRepo.findOne({
      where: { id: body.profileId },
    });
    if (!_profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    let dateLeave_: any = body.commandDateAffect;
    _profile.isLeave = true;
    _profile.leaveReason =
      "คำสั่งให้ข้าราชการออกจากราชการเพราะผลการทดลองปฏิบัติหน้าที่ราชการต่ำกว่ามาตรฐานที่กำหนด";
    _profile.dateLeave = dateLeave_;
    _profile.lastUpdateUserId = req.user.sub;
    _profile.lastUpdateFullName = req.user.name;
    _profile.lastUpdatedAt = new Date();

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await removeProfileInOrganize(profile.id, "OFFICER");
    await Promise.all([this.profileRepo.save(_profile), this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งปลดออกจากราชการ
   *
   * @summary API ออกคำสั่ง คำสั่งปลดออกจากราชการ (ADMIN)
   *
   */
  @Post("command19/{profileId}")
  async ExecuteCommand19Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    const _profile = await this.profileRepo.findOne({
      where: { id: body.profileId },
    });
    if (!_profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    let dateLeave_: any = body.commandDateAffect;
    _profile.isLeave = true;
    _profile.leaveReason = "ได้รับโทษทางวินัย ปลดออกจากราชการ";
    _profile.dateLeave = dateLeave_;
    _profile.lastUpdateUserId = req.user.sub;
    _profile.lastUpdateFullName = req.user.name;
    _profile.lastUpdatedAt = new Date();

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await removeProfileInOrganize(profile.id, "OFFICER");
    await Promise.all([this.profileRepo.save(_profile), this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งไล่ออกจากราชการ
   *
   * @summary API ออกคำสั่ง คำสั่งไล่ออกจากราชการ (ADMIN)
   *
   */
  @Post("command20/{profileId}")
  async ExecuteCommand20Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    const _profile = await this.profileRepo.findOne({
      where: { id: body.profileId },
    });
    if (!_profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    let dateLeave_: any = body.commandDateAffect;
    _profile.isLeave = true;
    _profile.leaveReason = "ได้รับโทษทางวินัย ไล่ออกจากราชการ";
    _profile.dateLeave = dateLeave_;
    _profile.lastUpdateUserId = req.user.sub;
    _profile.lastUpdateFullName = req.user.name;
    _profile.lastUpdatedAt = new Date();

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await removeProfileInOrganize(profile.id, "OFFICER");
    await Promise.all([this.profileRepo.save(_profile), this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งพักจากราชการ
   *
   * @summary API ออกคำสั่ง คำสั่งพักจากราชการ (ADMIN)
   *
   */
  @Post("command25/{profileId}")
  async ExecuteCommand25Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    const _profile = await this.profileRepo.findOne({
      where: { id: body.profileId },
    });
    if (!_profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    let dateLeave_: any = body.commandDateAffect;
    _profile.isLeave = true;
    _profile.leaveReason = "ได้รับโทษทางวินัย พักจากราชการ";
    _profile.dateLeave = dateLeave_;
    _profile.lastUpdateUserId = req.user.sub;
    _profile.lastUpdateFullName = req.user.name;
    _profile.lastUpdatedAt = new Date();

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await removeProfileInOrganize(profile.id, "OFFICER");
    await Promise.all([this.profileRepo.save(_profile), this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งให้ออกจากราชการไว้ก่อน
   *
   * @summary API ออกคำสั่ง คำสั่งให้ออกจากราชการไว้ก่อน (ADMIN)
   *
   */
  @Post("command26/{profileId}")
  async ExecuteCommand26Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    const _profile = await this.profileRepo.findOne({
      where: { id: body.profileId },
    });
    if (!_profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    let dateLeave_: any = body.commandDateAffect;
    _profile.isLeave = true;
    _profile.leaveReason = "ได้รับโทษทางวินัย ให้ออกจากราชการไว้ก่อน";
    _profile.dateLeave = dateLeave_;
    _profile.lastUpdateUserId = req.user.sub;
    _profile.lastUpdateFullName = req.user.name;

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await removeProfileInOrganize(profile.id, "OFFICER");
    await Promise.all([this.profileRepo.save(_profile), this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งลงโทษ ภาคทัณฑ์
   *
   * @summary API ออกคำสั่ง คำสั่งลงโทษ ภาคทัณฑ์ (ADMIN)
   *
   */
  @Post("command27/{profileId}")
  async ExecuteCommand27Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    // let dateLeave_: any = body.date;
    // profile.isLeave = true;
    // profile.leaveReason = "ได้รับโทษทางวินัย ลงโทษ ภาคทัณฑ์";
    // profile.dateLeave = dateLeave_;
    // profile.lastUpdateUserId = req.user.sub;
    // profile.lastUpdateFullName = req.user.name;

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await Promise.all([this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งลงโทษ ตัดเงินเดือน
   *
   * @summary API ออกคำสั่ง คำสั่งลงโทษ ตัดเงินเดือน (ADMIN)
   *
   */
  @Post("command28/{profileId}")
  async ExecuteCommand28Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    // let dateLeave_: any = body.date;
    // profile.isLeave = true;
    // profile.leaveReason = "ได้รับโทษทางวินัย ลงโทษ ตัดเงินเดือน";
    // profile.dateLeave = dateLeave_;
    // profile.lastUpdateUserId = req.user.sub;
    // profile.lastUpdateFullName = req.user.name;

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await Promise.all([this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งลงโทษ ลดขั้นเงินเดือน
   *
   * @summary API ออกคำสั่ง คำสั่งลงโทษ ลดขั้นเงินเดือน (ADMIN)
   *
   */
  @Post("command29/{profileId}")
  async ExecuteCommand29Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    // let dateLeave_: any = body.date;
    // profile.isLeave = true;
    // profile.leaveReason = "ได้รับโทษทางวินัย ลงโทษ ลดขั้นเงินเดือน";
    // profile.dateLeave = dateLeave_;
    // profile.lastUpdateUserId = req.user.sub;
    // profile.lastUpdateFullName = req.user.name;

    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;

    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await Promise.all([this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งเพิ่มโทษ
   *
   * @summary API ออกคำสั่ง คำสั่งเพิ่มโทษ (ADMIN)
   *
   */
  @Post("command30/{profileId}")
  async ExecuteCommand30Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    // let dateLeave_: any = body.date;
    // profile.isLeave = true;
    // profile.leaveReason = "ได้รับโทษทางวินัย เพิ่มโทษ";
    // profile.dateLeave = dateLeave_;
    // profile.lastUpdateUserId = req.user.sub;
    // profile.lastUpdateFullName = req.user.name;

    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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await Promise.all([this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งงดโทษ
   *
   * @summary API ออกคำสั่ง คำสั่งงดโทษ (ADMIN)
   *
   */
  @Post("command31/{profileId}")
  async ExecuteCommand31Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      commandNo: string | null;
      commandYear: number;
      commandDateAffect?: Date | null;
      commandDateSign?: Date | null;
      commandCode?: string | null;
      commandName?: string | null;
      remark: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary", "posType", "posLevel"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    // let dateLeave_: any = body.date;
    // profile.isLeave = true;
    // profile.leaveReason = "ได้รับโทษทางวินัย งดโทษ";
    // profile.dateLeave = dateLeave_;
    // profile.lastUpdateUserId = req.user.sub;
    // profile.lastUpdateFullName = req.user.name;

    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;

    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
      profileId: body.profileId,
      positionType: profile.posType.posTypeName,
      positionLevel: profile.posLevel.posLevelName,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      order:
        profile.profileSalary.length >= 0
          ? profile.profileSalary.length > 0
            ? profile.profileSalary[0].order + 1
            : 1
          : null,
      orgRoot: orgRootRef?.orgRootName ?? null,
      orgChild1: orgChild1Ref?.orgChild1Name ?? null,
      orgChild2: orgChild2Ref?.orgChild2Name ?? null,
      orgChild3: orgChild3Ref?.orgChild3Name ?? null,
      orgChild4: orgChild4Ref?.orgChild4Name ?? null,
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      positionName: profile.position,
      commandNo: body.commandNo,
      commandYear: body.commandYear,
      posNo: shortName,
      posNoAbb: profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        ?.posMasterNo,
      commandDateAffect: body.commandDateAffect,
      commandDateSign: body.commandDateSign,
      commandCode: body.commandCode,
      commandName: body.commandName,
      remark: body.remark,
    });
    await Promise.all([this.salaryRepo.save(profileSalary)]);

    return new HttpSuccess();
  }

  /**
   * API ออกคำสั่ง คำสั่งยุติเรื่อง
   *
   * @summary API ออกคำสั่ง คำสั่งยุติเรื่อง (ADMIN)
   *
   */
  @Post("command32/{profileId}")
  async ExecuteCommand32Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      date: Date | null;
      commandNo: string | null;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: ["profileSalary"],
      where: { id: body.profileId },
      order: {
        profileSalary: {
          order: "DESC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
    }
    let _null: any = null;
    profile.isLeave = false;
    profile.leaveReason = _null;
    profile.dateLeave = _null;
    profile.lastUpdateUserId = req.user.sub;
    profile.lastUpdateFullName = req.user.name;
    profile.lastUpdatedAt = new Date();

    await Promise.all([this.profileRepo.save(profile)]);

    return new HttpSuccess();
  }

  /**
   * API คำนวนวันเกษียณ
   *
   *
   */
  @Post("cal/retire")
  async calDateRetire(@Body() body: { birthDate: Date }) {
    const retireDate = await calculateRetireDate(body.birthDate);
    const age = calculateAge(body.birthDate);

    return new HttpSuccess({ retireDate, age });
  }

  /**
   * API แก้ไขประวัติในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @summary แก้ไขประวัติในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Patch("request-edit/myprofile/{id}")
  async updateProfileReEdit(
    @Request() request: RequestWithUser,
    @Path() id: string,
    @Body() body: UpdateProfileReqEdit,
  ) {
    const record = await this.profileRepo.findOneBy({ id });

    if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์นี้");

    Object.keys(body).forEach((key) => {
      const typedKey = key as keyof UpdateProfileReqEdit; // บอก TypeScript ว่า key เป็นฟิลด์ของ UpdateProfileReqEdit
      if (body[typedKey] === null || body[typedKey] === "") delete body[typedKey];
    });

    Object.assign(record, body);
    record.prefixMain = record.prefix;
    record.prefix = record.rank ?? record.prefixMain;
    record.createdUserId = request.user.sub;
    record.createdFullName = request.user.name;
    record.createdAt = new Date();
    record.lastUpdateUserId = request.user.sub;
    record.lastUpdateFullName = request.user.name;
    record.lastUpdatedAt = new Date();
    await this.profileHistoryRepo.save(
      Object.assign(new ProfileHistory(), {
        ...record,
        profileId: id,
        id: undefined,
      }),
    );
    await this.profileRepo.save(record);
    // setLogDataDiff(request, { before, after: record });

    if (record != null && record.keycloak != null && record.isDelete === false) {
      const result = await updateName(
        record.keycloak,
        record.firstName,
        record.lastName,
        record.prefix,
      );
      if (!result) {
        throw new Error(result.errorMessage);
      }
    }

    return new HttpSuccess();
  }

  /**
   * API แก้ไขประวัติบิดาในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @summary แก้ไขประวัติบิดาในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Patch("request-edit/father/{id}")
  public async UpdateFamilyFather(
    @Request() req: RequestWithUser,
    @Path() id: string,
    @Body() body: UpdateProfileFather,
  ) {
    const profile = await this.profileRepo.findOneBy({ id: id });
    if (!profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }

    let lastestData: any = await this.profileFamilyFatherRepository.findOne({
      where: { profileId: id },
      order: { createdAt: "DESC" },
    });

    Object.keys(body).forEach((key) => {
      const typedKey = key as keyof UpdateProfileFather; // บอก TypeScript ว่า key เป็นฟิลด์ของ UpdateProfileFather
      if (body[typedKey] === null || body[typedKey] === "") delete body[typedKey];
    });

    if (!lastestData) {
      lastestData = new ProfileFamilyFather();
      Object.assign(lastestData, body);
      lastestData.profileId = id;
    }

    Object.assign(lastestData, body);
    lastestData.createdUserId = req.user.sub;
    lastestData.createdFullName = req.user.name;
    lastestData.lastUpdateUserId = req.user.sub;
    lastestData.lastUpdateFullName = req.user.name;
    lastestData.createdAt = new Date();
    lastestData.lastUpdatedAt = new Date();

    const history = new ProfileFamilyFatherHistory();
    Object.assign(history, { ...lastestData, id: undefined });

    await this.profileFamilyFatherRepository.save(lastestData, { data: req });
    history.profileFamilyFatherId = lastestData.id;
    await this.profileFamilyFatherHistoryRepo.save(history, { data: req });
    return new HttpSuccess(lastestData.id);
  }

  /**
   * API แก้ไขประวัติมารดาในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @summary แก้ไขประวัติมารดาในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Patch("request-edit/mother/{id}")
  public async UpdateFamilyMother(
    @Request() req: RequestWithUser,
    @Path() id: string,
    @Body() body: UpdateProfileMother,
  ) {
    const profile = await this.profileRepo.findOneBy({ id: id });
    if (!profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }

    let lastestData = await this.profileFamilyMotherRepository.findOne({
      where: { profileId: id },
      order: { createdAt: "DESC" },
    });

    Object.keys(body).forEach((key) => {
      const typedKey = key as keyof UpdateProfileMother; // บอก TypeScript ว่า key เป็นฟิลด์ของ UpdateProfileMother
      if (body[typedKey] === null || body[typedKey] === "") delete body[typedKey];
    });

    if (!lastestData) {
      lastestData = new ProfileFamilyMother();
      Object.assign(lastestData, body);
      lastestData.profileId = id;
    }

    Object.assign(lastestData, body);
    lastestData.createdUserId = req.user.sub;
    lastestData.createdFullName = req.user.name;
    lastestData.lastUpdateUserId = req.user.sub;
    lastestData.lastUpdateFullName = req.user.name;
    lastestData.createdAt = new Date();
    lastestData.lastUpdatedAt = new Date();

    const history = new ProfileFamilyMotherHistory();
    Object.assign(history, { ...lastestData, id: undefined });

    await this.profileFamilyMotherRepository.save(lastestData, { data: req });
    history.profileFamilyMotherId = lastestData.id;
    await this.profileFamilyMotherHistoryRepo.save(history, { data: req });
    return new HttpSuccess(lastestData.id);
  }

  /**
   * API แก้ไขประวัติคู่สมรสในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @summary แก้ไขประวัติคู่สมรสในเมนูร้องขอแก้ไขทะเบียนประวัติ
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Patch("request-edit/couple/{id}")
  public async UpdateFamilyCouple(
    @Request() req: RequestWithUser,
    @Path() id: string,
    @Body() body: UpdateProfileCouple,
  ) {
    const profile = await this.profileRepo.findOneBy({ id: id });
    if (!profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }

    let lastestData = await this.profileFamilyCoupleRepository.findOne({
      where: { profileId: id },
      order: { createdAt: "DESC" },
    });

    Object.keys(body).forEach((key) => {
      const typedKey = key as keyof UpdateProfileCouple; // บอก TypeScript ว่า key เป็นฟิลด์ของ UpdateProfileCouple
      if (body[typedKey] === null || body[typedKey] === "") delete body[typedKey];
    });

    if (!lastestData) {
      lastestData = new ProfileFamilyCouple();
      Object.assign(lastestData, body);
      lastestData.profileId = id;
    }

    Object.assign(lastestData, body);
    lastestData.createdUserId = req.user.sub;
    lastestData.createdFullName = req.user.name;
    lastestData.lastUpdateUserId = req.user.sub;
    lastestData.lastUpdateFullName = req.user.name;
    lastestData.createdAt = new Date();
    lastestData.lastUpdatedAt = new Date();

    const history = new ProfileFamilyCoupleHistory();
    Object.assign(history, { ...lastestData, id: undefined });

    await this.profileFamilyCoupleRepository.save(lastestData, { data: req });
    history.profileFamilyCoupleId = lastestData.id;
    await this.profileFamilyCoupleHistoryRepo.save(history, { data: req });
    return new HttpSuccess(lastestData.id);
  }

  /**
   * API อัพเดทสถานะ privacy
   *
   * @summary  API อัพเดทสถานะ privacy
   *
   */
  @Put("privacy")
  async updatePrivacy(
    @Request() request: { user: Record<string, any> },
    @Body() body: UpdatePrivacyDto,
  ) {
    let isEmployee = false;
    let profile: any = null;
    profile = await this.profileRepo.findOneBy({
      keycloak: request.user.sub,
    });

    if (!profile) {
      profile = await this.profileEmpRepo.findOne({
        where: { keycloak: request.user.sub },
      });
      isEmployee = true;
    }

    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    }

    const system = body.system.trim().toUpperCase();
    switch (system) {
      case "CHECKIN":
        profile.privacyCheckin = body.accept;
        break;

      case "USER":
        profile.privacyUser = body.accept;
        break;

      case "MGT":
        profile.privacyMgt = body.accept;
        break;

      default:
        throw new HttpError(HttpStatus.BAD_REQUEST, "system ไม่ถูกต้อง");
    }
    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.lastUpdatedAt = new Date();

    if (isEmployee) {
      await this.profileEmpRepo.save(profile, { data: request });
    } else {
      await this.profileRepo.save(profile, { data: request });
    }

    return new HttpSuccess();
  }

  /**
   * API แก้ไขทะเบียนประวัติ
   *
   * @summary ORG_065 - แก้ไขทะเบียนประวัติ (ADMIN) #70
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Put("{id}")
  async updateProfile(
    @Request() request: RequestWithUser,
    @Path() id: string,
    @Body() body: UpdateProfile,
  ) {
    const _record = await this.profileRepo.findOneBy({ id: id });
    if (_record) {
      await new permission().PermissionOrgUserUpdate(request, "SYS_REGISTRY_OFFICER", _record.id);
    }
    const exists =
      !!body.citizenId &&
      (await this.profileRepo.findOne({
        where: { id: Not(id), citizenId: body.citizenId },
      }));

    if (exists) {
      throw new HttpError(HttpStatus.CONFLICT, "รหัสบัตรประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว");
    }

    if (body.posLevelId === "") body.posLevelId = null;
    if (body.posTypeId === "") body.posTypeId = null;

    if (body.posLevelId && !(await this.posLevelRepo.findOneBy({ id: body.posLevelId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้");
    }

    if (body.posTypeId && !(await this.posTypeRepo.findOneBy({ id: body.posTypeId }))) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
    }

    if (body.citizenId && body.citizenId.length !== 13) {
      throw new HttpError(
        HttpStatus.NOT_FOUND,
        "กรุณากรอกข้อมูลรหัสบัตรประจำตัวประชาชนให้ครบ 13 หลัก",
      );
    }

    if (body.citizenId) {
      Extension.CheckCitizen(body.citizenId);
    }
    const record = await this.profileRepo.findOneBy({ id });
    const before = structuredClone(record);
    // เช็คว่ามี profileHistory ของ profile นี้หรือไม่
    const historyCount = await this.profileHistoryRepo.count({
      where: { profileId: id },
    });

    // ถ้าไม่มีเลย ให้บันทึกข้อมูลเริ่มต้น (ก่อน update) ลงไปก่อน
    if (historyCount === 0) {
      await this.profileHistoryRepo.save(
        Object.assign(new ProfileHistory(), {
          ...before,
          birthDateOld: before?.birthDate,
          profileId: id,
          id: undefined,
        }),
      );
    }

    if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์นี้");

    Object.assign(record, body);
    record.dateRetireLaw = calculateRetireLaw(record.birthDate);
    record.prefixMain = record.prefix;
    record.prefix = record.rank && record.rank.length > 0 ? record.rank : record.prefixMain;
    record.createdUserId = request.user.sub;
    record.createdFullName = request.user.name;
    record.createdAt = new Date();
    record.lastUpdateUserId = request.user.sub;
    record.lastUpdateFullName = request.user.name;
    record.lastUpdatedAt = new Date();
    await this.profileHistoryRepo.save(
      Object.assign(new ProfileHistory(), {
        ...record,
        birthDateOld: _record?.birthDate,
        profileId: id,
        id: undefined,
      }),
    );
    await this.profileRepo.save(record, { data: request });
    setLogDataDiff(request, { before, after: record });

    if (record != null && record.keycloak != null && record.isDelete === false) {
      const result = await updateName(
        record.keycloak,
        record.firstName,
        record.lastName,
        record.prefix,
      );
      if (!result) {
        throw new Error(result.errorMessage);
      }
    }

    // บันทึกประวัติคนครองตำแหน่ง (ถ้า profile นี้ครองตำแหน่งอยู่)
    await updateHolderProfileHistory(record.id, request);

    return new HttpSuccess();
  }

  /**
   * API ลบทะเบียนประวัติ
   *
   * @summary ORG_065 - ลบทะเบียนประวัติ (ADMIN) #70
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Delete("{id}")
  async deleteProfile(@Path() id: string) {
    const data = await this.profileRepo.findOne({ where: { id: id } });
    if (!data) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    }
    await this.profileRepo.remove(data);

    return new HttpSuccess();
  }

  /**
   * API รายละเอียดรายการทะเบียนประวัติ
   *
   * @summary ORG_065 - รายละเอียดรายการทะเบียนประวัติ  (ADMIN) #70
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Get("user")
  async getProfileByUser(@Request() request: RequestWithUser) {
    const profile = await this.profileRepo.findOne({
      relations: {
        posLevel: true,
        posType: true,
      },
      where: { keycloak: request.user.sub },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    return new HttpSuccess(profile);
  }

  /**
   * API รายละเอียดรายการทะเบียนประวัติ
   *
   * @summary ORG_065 - รายละเอียดรายการทะเบียนประวัติ  (ADMIN) #70
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Get("keycloak")
  async getProfileIdByKeycloak(@Request() request: RequestWithUser) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
      select: ["id"],
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    return new HttpSuccess(profile.id);
  }

  @Get("type")
  async checkRole(@Request() request: RequestWithUser) {
    let role: any;
    const checkProfile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
    });
    role = "OFFICER";
    if (!checkProfile) {
      const checkEmployee = await this.profileEmpRepo.findOne({
        where: { keycloak: request.user.sub },
        select: ["employeeClass"],
      });
      if (checkEmployee?.employeeClass === "PERM" || checkEmployee?.employeeClass === "TEMP") {
        role = checkEmployee.employeeClass.toUpperCase();
      } else {
        role = "EMPLOYEE";
      }
      if (!checkProfile && !checkEmployee)
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์นี้");
    }
    return new HttpSuccess(role);
  }

  /**
   * API ประวัติการแก้ไขรายการทะเบียนประวัติ
   *
   * @summary ประวัติการแก้ไขรายการทะเบียนประวัติ
   *
   * @param {string} id  Id โปรไฟล์
   */
  @Get("history/user")
  async getHistoryProfileByUser(@Request() request: RequestWithUser) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
    });
    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    const profileHistory = await this.profileHistoryRepo.find({
      where: { profileId: profile.id },
      order: { createdAt: "ASC" },
    });

    if (profileHistory.length == 0) {
      await this.profileHistoryRepo.save(
        Object.assign(new ProfileHistory(), {
          ...profile,
          birthDateOld: profile?.birthDate,
          profileId: profile.id,
          id: undefined,
        }),
      );
      const firstRecord = await this.profileHistoryRepo.find({
        where: { profileId: profile.id },
        order: { createdAt: "ASC" },
      });
      return new HttpSuccess(firstRecord);
    }

    return new HttpSuccess(profileHistory);
  }

  /**
   * API รายการทะเบียนประวัติในระบบอื่น
   *
   * @summary ORG_065 - รายการทะเบียนประวัติในระบบอื่น
   *
   */
  @Get("otherSystem")
  @Example({
    status: 200,
    message: "สำเร็จ",
    result: {
      data: [
        {
          id: "ecb0b34c-037e-41f2-b95e-7e19f88b42ae",
          createdAt: "2024-03-24T12:39:12.105Z",
          createdUserId: "00000000-0000-0000-0000-000000000000",
          lastUpdatedAt: "2024-03-24T12:41:43.164Z",
          lastUpdateUserId: "00000000-0000-0000-0000-000000000000",
          createdFullName: "string",
          lastUpdateFullName: "string",
          rank: null,
          prefix: null,
          firstName: "Methapon",
          lastName: "Metanipat",
          citizenId: null,
          position: null,
          posLevelId: null,
          posTypeId: null,
          email: null,
          phone: null,
          keycloak: null,
          isProbation: false,
          dateRetire: null,
          birthDate: null,
          ethnicity: null,
          telephoneNumber: null,
          gender: null,
          relationship: null,
          bloodGroup: null,
          posLevel: null,
          posType: null,
          org: null,
        },
      ],
      total: 1,
    },
  })
  async listProfileNoPermission(
    @Request() request: RequestWithUser,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Query()
    searchField?: "firstName" | "lastName" | "fullName" | "citizenId" | "position" | "posNo",
    @Query() searchKeyword: string = "",
    @Query() posType?: string,
    @Query() posLevel?: string,
    @Query() yearLeave?: number,
    @Query() isProbation?: boolean,
    @Query() isRetire?: boolean,
    @Query() nodeId?: string,
  ) {
    let queryLike =
      "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword";
    if (searchField == "citizenId") {
      queryLike = "profile.citizenId LIKE :keyword";
    } else if (searchField == "position") {
      queryLike = "profile.position LIKE :keyword";
    } else if (searchField == "posNo") {
      queryLike = `
      CASE
        WHEN current_holders.orgChild4Id IS NOT NULL THEN CONCAT_WS(' ', orgChild4.orgChild4ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild3Id IS NOT NULL THEN CONCAT_WS(' ', orgChild3.orgChild3ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild2Id IS NOT NULL THEN CONCAT_WS(' ', orgChild2.orgChild2ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild1Id IS NOT NULL THEN CONCAT_WS(' ', orgChild1.orgChild1ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        ELSE CONCAT_WS(' ', orgRoot.orgRootShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
      END LIKE :keyword
    `;
    }
    let posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holder: { keycloak: request.user.sub },
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
    });
    let revisionId = "";
    if (nodeId == null) {
      const findRevision = await this.orgRevisionRepo.findOne({
        where: { orgRevisionIsCurrent: true },
      });
      if (!findRevision) {
        throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
      }
      revisionId = findRevision.id;
      if (posMaster != null) nodeId = posMaster.orgRootId ?? "";
    } else {
      const findRoot = await this.orgRootRepo.findOne({
        where: { id: nodeId },
      });
      if (!findRoot) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบสำนักงานนี้ในระบบ");
      }
      revisionId = findRoot.orgRevisionId;
    }
    let nodeCondition = "current_holders.orgRootId = :nodeId";
    const [record, total] = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .leftJoinAndSelect("current_holders.orgRevision", "orgRevision")
      .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("current_holders.orgRevisionId = :orgRevisionId", { orgRevisionId: revisionId })
      .andWhere(
        posType != undefined && posType != null && posType != ""
          ? "posType.posTypeName LIKE :keyword1"
          : "1=1",
        {
          keyword1: `${posType}`,
        },
      )
      .andWhere(
        posLevel != undefined && posLevel != null && posLevel != ""
          ? "posLevel.posLevelName LIKE :keyword2"
          : "1=1",
        {
          keyword2: `${posLevel}`,
        },
      )
      .andWhere(
        isProbation != undefined && isProbation != null
          ? `profile.isProbation = ${isProbation}`
          : "1=1",
      )
      .andWhere(
        isRetire != undefined && isRetire != null
          ? isRetire == false
            ? `profile.dateLeave IS null`
            : `profile.dateLeave IS NOT NULL`
          : "1=1",
      )
      .andWhere(
        searchKeyword != undefined && searchKeyword != null && searchKeyword != ""
          ? queryLike
          : "1=1",
        {
          keyword: `%${searchKeyword}%`,
        },
      )
      .andWhere(nodeCondition, {
        nodeId: nodeId,
      })
      .orderBy("current_holders.posMasterNo", "ASC")
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    const data = await Promise.all(
      record.map((_data) => {
        const posExecutive =
          _data.current_holders.length == 0 ||
            _data.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
            _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.positions.length == 0 ||
            _data.current_holders
              .find((x) => x.orgRevisionId == revisionId)
              ?.positions.find((x: any) => x.positionIsSelected == true) == null ||
            _data.current_holders
              .find((x) => x.orgRevisionId == revisionId)
              ?.positions.find((x: any) => x.positionIsSelected == true)?.posExecutive == null
            ? null
            : _data.current_holders
              .find((x) => x.orgRevisionId == revisionId)
              ?.positions.find((x: any) => x.positionIsSelected == true)?.posExecutive
              ?.posExecutiveName;

        const shortName =
          _data.current_holders.length == 0
            ? null
            : _data.current_holders.find((x) => x.orgRevisionId == revisionId) != null &&
              _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4 != null
              ? `${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4.orgChild4ShortName} ${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.posMasterNo}`
              : _data.current_holders.find((x) => x.orgRevisionId == revisionId) != null &&
                _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3 !=
                null
                ? `${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3.orgChild3ShortName} ${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.posMasterNo}`
                : _data.current_holders.find((x) => x.orgRevisionId == revisionId) != null &&
                  _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2 !=
                  null
                  ? `${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2.orgChild2ShortName} ${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.posMasterNo}`
                  : _data.current_holders.find((x) => x.orgRevisionId == revisionId) != null &&
                    _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1 !=
                    null
                    ? `${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1.orgChild1ShortName} ${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.posMasterNo}`
                    : _data.current_holders.find((x) => x.orgRevisionId == revisionId) != null &&
                      _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot !=
                      null
                      ? `${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot.orgRootShortName} ${_data.current_holders.find((x) => x.orgRevisionId == revisionId)?.posMasterNo}`
                      : null;
        const root =
          _data.current_holders.length == 0 ||
            (_data.current_holders.find((x) => x.orgRevisionId == revisionId) != null &&
              _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot == null)
            ? null
            : _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot;

        const child1 =
          _data.current_holders == null ||
            _data.current_holders.length == 0 ||
            _data.current_holders.find((x) => x.orgRevisionId == revisionId) == null
            ? null
            : _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1;

        const child2 =
          _data.current_holders == null ||
            _data.current_holders.length == 0 ||
            _data.current_holders.find((x) => x.orgRevisionId == revisionId) == null
            ? null
            : _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2;

        const child3 =
          _data.current_holders == null ||
            _data.current_holders.length == 0 ||
            _data.current_holders.find((x) => x.orgRevisionId == revisionId) == null
            ? null
            : _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3;

        const child4 =
          _data.current_holders == null ||
            _data.current_holders.length == 0 ||
            _data.current_holders.find((x) => x.orgRevisionId == revisionId) == null
            ? null
            : _data.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4;
        let _root = root?.orgRootName;
        let _child1 = child1?.orgChild1Name;
        let _child2 = child2?.orgChild2Name;
        let _child3 = child3?.orgChild3Name;
        let _child4 = child4?.orgChild4Name;

        return {
          id: _data.id,
          avatar: _data.avatar,
          avatarName: _data.avatarName,
          prefix: _data.prefix,
          rank: _data.rank,
          firstName: _data.firstName,
          lastName: _data.lastName,
          citizenId: _data.citizenId,
          posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
          posType: _data.posType == null ? null : _data.posType.posTypeName,
          posLevelId: _data.posLevel == null ? null : _data.posLevel.id,
          posTypeId: _data.posType == null ? null : _data.posType.id,
          position: _data.position,
          posExecutive: posExecutive,
          posNo: shortName,
          rootId: root == null ? null : root.id,
          root: root == null ? null : root.orgRootName,
          orgRootShortName: root == null ? null : root.orgRootShortName,
          orgRevisionId: root == null ? null : root.orgRevisionId,
          org:
            (_child4 == null ? "" : _child4 + "\n") +
            (_child3 == null ? "" : _child3 + "\n") +
            (_child2 == null ? "" : _child2 + "\n") +
            (_child1 == null ? "" : _child1 + "\n") +
            (_root == null ? "" : _root),
        };
      }),
    );

    return new HttpSuccess({ data: data, total });
  }

  /**
   * API Update amount
   *
   * @summary Update amount (ADMIN)
   *
   */
  @Get("update-amount")
  async updateProfileAmount(@Request() request: RequestWithUser) {
    const profiles = await this.profileRepo.find({
      order: { profileSalary: { order: "DESC" } },
      relations: ["profileSalary"],
    });
    profiles.map(async (x) => {
      const amount = x.profileSalary[0];
      x.amount = amount?.amount ?? 0;
      x.amountSpecial = amount?.amountSpecial ?? 0;
      x.positionSalaryAmount = amount?.positionSalaryAmount ?? 0;
      await this.profileRepo.save(x);
    });
    return new HttpSuccess();
  }

  /**
   * API ค้นหาและแสดงผู้พ้นจากราชการ ข้าราชการ กทม. สามัญ
   *
   * @summary ค้นหาและแสดงผู้พ้นจากราชการ ข้าราชการ กทม. สามัญ จากตำแหน่ง
   */
  @Get("profileLeave")
  @Example({
    status: 200,
    message: "สำเร็จ",
    result: {
      data: [
        {
          page: 1,
          pageSize: 12,
          posLevel: "ปฏิบัติงาน",
          posType: "ทั่วไป",
          isProbation: false,
          isRetire: true,
          node: 0,
          nodeId: "8349b6b6-d005-4eb7-9960-ceb5b96e1962",
          isAll: true,
          sortBy: "profile.dateAppoint",
          sort: "DESC",
          retireType: "RETIRE",
        },
      ],
      total: 1,
    },
  })
  async listProfileLeave(
    @Request() request: RequestWithUser,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Query()
    searchField?: "firstName" | "lastName" | "fullName" | "citizenId" | "position" | "posNo",
    @Query() searchKeyword: string = "",
    @Query() posType?: string,
    @Query() posLevel?: string,
    @Query() isProbation?: boolean,
    @Query() node?: number,
    @Query() nodeId?: string,
    @Query() isAll?: boolean,
    @Query() retireType?: string,
    @Query() sortBy: string = "profile.dateLeave",
    @Query() sort: "ASC" | "DESC" = "ASC",
  ) {
    let _data = await new permission().PermissionOrgList(request, "SYS_REGISTRY_RETIRE_OFFICER");

    const { data, total } = await this.profileLeaveService.getLeaveOfficer(request, {
      page,
      pageSize,
      searchField,
      searchKeyword,
      posType,
      posLevel,
      isProbation,
      node,
      nodeId,
      isAll,
      retireType,
      sortBy,
      sort,
      _data,
    });

    // let _data = await new permission().PermissionOrgList(request, "SYS_REGISTRY_OFFICER");
    // let queryLike =
    //   "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword";
    // if (searchField == "citizenId") {
    //   queryLike = "profile.citizenId LIKE :keyword";
    // } else if (searchField == "position") {
    //   queryLike = "profile.position LIKE :keyword";
    // }
    // else if (searchField == "posNo") {
    //   queryLike = `
    //     CONCAT(profileSalary.posNoAbb, profileSalary.posNo) LIKE :keyword
    //     OR CONCAT(profileSalary.posNoAbb, " ", profileSalary.posNo) LIKE :keyword
    //     OR profileSalary.posNo LIKE :keyword
    //   `;
    // }
    // let nodeCondition = "1=1";
    // let nodeAll = "";
    // let orgRoot = null;
    // let orgChild1 = null;
    // let orgChild2 = null;
    // let orgChild3 = null;
    // let orgChild4 = null;

    // let pmsCondition = "1=1";
    // let orgRootPms = null;
    // let orgChild1Pms = null;
    // let orgChild2Pms = null;
    // let orgChild3Pms = null;
    // let orgChild4Pms = null;

    // if (node === 0 && nodeId) {
    //   orgRoot = await this.orgRootRepo.findOne({ where: { id: nodeId } });
    //   if (orgRoot) {
    //     nodeCondition = "profileSalary.orgRoot = :orgRoot";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild1 IS NULL";
    // } else if (node === 1 && nodeId) {
    //   orgChild1 = await this.orgChild1Repo.findOne({ where: { id: nodeId } });
    //   if (orgChild1) {
    //     nodeCondition = "profileSalary.orgChild1 = :orgChild1";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild2 IS NULL";
    // } else if (node === 2 && nodeId) {
    //   orgChild2 = await this.orgChild2Repo.findOne({ where: { id: nodeId } });
    //   if (orgChild2) {
    //     nodeCondition = "profileSalary.orgChild2 = :orgChild2";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild3 IS NULL";
    // } else if (node === 3 && nodeId) {
    //   orgChild3 = await this.orgChild3Repo.findOne({ where: { id: nodeId } });
    //   if (orgChild3) {
    //     nodeCondition = "profileSalary.orgChild3 = :orgChild3";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild4 IS NULL";
    // } else if (node === 4 && nodeId) {
    //   orgChild4 = await this.orgChild4Repo.findOne({ where: { id: nodeId } });
    //   if (orgChild4) {
    //     nodeCondition = "profileSalary.orgChild4 = :orgChild4";
    //   }
    // }
    // nodeCondition = nodeCondition + nodeAll;

    // if (_data.root) {
    //   orgRootPms = await this.orgRootRepo.findOne({ where: { id: _data.root } });
    //   if (orgRootPms) {
    //     pmsCondition = "profileSalary.orgRoot = :orgRootPms";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild1 IS NULL";
    // } else if (_data.child1) {
    //   orgChild1Pms = await this.orgChild1Repo.findOne({ where: { id: _data.child1 } });
    //   if (orgChild1Pms) {
    //     pmsCondition = "profileSalary.orgChild1 = :orgChild1Pms";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild2 IS NULL";
    // } else if (_data.child2) {
    //   orgChild2Pms = await this.orgChild2Repo.findOne({ where: { id: _data.child2 } });
    //   if (orgChild2Pms) {
    //     pmsCondition = "profileSalary.orgChild2 = :orgChild2Pms";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild3 IS NULL";
    // } else if (_data.child3) {
    //   orgChild3Pms = await this.orgChild3Repo.findOne({ where: { id: _data.child3 } });
    //   if (orgChild3Pms) {
    //     pmsCondition = "profileSalary.orgChild3 = :orgChild3Pms";
    //   }
    //   if (isAll == false) nodeAll = " AND profileSalary.orgChild4 IS NULL";
    // } else if (_data.child4) {
    //   orgChild4Pms = await this.orgChild4Repo.findOne({ where: { id: _data.child4 } });
    //   if (orgChild4Pms) {
    //     pmsCondition = "profileSalary.orgChild4 = :orgChild4Pms";
    //   }
    // }
    // pmsCondition = pmsCondition + nodeAll;

    // const [record, total] = await this.profileRepo
    //   .createQueryBuilder("profile")
    //   .leftJoinAndSelect("profile.posLevel", "posLevel")
    //   .leftJoinAndSelect("profile.posType", "posType")
    //   .leftJoinAndSelect("profile.profileSalary", "profileSalary")
    //   .where(
    //     new Brackets((qb) => {
    //       qb.where("profile.isLeave = :isLeave", { isLeave: true }).orWhere(
    //         "profile.isRetirement = :isRetirement",
    //         { isRetirement: true },
    //       );
    //     }),
    //   )
    //   .andWhere(
    //     "profileSalary.order = (SELECT MAX(ps.order) FROM profileSalary ps WHERE ps.profileId = profile.id and ps.positionName != 'เกษียณอายุราชการ')",
    //   )

    //   .andWhere(
    //     posType != undefined && posType != null && posType != ""
    //       ? "posType.posTypeName LIKE :keyword1"
    //       : "1=1",
    //     {
    //       keyword1: `${posType}`,
    //     },
    //   )
    //   .andWhere(
    //     posLevel != undefined && posLevel != null && posLevel != ""
    //       ? "posLevel.posLevelName LIKE :keyword2"
    //       : "1=1",
    //     {
    //       keyword2: `${posLevel}`,
    //     },
    //   )
    //   .andWhere(
    //     isProbation != undefined && isProbation != null
    //       ? `profile.isProbation = ${isProbation}`
    //       : "1=1",
    //   )
    //   .andWhere(
    //     retireType != undefined && retireType != null ? `profile.leaveType = :retireType` : "1=1",
    //     { retireType: retireType },
    //   )
    //   .andWhere(pmsCondition, {
    //     orgRootPms: orgRootPms ? orgRootPms.orgRootName : "",
    //     orgChild1Pms: orgChild1Pms ? orgChild1Pms.orgChild1Name : "",
    //     orgChild2Pms: orgChild2Pms ? orgChild2Pms.orgChild2Name : "",
    //     orgChild3Pms: orgChild3Pms ? orgChild3Pms.orgChild3Name : "",
    //     orgChild4Pms: orgChild4Pms ? orgChild4Pms.orgChild4Name : "",
    //   })
    //   .andWhere(nodeCondition, {
    //     orgRoot: orgRoot ? orgRoot.orgRootName : "",
    //     orgChild1: orgChild1 ? orgChild1.orgChild1Name : "",
    //     orgChild2: orgChild2 ? orgChild2.orgChild2Name : "",
    //     orgChild3: orgChild3 ? orgChild3.orgChild3Name : "",
    //     orgChild4: orgChild4 ? orgChild4.orgChild4Name : "",
    //   })
    //   .andWhere(
    //     new Brackets((qb) => {
    //       qb.orWhere(
    //         searchKeyword != undefined && searchKeyword != null && searchKeyword != ""
    //           ? queryLike
    //           : "1=1",
    //         {
    //           keyword: `%${searchKeyword}%`,
    //         },
    //       );
    //     }),
    //   )
    //   .skip((page - 1) * pageSize)
    //   .take(pageSize)
    //   .getManyAndCount();

    // const data = await Promise.all(
    //   record.map((_data) => {
    //     return {
    //       id: _data.id,
    //       avatar: _data.avatar,
    //       avatarName: _data.avatarName,
    //       dateAppoint: _data.dateAppoint,
    //       prefix: _data.prefix,
    //       rank: _data.rank,
    //       firstName: _data.firstName,
    //       lastName: _data.lastName,
    //       citizenId: _data.citizenId,

    //       posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
    //       posType: _data.posType == null ? null : _data.posType.posTypeName,
    //       posLevelId: _data.posLevel == null ? null : _data.posLevel.id,
    //       posTypeId: _data.posType == null ? null : _data.posType.id,
    //       position: _data.position,
    //       posExecutive:
    //         _data.profileSalary[0].positionExecutive == null
    //           ? null
    //           : _data.profileSalary[0].positionExecutive,
    //       posNo:
    //         _data.profileSalary[0].posNoAbb && _data.profileSalary[0].posNo
    //           ? `${_data.profileSalary[0].posNoAbb} ${_data.profileSalary[0].posNo}`
    //           : _data.profileSalary[0].posNo || "",
    //       rootId: null,
    //       root: _data.profileSalary[0].orgRoot == null ? null : _data.profileSalary[0].orgRoot,
    //       orgRootShortName:
    //         _data.profileSalary[0].posNoAbb == null ? null : _data.profileSalary[0].posNoAbb,
    //       orgRevisionId: null,
    //       org:
    //         (_data.profileSalary[0].orgChild4 == null
    //           ? ""
    //           : _data.profileSalary[0].orgChild4 + "\n") +
    //         (_data.profileSalary[0].orgChild3 == null
    //           ? ""
    //           : _data.profileSalary[0].orgChild3 + "\n") +
    //         (_data.profileSalary[0].orgChild2 == null
    //           ? ""
    //           : _data.profileSalary[0].orgChild2 + "\n") +
    //         (_data.profileSalary[0].orgChild1 == null
    //           ? ""
    //           : _data.profileSalary[0].orgChild1 + "\n") +
    //         (_data.profileSalary[0].orgRoot == null ? "" : _data.profileSalary[0].orgRoot),
    //     };
    //   }),
    // );

    return new HttpSuccess({ data: data, total });
  }

  /**
   * API รายการทะเบียนประวัติที่เมนูระบบพัฒนา
   *
   * @summary รายการทะเบียนประวัติที่เมนูระบบพัฒนา
   *
   */
  @Get("development")
  @Example({
    status: 200,
    message: "สำเร็จ",
    result: {
      data: [
        {
          id: "ecb0b34c-037e-41f2-b95e-7e19f88b42ae",
          createdAt: "2024-03-24T12:39:12.105Z",
          createdUserId: "00000000-0000-0000-0000-000000000000",
          lastUpdatedAt: "2024-03-24T12:41:43.164Z",
          lastUpdateUserId: "00000000-0000-0000-0000-000000000000",
          createdFullName: "string",
          lastUpdateFullName: "string",
          rank: null,
          prefix: null,
          firstName: "Methapon",
          lastName: "Metanipat",
          citizenId: null,
          position: null,
          posLevelId: null,
          posTypeId: null,
          email: null,
          phone: null,
          keycloak: null,
          isProbation: false,
          dateRetire: null,
          birthDate: null,
          ethnicity: null,
          telephoneNumber: null,
          gender: null,
          relationship: null,
          bloodGroup: null,
          posLevel: null,
          posType: null,
          org: null,
        },
      ],
      total: 1,
    },
  })
  // ...existing code...
  async listProfileDev(
    @Request() request: RequestWithUser,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Query()
    searchField?: "firstName" | "lastName" | "fullName" | "citizenId" | "position" | "posNo",
    @Query() searchKeyword: string = "",
    @Query() posType?: string,
    @Query() posLevel?: string,
    @Query() yearLeave?: number,
    @Query() isProbation?: boolean,
    @Query() isRetire?: boolean,
    @Query() node?: number,
    @Query() nodeId?: string,
    @Query() isAll?: boolean,
    @Query() retireType?: string,
    // @Query() sortBy: string = "current_holders.posMasterNo",
    @Query() sort: "ASC" | "DESC" = "ASC",
    @Query("sortBy") sortBy?: string,
    @Query("descending") descending?: boolean,
  ) {
    let _data = await new permission().PermissionOrgList(request, "SYS_REGISTRY_OFFICER");
    let queryLike =
      "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword";
    if (searchField == "citizenId") {
      queryLike = "profile.citizenId LIKE :keyword";
    } else if (searchField == "position") {
      queryLike = "profile.position LIKE :keyword";
    } else if (searchField == "posNo") {
      queryLike = `
      CASE
        WHEN current_holders.orgChild4Id IS NOT NULL THEN CONCAT_WS(' ', orgChild4.orgChild4ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild3Id IS NOT NULL THEN CONCAT_WS(' ', orgChild3.orgChild3ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild2Id IS NOT NULL THEN CONCAT_WS(' ', orgChild2.orgChild2ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild1Id IS NOT NULL THEN CONCAT_WS(' ', orgChild1.orgChild1ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        ELSE CONCAT_WS(' ', orgRoot.orgRootShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
      END LIKE :keyword
    `;
    }
    let nodeCondition = "1=1";
    let nodeAll = "";
    if (node === 0 && nodeId) {
      nodeCondition = "current_holders.orgRootId = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild1Id IS NULL";
    } else if (node === 1 && nodeId) {
      nodeCondition = "current_holders.orgChild1Id = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild2Id IS NULL";
    } else if (node === 2 && nodeId) {
      nodeCondition = "current_holders.orgChild2Id = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild3Id IS NULL";
    } else if (node === 3 && nodeId) {
      nodeCondition = "current_holders.orgChild3Id = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild4Id IS NULL";
    } else if (node === 4 && nodeId) {
      nodeCondition = "current_holders.orgChild4Id = :nodeId";
    }
    nodeCondition = nodeCondition + nodeAll;
    // เลือกเฉพาะฟิลด์ที่จำเป็น
    let query = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoin("profile.posLevel", "posLevel")
      .leftJoin("profile.posType", "posType")
      .leftJoin("profile.current_holders", "current_holders")
      .leftJoin("current_holders.positions", "positions")
      .leftJoin("positions.posExecutive", "posExecutive")
      .leftJoin("current_holders.orgRoot", "orgRoot")
      .leftJoin("current_holders.orgChild1", "orgChild1")
      .leftJoin("current_holders.orgChild2", "orgChild2")
      .leftJoin("current_holders.orgChild3", "orgChild3")
      .leftJoin("current_holders.orgChild4", "orgChild4")
      .select([
        "profile.id",
        "profile.prefix",
        "profile.rank",
        "profile.firstName",
        "profile.lastName",
        "profile.citizenId",
        "profile.position",
        "posLevel.id",
        "posLevel.posLevelName",
        "posType.id",
        "posType.posTypeName",
        "current_holders.orgRevisionId",
        "current_holders.posMasterNo",
        "current_holders.posMasterNoPrefix",
        "current_holders.posMasterNoSuffix",
        "orgRoot.id",
        "orgRoot.ancestorDNA",
        "orgRoot.orgRootName",
        "orgRoot.orgRootShortName",
        "orgRoot.orgRootOrder",
        "orgChild1.orgChild1Name",
        "orgChild1.orgChild1ShortName",
        "orgChild1.orgChild1Order",
        "orgChild2.orgChild2Name",
        "orgChild2.orgChild2ShortName",
        "orgChild2.orgChild2Order",
        "orgChild3.orgChild3Name",
        "orgChild3.orgChild3ShortName",
        "orgChild3.orgChild3Order",
        "orgChild4.orgChild4Name",
        "orgChild4.orgChild4ShortName",
        "orgChild4.orgChild4Order",
        "positions.id",
        "posExecutive.id",
        "posExecutive.posExecutiveName",
      ])
      .where("current_holders.orgRevisionId = :orgRevisionId", {
        orgRevisionId: (
          await this.orgRevisionRepo.findOne({ where: { orgRevisionIsCurrent: true } })
        )?.id,
      })
      .andWhere(
        _data.root != undefined && _data.root != null
          ? _data.root[0] != null
            ? `current_holders.orgRootId IN (:...root)`
            : `current_holders.orgRootId is null`
          : "1=1",
        { root: _data.root },
      )
      .andWhere(
        _data.child1 != undefined && _data.child1 != null
          ? _data.child1[0] != null
            ? `current_holders.orgChild1Id IN (:...child1)`
            : // : `current_holders.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
            `current_holders.orgChild1Id is null`
          : "1=1",
        { child1: _data.child1 },
      )
      .andWhere(
        _data.child2 != undefined && _data.child2 != null
          ? _data.child2[0] != null
            ? `current_holders.orgChild2Id IN (:...child2)`
            : `current_holders.orgChild2Id is null`
          : "1=1",
        { child2: _data.child2 },
      )
      .andWhere(
        _data.child3 != undefined && _data.child3 != null
          ? _data.child3[0] != null
            ? `current_holders.orgChild3Id IN (:...child3)`
            : `current_holders.orgChild3Id is null`
          : "1=1",
        { child3: _data.child3 },
      )
      .andWhere(
        _data.child4 != undefined && _data.child4 != null
          ? _data.child4[0] != null
            ? `current_holders.orgChild4Id IN (:...child4)`
            : `current_holders.orgChild4Id is null`
          : "1=1",
        { child4: _data.child4 },
      )
      .andWhere(posType ? "posType.posTypeName LIKE :keyword1" : "1=1", { keyword1: `${posType}` })
      .andWhere(posLevel ? "posLevel.posLevelName LIKE :keyword2" : "1=1", {
        keyword2: `${posLevel}`,
      })
      .andWhere(
        isProbation !== undefined && isProbation !== null
          ? `profile.isProbation = ${isProbation}`
          : "1=1",
      )
      .andWhere(
        isRetire !== undefined && isRetire !== null
          ? isRetire == false
            ? `profile.isLeave IS FALSE`
            : isRetire == true && retireType
              ? `profile.isLeave IS TRUE AND profile.leaveType = '${retireType}'`
              : `profile.isLeave IS TRUE`
          : "1=1",
      )
      .andWhere(nodeCondition, { nodeId: nodeId })
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(searchKeyword ? queryLike : "1=1", { keyword: `%${searchKeyword}%` });
        }),
      )
      .addSelect("CASE WHEN current_holders.posMasterNo IS NULL THEN 1 ELSE 0 END", "sort_order");

    if (sortBy) {
      if (sortBy === "posLevel") {
        query = query.orderBy(`posLevel.posLevelName`, descending ? "DESC" : "ASC");
      } else if (sortBy === "posType") {
        query = query.orderBy(`posType.posTypeName`, descending ? "DESC" : "ASC");
      } else if (sortBy === "posExecutive") {
        query = query.orderBy(`posExecutive.posExecutiveName`, descending ? "DESC" : "ASC");
      } else {
        query = query.orderBy(`profile.${sortBy}`, descending ? "DESC" : "ASC");
      }
    } else {
      query = query
        .orderBy("sort_order", "ASC")
        .addOrderBy("orgRoot.orgRootOrder", sort)
        .addOrderBy("orgChild1.orgChild1Order", sort)
        .addOrderBy("orgChild2.orgChild2Order", sort)
        .addOrderBy("orgChild3.orgChild3Order", sort)
        .addOrderBy("orgChild4.orgChild4Order", sort)
        .addOrderBy("current_holders.posMasterNo", sort);
    }

    const [record, total] = await query
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    // map ข้อมูลแบบเร็วขึ้น
    const data = record.map((_data) => {
      const holder = _data.current_holders?.[0];
      const org = [
        holder?.orgChild4?.orgChild4Name,
        holder?.orgChild3?.orgChild3Name,
        holder?.orgChild2?.orgChild2Name,
        holder?.orgChild1?.orgChild1Name,
        holder?.orgRoot?.orgRootName,
      ]
        .filter(Boolean)
        .join("\n");

      const numPart = holder ? [holder.posMasterNoPrefix, holder.posMasterNo, holder.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
      const shortName = !holder
        ? null
        : holder.orgChild4 != null
          ? `${holder.orgChild4.orgChild4ShortName} ${numPart}`
          : holder.orgChild3 != null
            ? `${holder.orgChild3.orgChild3ShortName} ${numPart}`
            : holder.orgChild2 != null
              ? `${holder.orgChild2.orgChild2ShortName} ${numPart}`
              : holder.orgChild1 != null
                ? `${holder.orgChild1.orgChild1ShortName} ${numPart}`
                : holder.orgRoot != null
                  ? `${holder.orgRoot.orgRootShortName} ${numPart}`
                  : null;

      return {
        id: _data.id,
        avatar: _data.avatar,
        avatarName: _data.avatarName,
        prefix: _data.prefix,
        rank: _data.rank,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        posLevel: _data.posLevel?.posLevelName ?? null,
        posType: _data.posType?.posTypeName ?? null,
        posLevelId: _data.posLevel?.id ?? null,
        posTypeId: _data.posType?.id ?? null,
        position: _data.position,
        posExecutive:
          _data.current_holders[0]?.positions[0]?.posExecutive?.posExecutiveName ?? null,
        posNo: shortName ?? null,
        rootId: holder?.orgRoot?.id ?? null,
        root: holder?.orgRoot?.orgRootName ?? null,
        rootDnaId: holder?.orgRoot == null ? null : holder?.orgRoot?.ancestorDNA,
        orgRootShortName: holder?.orgRoot?.orgRootShortName ?? null,
        orgRevisionId: holder?.orgRoot?.orgRevisionId ?? null,
        org,
      };
    });

    return new HttpSuccess({ data, total });
  }

  /**
   * API รายละเอียดรายการทะเบียนประวัติ
   *
   * @summary ORG_065 - รายละเอียดรายการทะเบียนประวัติ  (ADMIN) #70
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Get("{id}")
  async getProfile(@Request() req: RequestWithUser, @Path() id: string) {
    let _workflow = await new permission().Workflow(req, id, "SYS_REGISTRY_OFFICER");
    if (_workflow == false)
      await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", id);
    let profile: any = await this.profileRepo.findOne({
      relations: {
        posLevel: true,
        posType: true,
      },
      where: { id },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    profile.profileType = "OFFICER";
    return new HttpSuccess(profile);
  }

  @Get("admin/{id}")
  async getProfileAdmin(@Path() id: string) {
    const profile: any = await this.profileRepo.findOne({
      relations: {
        posLevel: true,
        posType: true,
      },
      where: { id },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    profile.profileType = "OFFICER";
    return new HttpSuccess(profile);
  }

  // @Get("keycloak/{id}")
  // async getProfileByKeycloakId(@Path() id: string) {
  //   const profile = await this.profileRepo.findOne({
  //     relations: {
  //       posLevel: true,
  //       posType: true,
  //     },
  //     where: { keycloak: id },
  //   });

  //   if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

  //   return new HttpSuccess(profile);
  // }

  @Get("history/{id}")
  async getProfileHistory(@Path() id: string, @Request() req: RequestWithUser) {
    //await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", id); //ไม่แน่ใจOFFปิดไว้ก่อน
    const profile = await this.profileRepo.findOne({
      where: { id: id },
    });
    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    const profileHistory = await this.profileHistoryRepo.find({
      where: { profileId: id },
      order: { createdAt: "ASC" },
    });

    if (profileHistory.length == 0) {
      await this.profileHistoryRepo.save(
        Object.assign(new ProfileHistory(), {
          ...profile,
          birthDateOld: profile?.birthDate,
          profileId: id,
          id: undefined,
        }),
      );
      const firstRecord = await this.profileHistoryRepo.find({
        where: { profileId: id },
        order: { createdAt: "ASC" },
      });
      return new HttpSuccess(firstRecord);
    }

    return new HttpSuccess(profileHistory);
  }

  /**
   * API รายการทะเบียนประวัติ
   *
   * @summary ORG_065 - รายการทะเบียนประวัติ (ADMIN) #70
   *
   */
  @Get()
  @Example({
    status: 200,
    message: "สำเร็จ",
    result: {
      data: [
        {
          id: "ecb0b34c-037e-41f2-b95e-7e19f88b42ae",
          createdAt: "2024-03-24T12:39:12.105Z",
          createdUserId: "00000000-0000-0000-0000-000000000000",
          lastUpdatedAt: "2024-03-24T12:41:43.164Z",
          lastUpdateUserId: "00000000-0000-0000-0000-000000000000",
          createdFullName: "string",
          lastUpdateFullName: "string",
          rank: null,
          prefix: null,
          firstName: "Methapon",
          lastName: "Metanipat",
          citizenId: null,
          position: null,
          posLevelId: null,
          posTypeId: null,
          email: null,
          phone: null,
          keycloak: null,
          isProbation: false,
          dateRetire: null,
          birthDate: null,
          ethnicity: null,
          telephoneNumber: null,
          gender: null,
          relationship: null,
          bloodGroup: null,
          posLevel: null,
          posType: null,
          org: null,
        },
      ],
      total: 1,
    },
  })
  async listProfile(
    @Request() request: RequestWithUser,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Query()
    searchField?: "firstName" | "lastName" | "fullName" | "citizenId" | "position" | "posNo",
    @Query() searchKeyword: string = "",
    @Query() posType?: string,
    @Query() posLevel?: string,
    @Query() yearLeave?: number,
    @Query() isProbation?: boolean,
    @Query() isRetire?: boolean,
    @Query() node?: number,
    @Query() nodeId?: string,
    @Query() isAll?: boolean,
    @Query() retireType?: string,
    @Query() sortBy?: string,
    @Query() sort: "ASC" | "DESC" = "ASC",
  ) {
    let _data = await new permission().PermissionOrgList(request, "SYS_REGISTRY_OFFICER");
    let queryLike =
      "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword";
    if (searchField == "citizenId") {
      queryLike = "profile.citizenId LIKE :keyword";
    } else if (searchField == "position") {
      queryLike = "profile.position LIKE :keyword";
    } else if (searchField == "posNo") {
      queryLike = `
      CASE
        WHEN current_holders.orgChild4Id IS NOT NULL THEN CONCAT_WS(' ', orgChild4.orgChild4ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild3Id IS NOT NULL THEN CONCAT_WS(' ', orgChild3.orgChild3ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild2Id IS NOT NULL THEN CONCAT_WS(' ', orgChild2.orgChild2ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        WHEN current_holders.orgChild1Id IS NOT NULL THEN CONCAT_WS(' ', orgChild1.orgChild1ShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
        ELSE CONCAT_WS(' ', orgRoot.orgRootShortName, NULLIF(current_holders.posMasterNoPrefix,''), current_holders.posMasterNo, NULLIF(current_holders.posMasterNoSuffix,''))
      END LIKE :keyword
    `;
    }
    let nodeCondition = "1=1";
    let nodeAll = "";
    if (node === 0 && nodeId) {
      nodeCondition = "current_holders.orgRootId = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild1Id IS NULL";
    } else if (node === 1 && nodeId) {
      nodeCondition = "current_holders.orgChild1Id = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild2Id IS NULL";
    } else if (node === 2 && nodeId) {
      nodeCondition = "current_holders.orgChild2Id = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild3Id IS NULL";
    } else if (node === 3 && nodeId) {
      nodeCondition = "current_holders.orgChild3Id = :nodeId";
      if (isAll == false) nodeAll = " AND current_holders.orgChild4Id IS NULL";
    } else if (node === 4 && nodeId) {
      nodeCondition = "current_holders.orgChild4Id = :nodeId";
    }
    nodeCondition = nodeCondition + nodeAll;

    // เลือกเฉพาะฟิลด์ที่จำเป็น
    const [record, total] = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoin("profile.posLevel", "posLevel")
      .leftJoin("profile.posType", "posType")
      .leftJoin("profile.current_holders", "current_holders")
      .leftJoin("current_holders.positions", "positions")
      .leftJoin("positions.posExecutive", "posExecutive")
      .leftJoin("current_holders.orgRoot", "orgRoot")
      .leftJoin("current_holders.orgChild1", "orgChild1")
      .leftJoin("current_holders.orgChild2", "orgChild2")
      .leftJoin("current_holders.orgChild3", "orgChild3")
      .leftJoin("current_holders.orgChild4", "orgChild4")
      .select([
        "profile.id",
        "profile.prefix",
        "profile.rank",
        "profile.firstName",
        "profile.lastName",
        "profile.citizenId",
        "profile.position",
        "profile.avatar",
        "profile.avatarName",
        "profile.dateAppoint",
        "posLevel.id",
        "posLevel.posLevelName",
        "posType.id",
        "posType.posTypeName",
        "current_holders.orgRevisionId",
        "current_holders.posMasterNo",
        "current_holders.posMasterNoPrefix",
        "current_holders.posMasterNoSuffix",
        "orgRoot.id",
        "orgRoot.ancestorDNA",
        "orgRoot.orgRootName",
        "orgRoot.orgRootShortName",
        "orgRoot.orgRootOrder",
        "orgChild1.orgChild1Name",
        "orgChild1.orgChild1ShortName",
        "orgChild1.orgChild1Order",
        "orgChild2.orgChild2Name",
        "orgChild2.orgChild2ShortName",
        "orgChild2.orgChild2Order",
        "orgChild3.orgChild3Name",
        "orgChild3.orgChild3ShortName",
        "orgChild3.orgChild3Order",
        "orgChild4.orgChild4Name",
        "orgChild4.orgChild4ShortName",
        "orgChild4.orgChild4Order",
        "positions.id",
        "posExecutive.id",
        "posExecutive.posExecutiveName",
      ])
      // .where(node && nodeId ? "current_holders.orgRevisionId = :orgRevisionId" : "1=1", {
      //   orgRevisionId:
      //     node && nodeId
      //       ? (await this.orgRevisionRepo.findOne({ where: { orgRevisionIsCurrent: true } }))?.id
      //       : undefined,
      // })
      .where("current_holders.orgRevisionId = :orgRevisionId", {
        orgRevisionId: (
          await this.orgRevisionRepo.findOne({ where: { orgRevisionIsCurrent: true } })
        )?.id,
      })
      .andWhere(
        _data.root != undefined && _data.root != null
          ? _data.root[0] != null
            ? `current_holders.orgRootId IN (:...root)`
            : `current_holders.orgRootId is null`
          : "1=1",
        { root: _data.root },
      )
      .andWhere(
        _data.child1 != undefined && _data.child1 != null
          ? _data.child1[0] != null
            ? `current_holders.orgChild1Id IN (:...child1)`
            : // : `current_holders.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
            `current_holders.orgChild1Id is null`
          : "1=1",
        { child1: _data.child1 },
      )
      .andWhere(
        _data.child2 != undefined && _data.child2 != null
          ? _data.child2[0] != null
            ? `current_holders.orgChild2Id IN (:...child2)`
            : `current_holders.orgChild2Id is null`
          : "1=1",
        { child2: _data.child2 },
      )
      .andWhere(
        _data.child3 != undefined && _data.child3 != null
          ? _data.child3[0] != null
            ? `current_holders.orgChild3Id IN (:...child3)`
            : `current_holders.orgChild3Id is null`
          : "1=1",
        { child3: _data.child3 },
      )
      .andWhere(
        _data.child4 != undefined && _data.child4 != null
          ? _data.child4[0] != null
            ? `current_holders.orgChild4Id IN (:...child4)`
            : `current_holders.orgChild4Id is null`
          : "1=1",
        { child4: _data.child4 },
      )
      .andWhere(posType ? "posType.posTypeName LIKE :keyword1" : "1=1", { keyword1: `${posType}` })
      .andWhere(posLevel ? "posLevel.posLevelName LIKE :keyword2" : "1=1", {
        keyword2: `${posLevel}`,
      })
      .andWhere(
        isProbation !== undefined && isProbation !== null
          ? `profile.isProbation = ${isProbation}`
          : "1=1",
      )
      .andWhere(
        isRetire !== undefined && isRetire !== null
          ? isRetire == false
            ? `profile.isLeave IS FALSE`
            : isRetire == true && retireType
              ? `profile.isLeave IS TRUE AND profile.leaveType = '${retireType}'`
              : `profile.isLeave IS TRUE`
          : "1=1",
      )
      .andWhere(nodeCondition, { nodeId: nodeId })
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(searchKeyword ? queryLike : "1=1", { keyword: `%${searchKeyword}%` });
        }),
      )
      .addSelect("CASE WHEN current_holders.posMasterNo IS NULL THEN 1 ELSE 0 END", "sort_order")
      .orderBy(sortBy ? sortBy : "sort_order", sort)
      .addOrderBy("orgRoot.orgRootOrder", sort)
      .addOrderBy("orgChild1.orgChild1Order", sort)
      .addOrderBy("orgChild2.orgChild2Order", sort)
      .addOrderBy("orgChild3.orgChild3Order", sort)
      .addOrderBy("orgChild4.orgChild4Order", sort)
      .addOrderBy("current_holders.posMasterNo", sort)
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    // map ข้อมูลแบบเร็วขึ้น
    const data = record.map((_data) => {
      const holder = _data.current_holders?.[0];
      const org = [
        holder?.orgChild4?.orgChild4Name,
        holder?.orgChild3?.orgChild3Name,
        holder?.orgChild2?.orgChild2Name,
        holder?.orgChild1?.orgChild1Name,
        holder?.orgRoot?.orgRootName,
      ]
        .filter(Boolean)
        .join("\n");

      const numPart = holder ? [holder.posMasterNoPrefix, holder.posMasterNo, holder.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';

      const shortName = !holder
        ? null
        : holder.orgChild4 != null
          ? `${holder.orgChild4.orgChild4ShortName} ${numPart}`
          : holder.orgChild3 != null
            ? `${holder.orgChild3.orgChild3ShortName} ${numPart}`
            : holder.orgChild2 != null
              ? `${holder.orgChild2.orgChild2ShortName} ${numPart}`
              : holder.orgChild1 != null
                ? `${holder.orgChild1.orgChild1ShortName} ${numPart}`
                : holder.orgRoot != null
                  ? `${holder.orgRoot.orgRootShortName} ${numPart}`
                  : null;

      return {
        id: _data.id,
        avatar: _data.avatar,
        avatarName: _data.avatarName,
        dateAppoint: _data.dateAppoint,
        prefix: _data.prefix,
        rank: _data.rank,
        firstName: _data.firstName,
        lastName: _data.lastName,
        citizenId: _data.citizenId,
        posLevel: _data.posLevel?.posLevelName ?? null,
        posType: _data.posType?.posTypeName ?? null,
        posLevelId: _data.posLevel?.id ?? null,
        posTypeId: _data.posType?.id ?? null,
        position: _data.position,
        posNo: shortName ?? null,
        rootId: holder?.orgRoot?.id ?? null,
        child1Id: holder?.orgChild1Id ?? null,
        root: holder?.orgRoot?.orgRootName ?? null,
        rootDnaId: holder?.orgRoot == null ? null : holder?.orgRoot?.ancestorDNA,
        orgRootShortName: holder?.orgRoot?.orgRootShortName ?? null,
        orgRevisionId: holder?.orgRoot?.orgRevisionId ?? null,
        org,
      };
    });

    return new HttpSuccess({ data, total });
  }

  /**
   * API ค้นหารายชื่อไปครองตำแหน่ง
   *
   * @summary ORG_063 - ค้นหารายชื่อไปครองตำแหน่ง (ADMIN) #68
   */
  @Post("search")
  async searchProfileOrg(
    @Body()
    requestBody: {
      position?: string | null;
      posLevelId?: string | null;
      posTypeId?: string | null;
      page: number;
      pageSize: number;
      keyword?: string;
    },
  ) {
    const orgRevision = await this.orgRevisionRepo.findOne({
      where: {
        orgRevisionIsDraft: true,
        orgRevisionIsCurrent: false,
      },
      relations: ["posMasters"],
    });
    if (!orgRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }
    const [profiles, total] = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.next_holders", "next_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .where(
        requestBody.position != null && requestBody.position != ""
          ? "profile.position LIKE :position"
          : "1=1",
        {
          position: `%${requestBody.position}%`,
        },
      )
      .andWhere("profile.isLeave IS FALSE")
      .andWhere(
        new Brackets((qb) => {
          qb.where(
            requestBody.keyword != null && requestBody.keyword != ""
              ? "profile.prefix LIKE :keyword"
              : "1=1",
            {
              keyword: `%${requestBody.keyword}%`,
            },
          )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "profile.firstName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "profile.lastName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "CONCAT(profile.prefix,profile.firstName,' ',profile.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "CONCAT(profile.firstName,' ',profile.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "profile.citizenId LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            );
        }),
      )
      .andWhere(
        requestBody.posTypeId != null && requestBody.posTypeId != ""
          ? "profile.posTypeId LIKE :posTypeId"
          : "1=1",
        {
          posTypeId: `%${requestBody.posTypeId}%`,
        },
      )
      .andWhere(
        requestBody.posLevelId != null && requestBody.posLevelId != ""
          ? "profile.posLevelId LIKE :posLevelId"
          : "1=1",
        {
          posLevelId: `%${requestBody.posLevelId}%`,
        },
      )
      .andWhere(
        new Brackets((qb) => {
          qb.where("profile.id NOT IN (:...ids)", {
            ids:
              orgRevision.posMasters
                .filter((x) => x.next_holderId != null)
                .map((x) => x.next_holderId).length == 0
                ? ["zxc"]
                : orgRevision.posMasters
                  .filter((x) => x.next_holderId != null)
                  .map((x) => x.next_holderId),
          });
        }),
      )
      .skip((requestBody.page - 1) * requestBody.pageSize)
      .take(requestBody.pageSize)
      .orderBy("posType.posTypeRank", "ASC")
      .addOrderBy("posLevel.posLevelRank", "ASC")
      .getManyAndCount();

    const data = profiles.map((_data) => ({
      id: _data.id,
      prefix: _data.prefix,
      rank: _data.rank,
      firstName: _data.firstName,
      lastName: _data.lastName,
      citizenId: _data.citizenId,
      posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
      posType: _data.posType == null ? null : _data.posType.posTypeName,
      position: _data.position,
    }));

    return new HttpSuccess({ data: data, total });
  }

  // /**
  //  * API ค้นหาประวัติการครองตำแหน่ง ข้าราชการ
  //  *
  //  * @summary ค้นหาประวัติการครองตำแหน่ง ข้าราชการ
  //  *
  //  */
  // @Post("search/history/oc")
  // async searchHistoryOC(
  //   @Body()
  //   requestBody: {
  //     posNo?: string;
  //     position?: string;
  //   },
  // ) {
  //   const profiles = await this.profileRepo
  //     .createQueryBuilder("profile")
  //     .leftJoinAndSelect("profile.profileSalary", "profileSalary")
  //     .select([
  //       "profile.id",
  //       "profile.prefix",
  //       "profile.firstName",
  //       "profile.lastName",
  //       "profile.citizenId",
  //       "profileSalary.position",
  //       "profileSalary.posNo",
  //       "profileSalary.date",
  //     ])
  //     .andWhere(
  //       requestBody.position != null && requestBody.position != "" && requestBody.posNo == undefined
  //         ? "profileSalary.position LIKE :position"
  //         : "1=2",
  //       {
  //         position: `%${requestBody.position}%`,
  //       },
  //     )
  //     .orWhere(
  //       requestBody.posNo != null && requestBody.posNo != "" && requestBody.position == undefined
  //         ? "profileSalary.posNo LIKE :posNo"
  //         : "1=2",
  //       {
  //         posNo: `%${requestBody.posNo}%`,
  //       },
  //     )
  //     .getMany();

  //   const mapData = profiles.map((profile) => {
  //     let profileSalary;
  //     if (profile.profileSalary && profile.profileSalary.length > 0) {
  //       profileSalary = profile.profileSalary.reduce((latest, current) => {
  //         return new Date(current.date) > new Date(latest.date) ? current : latest;
  //       });
  //     }
  //     return {
  //       id: profile.id,
  //       // prefix: profile.prefix,
  //       // firstName: profile.firstName,
  //       // lastName: profile.lastName,
  //       fullName: `${profile.prefix}${profile.firstName} ${profile.lastName}`,
  //       citizenId: profile.citizenId,
  //       position: profileSalary ? profileSalary.position : null,
  //       posNo: profileSalary ? profileSalary.posNo : null,
  //       date: profileSalary ? profileSalary.date : null,
  //     };
  //   });

  //   return new HttpSuccess(mapData);
  // }

  /**
   * API ค้นหาประวัติการครองตำแหน่ง ข้าราชการ
   *
   * @summary ค้นหาประวัติการครองตำแหน่ง ข้าราชการ
   *
   */
  @Post("search/history/oc")
  async searchOC(
    @Body()
    requestBody: {
      posNo?: string;
      position?: string;
    },
  ) {
    let queryLike = `
      CASE 
        WHEN current_holders.orgChild4Id IS NOT NULL THEN CONCAT(orgChild4.orgChild4ShortName, " ", current_holders.posMasterNo)
        WHEN current_holders.orgChild3Id IS NOT NULL THEN CONCAT(orgChild3.orgChild3ShortName, " ", current_holders.posMasterNo)
        WHEN current_holders.orgChild2Id IS NOT NULL THEN CONCAT(orgChild2.orgChild2ShortName, " ", current_holders.posMasterNo)
        WHEN current_holders.orgChild1Id IS NOT NULL THEN CONCAT(orgChild1.orgChild1ShortName, " ", current_holders.posMasterNo)
        ELSE CONCAT(orgRoot.orgRootShortName, " ", current_holders.posMasterNo)
      END LIKE :keyword
    `;

    const profiles = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .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("positions.positionIsSelected = :posIsSelected", { posIsSelected: true })
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(
            requestBody.posNo != undefined && requestBody.posNo != null && requestBody.posNo != ""
              ? queryLike
              : "1=1",
            {
              keyword: `%${requestBody.posNo}%`,
            },
          );
        }),
      )
      .andWhere(
        requestBody.position != null && requestBody.position !== ""
          ? "positions.positionName LIKE :positionName"
          : "1=1",
        { positionName: `%${requestBody.position}%` },
      )
      .getMany();

    const mapData = profiles
      .map((profile) => {
        const shortNames = profile.current_holders.map((holder) => {
          const shortName =
            holder.orgChild4?.orgChild4ShortName ||
            holder.orgChild3?.orgChild3ShortName ||
            holder.orgChild2?.orgChild2ShortName ||
            holder.orgChild1?.orgChild1ShortName ||
            holder.orgRoot?.orgRootShortName;
          return `${shortName || ""} ${holder.posMasterNo || ""}`;
        });
        return profile.current_holders.map((holder, index) => {
          const position = holder.positions.find((position) => position.posMasterId === holder.id);
          const positionName = position ? position.positionName : null;

          return {
            id: profile.id,
            posMasterId: holder.id,
            fullName: `${profile.prefix}${profile.firstName} ${profile.lastName}`,
            citizenId: profile.citizenId,
            posNo: shortNames[index],
            positionName: positionName,
            date: holder.createdAt,
          };
        });
      })
      .flat();

    return new HttpSuccess(mapData);
  }

  /**
   * API ค้นหารายชื่อไปครองตำแหน่งจากโครงสร้างปัจจุบัน
   *
   * @summary ค้นหารายชื่อไปครองตำแหน่งจากโครงสร้างปัจจุบัน
   */
  @Post("search/current/person")
  async searchProfileCurrentPerson(
    @Body()
    requestBody: {
      position?: string | null;
      posLevelId?: string | null;
      posTypeId?: string | null;
      page: number;
      pageSize: number;
      keyword?: string;
    },
  ) {
    const orgRevision = await this.orgRevisionRepo.findOne({
      where: {
        orgRevisionIsCurrent: true,
        orgRevisionIsDraft: false,
      },
      relations: ["posMasters"],
    });
    if (!orgRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }
    const [profiles, total] = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .where(
        requestBody.position != null && requestBody.position != ""
          ? "profile.position LIKE :position"
          : "1=1",
        {
          position: `%${requestBody.position}%`,
        },
      )
      .andWhere("profile.isLeave IS FALSE")
      .andWhere(
        new Brackets((qb) => {
          qb.where(
            requestBody.keyword != null && requestBody.keyword != ""
              ? "profile.prefix LIKE :keyword"
              : "1=1",
            {
              keyword: `%${requestBody.keyword}%`,
            },
          )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "profile.firstName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "profile.lastName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "CONCAT(profile.prefix,profile.firstName,' ',profile.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "CONCAT(profile.firstName,' ',profile.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            )
            .orWhere(
              requestBody.keyword != null && requestBody.keyword != ""
                ? "profile.citizenId LIKE :keyword"
                : "1=1",
              {
                keyword: `%${requestBody.keyword}%`,
              },
            );
        }),
      )
      .andWhere(
        requestBody.posTypeId != null && requestBody.posTypeId != ""
          ? "profile.posTypeId LIKE :posTypeId"
          : "1=1",
        {
          posTypeId: `%${requestBody.posTypeId}%`,
        },
      )
      .andWhere(
        requestBody.posLevelId != null && requestBody.posLevelId != ""
          ? "profile.posLevelId LIKE :posLevelId"
          : "1=1",
        {
          posLevelId: `%${requestBody.posLevelId}%`,
        },
      )
      .andWhere(
        new Brackets((qb) => {
          qb.where("profile.id NOT IN (:...ids)", {
            ids:
              orgRevision.posMasters
                .filter((x) => x.current_holderId != null)
                .map((x) => x.current_holderId).length == 0
                ? ["zxc"]
                : orgRevision.posMasters
                  .filter((x) => x.current_holderId != null)
                  .map((x) => x.current_holderId),
          });
        }),
      )
      .skip((requestBody.page - 1) * requestBody.pageSize)
      .take(requestBody.pageSize)
      .orderBy("posType.posTypeRank", "ASC")
      .addOrderBy("posLevel.posLevelRank", "ASC")
      .getManyAndCount();

    const data = profiles.map((_data) => ({
      id: _data.id,
      prefix: _data.prefix,
      rank: _data.rank,
      firstName: _data.firstName,
      lastName: _data.lastName,
      citizenId: _data.citizenId,
      posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName,
      posType: _data.posType == null ? null : _data.posType.posTypeName,
      position: _data.position,
    }));

    return new HttpSuccess({ data: data, total });
  }

  /**
   * API ข้อมูลสิทธิ์การแก้ไขทะเบียนประวัติ
   *
   * @summary ORG_065 - ข้อมูลสิทธิ์การแก้ไขทะเบียนประวัติ
   *
   */
  @Get("keycloak/permissionProfile")
  async getPermissionProfile(@Request() request: { user: Record<string, any> }) {
    let orgRevisionPublish: any = await this.orgRevisionRepo
      .createQueryBuilder("orgRevision")
      .where("orgRevision.orgRevisionIsDraft = false")
      .andWhere("orgRevision.orgRevisionIsCurrent = true")
      .getOne();
    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้");
    }
    const permissionProflile = await this.permissionProflileRepository.findOne({
      relations: ["orgRootTree"],
      where: {
        profileId: profile.id,
        orgRootTree: {
          orgRevisionId: orgRevisionPublish.id,
        },
      },
    });

    const _profile: any = {
      profileId: profile?.id ?? null,
      isEdit: permissionProflile?.isEdit ?? false,
      isCheck: permissionProflile?.isCheck ?? false,
    };

    return new HttpSuccess(_profile);
  }

  /**
   * API ข้อมูลสิทธิ์การแก้ไขทะเบียนประวัติ
   *
   * @summary ORG_065 - ข้อมูลสิทธิ์การแก้ไขทะเบียนประวัติ
   *
   */
  @Get("keycloak/permissionProfile/{rootId}")
  async getPermissionProfileByRoot(
    @Request() request: { user: Record<string, any> },
    @Path() rootId: string,
  ) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้");
    }
    const permissionProflile = await this.permissionProflileRepository.findOne({
      where: {
        profileId: profile.id,
        orgRootId: rootId,
      },
    });

    const _profile: any = {
      profileId: profile?.id ?? null,
      isEdit: permissionProflile?.isEdit ?? false,
      isCheck: permissionProflile?.isCheck ?? false,
    };

    return new HttpSuccess(_profile);
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม keycloak
   *
   * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม keycloak (ADMIN) #70
   *
   */
  @Get("keycloak/position")
  async getProfileByKeycloak(
    @Request() request: { user: Record<string, any> },
    @Query("revisionId") revisionId?: string,
  ) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        // "profileSalary",
      ],
      // order: {
      //   profileSalary: {
      //     order: "DESC",
      //   },
      // },
    });
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        where: { keycloak: request.user.sub },
        relations: [
          "posLevel",
          "posType",
          "current_holders",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
          // "profileSalary",
        ],
        // order: {
        //   profileSalary: {
        //     order: "DESC",
        //   },
        // },
      });
      if (!profile) {
        if (request.user.role.includes("SUPER_ADMIN")) {
          return new HttpSuccess(null);
        } else {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
        }
      }

      let orgRevisionPublish: any = await this.orgRevisionRepo
        .createQueryBuilder("orgRevision")
        .where("orgRevision.orgRevisionIsDraft = false")
        .andWhere("orgRevision.orgRevisionIsCurrent = true")
        .getOne();
      if (!orgRevisionPublish) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
      }

      if (revisionId) {
        orgRevisionPublish = await this.orgRevisionRepo
          .createQueryBuilder("orgRevision")
          .where("orgRevision.id = :revisionId", { revisionId })
          .getOne();
        if (!orgRevisionPublish) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
        }
      }

      const posMaster =
        profile.current_holders == null ||
          profile.current_holders.length == 0 ||
          profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id) == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);

      const root =
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot ==
          null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot;
      const child1 =
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1 ==
          null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
            ?.orgChild1;
      const child2 =
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2 ==
          null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
            ?.orgChild2;
      const child3 =
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3 ==
          null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
            ?.orgChild3;
      const child4 =
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4 ==
          null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
            ?.orgChild4;

      const position = await this.positionRepository.findOne({
        relations: ["posExecutive"],
        where: {
          posMasterId: posMaster?.id,
        },
      });

      const _profile: any = {
        profileId: profile.id,
        keycloak: profile.keycloak,
        prefix: profile.prefix,
        rank: profile.rank,
        avatar: profile.avatar,
        profileType: "EMPLOYEE",
        isDirector: posMaster?.isDirector || false,
        isProbation: profile.isProbation,
        avatarName: profile.avatarName,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        birthDate: profile.birthDate,
        position: profile.position,
        leaveDate: profile.dateLeave,
        dateStart: profile.dateStart,
        dateRetireLaw: profile.dateRetireLaw,
        posMaster: posMaster == null ? null : posMaster.posMasterNo,
        posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
        posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName,
        posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
        posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
        posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
        posTypeShortName: profile.posType == null ? null : profile.posType.posTypeShortName,
        posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
        posTypeId: profile.posType == null ? null : profile.posType.id,
        posExecutiveName:
          position == null || position.posExecutive == null
            ? null
            : position.posExecutive.posExecutiveName,
        positionExecutiveField:
          position == null || position.positionExecutiveField == null
            ? null
            : position.positionExecutiveField,
        positionArea:
          position == null || position.positionArea == null ? null : position.positionArea,
        posExecutivePriority:
          position == null || position.posExecutive == null
            ? null
            : position.posExecutive.posExecutivePriority,
        posExecutiveId:
          position == null || position.posExecutive == null ? null : position.posExecutive.id,
        rootId: root == null ? null : root.id,
        rootDnaId: root == null ? null : root.ancestorDNA,
        root: root == null ? null : root.orgRootName,
        rootShortName: root == null ? null : root.orgRootShortName,
        child1Id: child1 == null ? null : child1.id,
        child1DnaId: child1 == null ? null : child1.ancestorDNA,
        child1: child1 == null ? null : child1.orgChild1Name,
        child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
        child2Id: child2 == null ? null : child2.id,
        child2DnaId: child2 == null ? null : child2.ancestorDNA,
        child2: child2 == null ? null : child2.orgChild2Name,
        child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
        child3Id: child3 == null ? null : child3.id,
        child3DnaId: child3 == null ? null : child3.ancestorDNA,
        child3: child3 == null ? null : child3.orgChild3Name,
        child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
        child4Id: child4 == null ? null : child4.id,
        child4DnaId: child4 == null ? null : child4.ancestorDNA,
        child4: child4 == null ? null : child4.orgChild4Name,
        child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
        node: null,
        nodeId: null,
        nodeDnaId: null,
        type: profile.employeeClass,
        salary: profile.amount,
        posNo: null,
        privacyCheckin: profile.privacyCheckin,
        privacyUser: profile.privacyUser,
        privacyMgt: profile.privacyMgt,
        isDeputy: root?.isDeputy ?? false,
      };
      const _numPart = posMaster ? [posMaster.posMasterNoPrefix, posMaster.posMasterNo, posMaster.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
      if (_profile.child4Id != null) {
        _profile.node = 4;
        _profile.nodeId = _profile.child4Id;
        _profile.nodeDnaId = _profile.child4DnaId;
        _profile.nodeShortName = _profile.child4ShortName;
        _profile.posNo = `${_profile.child4ShortName} ${_numPart}`;
      } else if (_profile.child3Id != null) {
        _profile.node = 3;
        _profile.nodeId = _profile.child3Id;
        _profile.nodeDnaId = _profile.child3DnaId;
        _profile.nodeShortName = _profile.child3ShortName;
        _profile.posNo = `${_profile.child3ShortName} ${_numPart}`;
      } else if (_profile.child2Id != null) {
        _profile.node = 2;
        _profile.nodeId = _profile.child2Id;
        _profile.nodeDnaId = _profile.child2DnaId;
        _profile.nodeShortName = _profile.child2ShortName;
        _profile.posNo = `${_profile.child2ShortName} ${_numPart}`;
      } else if (_profile.child1Id != null) {
        _profile.node = 1;
        _profile.nodeId = _profile.child1Id;
        _profile.nodeDnaId = _profile.child1DnaId;
        _profile.nodeShortName = _profile.child1ShortName;
        _profile.posNo = `${_profile.child1ShortName} ${_numPart}`;
      } else if (_profile.rootId != null) {
        _profile.node = 0;
        _profile.nodeId = _profile.rootId;
        _profile.nodeDnaId = _profile.rootDnaId;
        _profile.nodeShortName = _profile.rootShortName;
        _profile.posNo = `${_profile.rootShortName} ${_numPart}`;
      }
      return new HttpSuccess(_profile);
    }
    // ขรก.
    let orgRevisionPublish: any = await this.orgRevisionRepo
      .createQueryBuilder("orgRevision")
      .where("orgRevision.orgRevisionIsDraft = false")
      .andWhere("orgRevision.orgRevisionIsCurrent = true")
      .getOne();
    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }

    if (revisionId) {
      orgRevisionPublish = await this.orgRevisionRepo
        .createQueryBuilder("orgRevision")
        .where("orgRevision.id = :revisionId", { revisionId })
        .getOne();
      if (!orgRevisionPublish) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
      }
    }

    const posMaster =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);

    const root =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot;
    const child1 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1;
    const child2 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2;
    const child3 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3;
    const child4 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4;

    const position = await this.positionRepository.findOne({
      relations: ["posExecutive"],
      where: {
        posMasterId: posMaster?.id,
      },
    });

    const _profile: any = {
      profileId: profile.id,
      keycloak: profile.keycloak,
      prefix: profile.prefix,
      rank: profile.rank,
      avatar: profile.avatar,
      profileType: "OFFICER",
      isDirector: posMaster?.isDirector || false,
      isProbation: profile.isProbation,
      avatarName: profile.avatarName,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate,
      position: profile.position,
      leaveDate: profile.dateLeave,
      dateStart: profile.dateStart,
      dateRetireLaw: profile.dateRetireLaw,
      posMaster: posMaster == null ? null : posMaster.posMasterNo,
      posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
      posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName,
      posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
      posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
      posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
      posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
      posTypeId: profile.posType == null ? null : profile.posType.id,
      posExecutiveName:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutiveName,
      positionExecutiveField:
        position == null || position.positionExecutiveField == null
          ? null
          : position.positionExecutiveField,
      positionArea:
        position == null || position.positionArea == null ? null : position.positionArea,
      posExecutivePriority:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutivePriority,
      posExecutiveId:
        position == null || position.posExecutive == null ? null : position.posExecutive.id,
      rootId: root == null ? null : root.id,
      rootDnaId: root == null ? null : root.ancestorDNA,
      root: root == null ? null : root.orgRootName,
      rootShortName: root == null ? null : root.orgRootShortName,
      child1Id: child1 == null ? null : child1.id,
      child1DnaId: child1 == null ? null : child1.ancestorDNA,
      child1: child1 == null ? null : child1.orgChild1Name,
      child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
      child2Id: child2 == null ? null : child2.id,
      child2DnaId: child2 == null ? null : child2.ancestorDNA,
      child2: child2 == null ? null : child2.orgChild2Name,
      child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
      child3Id: child3 == null ? null : child3.id,
      child3DnaId: child3 == null ? null : child3.ancestorDNA,
      child3: child3 == null ? null : child3.orgChild3Name,
      child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
      child4Id: child4 == null ? null : child4.id,
      child4DnaId: child4 == null ? null : child4.ancestorDNA,
      child4: child4 == null ? null : child4.orgChild4Name,
      child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
      node: null,
      nodeId: null,
      nodeDnaId: null,
      salary: profile ? profile.amount : null,
      amountSpecial: profile ? profile.amountSpecial : null,
      posNo: null,
      privacyCheckin: profile.privacyCheckin,
      privacyUser: profile.privacyUser,
      privacyMgt: profile.privacyMgt,
      isDeputy: root?.isDeputy ?? false,
    };

    const _numPart = posMaster ? [posMaster.posMasterNoPrefix, posMaster.posMasterNo, posMaster.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
    if (_profile.child4Id != null) {
      _profile.node = 4;
      _profile.nodeId = _profile.child4Id;
      _profile.nodeDnaId = _profile.child4DnaId;
      _profile.nodeShortName = _profile.child4ShortName;
      _profile.posNo = `${_profile.child4ShortName} ${_numPart}`;
    } else if (_profile.child3Id != null) {
      _profile.node = 3;
      _profile.nodeId = _profile.child3Id;
      _profile.nodeDnaId = _profile.child3DnaId;
      _profile.nodeShortName = _profile.child3ShortName;
      _profile.posNo = `${_profile.child3ShortName} ${_numPart}`;
    } else if (_profile.child2Id != null) {
      _profile.node = 2;
      _profile.nodeId = _profile.child2Id;
      _profile.nodeDnaId = _profile.child2DnaId;
      _profile.nodeShortName = _profile.child2ShortName;
      _profile.posNo = `${_profile.child2ShortName} ${_numPart}`;
    } else if (_profile.child1Id != null) {
      _profile.node = 1;
      _profile.nodeId = _profile.child1Id;
      _profile.nodeDnaId = _profile.child1DnaId;
      _profile.nodeShortName = _profile.child1ShortName;
      _profile.posNo = `${_profile.child1ShortName} ${_numPart}`;
    } else if (_profile.rootId != null) {
      _profile.node = 0;
      _profile.nodeId = _profile.rootId;
      _profile.nodeDnaId = _profile.rootDnaId;
      _profile.nodeShortName = _profile.rootShortName;
      _profile.posNo = `${_profile.rootShortName} ${_numPart}`;
    }
    return new HttpSuccess(_profile);
  }
  /**
   * API ข้อมูลทะเบียนประวัติตาม keycloak
   *
   * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม keycloak (ADMIN) #70
   *
   */
  @Get("keycloak/position-act")
  async getProfileByKeycloakAct(
    @Request() request: { user: Record<string, any> },
    @Query("revisionId") revisionId?: string,
  ) {
    if (!revisionId) {
      let orgRevisionPublish = await this.orgRevisionRepo
        .createQueryBuilder("orgRevision")
        .where("orgRevision.orgRevisionIsDraft = false")
        .andWhere("orgRevision.orgRevisionIsCurrent = true")
        .getOne();
      if (!orgRevisionPublish) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
      }
      revisionId = orgRevisionPublish.id;
    }
    const posMasters = await this.posMasterRepo.findOne({
      where: {
        posMasterAssigns: { assignId: "SYS_PLACEMENT_PASS" },
        current_holder: {
          keycloak: request.user.sub,
        },
        orgRevisionId: revisionId,
      },
      relations: ["orgRoot", "orgChild1"],
    });
    if (posMasters == null) {
      return new HttpSuccess({
        isOfficer: null,
        rootId: null,
        child1Id: null,
        child2Id: null,
        child3Id: null,
        child4Id: null,
        rootDnaId: null,
      });
    }
    return new HttpSuccess({
      isOfficer: posMasters?.orgChild1?.isOfficer || false,
      rootId: posMasters?.orgRootId || null,
      child1Id: posMasters?.orgChild1Id || null,
      child2Id: posMasters?.orgChild2Id || null,
      child3Id: posMasters?.orgChild3Id || null,
      child4Id: posMasters?.orgChild4Id || null,
      rootDnaId: posMasters?.orgRoot?.ancestorDNA || null,
    });
  }

  /**
   * API เช็ค สกจ
   *
   * @summary เช็ค สกจ
   *
   */
  @Get("keycloak/idofficer")
  async getIsOfficerByKeycloak(@Request() request: RequestWithUser) {
    const posMasters = await this.posMasterRepo.findOne({
      where: {
        current_holder: {
          keycloak: request.user.sub,
        },
        orgRevision: {
          orgRevisionIsCurrent: true,
          orgRevisionIsDraft: false,
        },
      },
      relations: ["orgChild1"],
    });
    if (posMasters == null || posMasters.orgChild1 == null) {
      return new HttpSuccess(false);
    }
    return new HttpSuccess(posMasters.orgChild1.isOfficer);
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม keycloakid
   *
   * @summary ข้อมูลทะเบียนประวัติตาม keycloak + ผู้บังคับบัญชา
   *
   * @param id keycloak Id
   */
  @Get("keycloak/commander/{id}")
  async getProfileAndCommander(@Request() request: RequestWithUser, @Path() id: string) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: id },
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }
    const orgRevisionPublish = await this.orgRevisionRepo.findOne({
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });
    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }
    const posMaster =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);
    const root =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot;
    const child1 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1;
    const child2 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2;
    const child3 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3;
    const child4 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4;
    const position = await this.positionRepository.findOne({
      relations: ["posExecutive"],
      where: {
        posMasterId: posMaster?.id,
      },
    });

    //find org(สังกัด)
    const posMaster_ = await this.posMasterRepo.findOne({
      where: {
        orgRevisionId: orgRevisionPublish?.id,
        current_holderId: profile.id,
      },
      order: { createdAt: "DESC" },
      relations: {
        orgRoot: true,
        orgChild1: true,
        orgChild2: true,
        orgChild3: true,
        orgChild4: true,
      },
    });
    const fullNameParts = [
      posMaster_ == null || posMaster_.orgChild4 == null
        ? null
        : posMaster_.orgChild4.orgChild4Name,
      posMaster_ == null || posMaster_.orgChild3 == null
        ? null
        : posMaster_.orgChild3.orgChild3Name,
      posMaster_ == null || posMaster_.orgChild2 == null
        ? null
        : posMaster_.orgChild2.orgChild2Name,
      posMaster_ == null || posMaster_.orgChild1 == null
        ? null
        : posMaster_.orgChild1.orgChild1Name,
      posMaster_ == null || posMaster_.orgRoot == null ? null : posMaster_.orgRoot.orgRootName,
    ];
    const org = fullNameParts.filter((part) => part !== undefined && part !== null).join("\n");

    //find commander(ผู้บังคับบัญชา)
    let node = 4;
    let childId = posMaster?.orgChild4Id;
    let condition: any = { orgChild4Id: childId };

    if (posMaster?.orgChild4Id == null && posMaster?.orgChild3Id != null) {
      node = 3;
      childId = posMaster?.orgChild3Id;
      condition = { orgChild3Id: childId, orgChild4Id: IsNull() };
    } else if (posMaster?.orgChild3Id == null && posMaster?.orgChild2Id != null) {
      node = 2;
      childId = posMaster?.orgChild2Id;
      condition = { orgChild2Id: childId, orgChild3Id: IsNull() };
    } else if (posMaster?.orgChild2Id == null && posMaster?.orgChild1Id != null) {
      node = 1;
      childId = posMaster?.orgChild1Id;
      condition = { orgChild1Id: childId, orgChild2Id: IsNull() };
    } else if (posMaster?.orgChild1Id == null) {
      node = 0;
      childId = posMaster?.orgRootId;
      condition = { orgRootId: childId, orgChild1Id: IsNull() };
    }

    const findCmd = await this.posMasterRepo.findOne({
      where: {
        current_holderId: Not(IsNull()) || Not(""),
        orgRevisionId: orgRevisionPublish?.id,
        ...condition,
      },
      relations: ["current_holder"],
      order: { posMasterOrder: "ASC" },
    });

    let findOSAB: PosMaster | null = null;
    let findTSAB: PosMaster | null = null;
    //หาผู้บังคับบัญชาที่เหนือขึ้นไปอีก 1 ขั้น
    if (node !== 0) {
      findOSAB = await AppDataSource.getRepository(PosMaster)
        .createQueryBuilder("posMaster")
        .leftJoinAndSelect("posMaster.current_holder", "current_holder")
        .where("posMaster.current_holderId IS NOT NULL")
        .andWhere("posMaster.orgRevisionId = :revisionId", { revisionId: orgRevisionPublish?.id })
        .andWhere(
          new Brackets((qb) => {
            if (node === 4) {
              qb.andWhere("posMaster.orgChild4Id IS NULL");
              qb.andWhere("posMaster.orgChild3Id = :childId", {
                childId: posMaster?.orgChild3Id,
              });
            } else if (node === 3) {
              qb.andWhere("posMaster.orgChild3Id IS NULL");
              qb.andWhere("posMaster.orgChild2Id = :childId", {
                childId: posMaster?.orgChild2Id,
              });
            } else if (node === 2) {
              qb.andWhere("posMaster.orgChild2Id IS NULL");
              qb.andWhere("posMaster.orgChild1Id = :childId", {
                childId: posMaster?.orgChild1Id,
              });
            } else if (node === 1) {
              qb.andWhere("posMaster.orgChild1Id IS NULL");
              qb.andWhere("posMaster.orgRootId = :childId", { childId: posMaster?.orgRootId });
            }
          }),
        )
        .orderBy("posMaster.posMasterOrder", "ASC")
        .getOne();
    }

    //หาผู้บังคับบัญชาที่เหนือขึ้นไปอีก 2 ขั้น
    if (node !== 0 && node !== 1) {
      findTSAB = await AppDataSource.getRepository(PosMaster)
        .createQueryBuilder("posMaster")
        .leftJoinAndSelect("posMaster.current_holder", "current_holder")
        .where("posMaster.current_holderId IS NOT NULL")
        .andWhere("posMaster.orgRevisionId = :revisionId", { revisionId: orgRevisionPublish?.id })
        .andWhere(
          new Brackets((qb) => {
            if (node === 4) {
              qb.andWhere("posMaster.orgChild3Id IS NULL");
              qb.andWhere("posMaster.orgChild2Id = :childId", {
                childId: posMaster?.orgChild2Id,
              });
            } else if (node === 3) {
              qb.andWhere("posMaster.orgChild2Id IS NULL");
              qb.andWhere("posMaster.orgChild1Id = :childId", {
                childId: posMaster?.orgChild1Id,
              });
            } else if (node === 2) {
              qb.andWhere("posMaster.orgChild1Id IS NULL");
              qb.andWhere("posMaster.orgRootId = :childId", {
                childId: posMaster?.orgRootId,
              });
            }
          }),
        )
        .orderBy("posMaster.posMasterOrder", "ASC")
        .getOne();
    }

    let commandProfileId;
    let commanderFullname_: any = {};
    let commanderPosition_: any = {};
    let commanderRootName_: any = {};
    let commanderOrg_: any;
    let commandAboveProfileId;
    let commanderAboveFullname_: any = {};
    let commanderAbovePosition_: any = {};
    let commanderAboveRootName_: any = {};
    let commanderAboveOrg_: any;
    let dataCommander: any;

    commanderFullname_ =
      (findCmd?.current_holder?.prefix ?? "") +
      (findCmd?.current_holder?.firstName ?? "") +
      (findCmd?.current_holder?.firstName ? " " : "") +
      (findCmd?.current_holder?.lastName ?? "");
    commanderPosition_ = findCmd?.current_holder?.position ?? "";
    commanderAboveFullname_ =
      (findOSAB?.current_holder?.prefix ?? "") +
      (findOSAB?.current_holder?.firstName ?? "") +
      (findOSAB?.current_holder?.firstName ? " " : "") +
      (findOSAB?.current_holder?.lastName ?? "");
    commanderAbovePosition_ = findOSAB?.current_holder?.position ?? "";

    if (findCmd?.current_holderId == profile?.id) {
      commandProfileId = findOSAB?.current_holderId;
      commanderFullname_ =
        (findOSAB?.current_holder?.prefix ?? "") +
        (findOSAB?.current_holder?.firstName ?? "") +
        (findOSAB?.current_holder?.firstName ? " " : "") +
        (findOSAB?.current_holder?.lastName ?? "");
      commanderPosition_ = findOSAB?.current_holder?.position ?? "";
      commandAboveProfileId = findTSAB?.current_holderId;
      commanderAboveFullname_ =
        (findTSAB?.current_holder?.prefix ?? "") +
        (findTSAB?.current_holder?.firstName ?? "") +
        (findTSAB?.current_holder?.firstName ? " " : "") +
        (findTSAB?.current_holder?.lastName ?? "");
      commanderAbovePosition_ = findTSAB?.current_holder?.position ?? "";
      dataCommander = {
        commanderFullname: commanderFullname_,
        commanderPosition: commanderPosition_,
        commanderAboveFullname: commanderAboveFullname_,
        commanderAbovePosition: commanderAbovePosition_,
      };
    } else {
      commandProfileId = findCmd?.current_holderId;
      commandAboveProfileId = findOSAB?.current_holderId;
      dataCommander = {
        commanderFullname: commanderFullname_,
        commanderPosition: commanderPosition_,
        commanderAboveFullname: commanderAboveFullname_,
        commanderAbovePosition: commanderAbovePosition_,
      };
    }

    const commandProfile = await this.profileRepo.findOne({
      where: { id: String(commandProfileId) },
      relations: ["current_holders", "current_holders.orgRoot"],
    });

    commanderRootName_ =
      commandProfile?.current_holders == null ||
        commandProfile?.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
          ?.orgRoot == null
        ? null
        : commandProfile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
          ?.orgRoot;
    //find สังกัดผู้บังคับบัญชา
    const commanderPosMaster_ = await this.posMasterRepo.findOne({
      where: {
        orgRevisionId: orgRevisionPublish?.id,
        current_holderId: String(commandProfileId),
      },
      order: { createdAt: "DESC" },
      relations: {
        orgRoot: true,
        orgChild1: true,
        orgChild2: true,
        orgChild3: true,
        orgChild4: true,
      },
    });
    const commanderFullNameParts = [
      commanderPosMaster_ == null || commanderPosMaster_.orgChild4 == null
        ? null
        : commanderPosMaster_.orgChild4.orgChild4Name,
      commanderPosMaster_ == null || commanderPosMaster_.orgChild3 == null
        ? null
        : commanderPosMaster_.orgChild3.orgChild3Name,
      commanderPosMaster_ == null || commanderPosMaster_.orgChild2 == null
        ? null
        : commanderPosMaster_.orgChild2.orgChild2Name,
      commanderPosMaster_ == null || commanderPosMaster_.orgChild1 == null
        ? null
        : commanderPosMaster_.orgChild1.orgChild1Name,
      commanderPosMaster_ == null || commanderPosMaster_.orgRoot == null
        ? null
        : commanderPosMaster_.orgRoot.orgRootName,
    ];
    commanderOrg_ = commanderFullNameParts
      .filter((part) => part !== undefined && part !== null)
      .join(" ");

    const commandAboveProfile = await this.profileRepo.findOne({
      where: { id: String(commandAboveProfileId) },
      relations: ["current_holders", "current_holders.orgRoot"],
    });

    commanderAboveRootName_ =
      commandAboveProfile?.current_holders == null ||
        commandAboveProfile?.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
          ?.orgRoot == null
        ? null
        : commandAboveProfile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)
          ?.orgRoot;
    //find สังกัดผู้บังคับบัญชาเหนือไป1ขั้น
    const commanderAbovePosMaster_ = await this.posMasterRepo.findOne({
      where: {
        orgRevisionId: orgRevisionPublish?.id,
        current_holderId: String(commandAboveProfileId),
      },
      order: { createdAt: "DESC" },
      relations: {
        orgRoot: true,
        orgChild1: true,
        orgChild2: true,
        orgChild3: true,
        orgChild4: true,
      },
    });
    const commanderAboveFullNameParts = [
      commanderAbovePosMaster_ == null || commanderAbovePosMaster_.orgChild4 == null
        ? null
        : commanderAbovePosMaster_.orgChild4.orgChild4Name,
      commanderAbovePosMaster_ == null || commanderAbovePosMaster_.orgChild3 == null
        ? null
        : commanderAbovePosMaster_.orgChild3.orgChild3Name,
      commanderAbovePosMaster_ == null || commanderAbovePosMaster_.orgChild2 == null
        ? null
        : commanderAbovePosMaster_.orgChild2.orgChild2Name,
      commanderAbovePosMaster_ == null || commanderAbovePosMaster_.orgChild1 == null
        ? null
        : commanderAbovePosMaster_.orgChild1.orgChild1Name,
      commanderAbovePosMaster_ == null || commanderAbovePosMaster_.orgRoot == null
        ? null
        : commanderAbovePosMaster_.orgRoot.orgRootName,
    ];
    commanderAboveOrg_ = commanderAboveFullNameParts
      .filter((part) => part !== undefined && part !== null)
      .join(" ");

    const _profile: any = {
      profileId: profile.id,
      prefix: profile.prefix,
      rank: profile.rank,
      avatar: profile.avatar,
      isProbation: profile.isProbation,
      avatarName: profile.avatarName,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate,
      position: profile.position,
      leaveDate: profile.dateLeave,
      dateStart: profile.dateStart,
      dateRetireLaw: profile.dateRetireLaw,
      posMaster: posMaster == null ? null : posMaster.posMasterNo,
      posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
      posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName,
      posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
      posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
      posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
      posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
      posTypeId: profile.posType == null ? null : profile.posType.id,
      posExecutiveName:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutiveName,
      posExecutivePriority:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutivePriority,
      posExecutiveId:
        position == null || position.posExecutive == null ? null : position.posExecutive.id,
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      rootDnaId: root == null ? null : root.ancestorDNA,
      rootShortName: root == null ? null : root.orgRootShortName,
      child1Id: child1 == null ? null : child1.id,
      child1: child1 == null ? null : child1.orgChild1Name,
      child1DnaId: child1 == null ? null : child1.ancestorDNA,
      child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
      child2Id: child2 == null ? null : child2.id,
      child2: child2 == null ? null : child2.orgChild2Name,
      child2DnaId: child2 == null ? null : child2.ancestorDNA,
      child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
      child3Id: child3 == null ? null : child3.id,
      child3: child3 == null ? null : child3.orgChild3Name,
      child3DnaId: child3 == null ? null : child3.ancestorDNA,
      child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
      child4Id: child4 == null ? null : child4.id,
      child4: child4 == null ? null : child4.orgChild4Name,
      child4DnaId: child4 == null ? null : child4.ancestorDNA,
      child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
      node: null,
      nodeId: null,
      org: org ? org : null,
      // commander: dataCommander,
      commanderFullname:
        dataCommander && dataCommander.commanderFullname ? dataCommander.commanderFullname : null,
      commanderPosition:
        dataCommander && dataCommander.commanderPosition ? dataCommander.commanderPosition : null,
      commanderRootName:
        commanderRootName_ && commanderRootName_.orgRootName
          ? commanderRootName_.orgRootName
          : null,
      commanderOrg: commanderOrg_ ? commanderOrg_ : null,
      commanderAboveFullname:
        dataCommander && dataCommander.commanderAboveFullname
          ? dataCommander.commanderAboveFullname
          : null,
      commanderAbovePosition:
        dataCommander && dataCommander.commanderAbovePosition
          ? dataCommander.commanderAbovePosition
          : null,
      commanderAboveRootName:
        commanderAboveRootName_ && commanderAboveRootName_.orgRootName
          ? commanderAboveRootName_.orgRootName
          : null,
      commanderAboveOrg: commanderAboveOrg_ ? commanderAboveOrg_ : null,
    };

    if (_profile.child4Id != null) {
      _profile.node = 4;
      _profile.nodeId = _profile.child4Id;
      _profile.nodeShortName = _profile.child4ShortName;
    } else if (_profile.child3Id != null) {
      _profile.node = 3;
      _profile.nodeId = _profile.child3Id;
      _profile.nodeShortName = _profile.child3ShortName;
    } else if (_profile.child2Id != null) {
      _profile.node = 2;
      _profile.nodeId = _profile.child2Id;
      _profile.nodeShortName = _profile.child2ShortName;
    } else if (_profile.child1Id != null) {
      _profile.node = 1;
      _profile.nodeId = _profile.child1Id;
      _profile.nodeShortName = _profile.child1ShortName;
    } else if (_profile.rootId != null) {
      _profile.node = 0;
      _profile.nodeId = _profile.rootId;
      _profile.nodeShortName = _profile.rootShortName;
    }
    return new HttpSuccess(_profile);
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม profileid
   *
   * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม profileid (ADMIN) #70
   *
   */
  @Get("profileid/position/{id}")
  async getProfileByProfileid(@Request() request: RequestWithUser, @Path() id: string) {
    //await new permission().PermissionOrgUserGet(request, "SYS_REGISTRY_OFFICER", id); //ไม่แน่ใจOFFปิดไว้ก่อน
    const profile = await this.profileRepo.findOne({
      where: { id: id },
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        // "profileSalary",
        "profileEducations",
        "profileActpositions",
      ],
      order: {
        // profileSalary: {
        //   order: "DESC",
        // },
        profileEducations: {
          level: "ASC",
        },
        profileActpositions: {
          createdAt: "ASC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }

    const orgRevisionPublish = await this.orgRevisionRepo
      .createQueryBuilder("orgRevision")
      .where("orgRevision.orgRevisionIsDraft = false")
      .andWhere("orgRevision.orgRevisionIsCurrent = true")
      .getOne();
    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }

    const posMaster =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);
    const root =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot;
    const child1 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1;
    const child2 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2;
    const child3 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3;
    const child4 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4;
    const position = await this.positionRepository.findOne({
      relations: ["posExecutive"],
      where: {
        posMasterId: posMaster?.id,
      },
    });
    const holder = profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);
    const numPart = holder ? [holder.posMasterNoPrefix, holder.posMasterNo, holder.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
    const shortName =
      holder == null
        ? null
        : holder.orgChild4 != null
          ? `${holder.orgChild4.orgChild4ShortName} ${numPart}`
          : holder.orgChild3 != null
            ? `${holder.orgChild3.orgChild3ShortName} ${numPart}`
            : holder.orgChild2 != null
              ? `${holder.orgChild2.orgChild2ShortName} ${numPart}`
              : holder.orgChild1 != null
                ? `${holder.orgChild1.orgChild1ShortName} ${numPart}`
                : holder.orgRoot != null
                  ? `${holder.orgRoot.orgRootShortName} ${numPart}`
                  : null;
    // const posMasterActs = await this.posMasterActRepository.find({
    //   relations: [
    //     "posMaster",
    //     "posMaster.orgRoot",
    //     "posMaster.orgChild1",
    //     "posMaster.orgChild2",
    //     "posMaster.orgChild3",
    //     "posMaster.orgChild4",
    //     "posMaster.current_holder",
    //     "posMaster.current_holder.posLevel",
    //     "posMaster.current_holder.posType",
    //   ],
    //   where: {
    //     posMaster: {
    //       orgRevisionId: orgRevisionPublish.id,
    //     },
    //     posMasterChild: {
    //       current_holderId: profile.id,
    //     },
    //   },
    // });
    // const data = await Promise.all(
    //   posMasterActs
    //     .sort((a, b) => a.posMaster.posMasterOrder - b.posMaster.posMasterOrder)
    //     .map((item) => {
    //       const shortName =
    //         item.posMaster != null && item.posMaster.orgChild4 != null
    //           ? `${item.posMaster.orgChild4.orgChild4ShortName} ${item.posMaster.posMasterNo}`
    //           : item.posMaster != null && item.posMaster?.orgChild3 != null
    //             ? `${item.posMaster.orgChild3.orgChild3ShortName} ${item.posMaster.posMasterNo}`
    //             : item.posMaster != null && item.posMaster?.orgChild2 != null
    //               ? `${item.posMaster.orgChild2.orgChild2ShortName} ${item.posMaster.posMasterNo}`
    //               : item.posMaster != null && item.posMaster?.orgChild1 != null
    //                 ? `${item.posMaster.orgChild1.orgChild1ShortName} ${item.posMaster.posMasterNo}`
    //                 : item.posMaster != null && item.posMaster?.orgRoot != null
    //                   ? `${item.posMaster.orgRoot.orgRootShortName} ${item.posMaster.posMasterNo}`
    //                   : null;
    //       return {
    //         id: item.id,
    //         posMasterOrder: item.posMasterOrder,
    //         profileId: item.posMaster?.current_holder?.id ?? null,
    //         citizenId: item.posMaster?.current_holder?.citizenId ?? null,
    //         prefix: item.posMaster?.current_holder?.prefix ?? null,
    //         firstName: item.posMaster?.current_holder?.firstName ?? null,
    //         lastName: item.posMaster?.current_holder?.lastName ?? null,
    //         posLevel: item.posMaster?.current_holder?.posLevel?.posLevelName ?? null,
    //         posType: item.posMaster?.current_holder?.posType?.posTypeName ?? null,
    //         position: item.posMaster?.current_holder?.position ?? null,
    //         posNo: shortName,
    //       };
    //     }),
    // );
    const data = await Promise.all(
      profile.profileActpositions
        .filter((x) => x.status)
        .map(async (item) => {
          const commandRef = await this.commandReciveRepository.findOne({
            where: { commandId: item.commandId },
          });
          const posMasterActs = await this.posMasterActRepository.findOne({
            where: {
              id: commandRef?.refId,
              posMaster: {
                orgRevisionId: orgRevisionPublish.id,
              },
              statusReport: "DONE",
            },
            relations: ["posMaster", "posMaster.current_holder"],
          });
          const _profileAct = await this.profileRepo.findOne({
            where: { id: posMasterActs?.posMaster.current_holderId ?? "" },
            relations: ["posLevel", "posType"],
          });
          return {
            id: item.id,
            posMasterOrder: posMasterActs?.posMasterOrder,
            profileId: _profileAct?.id ?? null,
            citizenId: _profileAct?.citizenId ?? null,
            prefix: _profileAct?.prefix ?? null,
            firstName: _profileAct?.firstName ?? null,
            lastName: _profileAct?.lastName ?? null,
            posLevel: _profileAct?.posLevel.posLevelName ?? null,
            posType: _profileAct?.posType.posTypeName ?? null,
            position: item.position ?? null,
            posNo: item.posNo ?? null,
          };
        }),
    );
    const permissionProflile = await this.permissionProflileRepository.findOne({
      relations: ["orgRootTree"],
      where: {
        profileId: id,
        orgRootTree: {
          orgRevisionId: orgRevisionPublish.id,
        },
      },
    });

    const _profile: any = {
      profileId: profile.id,
      prefix: profile.prefix,
      rank: profile.rank,
      isProbation: profile.isProbation,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate,
      position: profile.position,
      leaveDate: profile.dateLeave,
      posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
      posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName,
      posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
      posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
      posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
      posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
      posTypeId: profile.posType == null ? null : profile.posType.id,
      posExecutiveName:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutiveName,
      positionExecutiveField:
        position == null || position.positionExecutiveField == null
          ? null
          : position.positionExecutiveField,
      positionArea:
        position == null || position.positionArea == null ? null : position.positionArea,
      rootId: root == null ? null : root.id,
      rootDnaId: root == null ? null : root.ancestorDNA,
      root: root == null ? null : root.orgRootName,
      rootShortName: root == null ? null : root.orgRootShortName,
      child1Id: child1 == null ? null : child1.id,
      child1DnaId: child1 == null ? null : child1.ancestorDNA,
      child1: child1 == null ? null : child1.orgChild1Name,
      child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
      child2Id: child2 == null ? null : child2.id,
      child2DnaId: child2 == null ? null : child2.ancestorDNA,
      child2: child2 == null ? null : child2.orgChild2Name,
      child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
      child3Id: child3 == null ? null : child3.id,
      child3DnaId: child3 == null ? null : child3.ancestorDNA,
      child3: child3 == null ? null : child3.orgChild3Name,
      child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
      child4Id: child4 == null ? null : child4.id,
      child4DnaId: child4 == null ? null : child4.ancestorDNA,
      child4: child4 == null ? null : child4.orgChild4Name,
      child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
      node: null,
      nodeId: null,
      nodeDnaId: null,
      posNo: shortName,
      isPosmasterAct: data.length > 0,
      posmasterAct: data,
      salary: profile ? profile.amount : null,
      education:
        profile && profile.profileEducations.length > 0
          ? await getTopDegrees(profile.profileEducations)
          : "-",
      statusCheckEdit: profile.statusCheckEdit,
      isEdit: permissionProflile?.isEdit ?? false,
      isCheck: permissionProflile?.isCheck ?? false,
    };

    if (_profile.child4Id != null) {
      _profile.node = 4;
      _profile.nodeId = _profile.child4Id;
      _profile.nodeDnaId = _profile.child4DnaId;
      _profile.nodeShortName = _profile.child4ShortName;
    } else if (_profile.child3Id != null) {
      _profile.node = 3;
      _profile.nodeId = _profile.child3Id;
      _profile.nodeDnaId = _profile.child3DnaId;
      _profile.nodeShortName = _profile.child3ShortName;
    } else if (_profile.child2Id != null) {
      _profile.node = 2;
      _profile.nodeId = _profile.child2Id;
      _profile.nodeDnaId = _profile.child2DnaId;
      _profile.nodeShortName = _profile.child2ShortName;
    } else if (_profile.child1Id != null) {
      _profile.node = 1;
      _profile.nodeId = _profile.child1Id;
      _profile.nodeDnaId = _profile.child1DnaId;
      _profile.nodeShortName = _profile.child1ShortName;
    } else if (_profile.rootId != null) {
      _profile.node = 0;
      _profile.nodeId = _profile.rootId;
      _profile.nodeDnaId = _profile.rootDnaId;
      _profile.nodeShortName = _profile.rootShortName;
    }
    return new HttpSuccess(_profile);
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม keycloakid
   *
   * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม keycloakid (ADMIN) #70
   *
   */
  @Get("keycloakid/position/{id}")
  async getProfileByKeycloakid(@Request() request: RequestWithUser, @Path() id: string) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: id },
      select: ["id"],
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }
    //await new permission().PermissionOrgUserGet(request, "SYS_REGISTRY_OFFICER", profile.id); //ไม่แน่ใจOFFปิดไว้ก่อน
    return new HttpSuccess(profile);
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม citizenId
   *
   * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม citizenId (ADMIN) #70
   *
   * @param id หมายเลขประจำตัวประชาชน (citizenId)
   */
  @Get("citizenid/position/{id}")
  async getProfileByCitizenId(@Request() request: RequestWithUser, @Path() id: string) {
    const profile = await this.profileRepo.findOne({
      where: { citizenId: id, isActive: true },
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        // "profileSalary",
        "profileEducations",
      ],
      order: {
        // profileSalary: {
        //   order: "DESC",
        // },
        profileEducations: {
          level: "ASC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }
    //await new permission().PermissionOrgUserGet(request, "SYS_REGISTRY_OFFICER", profile.id); //ไม่แน่ใจOFFปิดไว้ก่อน

    const orgRevisionPublish = await this.orgRevisionRepo
      .createQueryBuilder("orgRevision")
      .where("orgRevision.orgRevisionIsDraft = false")
      .andWhere("orgRevision.orgRevisionIsCurrent = true")
      .getOne();
    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }

    const posMaster =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);
    const root =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot;
    const child1 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1;
    const child2 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2;
    const child3 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3;
    const child4 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4;
    const position = await this.positionRepository.findOne({
      relations: ["posExecutive"],
      where: {
        posMasterId: posMaster?.id,
      },
    });
    const _profile: any = {
      profileId: profile.id,
      prefix: profile.prefix,
      rank: profile.rank,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      leaveDate: profile.dateLeave,
      posMasterId: posMaster == null ? null : posMaster.id,
      posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
      posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName,
      posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
      posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
      posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
      posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
      posTypeId: profile.posType == null ? null : profile.posType.id,
      posExecutiveName:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutiveName,
      positionExecutiveField:
        position == null || position.positionExecutiveField == null
          ? null
          : position.positionExecutiveField,
      positionArea:
        position == null || position.positionArea == null ? null : position.positionArea,
      orgRevisionId: root == null ? null : root.orgRevisionId,
      rootId: root == null ? null : root.id,
      rootDnaId: root == null ? null : root.ancestorDNA,
      root: root == null ? null : root.orgRootName,
      rootShortName: root == null ? null : root.orgRootShortName,
      child1Id: child1 == null ? null : child1.id,
      child1DnaId: child1 == null ? null : child1.ancestorDNA,
      child1: child1 == null ? null : child1.orgChild1Name,
      child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
      child2Id: child2 == null ? null : child2.id,
      child2DnaId: child2 == null ? null : child2.ancestorDNA,
      child2: child2 == null ? null : child2.orgChild2Name,
      child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
      child3Id: child3 == null ? null : child3.id,
      child3DnaId: child3 == null ? null : child3.ancestorDNA,
      child3: child3 == null ? null : child3.orgChild3Name,
      child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
      child4Id: child4 == null ? null : child4.id,
      child4DnaId: child4 == null ? null : child4.ancestorDNA,
      child4: child4 == null ? null : child4.orgChild4Name,
      child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
      node: null,
      nodeId: null,
      amount: profile ? profile.amount : null,
      AmountOld: profile ? profile.amount : null,
      positionSalaryAmount: profile ? profile.positionSalaryAmount : null,
      mouthSalaryAmount: profile ? profile.mouthSalaryAmount : null,
      education:
        profile && profile.profileEducations.length > 0
          ? await getTopDegrees(profile.profileEducations)
          : "",
      dateAppoint: profile.dateAppoint,
      avatarUrl:
        profile.avatar && profile.avatarName ? `${profile.avatar}/${profile.avatarName}` : null,
    };

    const _numPart = posMaster ? [posMaster.posMasterNoPrefix, posMaster.posMasterNo, posMaster.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
    if (_profile.child4Id != null) {
      _profile.node = 4;
      _profile.nodeId = _profile.child4Id;
      _profile.nodeShortName = _profile.child4ShortName;
      _profile.posNo = `${_profile.child4ShortName} ${_numPart}`;
    } else if (_profile.child3Id != null) {
      _profile.node = 3;
      _profile.nodeId = _profile.child3Id;
      _profile.nodeShortName = _profile.child3ShortName;
      _profile.posNo = `${_profile.child3ShortName} ${_numPart}`;
    } else if (_profile.child2Id != null) {
      _profile.node = 2;
      _profile.nodeId = _profile.child2Id;
      _profile.nodeShortName = _profile.child2ShortName;
      _profile.posNo = `${_profile.child2ShortName} ${_numPart}`;
    } else if (_profile.child1Id != null) {
      _profile.node = 1;
      _profile.nodeId = _profile.child1Id;
      _profile.nodeShortName = _profile.child1ShortName;
      _profile.posNo = `${_profile.child1ShortName} ${_numPart}`;
    } else if (_profile.rootId != null) {
      _profile.node = 0;
      _profile.nodeId = _profile.rootId;
      _profile.nodeShortName = _profile.rootShortName;
      _profile.posNo = `${_profile.rootShortName} ${_numPart}`;
    }
    return new HttpSuccess(_profile);
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม profileempid
   *
   * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม profileempid (ADMIN) #70
   *
   */
  @Get("profileempid/position/{id}")
  async getProfileByProfileempid(@Request() request: RequestWithUser, @Path() id: string) {
    //await new permission().PermissionOrgUserGet(request, "SYS_REGISTRY_OFFICER", id); //ไม่แน่ใจOFFปิดไว้ก่อน
    const profile = await this.profileEmpRepo.findOne({
      where: { id: id },
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        "profileEducations",
      ],
      order: {
        profileEducations: {
          level: "ASC",
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }

    const orgRevisionPublish = await this.orgRevisionRepo
      .createQueryBuilder("orgRevision")
      .where("orgRevision.orgRevisionIsDraft = false")
      .andWhere("orgRevision.orgRevisionIsCurrent = true")
      .getOne();
    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }

    const posMaster =
      profile.current_holders == null ||
        profile.current_holders.length == 0 ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id) == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id);
    const root =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot == null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgRoot;
    const child1 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild1;
    const child2 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild2;
    const child3 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild3;
    const child4 =
      profile.current_holders == null ||
        profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4 ==
        null
        ? null
        : profile.current_holders.find((x) => x.orgRevisionId == orgRevisionPublish.id)?.orgChild4;
    const _profile: any = {
      profileId: profile.id,
      prefix: profile.prefix,
      rank: profile.rank,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate,
      position: profile.position,
      leaveDate: profile.dateLeave,
      posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
      posLevelName:
        profile.posType == null && profile.posLevel == null
          ? null
          : `${profile.posType.posTypeShortName} ${profile.posLevel.posLevelName}`,
      posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
      posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
      posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
      posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
      posTypeId: profile.posType == null ? null : profile.posType.id,
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      rootShortName: root == null ? null : root.orgRootShortName,
      child1Id: child1 == null ? null : child1.id,
      child1: child1 == null ? null : child1.orgChild1Name,
      child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
      child2Id: child2 == null ? null : child2.id,
      child2: child2 == null ? null : child2.orgChild2Name,
      child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
      child3Id: child3 == null ? null : child3.id,
      child3: child3 == null ? null : child3.orgChild3Name,
      child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
      child4Id: child4 == null ? null : child4.id,
      child4: child4 == null ? null : child4.orgChild4Name,
      child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
      rootDnaId: root == null ? null : root.ancestorDNA,
      child1DnaId: child1 == null ? null : child1.ancestorDNA,
      child2DnaId: child2 == null ? null : child2.ancestorDNA,
      child3DnaId: child3 == null ? null : child3.ancestorDNA,
      child4DnaId: child4 == null ? null : child4.ancestorDNA,
      node: null,
      nodeId: null,
      salary: profile.amount,
      education:
        profile && profile.profileEducations.length > 0
          ? await getTopDegrees(profile.profileEducations)
          : "-",
    };

    const _numPart = posMaster ? [posMaster.posMasterNoPrefix, posMaster.posMasterNo, posMaster.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
    if (_profile.child4Id != null) {
      _profile.node = 4;
      _profile.nodeId = _profile.child4Id;
      _profile.nodeShortName = _profile.child4ShortName;
      _profile.posNo = `${_profile.child4ShortName} ${_numPart}`;
    } else if (_profile.child3Id != null) {
      _profile.node = 3;
      _profile.nodeId = _profile.child3Id;
      _profile.nodeShortName = _profile.child3ShortName;
      _profile.posNo = `${_profile.child3ShortName} ${_numPart}`;
    } else if (_profile.child2Id != null) {
      _profile.node = 2;
      _profile.nodeId = _profile.child2Id;
      _profile.nodeShortName = _profile.child2ShortName;
      _profile.posNo = `${_profile.child2ShortName} ${_numPart}`;
    } else if (_profile.child1Id != null) {
      _profile.node = 1;
      _profile.nodeId = _profile.child1Id;
      _profile.nodeShortName = _profile.child1ShortName;
      _profile.posNo = `${_profile.child1ShortName} ${_numPart}`;
    } else if (_profile.rootId != null) {
      _profile.node = 0;
      _profile.nodeId = _profile.rootId;
      _profile.nodeShortName = _profile.rootShortName;
      _profile.posNo = `${_profile.rootShortName} ${_numPart}`;
    }
    return new HttpSuccess(_profile);
  }

  /**
   * API ค้นหาข้อมูลทะเบียนประวัติ
   *
   * @summary ORG_065 - ค้นหาข้อมูลทะเบียนประวัติ (ADMIN) #70
   *
   */
  @Post("search-personal")
  async getProfileBySearchKeyword(
    @Request() request: RequestWithUser,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Body()
    body: {
      fieldName?: string | null;
      keyword?: string;
      system?: string;
    },
    @Query("sortBy") sortBy?: string,
    @Query("descending") descending?: boolean,
  ) {
    // ค้นหารายชื่อถ้าไม่ส่ง system มาให้ default ตามทะเบียนประวัติ
    let _system: string = "SYS_REGISTRY_OFFICER";
    if (body.system) _system = body.system;
    let _data = await new permission().PermissionOrgList(request, _system);
    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }
    // let queryLike = `CONCAT(
    //       IFNULL(orgChild4.orgChild4ShortName, '')," ",
    //       IFNULL(current_holders.posMasterNo , '')
    //     ) LIKE :keyword OR CONCAT(
    //       IFNULL(orgChild3.orgChild3ShortName, '')," ",
    //       IFNULL(current_holders.posMasterNo , '')
    //     ) LIKE :keyword OR CONCAT(
    //       IFNULL(orgChild2.orgChild2ShortName, '')," ",
    //       IFNULL(current_holders.posMasterNo , '')
    //     ) LIKE :keyword OR CONCAT(
    //       IFNULL(orgChild1.orgChild1ShortName, '')," ",
    //       IFNULL(current_holders.posMasterNo , '')
    //     ) LIKE :keyword OR CONCAT(
    //       IFNULL(orgRoot.orgRootShortName, '')," ",
    //       IFNULL(current_holders.posMasterNo , '')
    //     ) LIKE :keyword`;
    let queryLike = "1=1";
    switch (body.fieldName) {
      case "citizenId":
        queryLike = "profile.citizenId LIKE :keyword";
        break;

      case "fullName":
        queryLike =
          "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword";
        break;

      case "position":
        queryLike = "profile.position LIKE :keyword";
        break;

      case "posNo":
        queryLike = `
          CASE 
            WHEN current_holders.orgChild4Id IS NOT NULL THEN CONCAT(orgChild4.orgChild4ShortName, " ", current_holders.posMasterNo)
            WHEN current_holders.orgChild3Id IS NOT NULL THEN CONCAT(orgChild3.orgChild3ShortName, " ", current_holders.posMasterNo)
            WHEN current_holders.orgChild2Id IS NOT NULL THEN CONCAT(orgChild2.orgChild2ShortName, " ", current_holders.posMasterNo)
            WHEN current_holders.orgChild1Id IS NOT NULL THEN CONCAT(orgChild1.orgChild1ShortName, " ", current_holders.posMasterNo)
            ELSE CONCAT(orgRoot.orgRootShortName, " ", current_holders.posMasterNo)
          END LIKE :keyword
        `;
        break;

      case "posType":
        queryLike = "posType.posTypeName LIKE :keyword";
        break;

      case "posLevel":
        queryLike = "posLevel.posLevelName LIKE :keyword";
        break;

      case "organization":
        queryLike = "orgRoot.orgRootName LIKE :keyword";
        break;

      default:
        queryLike = "1=1";
        break;
    }

    let query = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.posType", "posType")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .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("current_holders.orgRevision = :revisionId", { revisionId: findRevision?.id })
      .andWhere(
        _data.root != undefined && _data.root != null
          ? _data.root[0] != null
            ? `current_holders.orgRootId IN (:...root)`
            : `current_holders.orgRootId is null`
          : "1=1",
        { root: _data.root },
      )
      .andWhere(
        _data.child1 != undefined && _data.child1 != null
          ? _data.child1[0] != null
            ? `current_holders.orgChild1Id IN (:...child1)`
            : // : `current_holders.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
            `current_holders.orgChild1Id is null`
          : "1=1",
        { child1: _data.child1 },
      )
      .andWhere(
        _data.child2 != undefined && _data.child2 != null
          ? _data.child2[0] != null
            ? `current_holders.orgChild2Id IN (:...child2)`
            : `current_holders.orgChild2Id is null`
          : "1=1",
        { child2: _data.child2 },
      )
      .andWhere(
        _data.child3 != undefined && _data.child3 != null
          ? _data.child3[0] != null
            ? `current_holders.orgChild3Id IN (:...child3)`
            : `current_holders.orgChild3Id is null`
          : "1=1",
        { child3: _data.child3 },
      )
      .andWhere(
        _data.child4 != undefined && _data.child4 != null
          ? _data.child4[0] != null
            ? `current_holders.orgChild4Id IN (:...child4)`
            : `current_holders.orgChild4Id is null`
          : "1=1",
        { child4: _data.child4 },
      )
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(body.keyword ? queryLike : "1=1", { keyword: `%${body.keyword}%` });
        }),
      );

    if (sortBy) {
      if (sortBy === "name") {
        query = query
          .orderBy(`profile.prefix`, descending ? "DESC" : "ASC")
          .addOrderBy(`profile.firstName`, descending ? "DESC" : "ASC")
          .addOrderBy(`profile.lastName`, descending ? "DESC" : "ASC");
      } else if (sortBy === "organization") {
        query = query.orderBy(`orgRoot.orgRootName`, descending ? "DESC" : "ASC");
      } else {
        query = query.orderBy(`profile.${sortBy}`, descending ? "DESC" : "ASC");
      }
    }

    const [findProfile, total] = await query
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    // const findRevision = await this.orgRevisionRepo.findOne({
    //   where: { orgRevisionIsCurrent: true },
    // });
    // if (!findRevision) {
    //   throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    // }

    const mapDataProfile = await Promise.all(
      findProfile.map(async (item: Profile) => {
        const fullName = `${item.prefix}${item.firstName} ${item.lastName}`;
        const holder = item.current_holders?.find((x) => x.orgRevisionId == findRevision.id);
        const _numPart = holder ? [holder.posMasterNoPrefix, holder.posMasterNo, holder.posMasterNoSuffix].filter((p) => p !== null && p !== undefined && p !== '').join(' ') : '';
        const shortName = !holder
          ? null
          : holder.orgChild4 != null
            ? `${holder.orgChild4.orgChild4ShortName} ${_numPart}`
            : holder.orgChild3 != null
              ? `${holder.orgChild3.orgChild3ShortName} ${_numPart}`
              : holder.orgChild2 != null
                ? `${holder.orgChild2.orgChild2ShortName} ${_numPart}`
                : holder.orgChild1 != null
                  ? `${holder.orgChild1.orgChild1ShortName} ${_numPart}`
                  : holder.orgRoot != null
                    ? `${holder.orgRoot.orgRootShortName} ${_numPart}`
                    : null;

        const root =
          item.current_holders.length == 0 ||
            (holder != null &&
              holder?.orgRoot == null)
            ? null
            : holder?.orgRoot;

        const rootHolder = item.current_holders?.find(
          (x) => x.orgRevisionId == findRevision.id,
        )?.orgRoot;
        const child1Holder = item.current_holders?.find(
          (x) => x.orgRevisionId == findRevision.id,
        )?.orgChild1;
        const child2Holder = item.current_holders?.find(
          (x) => x.orgRevisionId == findRevision.id,
        )?.orgChild2;
        const child3Holder = item.current_holders?.find(
          (x) => x.orgRevisionId == findRevision.id,
        )?.orgChild3;
        const child4Holder = item.current_holders?.find(
          (x) => x.orgRevisionId == findRevision.id,
        )?.orgChild4;
        const posMasterNo = item.current_holders?.find(
          (x) => x.orgRevisionId == findRevision.id,
        )?.posMasterNo;

        const latestProfileEducation = await this.profileEducationRepo.findOne({
          where: { profileId: item.id, isDeleted: false },
          order: { level: "ASC" },
        });

        return {
          id: item.id,
          keycloak: item.keycloak,
          prefix: item.prefix,
          rank: item.rank,
          firstName: item.firstName,
          lastName: item.lastName,
          position: item.position,
          citizenId: item.citizenId,
          email: item.email,
          phone: item.phone,
          name: fullName,
          birthDate: item.birthDate,
          positionLevel: item.posLevelId,
          positionLevelName: item.posLevel?.posLevelName,
          positionType: item.posTypeId,
          positionTypeName: item.posType?.posTypeName,
          posNo: shortName,
          organization: root == null ? null : root.orgRootName,
          salary: item.amount,
          root: rootHolder?.orgRootName ?? null,
          rootId: rootHolder?.id ?? null,
          rootDnaId: rootHolder?.ancestorDNA ?? null,
          rootShortName: rootHolder?.orgRootShortName ?? null,
          child1: child1Holder?.orgChild1Name ?? null,
          child1Id: child1Holder?.id ?? null,
          child1DnaId: child1Holder?.ancestorDNA ?? null,
          child1ShortName: child1Holder?.orgChild1ShortName ?? null,
          child2: child2Holder?.orgChild2Name ?? null,
          child2Id: child2Holder?.id ?? null,
          child2DnaId: child2Holder?.ancestorDNA ?? null,
          child2ShortName: child2Holder?.orgChild2ShortName ?? null,
          child3: child3Holder?.orgChild3Name ?? null,
          child3Id: child3Holder?.id ?? null,
          child3DnaId: child3Holder?.ancestorDNA ?? null,
          child3ShortName: child3Holder?.orgChild3ShortName ?? null,
          child4: child4Holder?.orgChild4Name ?? null,
          child4Id: child4Holder?.id ?? null,
          child4DnaId: child4Holder?.ancestorDNA ?? null,
          child4ShortName: child4Holder?.orgChild4ShortName ?? null,
          posMasterNo: posMasterNo ?? null,
          posTypeId: item.posTypeId,
          posTypeName: item.posType?.posTypeName,
          posLevelId: item.posLevelId,
          posLevelName: item.posLevel?.posLevelName,
          educationDegree:
            latestProfileEducation != null && latestProfileEducation.educationLevel != null
              ? latestProfileEducation.educationLevel
              : null,
        };
      }),
    );

    return new HttpSuccess({ data: mapDataProfile, total });
  }

  /**
   * API ค้นหาผู้บังคับบัญชา
   *
   * @summary ORG_069 - ค้นหาผู้บังคับบัญชา (ADMIN) #75
   *
   */
  @Get("search/commander")
  async searchCommander(@Request() request: { user: Record<string, any> }) {
    let fullName_: any = {};
    let position_: any = {};
    let commanderAboveFullname_: any = {};
    let commanderAbovePosition_: any = {};
    let commanderFullname_: any = {};
    let commanderPosition_: any = {};
    let commanderOrg_: any = {};
    let commanderAboveOrg_: any = {};

    const findProfile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
      relations: ["posLevel"],
    });

    const findRevision = await this.orgRevisionRepo.findOne({
      where: {
        orgRevisionIsCurrent: true,
      },
    });

    const findPosMaster = await this.posMasterRepo.findOne({
      where: {
        current_holderId: findProfile?.id,
        orgRevisionId: findRevision?.id,
      },
    });

    let node = 4;
    let childId = findPosMaster?.orgChild4Id;
    let condition: any = { orgChild4Id: childId };

    if (findPosMaster?.orgChild4Id == null && findPosMaster?.orgChild3Id != null) {
      node = 3;
      childId = findPosMaster?.orgChild3Id;
      condition = { orgChild3Id: childId, orgChild4Id: IsNull() };
    } else if (findPosMaster?.orgChild3Id == null && findPosMaster?.orgChild2Id != null) {
      node = 2;
      childId = findPosMaster?.orgChild2Id;
      condition = { orgChild2Id: childId, orgChild3Id: IsNull() };
    } else if (findPosMaster?.orgChild2Id == null && findPosMaster?.orgChild1Id != null) {
      node = 1;
      childId = findPosMaster?.orgChild1Id;
      condition = { orgChild1Id: childId, orgChild2Id: IsNull() };
    } else if (findPosMaster?.orgChild1Id == null) {
      node = 0;
      childId = findPosMaster?.orgRootId;
      condition = { orgRootId: childId, orgChild1Id: IsNull() };
    }

    const findCmd = await this.posMasterRepo.findOne({
      where: {
        current_holderId: Not(IsNull()) || Not(""),
        orgRevisionId: findRevision?.id,
        ...condition,
      },
      relations: [
        "current_holder",
        "current_holder.posLevel",
        "orgRoot",
        "orgChild1",
        "orgChild2",
        "orgChild3",
        "orgChild4",
      ],
      order: { posMasterOrder: "ASC" },
    });
    let findOSAB: PosMaster | null = null;
    let findTSAB: PosMaster | null = null;
    //หาผู้บังคับบัญชาที่เหนือขึ้นไปอีก 1 ขั้น
    if (node !== 0) {
      findOSAB = await AppDataSource.getRepository(PosMaster)
        .createQueryBuilder("posMaster")
        .leftJoinAndSelect("posMaster.current_holder", "current_holder")
        .leftJoinAndSelect("current_holder.posLevel", "posLevel")
        .leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
        .leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
        .leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
        .leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
        .leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
        .where("posMaster.current_holderId IS NOT NULL")
        .andWhere("posMaster.orgRevisionId = :revisionId", { revisionId: findRevision?.id })
        .andWhere(
          new Brackets((qb) => {
            if (node === 4) {
              qb.andWhere("posMaster.orgChild4Id IS NULL");
              qb.andWhere("posMaster.orgChild3Id = :childId", {
                childId: findPosMaster?.orgChild3Id,
              });
            } else if (node === 3) {
              qb.andWhere("posMaster.orgChild3Id IS NULL");
              qb.andWhere("posMaster.orgChild2Id = :childId", {
                childId: findPosMaster?.orgChild2Id,
              });
            } else if (node === 2) {
              qb.andWhere("posMaster.orgChild2Id IS NULL");
              qb.andWhere("posMaster.orgChild1Id = :childId", {
                childId: findPosMaster?.orgChild1Id,
              });
            } else if (node === 1) {
              qb.andWhere("posMaster.orgChild1Id IS NULL");
              qb.andWhere("posMaster.orgRootId = :childId", { childId: findPosMaster?.orgRootId });
            }
          }),
        )
        .orderBy("posMaster.posMasterOrder", "ASC")
        .getOne();
    }

    //หาผู้บังคับบัญชาที่เหนือขึ้นไปอีก 2 ขั้น
    if (node !== 0 && node !== 1) {
      findTSAB = await AppDataSource.getRepository(PosMaster)
        .createQueryBuilder("posMaster")
        .leftJoinAndSelect("posMaster.current_holder", "current_holder")
        .leftJoinAndSelect("current_holder.posLevel", "posLevel")
        .leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
        .leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
        .leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
        .leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
        .leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
        .where("posMaster.current_holderId IS NOT NULL")
        .andWhere("posMaster.orgRevisionId = :revisionId", { revisionId: findRevision?.id })
        .andWhere(
          new Brackets((qb) => {
            if (node === 4) {
              qb.andWhere("posMaster.orgChild3Id IS NULL");
              qb.andWhere("posMaster.orgChild2Id = :childId", {
                childId: findPosMaster?.orgChild2Id,
              });
            } else if (node === 3) {
              qb.andWhere("posMaster.orgChild2Id IS NULL");
              qb.andWhere("posMaster.orgChild1Id = :childId", {
                childId: findPosMaster?.orgChild1Id,
              });
            } else if (node === 2) {
              qb.andWhere("posMaster.orgChild1Id IS NULL");
              qb.andWhere("posMaster.orgRootId = :childId", {
                childId: findPosMaster?.orgRootId,
              });
            }
          }),
        )
        .orderBy("posMaster.posMasterOrder", "ASC")
        .getOne();
    }
    const commanderOrg = [
      findCmd?.orgChild4?.orgChild4Name ?? null,
      findCmd?.orgChild3?.orgChild3Name ?? null,
      findCmd?.orgChild2?.orgChild2Name ?? null,
      findCmd?.orgChild1?.orgChild1Name ?? null,
      findCmd?.orgRoot?.orgRootName ?? null,
    ];
    const _commanderOrg = commanderOrg
      .filter((part) => part !== undefined && part !== null)
      .join(" ");

    const commanderAbroveOrg = [
      findOSAB?.orgChild4?.orgChild4Name ?? null,
      findOSAB?.orgChild3?.orgChild3Name ?? null,
      findOSAB?.orgChild2?.orgChild2Name ?? null,
      findOSAB?.orgChild1?.orgChild1Name ?? null,
      findOSAB?.orgRoot?.orgRootName ?? null,
    ];
    const _commanderAbroveOrg = commanderAbroveOrg
      .filter((part) => part !== undefined && part !== null)
      .join(" ");

    fullName_ =
      (findProfile?.prefix ?? "") +
      (findProfile?.firstName ?? "") +
      (findProfile?.firstName ? " " : "") +
      (findProfile?.lastName ?? "");
    position_ =
      (findProfile?.position ? findProfile?.position : "") +
      (findProfile?.posLevel?.posLevelName ? findProfile?.posLevel?.posLevelName : "");
    commanderFullname_ =
      (findCmd?.current_holder?.prefix ?? "") +
      (findCmd?.current_holder?.firstName ?? "") +
      (findCmd?.current_holder?.firstName ? " " : "") +
      (findCmd?.current_holder?.lastName ?? "");
    commanderOrg_ = _commanderOrg;
    commanderPosition_ =
      (findCmd?.current_holder?.position ? findCmd?.current_holder?.position : "") +
      (findCmd?.current_holder?.posLevel?.posLevelName
        ? findCmd?.current_holder?.posLevel?.posLevelName
        : "");
    commanderAboveFullname_ =
      (findOSAB?.current_holder?.prefix ?? "") +
      (findOSAB?.current_holder?.firstName ?? "") +
      (findOSAB?.current_holder?.firstName ? " " : "") +
      (findOSAB?.current_holder?.lastName ?? "");
    commanderAboveOrg_ = _commanderAbroveOrg;
    commanderAbovePosition_ =
      (findOSAB?.current_holder?.position ? findOSAB?.current_holder?.position : "") +
      (findOSAB?.current_holder?.posLevel?.posLevelName
        ? findOSAB?.current_holder?.posLevel?.posLevelName
        : "");

    const commanderAbrove2Org = [
      findTSAB?.orgChild4?.orgChild4Name ?? null,
      findTSAB?.orgChild3?.orgChild3Name ?? null,
      findTSAB?.orgChild2?.orgChild2Name ?? null,
      findTSAB?.orgChild1?.orgChild1Name ?? null,
      findTSAB?.orgRoot?.orgRootName ?? null,
    ];
    const _commanderAbrove2Org = commanderAbrove2Org
      .filter((part) => part !== undefined && part !== null)
      .join(" ");

    if (findCmd?.current_holderId == findProfile?.id) {
      commanderFullname_ =
        (findOSAB?.current_holder?.prefix ?? "") +
        (findOSAB?.current_holder?.firstName ?? "") +
        (findOSAB?.current_holder?.firstName ? " " : "") +
        (findOSAB?.current_holder?.lastName ?? "");
      commanderOrg_ = _commanderAbroveOrg;
      commanderPosition_ =
        (findOSAB?.current_holder?.position ? findOSAB?.current_holder?.position : "") +
        (findOSAB?.current_holder?.posLevel?.posLevelName
          ? findOSAB?.current_holder?.posLevel?.posLevelName
          : "");
      commanderAboveFullname_ =
        (findTSAB?.current_holder?.prefix ?? "") +
        (findTSAB?.current_holder?.firstName ?? "") +
        (findTSAB?.current_holder?.firstName ? " " : "") +
        (findTSAB?.current_holder?.lastName ?? "");
      commanderAboveOrg_ = _commanderAbrove2Org;
      commanderAbovePosition_ =
        (findTSAB?.current_holder?.position ? findTSAB?.current_holder?.position : "") +
        (findTSAB?.current_holder?.posLevel?.posLevelName
          ? findTSAB?.current_holder?.posLevel?.posLevelName
          : "");

      const formattedDataTSAB = {
        fullname: fullName_,
        position: position_,
        commanderAboveFullname: commanderAboveFullname_,
        commanderAboveOrg: commanderAboveOrg_,
        commanderAbovePosition: commanderAbovePosition_,
        commanderFullname: commanderFullname_,
        commanderOrg: commanderOrg_,
        commanderPosition: commanderPosition_,
      };
      return new HttpSuccess(formattedDataTSAB);
    }

    const formattedData = {
      fullname: fullName_,
      position: position_,
      commanderAboveFullname: commanderAboveFullname_,
      commanderAboveOrg: commanderAboveOrg_,
      commanderAbovePosition: commanderAbovePosition_,
      commanderFullname: commanderFullname_,
      commanderOrg: commanderOrg_,
      commanderPosition: commanderPosition_,
    };
    return new HttpSuccess(formattedData);
  }

  /**
   * API เช็คเลขบัตร
   *
   * @summary เช็คเลขบัตร  (ADMIN)
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Put("citizenId/{id}")
  async checkCitizenIdProfile(
    @Path() id: string,
    @Body()
    requestBody: { citizenId: string },
  ) {
    const profile = await this.profileRepo.findOne({
      where: { id: Not(id), citizenId: requestBody.citizenId },
    });
    if (profile) {
      throw new HttpError(
        HttpStatus.INTERNAL_SERVER_ERROR,
        "เลขประจำตัวประชาชนนี้มีอยู่ในระบบแล้ว",
      );
    }
    return new HttpSuccess();
  }

  /**
   * API ค้นหาข้อมูลทะเบียนประวัติ ทดลองปฏิบัติหน้าที่ราชการ
   *
   * @summary ค้นหาข้อมูลทะเบียนประวัติ ทดลองปฏิบัติหน้าที่ราชการ (ADMIN)
   *
   */
  @Post("probation")
  async getProfileBySearchKeywordProbation(
    @Request() request: RequestWithUser,
    @Body()
    body: {
      page: number;
      pageSize: number;
      keyword?: string;
      sortBy?: string;
      descending?: boolean;
    },
  ) {
    let _data: any = {
      root: null,
      child1: null,
      child2: null,
      child3: null,
      child4: null,
    };
    const isProbation: boolean = true;
    if (!request.user.role.includes("SUPER_ADMIN")) {
      _data = await new permission().PermissionOrgCreate(request, "SYS_PROBATION");
    }
    let query = await AppDataSource.getRepository(Profile)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.profileSalary", "profileSalary")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.orgRevision", "orgRevision")
      .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")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .andWhere("profile.isLeave = false")
      .andWhere(
        _data.root != undefined && _data.root != null
          ? _data.root[0] != null
            ? `current_holders.orgRootId IN (:...root)`
            : `current_holders.orgRootId is null`
          : "1=1",
        {
          root: _data.root,
        },
      )
      .andWhere(
        _data.child1 != undefined && _data.child1 != null
          ? _data.child1[0] != null
            ? `current_holders.orgChild1Id IN (:...child1)`
            : // : `current_holders.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
            `current_holders.orgChild1Id is null`
          : "1=1",
        {
          child1: _data.child1,
        },
      )
      .andWhere(
        _data.child2 != undefined && _data.child2 != null
          ? _data.child2[0] != null
            ? `current_holders.orgChild2Id IN (:...child2)`
            : `current_holders.orgChild2Id is null`
          : "1=1",
        {
          child2: _data.child2,
        },
      )
      .andWhere(
        _data.child3 != undefined && _data.child3 != null
          ? _data.child3[0] != null
            ? `current_holders.orgChild3Id IN (:...child3)`
            : `current_holders.orgChild3Id is null`
          : "1=1",
        {
          child3: _data.child3,
        },
      )
      .andWhere(
        _data.child4 != undefined && _data.child4 != null
          ? _data.child4[0] != null
            ? `current_holders.orgChild4Id IN (:...child4)`
            : `current_holders.orgChild4Id is null`
          : "1=1",
        {
          child4: _data.child4,
        },
      )
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(
            `CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword and profile.isProbation = ${isProbation}`,
            {
              keyword: `%${body.keyword}%`,
            },
          )
            .orWhere(`profile.position LIKE :keyword and profile.isProbation = ${isProbation}`, {
              keyword: `%${body.keyword}%`,
            })
            .orWhere(
              `posLevel.posLevelName LIKE :keyword and profile.isProbation = ${isProbation}`,
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(`posType.posTypeName LIKE :keyword and profile.isProbation = ${isProbation}`, {
              keyword: `%${body.keyword}%`,
            })
            .orWhere(`orgRoot.orgRootName LIKE :keyword and profile.isProbation = ${isProbation}`, {
              keyword: `%${body.keyword}%`,
            })
            .orWhere(
              `orgChild1.orgChild1Name LIKE :keyword and profile.isProbation = ${isProbation}`,
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              `orgChild2.orgChild2Name LIKE :keyword and profile.isProbation = ${isProbation}`,
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              `orgChild3.orgChild3Name LIKE :keyword and profile.isProbation = ${isProbation}`,
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              `orgChild4.orgChild4Name LIKE :keyword and profile.isProbation = ${isProbation}`,
              {
                keyword: `%${body.keyword}%`,
              },
            );
        }),
      );

    if (body.sortBy) {
      if (body.sortBy === "posLevelName") {
        query = query.orderBy(`posLevel.posLevelName`, body.descending ? "DESC" : "ASC");
      } else if (body.sortBy === "posTypeName") {
        query = query.orderBy(`posType.posTypeName`, body.descending ? "DESC" : "ASC");
      } else if (body.sortBy === "commandNo") {
        // Use subquery to get the latest commandNo for each profile
        const subquery = AppDataSource.getRepository(ProfileSalary)
          .createQueryBuilder("ps")
          .select("ps.commandNo", "commandNo")
          .where("ps.profileId = profile.id")
          .orderBy("ps.order", "DESC")
          .addOrderBy("ps.commandNo", "DESC")
          .limit(1);

        query = query
          .addSelect(`(${subquery.getSql()})`, "latestCommandNo")
          .orderBy("latestCommandNo", body.descending ? "DESC" : "ASC")
          .addOrderBy("profile.id", "ASC"); // Secondary sort for consistency
      } else if (body.sortBy === "orgRootName") {
        query = query.orderBy(`orgRoot.orgRootName`, body.descending ? "DESC" : "ASC");
      } else {
        query = query.orderBy(`profile.${body.sortBy}`, body.descending ? "DESC" : "ASC");
      }
    } else {
      query = query.orderBy("profile.citizenId", "ASC");
    }

    const [findProfile, total] = await query
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();

    const orgRevisionActive = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });
    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }

    const mapDataProfile = await Promise.all(
      findProfile.map(async (item: Profile) => {
        const posMaster =
          item.current_holders == null ||
            item.current_holders.length == 0 ||
            item.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision.id);
        const position =
          posMaster == null ||
            item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.positions == null ||
            item.current_holders?.find((x) => x.orgRevisionId == findRevision.id)?.positions.length ==
            0 ||
            item.current_holders
              .find((x) => x.orgRevisionId == findRevision.id)
              ?.positions?.find((position) => position.positionIsSelected == true) == null
            ? null
            : item.current_holders
              .find((x) => x.orgRevisionId == findRevision.id)
              ?.positions?.find((position) => position.positionIsSelected == true);
        const posExecutive =
          position == null ||
            item.current_holders
              .find((x) => x.orgRevisionId == findRevision.id)
              ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
            null ||
            item.current_holders
              .find((x) => x.orgRevisionId == findRevision.id)
              ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
              ?.posExecutiveName == null
            ? null
            : item.current_holders
              .find((x) => x.orgRevisionId == findRevision.id)
              ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
              .posExecutiveName;

        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 {
          id: item.id,
          prefix: item.prefix,
          rank: item.rank,
          firstName: item.firstName,
          lastName: item.lastName,
          position: item.position,
          idcard: item.citizenId,
          commandNo:
            item.profileSalary.sort((a, b) => b.order - a.order).length == 0
              ? null
              : item.profileSalary.sort((a, b) => b.order - a.order)[0].commandNo,
          posLevelName: item.posLevel == null ? null : item.posLevel.posLevelName,
          posTypeName: item.posType == null ? null : item.posType.posTypeName,
          posNo: shortName == null ? null : shortName,
          positionField: position == null ? null : position.positionField,
          positionArea: position == null ? null : position.positionArea,
          posExecutiveName: posExecutive,
          positionExecutiveField: position == null ? null : position.positionExecutiveField,
          isProbation: item.isProbation,
          orgRootName:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.orgRootName == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.orgRootName,
          orgChild1Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1
                ?.orgChild1Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild1?.orgChild1Name,
          orgChild2Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2
                ?.orgChild2Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild2?.orgChild2Name,
          orgChild3Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3
                ?.orgChild3Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild3?.orgChild3Name,
          orgChild4Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4
                ?.orgChild4Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild4?.orgChild4Name,
          root:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.orgRootName == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.id,
          orgChild1:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1
                ?.orgChild1Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild1?.id,
          orgChild2:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2
                ?.orgChild2Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild2?.id,
          orgChild3:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3
                ?.orgChild3Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild3?.id,
          orgChild4:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4
                ?.orgChild4Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild4?.id,
          rootDna:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.orgRootName == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.ancestorDNA,
          orgChild1Dna:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1
                ?.orgChild1Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild1?.ancestorDNA,
          orgChild2Dna:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2
                ?.orgChild2Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild2?.ancestorDNA,
          orgChild3Dna:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3
                ?.orgChild3Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild3?.ancestorDNA,
          orgChild4Dna:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4
                ?.orgChild4Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild4?.ancestorDNA,
        };
      }),
    );

    return new HttpSuccess({ data: mapDataProfile, total });
  }

  /**
   * API ค้นหาข้อมูลทะเบียนประวัติ เกษียณข้าราชการ
   *
   * @summary ค้นหาข้อมูลทะเบียนประวัติ เกษียณข้าราชการ (ADMIN)
   *
   */
  @Post("retire")
  async getProfileBySearchKeywordRetire(
    @Body()
    body: {
      page: number;
      pageSize: number;
      keyword?: string;
    },
  ) {
    const orgRevisionActive = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });
    if (!orgRevisionActive) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }
    let query = AppDataSource.getRepository(Profile)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.orgRevision", "orgRevision")
      .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")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .andWhere(
        new Brackets((qb) => {
          qb.where("profile.position LIKE :keyword", { keyword: `%${body.keyword}%` })
            .orWhere("posLevel.posLevelName LIKE :keyword", { keyword: `%${body.keyword}%` })
            .orWhere("posType.posTypeName LIKE :keyword", { keyword: `%${body.keyword}%` })
            .orWhere(
              "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword",
              { keyword: `%${body.keyword}%` },
            );
        }),
      )
      .andWhere("profile.isLeave = false")
      .andWhere("current_holders.orgRevisionId = :orgRevisionId", {
        orgRevisionId: orgRevisionActive.id,
      });

    const [findProfile, total] = await query
      .orderBy("profile.citizenId", "ASC")
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();

    const mapDataProfile = await Promise.all(
      findProfile.map(async (item: Profile) => {
        const posMaster =
          item.current_holders == null ||
            item.current_holders.length == 0 ||
            item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id) == null
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id);
        const position =
          posMaster == null ||
            item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.positions ==
            null ||
            item.current_holders?.find((x) => x.orgRevisionId == orgRevisionActive.id)?.positions
              .length == 0 ||
            item.current_holders
              .find((x) => x.orgRevisionId == orgRevisionActive.id)
              ?.positions?.find((position) => position.positionIsSelected == true) == null
            ? null
            : item.current_holders
              .find((x) => x.orgRevisionId == orgRevisionActive.id)
              ?.positions?.find((position) => position.positionIsSelected == true);
        const posExecutive =
          position == null ||
            item.current_holders
              .find((x) => x.orgRevisionId == orgRevisionActive.id)
              ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
            null ||
            item.current_holders
              .find((x) => x.orgRevisionId == orgRevisionActive.id)
              ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
              ?.posExecutiveName == null
            ? null
            : item.current_holders
              .find((x) => x.orgRevisionId == orgRevisionActive.id)
              ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
              .posExecutiveName;

        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id) != null &&
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)
                ?.orgChild4 != null
              ? `${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)
                  ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id) !=
                  null &&
                  item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)
                    ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id) !=
                    null &&
                    item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)
                      ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id) !=
                      null &&
                      item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)
                        ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive.id)?.posMasterNo}`
                      : null;

        return {
          id: item.id,
          prefix: item.prefix,
          rank: item.rank,
          firstName: item.firstName,
          lastName: item.lastName,
          position: item.position,
          idcard: item.citizenId,
          posLevelName: item.posLevel == null ? null : item.posLevel.posLevelName,
          posTypeName: item.posType == null ? null : item.posType.posTypeName,
          posNo: `${shortName} ${posMaster == null ? null : posMaster.posMasterNo}`,
          positionField: position == null ? null : position.positionField,
          positionArea: position == null ? null : position.positionArea,
          posExecutiveName: posExecutive,
          positionExecutiveField: position == null ? null : position.positionExecutiveField,
          isProbation: item.isProbation,
          orgRootName:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.orgRootName == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot
                ?.orgRootName,
          orgChild1Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1
                ?.orgChild1Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild1?.orgChild1Name,
          orgChild2Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2
                ?.orgChild2Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild2?.orgChild2Name,
          orgChild3Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3
                ?.orgChild3Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild3?.orgChild3Name,
          orgChild4Name:
            item.current_holders == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) == null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4 ==
              null ||
              item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4
                ?.orgChild4Name == null
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                ?.orgChild4?.orgChild4Name,
        };
      }),
    );

    return new HttpSuccess({ data: mapDataProfile, total });
  }

  /**
   * API รายชื่อราชการที่เลื่อนเงินเดือน
   *
   * @summary ORG_072 - รายชื่อราชการที่เลื่อนเงินเดือน #76
   *
   */
  @Post("salary/gen")
  async salaryGen(
    @Body()
    body: {
      page: number;
      pageSize: number;
      keyword?: string;
      rootId?: string;
      year: number;
      period: string;
      sortBy?: string;
      descending?: boolean;
    },
  ) {
    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }

    let query = await AppDataSource.getRepository(PosMaster)
      .createQueryBuilder("posMaster")
      .leftJoinAndSelect("posMaster.current_holder", "current_holder")
      .leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
      .leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
      .leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
      .leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
      .leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
      .leftJoinAndSelect("posMaster.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .leftJoinAndSelect("current_holder.profileSalary", "profileSalary")
      .leftJoinAndSelect("current_holder.profileDisciplines", "profileDisciplines")
      .leftJoinAndSelect("current_holder.posLevel", "posLevel")
      .leftJoinAndSelect("current_holder.posType", "posType")
      .where((qb) => {
        if (body.rootId) {
          qb.andWhere("posMaster.orgRootId = :rootId", { rootId: body.rootId });
        } else {
          qb.andWhere("posMaster.orgRevisionId = :orgRevisionId", {
            orgRevisionId: findRevision?.id,
          });
        }
        qb.andWhere("posMaster.current_holderId IS NOT NULL");
      })
      .andWhere(
        new Brackets((qb) => {
          qb.where(
            body.keyword != null && body.keyword != ""
              ? "current_holder.prefix LIKE :keyword"
              : "1=1",
            {
              keyword: `%${body.keyword}%`,
            },
          )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.firstName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.lastName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(current_holder.prefix,current_holder.firstName,' ',current_holder.lastName) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(orgRoot.orgRootShortName,' ',posMaster.posMasterNo) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(orgChild1.orgChild1ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(orgChild2.orgChild2ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(orgChild3.orgChild3ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "CONCAT(orgChild4.orgChild4ShortName,' ',posMaster.posMasterNo) LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.position LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )

            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.citizenId LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "posType.posTypeName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "posLevel.posLevelName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            );
        }),
      );

    if (body.sortBy) {
      if (body.sortBy === "posType") {
        query = query.orderBy(`posType.posTypeName`, body.descending ? "DESC" : "ASC");
      } else if (body.sortBy === "posLevel") {
        query = query.orderBy(`posLevel.posLevelName`, body.descending ? "DESC" : "ASC");
      } else if (body.sortBy === "orgShortName" || body.sortBy === "posMasterNo") {
        query = query
          .orderBy(`orgRoot.orgRootShortName`, body.descending ? "DESC" : "ASC")
          .addOrderBy(`orgChild1.orgChild1ShortName`, body.descending ? "DESC" : "ASC")
          .addOrderBy(`orgChild2.orgChild2ShortName`, body.descending ? "DESC" : "ASC")
          .addOrderBy(`orgChild3.orgChild3ShortName`, body.descending ? "DESC" : "ASC")
          .addOrderBy(`orgChild4.orgChild4ShortName`, body.descending ? "DESC" : "ASC")
          .addOrderBy(`posMaster.posMasterNo`, body.descending ? "DESC" : "ASC");
      } else {
        query = query.orderBy(`current_holder.${body.sortBy}`, body.descending ? "DESC" : "ASC");
      }
    } else {
      query = query.orderBy("current_holder.citizenId", "ASC");
    }

    const [findPosMaster, total] = await query
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();
    if (!findPosMaster) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. PosMaster");
    }

    const formattedData = findPosMaster.map((item) => {
      let orgShortName = "";

      if (item.orgChild1Id === null) {
        orgShortName = item.orgRoot?.orgRootShortName;
      } else if (item.orgChild2Id === null) {
        orgShortName = item.orgChild1?.orgChild1ShortName;
      } else if (item.orgChild3Id === null) {
        orgShortName = item.orgChild2?.orgChild2ShortName;
      } else if (item.orgChild4Id === null) {
        orgShortName = item.orgChild3?.orgChild3ShortName;
      } else {
        orgShortName = item.orgChild4?.orgChild4ShortName;
      }
      const posExecutive =
        item.positions == null ||
          item.positions?.find((position) => position.positionIsSelected == true) == null ||
          item.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
          null ||
          item.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
            ?.posExecutiveName == null
          ? null
          : item.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
            .posExecutiveName;

      // const amount =
      //   item.current_holder == null || item.current_holder.profileSalary.length == 0
      //     ? null
      //     : item.current_holder.profileSalary.sort((a: any, b: any) => b.date - a.date)[0].amount;
      const amount = item.current_holder ? item.current_holder.amount : null;
      let datePeriodStart = new Date(
        `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(new Date().getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
      );
      let datePeriodEnd = new Date(
        `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(new Date().getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
      );
      if (body.period.toLocaleUpperCase() == "APR") {
        datePeriodStart = new Date(`${body.year}-03-31T00:00:00.000Z`);
        datePeriodEnd = new Date(`${body.year}-03-31T00:00:00.000Z`);
      }
      if (body.period.toLocaleUpperCase() == "OCT") {
        datePeriodStart = new Date(`${body.year}-09-30T00:00:00.000Z`);
        datePeriodEnd = new Date(`${body.year}-09-30T00:00:00.000Z`);
      }
      datePeriodStart = new Date(
        new Date(datePeriodStart.setDate(datePeriodStart.getDate() + 1)).setMonth(
          datePeriodStart.getMonth() - 6,
        ),
      );
      const specialPosition = item.positions.find(
        (position) => position.positionIsSelected === true,
      );
      const isSpecial = specialPosition ? specialPosition.isSpecial : null;

      return {
        profileId: item.current_holder.id,
        prefix: item.current_holder.prefix,
        rank: item.current_holder.rank,
        firstName: item.current_holder.firstName,
        lastName: item.current_holder.lastName,
        citizenId: item.current_holder.citizenId,
        posMasterNoPrefix: item.posMasterNoPrefix,
        posMasterNo: item.posMasterNo,
        posMasterNoSuffix: item.posMasterNoSuffix,
        orgShortName: orgShortName,
        position: item.current_holder.position,
        posType:
          item.current_holder.posType == null ? null : item.current_holder.posType.posTypeName,
        posLevel:
          item.current_holder.posLevel == null ? null : item.current_holder.posLevel.posLevelName,
        posExecutive: posExecutive,
        amount: amount ? amount : null,
        // revisionId: item.orgRevisionId,
        rootId: item.orgRootId,
        root: item.orgRoot?.orgRootName ? item.orgRoot.orgRootName : null,
        child1Id: item.orgChild1Id,
        child1: item.orgChild1?.orgChild1Name ? item.orgChild1.orgChild1Name : null,
        child2Id: item.orgChild2Id,
        child2: item.orgChild2?.orgChild2Name ? item.orgChild2.orgChild2Name : null,
        child3Id: item.orgChild3Id,
        child3: item.orgChild3?.orgChild3Name ? item.orgChild3.orgChild3Name : null,
        child4Id: item.orgChild4Id,
        child4: item.orgChild4?.orgChild4Name ? item.orgChild4.orgChild4Name : null,
        result: null,
        duration: null,
        isPunish:
          item.current_holder.profileDisciplines.filter(
            (x: any) =>
              new Date(
                `${new Date(x.date).getFullYear()}-${String(new Date(x.date).getMonth() + 1).padStart(2, "0")}-${String(new Date(x.date).getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
              ) >= datePeriodStart &&
              new Date(
                `${new Date(x.date).getFullYear()}-${String(new Date(x.date).getMonth() + 1).padStart(2, "0")}-${String(new Date(x.date).getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
              ) <= datePeriodEnd,
          ).length > 0
            ? true
            : false,
        isSuspension: item.current_holder.dateRetire == null ? false : true,
        isAbsent: false,
        isLeave: false,
        isRetired:
          item.current_holder.birthDate == null ||
            calculateRetireDate(item.current_holder.birthDate).getFullYear() != body.year
            ? false
            : true,
        isSpecial: isSpecial,
      };
    });

    return new HttpSuccess({ data: formattedData, total: total });
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม keycloak by revisionId
   *
   * @summary ข้อมูลทะเบียนประวัติตาม keycloak by revisionId (ADMIN)
   *
   */
  @Get("keycloak/position/{revisionId}")
  async getProfileByKeycloakByRevision(
    @Path() revisionId: string,
    @Request() request: RequestWithUser,
  ) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }

    const posMaster = await this.posMasterRepo.findOne({
      where: {
        current_holderId: profile.id,
        orgRevisionId: revisionId,
      },
    });
    const position = await this.positionRepository.findOne({
      relations: ["posExecutive"],
      where: {
        posMasterId: posMaster?.id,
      },
    });

    const _profile = {
      profileId: profile.id,
      prefix: profile.prefix,
      rank: profile.rank,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      isDirector: posMaster?.isDirector ?? null,
      isProbation: profile.isProbation,
      posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName,
      posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank,
      posLevelId: profile.posLevel == null ? null : profile.posLevel.id,
      posTypeName: profile.posType == null ? null : profile.posType.posTypeName,
      posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank,
      posTypeId: profile.posType == null ? null : profile.posType.id,
      posExecutiveName:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutiveName,
      posExecutivePriority:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutivePriority,
      posExecutiveId:
        position == null || position.posExecutive == null ? null : position.posExecutive.id,
      rootId:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRootId,
      rootDnaId:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.ancestorDNA,
      root:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgRoot.orgRootName,
      child1Id:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1Id,
      child1DnaId:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.ancestorDNA,
      child1:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild1
            .orgChild1Name,
      child2Id:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2Id,
      child2DnaId:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.ancestorDNA,
      child2:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild2
            .orgChild2Name,
      child3Id:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3Id,
      child3DnaId:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.ancestorDNA,
      child3:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild3
            .orgChild3Name,
      child4Id:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4Id,
      child4DnaId:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.ancestorDNA,
      child4:
        profile.current_holders == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId) == null ||
          profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4 == null
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == revisionId)?.orgChild4
            .orgChild4Name,
    };
    return new HttpSuccess(_profile);
  }

  /**
   * API ข้อมูลบุลคลที่มีอายุเกษียณราชการตามปี
   *
   * @summary ข้อมูลบุลคลที่มีอายุเกษียณราชการตามปี
   *
   */
  @Get("profileid/retire/{year}")
  async getProfileByRetireYear(@Path() year: number, @Request() req: RequestWithUser) {
    //await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", id); //ไม่แน่ใจOFFปิดไว้ก่อน
    const profiles = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .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")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      // calculate range: start = 2 Oct of (year-1), end = 1 Oct of year (inclusive)
      .where("profile.dateRetire BETWEEN :start AND :end", {
        start: `${year - 1}-10-01`,
        end: `${year}-09-30`,
      })
      .andWhere("profile.isLeave = :isLeave AND profile.isRetirement = :isRetirement", {
        isLeave: false,
        isRetirement: false,
      })
      .getMany();

    if (!profiles || profiles.length === 0) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลที่มีอายุเกษียณราชการในปีนี้");
    }

    // const orgRevisionActive = await this.orgRevisionRepo.findOne({
    //   where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    // });

    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }
    const formattedData = profiles.map((item) => {
      const posMaster =
        item.current_holders == null ||
          item.current_holders.length == 0 ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
          ? null
          : item.current_holders.find((x) => x.orgRevisionId == findRevision.id);
      const position =
        posMaster == null ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.positions == null ||
          item.current_holders?.find((x) => x.orgRevisionId == findRevision.id)?.positions.length ==
          0 ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true) == null
          ? null
          : item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true);
      const posExecutive =
        position == null ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
          null ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
            ?.posExecutiveName == null
          ? null
          : item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
            .posExecutiveName;

      const positionExecutiveField =
        position == null ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)
            ?.positionExecutiveField == null ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)
            ?.positionExecutiveField == null
          ? null
          : item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)
            ?.positionExecutiveField;

      const positionArea =
        position == null ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.positionArea ==
          null ||
          item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.positionArea == null
          ? null
          : item.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.positionArea;

      const posExecutiveId =
        position == null || position.posExecutive == null ? null : position.posExecutive.id;

      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 root =
        item.current_holders == null ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot == null
          ? null
          : item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;
      const child1 =
        item.current_holders == null ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild1 == null
          ? null
          : item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild1;
      const child2 =
        item.current_holders == null ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild2 == null
          ? null
          : item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild2;
      const child3 =
        item.current_holders == null ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild3 == null
          ? null
          : item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild3;
      const child4 =
        item.current_holders == null ||
          item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild4 == null
          ? null
          : item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild4;

      let node = null;
      let nodeId = null;
      let nodeShortName = null;

      if (root) {
        node = 0;
        nodeId = root.id;
        nodeShortName = root.orgRootShortName;
      }
      if (child1) {
        node = 1;
        nodeId = child1.id;
        nodeShortName = child1.orgChild1ShortName;
      }
      if (child2) {
        node = 2;
        nodeId = child2.id;
        nodeShortName = child2.orgChild2ShortName;
      }
      if (child3) {
        node = 3;
        nodeId = child3.id;
        nodeShortName = child3.orgChild3ShortName;
      }
      if (child4) {
        node = 4;
        nodeId = child4.id;
        nodeShortName = child4.orgChild4ShortName;
      }

      return {
        profileId: item.id,
        prefix: item.prefix,
        rank: item.rank,
        firstName: item.firstName,
        lastName: item.lastName,
        citizenId: item.citizenId,
        root: root == null ? null : root.orgRootName,
        rootId: root == null ? null : root.id,
        rootShortName: root == null ? null : root.orgRootShortName,
        child1: child1 == null ? null : child1.orgChild1Name,
        child1Id: child1 == null ? null : child1.id,
        child1ShortName: child1 == null ? null : child1.orgChild1ShortName,
        child2: child2 == null ? null : child2.orgChild2Name,
        child2Id: child2 == null ? null : child2.id,
        child2ShortName: child2 == null ? null : child2.orgChild2ShortName,
        child3: child3 == null ? null : child3.orgChild3Name,
        child3Id: child3 == null ? null : child3.id,
        child3ShortName: child3 == null ? null : child3.orgChild3ShortName,
        child4: child4 == null ? null : child4.orgChild4Name,
        child4Id: child4 == null ? null : child4.id,
        child4ShortName: child4 == null ? null : child4.orgChild4ShortName,
        dateRetire: item.dateRetire,
        posLevelId: item.posLevel == null ? null : item.posLevel.id,
        posLevelName: item.posLevel == null ? null : item.posLevel.posLevelName,
        posLevelRank: item.posLevel == null ? null : item.posLevel.posLevelRank,
        posTypeId: item.posType == null ? null : item.posType.id,
        posTypeName: item.posType == null ? null : item.posType.posTypeName,
        posTypeRank: item.posType == null ? null : item.posType.posTypeRank,
        posNo: shortName,
        posMasterNo: posMaster == null ? null : posMaster.posMasterNo,
        position: item.position,
        posExecutiveId: posExecutiveId,
        posExecutiveName: posExecutive,
        positionExecutiveField: positionExecutiveField,
        positionArea: positionArea,
        node: node,
        nodeId: nodeId,
        nodeShortName: nodeShortName,
      };
    });
    return new HttpSuccess(formattedData);
  }

  /**
   * API อัพเดทถึงแก่กรรม
   *
   * @summary อัพเดทถึงแก่กรรม (ADMIN)
   *
   * @param {string} id  Id ทะเบียนประวัติ
   */
  @Post("leave/{id}")
  async updateLeaveUser(
    @Path() id: string,
    @Body()
    requestBody: { isLeave: boolean; leaveReason?: any; dateLeave?: any },
    @Request() request: RequestWithUser,
  ) {
    const profile = await this.profileRepo.findOne({
      where: { id: id },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        "current_holders.positions",
        "current_holders.positions.posExecutive",
      ],
    });
    if (!profile) throw new HttpError(HttpStatus.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;
    let position =
      profile.current_holders
        .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
    const dest_item = await this.salaryRepo.findOne({
      where: { profileId: id },
      order: { order: "DESC" },
    });
    const data: any = {
      order: dest_item == null ? 1 : dest_item.order + 1,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      profileId: profile.id,
      posNo: orgRevisionRef?.posMasterNo,
      positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
      positionType: profile.posType?.posTypeName,
      positionLevel: profile.posLevel?.posLevelName,
      amountSpecial: profile.amountSpecial,
      orgRoot: orgRootRef?.orgRootName,
      orgChild1: orgChild1Ref?.orgChild1Name,
      orgChild2: orgChild2Ref?.orgChild2Name,
      orgChild3: orgChild3Ref?.orgChild3Name,
      orgChild4: orgChild4Ref?.orgChild4Name,
      commandYear: new Date().getFullYear() + 543,
      // commandDateSign: new Date(),
      commandDateAffect: requestBody.dateLeave,
      commandCode: "16",
      commandName: "พ้นจากราชการ",
      posNoAbb: shortName,
      isEntry: false,
      positionName: profile.position,
      createdUserId: request.user.sub,
      createdFullName: request.user.name,
      lastUpdateUserId: request.user.sub,
      lastUpdateFullName: request.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
      remark: "ถึงแก่กรรม",
      isGovernment: false,
    };
    delete data.id;

    const history = new ProfileSalaryHistory();
    Object.assign(history, { ...data, id: undefined });
    data.dateGovernment = data.createdAt;
    await this.salaryRepo.save(data);
    history.profileSalaryId = data.id;
    await this.salaryHistoryRepo.save(history);

    const before = structuredClone(profile);
    let _null: any = null;
    profile.isLeave = requestBody.isLeave;
    profile.leaveReason = requestBody.leaveReason;
    profile.dateLeave = requestBody.dateLeave;
    profile.leaveDate = requestBody.dateLeave;
    profile.leaveType = "RETIRE_DECEASED";
    // profile.position = _null;
    // profile.posLevelId = _null;
    // profile.posTypeId = _null;
    if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
      const delUserKeycloak = await deleteUser(profile.keycloak);
      if (delUserKeycloak) {
        // Task #228
        // profile.keycloak = _null;
        profile.roleKeycloaks = [];
        profile.isActive = false;
        profile.isDelete = true;
      }
    }
    await this.profileRepo.save(profile, { data: request });
    setLogDataDiff(request, { before, after: profile });
    if (requestBody.isLeave == true) {
      if (orgRevisionRef) {
        await CreatePosMasterHistoryOfficer(orgRevisionRef.id, request, "DELETE");
      }
      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(" ");
    }
    return new HttpSuccess();
  }

  /**
   * API ค้นหาข้อมูลทะเบียนประวัติที่ยังไม่เชื่อม keycloak
   *
   * @summary  ค้นหาข้อมูลทะเบียนประวัติที่ยังไม่เชื่อม keycloak
   *
   */
  @Post("search-personal-no-keycloak")
  async getProfileBySearchKeywordNoKeyCloak(
    @Request() request: RequestWithUser,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Body()
    body: {
      fieldName: string;
      keyword?: string;
      system?: string;
    },
  ) {
    // comment ออกก่อนเพราะยังไม่ได้ใช้
    // // ค้นหารายชื่อถ้าไม่ส่ง system มาให้ default ตามทะเบียนประวัติ
    // let _system: string = "SYS_REGISTRY_OFFICER";
    // if (body.system) _system = body.system;
    // let _data = await new permission().PermissionOrgList(request, _system);
    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }

    let queryLike = "1=1";
    switch (body.fieldName) {
      case "citizenId":
        queryLike = "profile.citizenId LIKE :keyword";
        break;

      case "fullname":
      case "fullName":
        queryLike =
          "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) LIKE :keyword";
        break;

      case "firstname":
      case "firstName":
        queryLike = "profile.firstName LIKE :keyword";
        break;

      case "lastname":
      case "lastName":
        queryLike = "profile.lastName LIKE :keyword";
        break;

      default:
        queryLike = "1=1";
        break;
    }

    let query = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.posType", "posType")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .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(body.system ? "profile.isActive = :isActive" : "profile.isDelete = :isDelete", {
        isActive: false,
        isDelete: true,
      })
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(body.keyword ? queryLike : "1=1", { keyword: `%${body.keyword}%` });
        }),
      );

    const [findProfile, total] = await query
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    const mapDataProfile = await Promise.all(
      findProfile.map(async (item: Profile) => {
        const fullName = `${item.prefix} ${item.firstName} ${item.lastName}`;
        let shortName = null;
        let root = null;
        let posMasterNo = null;
        if (item.isLeave == false) {
          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;
          root =
            item.current_holders.length == 0 ||
              (item.current_holders.find((x) => x.orgRevisionId == findRevision.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot == null)
              ? null
              : item.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;
          root = root == null ? null : root.orgRootName;
          posMasterNo = item.current_holders?.find(
            (x) => x.orgRevisionId == findRevision.id,
          )?.posMasterNo;
        } else {
          const profileSalary = await this.salaryRepo
            .createQueryBuilder("s")
            .where("s.profileId = :profileId", { profileId: item.id })
            .andWhere("s.commandCode IN (:...codes)", {
              codes: [
                "0",
                "9",
                "1",
                "2",
                "3",
                "4",
                "8",
                "10",
                "11",
                "12",
                "13",
                "14",
                "15",
                "16",
                "20",
              ],
            })
            .orderBy("s.order", "DESC")
            .addOrderBy("s.createdAt", "DESC")
            .take(2)
            .getMany();
          if (profileSalary.length > 0) {
            shortName = item.isRetirement
              ? profileSalary.length > 1
                ? `${profileSalary[1]?.posNoAbb} ${profileSalary[1]?.posNo}`
                : `${profileSalary[0]?.posNoAbb} ${profileSalary[0]?.posNo}`
              : `${profileSalary[0]?.posNoAbb} ${profileSalary[0]?.posNo}`;
            posMasterNo = item.isRetirement
              ? profileSalary.length > 1
                ? profileSalary[1]?.posNo
                : profileSalary[0]?.posNo
              : profileSalary[0]?.posNo;
            root = item.isRetirement
              ? profileSalary.length > 1
                ? profileSalary[1]?.orgRoot
                : profileSalary[0]?.orgRoot
              : profileSalary[0]?.orgRoot;
          }
        }

        const latestProfileEducation = await this.profileEducationRepo.findOne({
          where: { profileId: item.id, isDeleted: false },
          order: { level: "ASC" },
        });

        return {
          id: item.id,
          prefix: item.prefix,
          rank: item.rank,
          firstName: item.firstName,
          lastName: item.lastName,
          position: item.position,
          citizenId: item.citizenId,
          email: item.email,
          phone: item.phone,
          name: fullName,
          birthDate: item.birthDate,
          positionLevel: item.posLevelId,
          positionLevelName: item.posLevel?.posLevelName,
          positionType: item.posTypeId,
          positionTypeName: item.posType?.posTypeName,
          posNo: shortName,
          organization: root,
          salary: item.amount,
          posMasterNo: posMasterNo ?? null,
          posTypeId: item.posTypeId,
          posTypeName: item.posType?.posTypeName,
          posLevelId: item.posLevelId,
          posLevelName: item.posLevel?.posLevelName,
          educationDegree:
            latestProfileEducation != null && latestProfileEducation.educationLevel != null
              ? latestProfileEducation.educationLevel
              : null,
        };
      }),
    );

    return new HttpSuccess({ data: mapDataProfile, total });
  }
  /**
   * API ค้นหาข้อมูลทะเบียนประวัติที่เกี่ยวข้องคำสั่ง
   *
   * @summary  ค้นหาข้อมูลทะเบียนประวัติที่เกี่ยวข้องคำสั่ง
   *
   */
  @Post("search/profile/command")
  async searchProfileBycommand(
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Body()
    body: {
      commandType: string;
      posno: string;
      year: number;
    },
  ) {
    const [profiles, total] = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.profileSalary", "profileSalary")
      .where("YEAR(profileSalary.date) = :year", { year: body.year })
      .where("profileSalary.commandNo LIKE :commandNo", {
        commandNo: `%${body.posno}%`,
      })
      //   .andWhere("profileSalary.commandType LIKE :commandType", {
      //     commandType: `${body.commandType}`,
      //   })
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .distinct(true) // Ensure unique profiles
      .getManyAndCount();
    const _profiles = profiles.map((_data) => ({
      id: _data.id,
      fullName: `${_data.prefix}${_data.firstName} ${_data.lastName}`,
      citizenId: _data.citizenId,
      posNo: _data.profileSalary.filter((x) => x.id != null)[0].commandNo,
      position: _data.profileSalary.filter((x) => x.id != null)[0].positionName,
    }));

    return new HttpSuccess({ data: _profiles, total });
  }
  /**
   *
   * @summary ปรับคนเป็นทดลองงาน  (ADMIN)
   *
   */
  @Get("probation/{id}")
  async getProbationProfile(@Path() id: string) {
    const profile = await this.profileRepo.findOne({
      where: { id },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    profile.isProbation = true;
    await this.profileRepo.save(profile);
    return new HttpSuccess(profile);
  }

  /**
   * API สร้างทะเบียนประวัติใหม่
   *
   * @summary ORG_065 - สร้างทะเบียนประวัติใหม่ (ADMIN) #XXX
   *
   */
  @Post("all/dump-db")
  async createProfileAllDump(
    @Request() request: RequestWithUser,
    @Body() body: CreateProfileAllFields,
  ) {
    const citizen = await this.profileRepo.findOne({
      where: { citizenId: body.citizenId },
      select: ["id"],
    });
    if (citizen) return new HttpSuccess(citizen.id);
    const _null: any = null;
    const profile: Profile = Object.assign(new Profile(), body);
    if (body && body.posLevelId) {
      const findPosLevel = await this.posLevelRepo.findOne({
        where: { posLevelName: body.posLevelId },
        select: ["id", "posLevelName"],
      });
      if (findPosLevel) {
        profile.posLevelId = findPosLevel.id;
      } else {
        profile.posLevelId = _null;
      }
    } else {
      profile.posLevelId = _null;
    }
    if (body && body.posTypeId) {
      const findPosType = await this.posTypeRepo.findOne({
        where: { posTypeName: body.posTypeId },
        select: ["id", "posTypeName"],
      });
      if (findPosType) {
        profile.posTypeId = findPosType.id;
      } else {
        profile.posTypeId = _null;
      }
    } else {
      profile.posTypeId = _null;
    }
    // if (body && body.prefix) {
    //   const findPrefix = await this.prefixRepo.findOne({
    //     where: { name: body.prefix },
    //     select: ["id", "name"],
    //   });
    //   if (findPrefix) {
    //     profile.prefix = findPrefix.id;
    //   } else {
    //     profile.prefix = _null;
    //   }
    // } else {
    //   profile.prefix = _null;
    // }
    //current
    if (body && body.currentProvinceId) {
      const findProvince = await this.provinceRepo.findOne({
        where: { name: body.currentProvinceId },
        select: ["id", "name"],
      });
      if (findProvince) {
        profile.currentProvinceId = findProvince.id;
      } else {
        profile.currentProvinceId = _null;
      }
    } else {
      profile.currentProvinceId = _null;
    }
    if (body && body.currentDistrictId) {
      const findDistrict = await this.districtRepo.findOne({
        where: { name: body.currentDistrictId },
        select: ["id", "name"],
      });
      if (findDistrict) {
        profile.currentDistrictId = findDistrict.id;
      } else {
        profile.currentDistrictId = _null;
      }
    } else {
      profile.currentDistrictId = _null;
    }
    if (body && body.currentSubDistrictId) {
      const findSubDistrict = await this.subDistrictRepo.findOne({
        where: { name: body.currentSubDistrictId },
        select: ["id", "name"],
      });
      if (findSubDistrict) {
        profile.currentSubDistrictId = findSubDistrict.id;
      } else {
        profile.currentSubDistrictId = _null;
      }
    } else {
      profile.currentSubDistrictId = _null;
    }
    //register
    if (body && body.registrationProvinceId) {
      const findProvince_regis = await this.provinceRepo.findOne({
        where: { name: body.registrationProvinceId },
        select: ["id", "name"],
      });
      if (findProvince_regis) {
        profile.registrationProvinceId = findProvince_regis.id;
      } else {
        profile.registrationProvinceId = _null;
      }
    } else {
      profile.registrationProvinceId = _null;
    }
    if (body && body.registrationDistrictId) {
      const findDistrict_regis = await this.districtRepo.findOne({
        where: { name: body.registrationDistrictId },
        select: ["id", "name"],
      });
      if (findDistrict_regis) {
        profile.registrationDistrictId = findDistrict_regis.id;
      } else {
        profile.registrationDistrictId = _null;
      }
    } else {
      profile.registrationDistrictId = _null;
    }
    if (body && body.registrationSubDistrictId) {
      const findSubDistrict_regis = await this.subDistrictRepo.findOne({
        where: { name: body.registrationSubDistrictId },
        select: ["id", "name"],
      });
      if (findSubDistrict_regis) {
        profile.registrationSubDistrictId = findSubDistrict_regis.id;
      } else {
        profile.registrationSubDistrictId = _null;
      }
    } else {
      profile.registrationSubDistrictId = _null;
    }

    profile.prefixMain = profile.prefix;
    profile.prefix = profile.rank && profile.rank.length > 0 ? profile.rank : profile.prefixMain;
    profile.createdUserId = request.user.sub;
    profile.createdFullName = request.user.name;
    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.createdAt = new Date();
    profile.lastUpdatedAt = new Date();
    // return new HttpSuccess(profile);
    await this.profileRepo.save(profile);
    return new HttpSuccess(profile.id);
  }
  /**
   *
   * @summary  (ADMIN)
   *
   */
  @Get("retireDate/mock")
  async calRetireDate() {
    const profile = await this.profileEmpRepo.find();
    const _null: any = null;
    const profiles = profile.map((_data) => ({
      ..._data,
      dateRetire: _data.birthDate == null ? _null : calculateRetireDate(_data.birthDate),
      dateRetireLaw: _data.birthDate == null ? _null : calculateRetireLaw(_data.birthDate),
    }));
    await this.profileEmpRepo.save(profiles);
    return new HttpSuccess();
  }
  /**
   *
   * @summary  (ADMIN)
   *
   */
  @Get("gensalary/latest")
  async calSalaryDate() {
    const profile = await this.profileRepo.find();
    const _null: any = null;
    const profiles = await Promise.all(
      profile.map(async (_data) => {
        const salary = await this.salaryRepo.findOne({
          where: {
            profileId: _data.id,
          },
          order: { order: "DESC" },
        });
        const type = await this.posTypeRepo.findOne({
          where: {
            posTypeName: salary?.positionType ?? "",
          },
        });
        const level = await this.posLevelRepo.findOne({
          where: {
            posLevelName: salary?.positionLevel ?? "",
          },
        });
        return {
          ..._data,
          position: salary?.positionName ?? _null,
          posLevelId: level?.id ?? _null,
          posTypeId: type?.id ?? _null,
        };
      }),
    );
    await this.profileRepo.save(profiles);
    return new HttpSuccess();
  }
  /**
   *
   * @summary  (ADMIN)
   *
   */
  @Get("deleteprofile/all")
  async deleteHistoryLatest() {
    const [profile, total] = await this.profileRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("profile.next_holders", "next_holders")
      .skip(1)
      .take(50)
      .getManyAndCount();

    return new HttpSuccess();
  }

  /**
   * API แก้ไขเบอร์โทรศัพท์
   *
   * @summary แก้ไขเบอร์โทรศัพท์ (USER)
   *
   */
  @Put("updatePhoneNumber/user")
  async updatePhoneNumber(
    @Request() request: RequestWithUser,
    @Body()
    body: {
      phone: string;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: {
        posLevel: true,
        posType: true,
      },
      where: { keycloak: request.user.sub },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    const history = new ProfileHistory();

    Object.assign(profile, body);
    Object.assign(history, { ...profile, id: undefined });

    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.lastUpdatedAt = new Date();
    history.lastUpdateUserId = request.user.sub;
    history.lastUpdateFullName = request.user.name;
    history.createdUserId = request.user.sub;
    history.createdFullName = request.user.name;
    history.createdAt = new Date();
    history.lastUpdatedAt = new Date();

    await Promise.all([
      this.profileRepo.save(profile, { data: request }),
      this.profileHistoryRepo.save(history, { data: request }),
    ]);
    return new HttpSuccess();
  }

  /**
   * API แก้ไขอีเมล
   *
   * @summary แก้ไขอีเมล (USER)
   *
   */
  @Put("updateEmail/user")
  async updateEmail(
    @Request() request: RequestWithUser,
    @Body()
    body: {
      email: string;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: {
        posLevel: true,
        posType: true,
      },
      where: { keycloak: request.user.sub },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    const history = new ProfileHistory();

    Object.assign(profile, body);
    Object.assign(history, { ...profile, id: undefined });

    profile.statusEmail = "NOT_VERIFIED";
    profile.lastUpdateUserId = request.user.sub;
    profile.lastUpdateFullName = request.user.name;
    profile.lastUpdatedAt = new Date();
    history.lastUpdateUserId = request.user.sub;
    history.lastUpdateFullName = request.user.name;
    history.createdUserId = request.user.sub;
    history.createdFullName = request.user.name;
    history.createdAt = new Date();
    history.lastUpdatedAt = new Date();

    await Promise.all([
      this.profileRepo.save(profile, { data: request }),
      this.profileHistoryRepo.save(history, { data: request }),
    ]);
    const verifyemailBody = {
      profileId: profile.id,
      email: body.email,
      subject: "ยืนยันอีเมล",
    };
    this.sendVerifyEmail(request, verifyemailBody);
    return new HttpSuccess();
  }

  @Post("noti-admin")
  public async notiAllAdmin(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      subject: string;
      body: string;
    },
  ) {
    if (!req.user.role.includes("SUPER_ADMIN"))
      throw new HttpError(HttpStatus.FORBIDDEN, "ไม่มีสิทธิ์ส่งข้อความ");
    const profileNoti = await this.profileRepo.find({
      where: {
        roleKeycloaks: {
          name: "ADMIN",
        },
      },
    });
    let _profileNoti = profileNoti.map((x) => ({
      receiverUserId: x.id,
      notiLink: "",
    }));
    await new CallAPI()
      .PostData(req, "/placement/noti/profiles", {
        subject: body.subject,
        body: body.body,
        receiverUserIds: _profileNoti,
        payload: "", //แนบไฟล์
        isSendMail: true,
        isSendInbox: true,
        isSendNotification: true,
      })
      .catch((error) => {
        console.error("Error calling API:", error);
      });

    return new HttpSuccess();
  }

  /**
   * API ข้อมูลทะเบียนประวัติตาม keycloak สำหรับเช็คอินเข้าใช้งานระบบ
   *
   * @summary ข้อมูลทะเบียนประวัติตาม keycloak สำหรับเช็คอินเข้าใช้งานระบบ
   *
   */
  @Get("keycloak/position-checkin")
  async getProfileByKeycloakForCheckin(@Request() request: { user: Record<string, any> }) {
    const userSub = request.user.sub;
    const relations = [
      "current_holders",
      "current_holders.orgRoot",
      "current_holders.orgChild1",
      "current_holders.orgChild2",
      "current_holders.orgChild3",
      "current_holders.orgChild4",
    ];

    const [officerProfile, orgRevisionPublish] = await Promise.all([
      this.profileRepo.findOne({
        where: { keycloak: userSub },
        relations,
      }),
      this.orgRevisionRepo.findOne({
        where: {
          orgRevisionIsDraft: false,
          orgRevisionIsCurrent: true,
        },
      }),
    ]);

    if (!orgRevisionPublish) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
    }

    let profile: any = officerProfile;
    let profileType: "OFFICER" | "EMPLOYEE" = "OFFICER";

    if (!profile) {
      profile = await this.profileEmpRepo.findOne({
        where: { keycloak: userSub },
        relations,
      });
      profileType = "EMPLOYEE";
    }

    if (!profile) {
      if (request.user.role.includes("SUPER_ADMIN")) {
        return new HttpSuccess(null);
      }
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }

    const currentHolder =
      profile.current_holders?.find((x: any) => x.orgRevisionId == orgRevisionPublish.id) ?? null;
    const root = currentHolder?.orgRoot ?? null;
    const child1 = currentHolder?.orgChild1 ?? null;
    const child2 = currentHolder?.orgChild2 ?? null;
    const child3 = currentHolder?.orgChild3 ?? null;
    const child4 = currentHolder?.orgChild4 ?? null;

    const _profile: any = {
      profileId: profile.id,
      keycloak: profile.keycloak,
      prefix: profile.prefix,
      avatar: profile.avatar,
      profileType,
      isProbation: profile.isProbation,
      avatarName: profile.avatarName,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      root: root?.orgRootName ?? null,
      child1: child1?.orgChild1Name ?? null,
      child2: child2?.orgChild2Name ?? null,
      child3: child3?.orgChild3Name ?? null,
      child4: child4?.orgChild4Name ?? null,
      privacyCheckin: profile.privacyCheckin,
      privacyUser: profile.privacyUser,
      privacyMgt: profile.privacyMgt,
      ...(profileType !== "OFFICER" ? { type: profile.employeeClass } : {}),
    };

    return new HttpSuccess(_profile);
  }
}
