import {
  Body,
  Controller,
  Get,
  Path,
  Post,
  Put,
  Request,
  Response,
  Route,
  Security,
  SuccessResponse,
  Tags,
} from "tsoa";
import { And, Between, Brackets, In, IsNull, LessThanOrEqual, Not } from "typeorm";
import { AppDataSource } from "../database/data-source";
import { Assign } from "../entities/Assign";
import { EmployeePosDict } from "../entities/EmployeePosDict";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { OrgChild1 } from "../entities/OrgChild1";
import { OrgChild2 } from "../entities/OrgChild2";
import { OrgChild3 } from "../entities/OrgChild3";
import { OrgChild4 } from "../entities/OrgChild4";
import { OrgRevision } from "../entities/OrgRevision";
import { OrgRoot } from "../entities/OrgRoot";
import { Position } from "../entities/Position";
import { PosMaster } from "../entities/PosMaster";
import { PosMasterHistory } from "../entities/PosMasterHistory";
import { PosMasterEmployeeHistory } from "../entities/PosMasterEmployeeHistory";
import { Profile } from "../entities/Profile";
import { ProfileEducation } from "../entities/ProfileEducation";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import { CreateProfileInsignia, ProfileInsignia } from "../entities/ProfileInsignia";
import { ProfileSalary } from "../entities/ProfileSalary";
import Extension from "../interfaces/extension";
import HttpError from "../interfaces/http-error";
import HttpStatus from "../interfaces/http-status";
import HttpSuccess from "../interfaces/http-success";
import { calculateRetireLaw } from "../interfaces/utils";
import { RequestWithUser } from "../middlewares/user";
@Route("api/v1/org/dotnet")
@Tags("Dotnet")
// @Security("bearerAuth")
@Response(
  HttpStatus.INTERNAL_SERVER_ERROR,
  "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
@SuccessResponse(HttpStatus.OK, "สำเร็จ")
export class OrganizationDotnetController extends Controller {
  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 orgRevisionRepo = AppDataSource.getRepository(OrgRevision);
  private profileRepo = AppDataSource.getRepository(Profile);
  private profileEmpRepo = AppDataSource.getRepository(ProfileEmployee);
  private positionRepository = AppDataSource.getRepository(Position);
  private posMasterRepository = AppDataSource.getRepository(PosMaster);
  private posMasterHistoryRepository = AppDataSource.getRepository(PosMasterHistory);
  private posMasterEmployeeHistoryRepository = AppDataSource.getRepository(PosMasterEmployeeHistory);
  private empPosMasterRepository = AppDataSource.getRepository(EmployeePosMaster);
  private insigniaRepo = AppDataSource.getRepository(ProfileInsignia);
  private employeePosDictRepository = AppDataSource.getRepository(EmployeePosDict);
  private assignRepository = AppDataSource.getRepository(Assign);
  private salaryRepo = AppDataSource.getRepository(ProfileSalary);
  private educationRepo = AppDataSource.getRepository(ProfileEducation);

  /**
   * ทำไว้ให้ service อื่นๆ ภายในระบบ call มาตรวจสอบเลขบัตรประจำตัวประชาชน
   *
   * @summary API ตรวจสอบเช็คเลขบัตรประจำตัวประชาชน
   *
   */
  @Post("check-citizen")
  @Security("internalAuth")
  public async CheckCitizen(
    @Body()
    body: {
      citizenId: string;
    },
  ) {
    let citizen = Extension.CheckCitizen(body.citizenId);
    return new HttpSuccess(citizen);
  }

  /**
   * 1. API Search Profile
   *
   * @summary 1. API Search Profile
   *
   */
  @Post("search")
  @Security("internalAuth")
  public async SearchProfile(
    @Body()
    body: {
      citizenId?: string | null;
      firstName?: string | null;
      lastName?: string | null;
      role?: string | null;
      nodeId?: string | null;
      node?: number | null;
      page: number;
      pageSize: number;
      selectedNodeId?: string | null;
      selectedNode?: number | null;
    },
  ) {
    let condition = "1=1";
    let conditionParams = {};

    let selectedNodeCondition = "1=1";
    let selectedNodeConditionParams = {};

    if (body.selectedNodeId && body.selectedNode != null) {
      switch (body.selectedNode) {
        case 0:
          selectedNodeCondition = "orgRoot.ancestorDNA = :selectedNodeId";
          break;
        case 1:
          selectedNodeCondition = "orgChild1.ancestorDNA = :selectedNodeId";
          break;
        case 2:
          selectedNodeCondition = "orgChild2.ancestorDNA = :selectedNodeId";
          break;
        case 3:
          selectedNodeCondition = "orgChild3.ancestorDNA = :selectedNodeId";
          break;
        case 4:
          selectedNodeCondition = "orgChild4.ancestorDNA = :selectedNodeId";
          break;
        default:
          selectedNodeCondition = "1=1";
          break;
      }
      selectedNodeConditionParams = { selectedNodeId: body.selectedNodeId };
    }

    if (body.role === "CHILD") {
      switch (body.node) {
        case 0:
          condition = "orgRoot.ancestorDNA = :nodeId";
          break;
        case 1:
          condition = "orgChild1.ancestorDNA = :nodeId";
          break;
        case 2:
          condition = "orgChild2.ancestorDNA = :nodeId";
          break;
        case 3:
          condition = "orgChild3.ancestorDNA = :nodeId";
          break;
        case 4:
          condition = "orgChild4.ancestorDNA = :nodeId";
          break;
        default:
          condition = "1=1";
          break;
      }
      conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "BROTHER") {
      switch (body.node) {
        case 0:
          condition = "orgRoot.ancestorDNA = :nodeId";
          break;
        case 1:
          condition = "orgRoot.ancestorDNA = :nodeId";
          break;
        case 2:
          condition = "orgChild1.ancestorDNA = :nodeId";
          break;
        case 3:
          condition = "orgChild2.ancestorDNA = :nodeId";
          break;
        case 4:
          condition = "orgChild3.ancestorDNA = :nodeId";
          break;
        default:
          condition = "1=1";
          break;
      }
      conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "ROOT") {
      condition = "orgRoot.ancestorDNA = :nodeId";
      conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "PARENT") {
      // condition = "orgRoot.ancestorDNA = :nodeId AND current_holders.orgChild1 IS NOT NULL";
      // conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          condition = "orgRoot.ancestorDNA = :nodeId AND current_holders.orgChild1 IS NULL";
          break;
        case 1:
          condition = "orgChild1.ancestorDNA = :nodeId AND current_holders.orgChild2 IS NULL";
          break;
        case 2:
          condition = "orgChild2.ancestorDNA = :nodeId AND current_holders.orgChild3 IS NULL";
          break;
        case 3:
          condition = "orgChild3.ancestorDNA = :nodeId AND current_holders.orgChild4 IS NULL";
          break;
        case 4:
          condition = "orgChild4.ancestorDNA = :nodeId";
          break;
        default:
          condition = "1=1";
          break;
      }
      conditionParams = { nodeId: body.nodeId };
    }

    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }
    const [profiles, total] = 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.orgRevision", "orgRevision")
      .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: findRevision.id })
      .andWhere(
        new Brackets((qb) => {
          if (body.citizenId) {
            qb.andWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` });
          }
          if (body.firstName) {
            qb.andWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` });
          }
          if (body.lastName) {
            qb.andWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` });
          }
        }),
      )
      .andWhere(condition, conditionParams)
      .andWhere(selectedNodeCondition, selectedNodeConditionParams)

      .select([
        "profile.id",
        "profile.citizenId",
        "profile.prefix",
        "profile.firstName",
        "profile.lastName",
        "current_holders",
        "orgRevision",
        "orgRoot",
        "orgChild1",
        "orgChild2",
        "orgChild3",
        "orgChild4",
      ])
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();

    const mapProfiles = profiles.map((profile) => ({
      id: profile.id,
      citizenId: profile.citizenId,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      rootDnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgRoot?.ancestorDNA ?? null,
      child1DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild1?.ancestorDNA ?? null,
      child2DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild2?.ancestorDNA ?? null,
      child3DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild3?.ancestorDNA ?? null,
      child4DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild4?.ancestorDNA ?? null,
    }));

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

  /**
   * 6.	Search Employee
   *
   * @summary 6. Search Employee
   *
   */
  @Post("search-employee")
  @Security("internalAuth")
  public async SearchProfileEmployee(
    @Body()
    body: {
      citizenId?: string | null;
      firstName?: string | null;
      lastName?: string | null;
      role?: string | null;
      nodeId?: string | null;
      node?: number | null;
      page: number;
      pageSize: number;
    },
  ) {
    let condition = "1=1";
    let conditionParams = {};
    if (body.role === "CHILD") {
      switch (body.node) {
        case 0:
          condition = "orgRoot.ancestorDNA = :nodeId";
          break;
        case 1:
          condition = "orgChild1.ancestorDNA = :nodeId";
          break;
        case 2:
          condition = "orgChild2.ancestorDNA = :nodeId";
          break;
        case 3:
          condition = "orgChild3.ancestorDNA = :nodeId";
          break;
        case 4:
          condition = "orgChild4.ancestorDNA = :nodeId";
          break;
        default:
          condition = "1=1";
          break;
      }
      conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "BROTHER") {
      switch (body.node) {
        case 0:
          condition = "orgRoot.ancestorDNA = :nodeId";
          break;
        case 1:
          condition = "orgRoot.ancestorDNA = :nodeId";
          break;
        case 2:
          condition = "orgChild1.ancestorDNA = :nodeId";
          break;
        case 3:
          condition = "orgChild2.ancestorDNA = :nodeId";
          break;
        case 4:
          condition = "orgChild3.ancestorDNA = :nodeId";
          break;
        default:
          condition = "1=1";
          break;
      }
      conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "ROOT") {
      condition = "orgRoot.ancestorDNA = :nodeId";
      conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "PARENT") {
      // condition = "orgRoot.ancestorDNA = :nodeId AND current_holders.orgChild1 IS NOT NULL";
      // conditionParams = { nodeId: body.nodeId };
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          condition = "orgRoot.ancestorDNA = :nodeId AND current_holders.orgChild1 IS NULL";
          break;
        case 1:
          condition = "orgChild1.ancestorDNA = :nodeId AND current_holders.orgChild2 IS NULL";
          break;
        case 2:
          condition = "orgChild2.ancestorDNA = :nodeId AND current_holders.orgChild3 IS NULL";
          break;
        case 3:
          condition = "orgChild3.ancestorDNA = :nodeId AND current_holders.orgChild4 IS NULL";
          break;
        case 4:
          condition = "orgChild4.ancestorDNA = :nodeId";
          break;
        default:
          condition = "1=1";
          break;
      }
      conditionParams = { nodeId: body.nodeId };
    }

    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
    }
    const [profileEmp, total] = await this.profileEmpRepo
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.posLevel", "posLevel")
      .leftJoinAndSelect("profile.posType", "posType")
      .leftJoinAndSelect("profile.profileSalary", "profileSalary")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.orgRoot", "orgRoot")
      .leftJoinAndSelect("current_holders.orgRevision", "orgRevision")
      .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: findRevision.id })
      .andWhere(
        new Brackets((qb) => {
          if (body.citizenId) {
            qb.andWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` });
          }
          if (body.firstName) {
            qb.andWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` });
          }
          if (body.lastName) {
            qb.andWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` });
          }
        }),
      )
      .andWhere(condition, conditionParams)
      .select([
        "profile.id",
        "profile.citizenId",
        "profile.prefix",
        "profile.firstName",
        "profile.lastName",
        "current_holders",
        "orgRevision",
        "orgRoot",
        "orgChild1",
        "orgChild2",
        "orgChild3",
        "orgChild4",
      ])
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();

    const mapProfiles = profileEmp.map((profile) => ({
      id: profile.id,
      citizenId: profile.citizenId,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      rootDnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgRoot?.ancestorDNA ?? null,
      child1DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild1?.ancestorDNA ?? null,
      child2DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild2?.ancestorDNA ?? null,
      child3DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild3?.ancestorDNA ?? null,
      child4DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.id === findRevision.id && x.orgRevision?.orgRevisionIsDraft === false,
        )?.orgChild4?.ancestorDNA ?? null,
    }));

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

  /**
   * 2.	API ข้อมูลหน่วยงานตามโครงสร้าง
   *
   * @summary 2. API ข้อมูลหน่วยงานตามโครงสร้าง
   *
   * @param {string} id  Id หน่วยงาน
   */
  @Get("org/{id}")
  @Security("internalAuth")
  async GetOrganizationById(@Path() id: string) {
    const orgRoot = await this.orgRootRepo.findOne({
      where: { id: id },
    });
    if (!orgRoot) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    return new HttpSuccess(orgRoot);
  }

  @Get("agency/{id}")
  @Security("internalAuth")
  async GetOrgAgencyById(@Path() id: string) {
    const orgRoot = await this.orgRootRepo.findOne({
      where: { id: id },
    });
    if (!orgRoot) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    return new HttpSuccess(orgRoot);
  }

  @Get("go-agency/{id}")
  @Security("internalAuth")
  async GetOrgGoAgencyById(@Path() id: string) {
    const orgRoot = await this.orgRootRepo.findOne({
      where: { id: id },
    });
    if (!orgRoot) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    return new HttpSuccess(orgRoot);
  }

  /**
   * API Get ProfileId
   *
   * @summary Get ProfileId
   *
   */
  @Get("get-profileId")
  @Security("bearerAuth")
  async getProfileInbox(@Request() request: { user: Record<string, any> }) {
    let profile: any;
    //OFF
    profile = await this.profileRepo.findOne({
      where: { keycloak: request.user.sub },
      select: { id: true },
    });
    //EMP
    if (!profile) {
      profile = await this.profileEmpRepo.findOne({
        where: { keycloak: request.user.sub },
        select: { id: true },
      });
      if (!profile) {
        if (request.user.role.includes("SUPER_ADMIN")) {
          return new HttpSuccess(null);
        } else {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
        }
      }
    }
    const result = {
      profileId: profile ? profile.id : null,
    };
    return new HttpSuccess(result);
  }

  /**
   * 3.	API Get Profile จาก keycloak id
   *
   * @summary 3. API Get Profile จาก keycloak id
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("keycloak-old/{keycloakId}")
  @Security("internalAuth")
  async GetProfileByKeycloakIdAsyncOld(@Path() keycloakId: string) {
    const profile = await this.profileRepo.findOne({
      relations: [
        "registrationProvince",
        "registrationDistrict",
        "registrationSubDistrict",
        "currentProvince",
        "currentDistrict",
        "currentSubDistrict",
        "posLevel",
        "posType",
        "profileSalary",
        "profileInsignias",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { keycloak: keycloakId },
      order: {
        profileSalary: {
          commandDateAffect: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });
    let fullname = "";
    let commanderPositionName = "";
    let commanderId = "";
    let commanderKeycloak = "";

    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        relations: [
          "registrationProvince",
          "registrationDistrict",
          "registrationSubDistrict",
          "currentProvince",
          "currentDistrict",
          "currentSubDistrict",
          "posLevel",
          "posType",
          "profileSalary",
          "profileInsignias",
          "current_holders",
          "current_holders.orgRevision",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
        where: { keycloak: keycloakId },
        order: {
          profileSalary: {
            commandDateAffect: "DESC",
          },
          profileInsignias: {
            receiveDate: "DESC",
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

      const org = {
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.id ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.id ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.id ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.id ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.id ?? null,
      };
      let pos = await this.empPosMasterRepository.findOne({
        relations: ["current_holder"],
        where: {
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
          isDirector: true,
          orgRootId: org?.root ?? "",
          orgChild1Id: org?.child1 ?? "",
          orgChild2Id: org?.child2 ?? "",
          orgChild3Id: org?.child3 ?? "",
          orgChild4Id: org?.child4 ?? "",
        },
      });

      if (pos) {
        fullname =
          pos.current_holder.prefix +
          pos.current_holder.firstName +
          " " +
          pos.current_holder.lastName;
        commanderPositionName = pos.current_holder?.position;
        commanderId = pos.current_holder?.id;
        commanderKeycloak = pos.current_holder?.keycloak;
      } else {
        let pos = await this.empPosMasterRepository.findOne({
          relations: ["current_holder"],
          where: {
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
            isDirector: true,
            orgRootId: org?.root ?? "",
            orgChild1Id: org?.child1 ?? "",
            orgChild2Id: org?.child2 ?? "",
            orgChild3Id: org?.child3 ?? "",
            orgChild4Id: IsNull(),
          },
        });
        if (pos) {
          fullname =
            pos.current_holder.prefix +
            pos.current_holder.firstName +
            " " +
            pos.current_holder.lastName;
          commanderPositionName = pos.current_holder?.position;
          commanderId = pos.current_holder?.id;
          commanderKeycloak = pos.current_holder?.keycloak;
        } else {
          let pos = await this.empPosMasterRepository.findOne({
            relations: ["current_holder"],
            where: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
              isDirector: true,
              orgRootId: org?.root ?? "",
              orgChild1Id: org?.child1 ?? "",
              orgChild2Id: org?.child2 ?? "",
              orgChild3Id: IsNull(),
              orgChild4Id: IsNull(),
            },
          });
          if (pos) {
            fullname =
              pos.current_holder.prefix +
              pos.current_holder.firstName +
              " " +
              pos.current_holder.lastName;
            commanderPositionName = pos.current_holder?.position;
            commanderId = pos.current_holder?.id;
            commanderKeycloak = pos.current_holder?.keycloak;
          } else {
            let pos = await this.empPosMasterRepository.findOne({
              relations: ["current_holder"],
              where: {
                orgRevision: {
                  orgRevisionIsCurrent: true,
                  orgRevisionIsDraft: false,
                },
                isDirector: true,
                orgRootId: org?.root ?? "",
                orgChild1Id: org?.child1 ?? "",
                orgChild2Id: IsNull(),
                orgChild3Id: IsNull(),
                orgChild4Id: IsNull(),
              },
            });
            if (pos) {
              fullname =
                pos.current_holder.prefix +
                pos.current_holder.firstName +
                " " +
                pos.current_holder.lastName;
              commanderPositionName = pos.current_holder?.position;
              commanderId = pos.current_holder?.id;
              commanderKeycloak = pos.current_holder?.keycloak;
            } else {
              let pos = await this.empPosMasterRepository.findOne({
                relations: ["current_holder"],
                where: {
                  orgRevision: {
                    orgRevisionIsCurrent: true,
                    orgRevisionIsDraft: false,
                  },
                  isDirector: true,
                  orgRootId: org?.root ?? "",
                  orgChild1Id: IsNull(),
                  orgChild2Id: IsNull(),
                  orgChild3Id: IsNull(),
                  orgChild4Id: IsNull(),
                },
              });
              if (pos) {
                fullname =
                  pos.current_holder.prefix +
                  pos.current_holder.firstName +
                  " " +
                  pos.current_holder.lastName;
                commanderPositionName = pos.current_holder?.position;
                commanderId = pos.current_holder?.id;
                commanderKeycloak = pos.current_holder?.keycloak;
              } else {
                fullname = "";
                commanderPositionName = "";
                commanderId = "";
                commanderKeycloak = "";
              }
            }
          }
        }
      }
      let positionLeaveName =
        profile.posType == null && profile.posLevel == null
          ? ""
          : `${profile.posType?.posTypeShortName ?? ""} ${profile.posLevel?.posLevelName ?? ""}`;

      const _profileCurrent = profile?.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );
      let oc = "";
      if (_profileCurrent != null) {
        if (_profileCurrent.orgChild1Id === null) {
          oc = _profileCurrent.orgRoot?.orgRootName;
        } else if (_profileCurrent.orgChild2Id === null) {
          oc = `${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
        } else if (_profileCurrent.orgChild3Id === null) {
          oc = `${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
        } else if (_profileCurrent.orgChild4Id === null) {
          oc = `${_profileCurrent.orgChild3?.orgChild3Name} ${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
        } else {
          oc = `${_profileCurrent.orgChild4?.orgChild4Name}`;
        }
      }
      const mapProfile = {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        position: profile.position,
        posLevelId: profile.posLevelId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender,
        relationship: profile.relationship,
        religion: profile.religion,
        bloodGroup: profile.bloodGroup,
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationProvince: profile.registrationProvince?.name ?? null,
        registrationDistrict: profile.registrationDistrict?.name ?? null,
        registrationSubDistrict: profile.registrationSubDistrict?.name ?? null,
        registrationZipCode: profile.registrationZipCode,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentDistrictId: profile.currentDistrictId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentProvince: profile.currentProvince?.name ?? null,
        currentDistrict: profile.currentDistrict?.name ?? null,
        currentSubDistrict: profile.currentSubDistrict?.name ?? null,
        currentZipCode: profile.currentZipCode,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.orgChild1Name ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.orgChild2Name ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.orgChild3Name ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.orgChild4Name ?? null,
        rootId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRootId ?? null,
        child1Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1Id ?? null,
        child2Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2Id ?? null,
        child3Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3Id ?? null,
        child4Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4Id ?? null,
        rootDnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.ancestorDNA ?? null,
        child1DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.ancestorDNA ?? null,
        child2DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.ancestorDNA ?? null,
        child3DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.ancestorDNA ?? null,
        child4DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.ancestorDNA ?? null,
        commander: fullname,
        commanderPositionName,
        commanderId,
        commanderKeycloak,
        posLevel:
          (profile.posType == null || profile.posType?.posTypeShortName == null
            ? ""
            : profile.posType?.posTypeShortName + " ") + (profile.posLevel?.posLevelName ?? ""),
        posType: profile.posType?.posTypeName ?? null,
        profileSalary: profile.profileSalary.length > 0 ? profile.profileSalary[0] : null,
        profileInsignia: profile.profileInsignias.length > 0 ? profile.profileInsignias[0] : null,
        profileType: "EMPLOYEE",
        positionLeaveName: positionLeaveName,
        oc: oc,
      };

      return new HttpSuccess(mapProfile);
    }

    const org = {
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.id ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.id ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.id ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.id ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.id ?? null,
    };

    let pos = await this.posMasterRepository.findOne({
      relations: ["current_holder"],
      where: {
        orgRevision: {
          orgRevisionIsCurrent: true,
          orgRevisionIsDraft: false,
        },
        isDirector: true,
        orgRootId: org?.root ?? "",
        orgChild1Id: org?.child1 ?? "",
        orgChild2Id: org?.child2 ?? "",
        orgChild3Id: org?.child3 ?? "",
        orgChild4Id: org?.child4 ?? "",
        current_holderId: Not(IsNull()),
      },
    });

    if (pos) {
      fullname =
        pos.current_holder.prefix +
        pos.current_holder.firstName +
        " " +
        pos.current_holder.lastName;
      commanderPositionName = pos.current_holder?.position;
      commanderId = pos.current_holder?.id;
      commanderKeycloak = pos.current_holder?.keycloak;
    } else {
      let pos = await this.posMasterRepository.findOne({
        relations: ["current_holder"],
        where: {
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
          isDirector: true,
          orgRootId: org?.root ?? "",
          orgChild1Id: org?.child1 ?? "",
          orgChild2Id: org?.child2 ?? "",
          orgChild3Id: org?.child3 ?? "",
          orgChild4Id: IsNull(),
          current_holderId: Not(IsNull()),
        },
      });
      if (pos) {
        fullname =
          pos.current_holder.prefix +
          pos.current_holder.firstName +
          " " +
          pos.current_holder.lastName;
        commanderPositionName = pos.current_holder?.position;
        commanderId = pos.current_holder?.id;
        commanderKeycloak = pos.current_holder?.keycloak;
      } else {
        let pos = await this.posMasterRepository.findOne({
          relations: ["current_holder"],
          where: {
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
            isDirector: true,
            orgRootId: org?.root ?? "",
            orgChild1Id: org?.child1 ?? "",
            orgChild2Id: org?.child2 ?? "",
            orgChild3Id: IsNull(),
            orgChild4Id: IsNull(),
            current_holderId: Not(IsNull()),
          },
        });
        if (pos) {
          fullname =
            pos.current_holder.prefix +
            pos.current_holder.firstName +
            " " +
            pos.current_holder.lastName;
          commanderPositionName = pos.current_holder?.position;
          commanderId = pos.current_holder?.id;
          commanderKeycloak = pos.current_holder?.keycloak;
        } else {
          let pos = await this.posMasterRepository.findOne({
            relations: ["current_holder"],
            where: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
              isDirector: true,
              orgRootId: org?.root ?? "",
              orgChild1Id: org?.child1 ?? "",
              orgChild2Id: IsNull(),
              orgChild3Id: IsNull(),
              orgChild4Id: IsNull(),
              current_holderId: Not(IsNull()),
            },
          });
          if (pos) {
            fullname =
              pos.current_holder.prefix +
              pos.current_holder.firstName +
              " " +
              pos.current_holder.lastName;
            commanderPositionName = pos.current_holder?.position;
            commanderId = pos.current_holder?.id;
            commanderKeycloak = pos.current_holder?.keycloak;
          } else {
            let pos = await this.posMasterRepository.findOne({
              relations: ["current_holder"],
              where: {
                orgRevision: {
                  orgRevisionIsCurrent: true,
                  orgRevisionIsDraft: false,
                },
                isDirector: true,
                orgRootId: org?.root ?? "",
                orgChild1Id: IsNull(),
                orgChild2Id: IsNull(),
                orgChild3Id: IsNull(),
                orgChild4Id: IsNull(),
                current_holderId: Not(IsNull()),
              },
            });
            if (pos) {
              fullname =
                pos.current_holder.prefix +
                pos.current_holder.firstName +
                " " +
                pos.current_holder.lastName;
              commanderPositionName = pos.current_holder?.position;
              commanderId = pos.current_holder?.id;
              commanderKeycloak = pos.current_holder?.keycloak;
            } else {
              fullname = "";
              commanderPositionName = "";
              commanderId = "";
              commanderKeycloak = "";
            }
          }
        }
      }
    }

    let positionLeaveName =
      profile.posType != null &&
      profile.posLevel != null &&
      (profile.posType.posTypeName == "บริหาร" || profile.posType.posTypeName == "อำนวยการ")
        ? `${profile.posType?.posTypeName ?? ""}${profile.posLevel?.posLevelName ?? ""}`
        : profile.posLevel?.posLevelName ?? null;
    const _profileCurrent = profile?.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );
    let oc = "";
    if (_profileCurrent != null) {
      if (_profileCurrent.orgChild1Id === null) {
        oc = _profileCurrent.orgRoot?.orgRootName;
      } else if (_profileCurrent.orgChild2Id === null) {
        oc = `${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
      } else if (_profileCurrent.orgChild3Id === null) {
        oc = `${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
      } else if (_profileCurrent.orgChild4Id === null) {
        oc = `${_profileCurrent.orgChild3?.orgChild3Name} ${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
      } else {
        oc = `${_profileCurrent.orgChild4?.orgChild4Name}`;
      }
    }
    const position = await this.positionRepository.findOne({
      where: {
        positionIsSelected: true,
        posMaster: {
          orgRevisionId: profile.current_holders.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRevisionId,
          current_holderId: profile.id,
        },
      },
      order: { createdAt: "DESC" },
      relations: {
        posExecutive: true,
      },
    });
    const mapProfile = {
      id: profile.id,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      rank: profile.rank,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      posLevelId: profile.posLevelId,
      email: profile.email,
      phone: profile.phone,
      keycloak: profile.keycloak,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      leaveReason: profile.leaveReason,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate ?? new Date(),
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.phone,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      registrationAddress: profile.registrationAddress,
      registrationProvinceId: profile.registrationProvinceId,
      registrationDistrictId: profile.registrationDistrictId,
      registrationSubDistrictId: profile.registrationSubDistrictId,
      registrationProvince: profile.registrationProvince?.name ?? null,
      registrationDistrict: profile.registrationDistrict?.name ?? null,
      registrationSubDistrict: profile.registrationSubDistrict?.name ?? null,
      registrationZipCode: profile.registrationZipCode,
      currentAddress: profile.currentAddress,
      currentProvinceId: profile.currentProvinceId,
      currentDistrictId: profile.currentDistrictId,
      currentSubDistrictId: profile.currentSubDistrictId,
      currentProvince: profile.currentProvince?.name ?? null,
      currentDistrict: profile.currentDistrict?.name ?? null,
      currentSubDistrict: profile.currentSubDistrict?.name ?? null,
      currentZipCode: profile.currentZipCode,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.orgRootName ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.orgChild1Name ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.orgChild2Name ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.orgChild3Name ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.orgChild4Name ?? null,
      rootId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRootId ?? null,
      child1Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1Id ?? null,
      child2Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2Id ?? null,
      child3Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3Id ?? null,
      child4Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4Id ?? null,
      rootDnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.ancestorDNA ?? null,
      child1DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.ancestorDNA ?? null,
      child2DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.ancestorDNA ?? null,
      child3DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.ancestorDNA ?? null,
      child4DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.ancestorDNA ?? null,
      commander: fullname,
      commanderPositionName,
      commanderId,
      commanderKeycloak,
      posLevel: profile.posLevel?.posLevelName ?? null,
      posType: profile.posType?.posTypeName ?? null,
      profileSalary: profile.profileSalary.length > 0 ? profile.profileSalary[0] : null,
      profileInsignia: profile.profileInsignias.length > 0 ? profile.profileInsignias[0] : null,
      profileType: "OFFICER",
      positionLeaveName: positionLeaveName,
      posExecutiveName:
        position == null || position.posExecutive == null
          ? null
          : position.posExecutive.posExecutiveName,
      oc: oc,
    };

    return new HttpSuccess(mapProfile);
  }

  @Get("keycloak/{keycloakId}")
  @Security("internalAuth")
  async GetProfileByKeycloakIdAsync(@Path() keycloakId: string) {
    /* =========================
     * 1. Load profile
     * ========================= */
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      relations: {
        registrationProvince: true,
        registrationDistrict: true,
        registrationSubDistrict: true,
        currentProvince: true,
        currentDistrict: true,
        currentSubDistrict: true,
        posLevel: true,
        posType: true,
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
          orgChild2: true,
          orgChild3: true,
          orgChild4: true,
        },
      },
    });

    // Employee
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        where: { keycloak: keycloakId },
        relations: {
          registrationProvince: true,
          registrationDistrict: true,
          registrationSubDistrict: true,
          currentProvince: true,
          currentDistrict: true,
          currentSubDistrict: true,
          posLevel: true,
          posType: true,
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      const currentHolder = profile.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );

      const org = {
        root: currentHolder?.orgRootId ?? null,
        child1: currentHolder?.orgChild1Id ?? null,
        child2: currentHolder?.orgChild2Id ?? null,
        child3: currentHolder?.orgChild3Id ?? null,
        child4: currentHolder?.orgChild4Id ?? null,
      };

      let commanderFullname = "";
      let commanderPositionName = "";
      let commanderId = "";
      let commanderKeycloak = "";

      const pos = await this.empPosMasterRepository
        .createQueryBuilder("pos")
        .leftJoinAndSelect("pos.current_holder", "holder")
        .leftJoin("pos.orgRevision", "rev")
        .where("rev.orgRevisionIsCurrent = true")
        .andWhere("rev.orgRevisionIsDraft = false")
        .andWhere("pos.isDirector = true")
        .andWhere("pos.current_holderId IS NOT NULL")
        .andWhere("pos.orgRootId = :root", { root: org.root })
        .andWhere(
          `(pos.orgChild1Id = :c1 OR pos.orgChild1Id IS NULL)
          AND (pos.orgChild2Id = :c2 OR pos.orgChild2Id IS NULL)
          AND (pos.orgChild3Id = :c3 OR pos.orgChild3Id IS NULL)
          AND (pos.orgChild4Id = :c4 OR pos.orgChild4Id IS NULL)`,
          {
            c1: org.child1,
            c2: org.child2,
            c3: org.child3,
            c4: org.child4,
          },
        )
        .orderBy(
          `(CASE WHEN pos.orgChild4Id IS NULL THEN 1 ELSE 0 END) +
          (CASE WHEN pos.orgChild3Id IS NULL THEN 1 ELSE 0 END) +
          (CASE WHEN pos.orgChild2Id IS NULL THEN 1 ELSE 0 END) +
          (CASE WHEN pos.orgChild1Id IS NULL THEN 1 ELSE 0 END)`,
          "ASC",
        )
        .getOne();

      if (pos?.current_holder) {
        commanderFullname = `${pos.current_holder.prefix}${pos.current_holder.firstName} ${pos.current_holder.lastName}`;
        commanderPositionName = pos.current_holder.position;
        commanderId = pos.current_holder.id;
        commanderKeycloak = pos.current_holder.keycloak;
      }

      const [latestSalary, latestInsignia] = await Promise.all([
        this.salaryRepo.findOne({
          where: { profileEmployeeId: profile.id },
          order: { commandDateAffect: "DESC" },
        }),
        this.insigniaRepo.findOne({
          where: { profileEmployeeId: profile.id, isDeleted: false },
          order: { receiveDate: "DESC" },
        }),
      ]);

      let oc = "";
      if (currentHolder) {
        if (!currentHolder.orgChild1Id) {
          oc = currentHolder.orgRoot?.orgRootName;
        } else if (!currentHolder.orgChild2Id) {
          oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild3Id) {
          oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild4Id) {
          oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else {
          oc = currentHolder.orgChild4?.orgChild4Name;
        }
      }

      const positionLeaveName =
        profile.posType &&
        profile.posLevel &&
        (profile.posType.posTypeName === "บริหาร" || profile.posType.posTypeName === "อำนวยการ")
          ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}`
          : profile.posLevel?.posLevelName ?? null;

      const mapProfile = {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        position: profile.position,
        posLevelId: profile.posLevelId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender,
        relationship: profile.relationship,
        religion: profile.religion,
        bloodGroup: profile.bloodGroup,
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationZipCode: profile.registrationZipCode,
        registrationProvince: profile.registrationProvince?.name ?? null,
        registrationDistrict: profile.registrationDistrict?.name ?? null,
        registrationSubDistrict: profile.registrationSubDistrict?.name ?? null,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentDistrictId: profile.currentDistrictId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentZipCode: profile.currentZipCode,
        currentProvince: profile.currentProvince?.name ?? null,
        currentDistrict: profile.currentDistrict?.name ?? null,
        currentSubDistrict: profile.currentSubDistrict?.name ?? null,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        root: currentHolder?.orgRoot?.orgRootName ?? null,
        rootId: currentHolder?.orgRootId ?? null,
        rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
        child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
        child1Id: currentHolder?.orgChild1Id ?? null,
        child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
        child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
        child2Id: currentHolder?.orgChild2Id ?? null,
        child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
        child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
        child3Id: currentHolder?.orgChild3Id ?? null,
        child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
        child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
        child4Id: currentHolder?.orgChild4Id ?? null,
        child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
        commander: commanderFullname,
        commanderPositionName,
        commanderId,
        commanderKeycloak,
        posLevel: profile.posLevel?.posLevelName ?? null,
        posType: profile.posType?.posTypeName ?? null,
        profileSalary: latestSalary ?? null,
        profileInsignia: latestInsignia ?? null,
        profileType: "EMPLOYEE",
        positionLeaveName,
        oc,
      };

      return new HttpSuccess(mapProfile);
    }

    /* =========================================
     * 2. current holder
     * ========================================= */
    const currentHolder = profile.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );

    const org = {
      root: currentHolder?.orgRootId ?? null,
      child1: currentHolder?.orgChild1Id ?? null,
      child2: currentHolder?.orgChild2Id ?? null,
      child3: currentHolder?.orgChild3Id ?? null,
      child4: currentHolder?.orgChild4Id ?? null,
    };

    /* =================================================
     * 3. หา commander
     * ================================================= */
    let commanderFullname = "";
    let commanderPositionName = "";
    let commanderId = "";
    let commanderKeycloak = "";

    const pos = await this.posMasterRepository
      .createQueryBuilder("pos")
      .leftJoinAndSelect("pos.current_holder", "holder")
      .leftJoin("pos.orgRevision", "rev")
      .where("rev.orgRevisionIsCurrent = true")
      .andWhere("rev.orgRevisionIsDraft = false")
      .andWhere("pos.isDirector = true")
      .andWhere("pos.current_holderId IS NOT NULL")
      .andWhere("pos.orgRootId = :root", { root: org.root })
      .andWhere(
        `(pos.orgChild1Id = :c1 OR pos.orgChild1Id IS NULL)
        AND (pos.orgChild2Id = :c2 OR pos.orgChild2Id IS NULL)
        AND (pos.orgChild3Id = :c3 OR pos.orgChild3Id IS NULL)
        AND (pos.orgChild4Id = :c4 OR pos.orgChild4Id IS NULL)`,
        {
          c1: org.child1,
          c2: org.child2,
          c3: org.child3,
          c4: org.child4,
        },
      )
      .orderBy(
        `(CASE WHEN pos.orgChild4Id IS NULL THEN 1 ELSE 0 END) +
        (CASE WHEN pos.orgChild3Id IS NULL THEN 1 ELSE 0 END) +
        (CASE WHEN pos.orgChild2Id IS NULL THEN 1 ELSE 0 END) +
        (CASE WHEN pos.orgChild1Id IS NULL THEN 1 ELSE 0 END)`,
        "ASC",
      )
      .getOne();

    if (pos?.current_holder) {
      commanderFullname = `${pos.current_holder.prefix}${pos.current_holder.firstName} ${pos.current_holder.lastName}`;
      commanderPositionName = pos.current_holder.position;
      commanderId = pos.current_holder.id;
      commanderKeycloak = pos.current_holder.keycloak;
    }

    /* =========================================
     * 4. salary / insignia (เอาแค่ล่าสุด)
     * ========================================= */
    const [latestSalary, latestInsignia] = await Promise.all([
      this.salaryRepo.findOne({
        where: { profileId: profile.id },
        order: { commandDateAffect: "DESC" },
      }),
      this.insigniaRepo.findOne({
        where: { profileId: profile.id, isDeleted: false },
        order: { receiveDate: "DESC" },
      }),
    ]);

    /* =========================================
     * 5. position executive
     * ========================================= */
    const position = await this.positionRepository.findOne({
      where: {
        positionIsSelected: true,
        posMaster: {
          orgRevisionId: currentHolder?.orgRevisionId,
          current_holderId: profile.id,
        },
      },
      order: { createdAt: "DESC" },
      relations: { posExecutive: true },
    });

    /* =========================================
     * 6. OC name
     * ========================================= */
    let oc = "";
    if (currentHolder) {
      if (!currentHolder.orgChild1Id) {
        oc = currentHolder.orgRoot?.orgRootName;
      } else if (!currentHolder.orgChild2Id) {
        oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild3Id) {
        oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild4Id) {
        oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else {
        oc = currentHolder.orgChild4?.orgChild4Name;
      }
    }

    /* =========================================
     * 7. position level name
     * ========================================= */
    const positionLeaveName =
      profile.posType &&
      profile.posLevel &&
      (profile.posType.posTypeName === "บริหาร" || profile.posType.posTypeName === "อำนวยการ")
        ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}`
        : profile.posLevel?.posLevelName ?? null;

    /* =========================================
     * 8. map response
     * ========================================= */
    const mapProfile = {
      id: profile.id,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      rank: profile.rank,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      posLevelId: profile.posLevelId,
      email: profile.email,
      phone: profile.phone,
      keycloak: profile.keycloak,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      leaveReason: profile.leaveReason,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate ?? new Date(),
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.phone,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      registrationAddress: profile.registrationAddress,
      registrationProvinceId: profile.registrationProvinceId,
      registrationDistrictId: profile.registrationDistrictId,
      registrationSubDistrictId: profile.registrationSubDistrictId,
      registrationZipCode: profile.registrationZipCode,
      registrationProvince: profile.registrationProvince?.name ?? null,
      registrationDistrict: profile.registrationDistrict?.name ?? null,
      registrationSubDistrict: profile.registrationSubDistrict?.name ?? null,
      currentAddress: profile.currentAddress,
      currentProvinceId: profile.currentProvinceId,
      currentDistrictId: profile.currentDistrictId,
      currentSubDistrictId: profile.currentSubDistrictId,
      currentZipCode: profile.currentZipCode,
      currentProvince: profile.currentProvince?.name ?? null,
      currentDistrict: profile.currentDistrict?.name ?? null,
      currentSubDistrict: profile.currentSubDistrict?.name ?? null,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      root: currentHolder?.orgRoot?.orgRootName ?? null,
      rootId: currentHolder?.orgRootId ?? null,
      rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
      child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
      child1Id: currentHolder?.orgChild1Id ?? null,
      child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
      child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
      child2Id: currentHolder?.orgChild2Id ?? null,
      child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
      child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
      child3Id: currentHolder?.orgChild3Id ?? null,
      child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
      child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
      child4Id: currentHolder?.orgChild4Id ?? null,
      child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
      commander: commanderFullname,
      commanderPositionName,
      commanderId,
      commanderKeycloak,
      posLevel: profile.posLevel?.posLevelName ?? null,
      posType: profile.posType?.posTypeName ?? null,
      profileSalary: latestSalary ?? null,
      profileInsignia: latestInsignia ?? null,
      profileType: "OFFICER",
      positionLeaveName,
      posExecutiveName: position?.posExecutive?.posExecutiveName ?? null,
      oc,
    };

    return new HttpSuccess(mapProfile);
  }

  @Get("by-keycloak/{keycloakId}")
  @Security("internalAuth")
  async NewGetProfileByKeycloakIdAsync(@Path() keycloakId: string) {
    /* =========================
     * 1. Load profile
     * ========================= */
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      relations: {
        posLevel: true,
        posType: true,
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
          orgChild2: true,
          orgChild3: true,
          orgChild4: true,
        },
      },
    });

    // Employee
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        where: { keycloak: keycloakId },
        relations: {
          posLevel: true,
          posType: true,
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      const currentHolder = profile.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );

      let oc = "";
      if (currentHolder) {
        if (!currentHolder.orgChild1Id) {
          oc = currentHolder.orgRoot?.orgRootName;
        } else if (!currentHolder.orgChild2Id) {
          oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild3Id) {
          oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild4Id) {
          oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else {
          oc = currentHolder.orgChild4?.orgChild4Name;
        }
      }

      const mapProfile = {
        profileType: "EMPLOYEE",
        id: profile.id,
        keycloak: profile.keycloak,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        position: profile.position,
        email: profile.email,
        phone: profile.phone,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender,
        relationship: profile.relationship,
        religion: profile.religion,
        bloodGroup: profile.bloodGroup,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,

        posType: profile.posType?.posTypeName ?? null,
        posLevel:
          profile.posType?.posTypeShortName == null && profile.posLevel?.posLevelName == null
            ? null
            : `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`,
        oc,

        root: currentHolder?.orgRoot?.orgRootName ?? null,
        rootId: currentHolder?.orgRootId ?? null,
        rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
        child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
        child1Id: currentHolder?.orgChild1Id ?? null,
        child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
        child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
        child2Id: currentHolder?.orgChild2Id ?? null,
        child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
        child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
        child3Id: currentHolder?.orgChild3Id ?? null,
        child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
        child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
        child4Id: currentHolder?.orgChild4Id ?? null,
        child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
      };

      return new HttpSuccess(mapProfile);
    }

    /* =========================================
     * 2. current holder
     * ========================================= */
    const currentHolder = profile.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );

    /* =========================================
     * 5. position executive
     * ========================================= */
    const position = await this.positionRepository.findOne({
      where: {
        positionIsSelected: true,
        posMaster: {
          orgRevisionId: currentHolder?.orgRevisionId,
          current_holderId: profile.id,
        },
      },
      order: { createdAt: "DESC" },
      relations: { posExecutive: true },
    });

    /* =========================================
     * 6. OC name
     * ========================================= */
    let oc = "";
    if (currentHolder) {
      if (!currentHolder.orgChild1Id) {
        oc = currentHolder.orgRoot?.orgRootName;
      } else if (!currentHolder.orgChild2Id) {
        oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild3Id) {
        oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild4Id) {
        oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else {
        oc = currentHolder.orgChild4?.orgChild4Name;
      }
    }

    /* =========================================
     * 7. position level name
     * ========================================= */
    const positionLeaveName =
      profile.posType &&
      profile.posLevel &&
      (profile.posType.posTypeName === "บริหาร" || profile.posType.posTypeName === "อำนวยการ")
        ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}`
        : profile.posLevel?.posLevelName ?? null;

    /* =========================================
     * 8. map response
     * ========================================= */
    const mapProfile = {
      profileType: "OFFICER",
      id: profile.id,
      keycloak: profile.keycloak,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      email: profile.email,
      phone: profile.phone,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate ?? new Date(),
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.phone,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,

      posLevel: profile.posLevel?.posLevelName ?? null,
      posType: profile.posType?.posTypeName ?? null,
      posExecutiveName: position?.posExecutive?.posExecutiveName ?? null,
      positionLeaveName,
      oc,

      root: currentHolder?.orgRoot?.orgRootName ?? null,
      rootId: currentHolder?.orgRootId ?? null,
      rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
      child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
      child1Id: currentHolder?.orgChild1Id ?? null,
      child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
      child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
      child2Id: currentHolder?.orgChild2Id ?? null,
      child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
      child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
      child3Id: currentHolder?.orgChild3Id ?? null,
      child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
      child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
      child4Id: currentHolder?.orgChild4Id ?? null,
      child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
    };

    return new HttpSuccess(mapProfile);
  }

  // เพิ่มที่อยู่ปัจจุบัน + ตำแหน่งหัวหน้า
  @Get("by-keycloak2/{keycloakId}")
  @Security("internalAuth")
  async NewGetProfileByKeycloak2IdAsync(@Path() keycloakId: string) {
    /* =========================
     * 1. Load profile
     * ========================= */
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      relations: {
        posLevel: true,
        posType: true,
        currentProvince: true,
        currentDistrict: true,
        currentSubDistrict: true,
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
          orgChild2: true,
          orgChild3: true,
          orgChild4: true,
        },
      },
    });
    let commanderFullname = "";
    let commanderPositionName = "";
    let commanderId = "";
    // Employee
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        where: { keycloak: keycloakId },
        relations: {
          posLevel: true,
          posType: true,
          currentProvince: true,
          currentDistrict: true,
          currentSubDistrict: true,
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      const currentHolder = profile.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );

      const pos = await this.empPosMasterRepository
        .createQueryBuilder("pos")
        .leftJoinAndSelect("pos.current_holder", "holder")
        .leftJoin("pos.orgRevision", "rev")
        .where("rev.orgRevisionIsCurrent = true")
        .andWhere("rev.orgRevisionIsDraft = false")
        .andWhere("pos.isDirector = true")
        .andWhere("pos.current_holderId IS NOT NULL")
        .andWhere("pos.orgRootId = :root", { root: currentHolder?.orgRootId })
        .andWhere(
          `(pos.orgChild1Id = :c1 OR pos.orgChild1Id IS NULL)
          AND (pos.orgChild2Id = :c2 OR pos.orgChild2Id IS NULL)
          AND (pos.orgChild3Id = :c3 OR pos.orgChild3Id IS NULL)
          AND (pos.orgChild4Id = :c4 OR pos.orgChild4Id IS NULL)`,
          {
            c1: currentHolder?.orgChild1Id,
            c2: currentHolder?.orgChild2Id,
            c3: currentHolder?.orgChild3Id,
            c4: currentHolder?.orgChild4Id,
          },
        )
        .orderBy(
          `(CASE WHEN pos.orgChild4Id IS NULL THEN 1 ELSE 0 END) +
          (CASE WHEN pos.orgChild3Id IS NULL THEN 1 ELSE 0 END) +
          (CASE WHEN pos.orgChild2Id IS NULL THEN 1 ELSE 0 END) +
          (CASE WHEN pos.orgChild1Id IS NULL THEN 1 ELSE 0 END)`,
          "ASC",
        )
        .getOne();

      if (pos?.current_holder) {
        commanderFullname = `${pos.current_holder.prefix}${pos.current_holder.firstName} ${pos.current_holder.lastName}`;
        commanderPositionName = pos.current_holder.position;
        commanderId = pos.current_holder.id;
      }

      let oc = "";
      if (currentHolder) {
        if (!currentHolder.orgChild1Id) {
          oc = currentHolder.orgRoot?.orgRootName;
        } else if (!currentHolder.orgChild2Id) {
          oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild3Id) {
          oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild4Id) {
          oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else {
          oc = currentHolder.orgChild4?.orgChild4Name;
        }
      }

      const mapProfile = {
        profileType: "EMPLOYEE",
        id: profile.id,
        keycloak: profile.keycloak,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        position: profile.position,
        email: profile.email,
        phone: profile.phone,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender,
        relationship: profile.relationship,
        religion: profile.religion,
        bloodGroup: profile.bloodGroup,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,

        posType: profile.posType?.posTypeName ?? null,
        posLevel:
          profile.posType?.posTypeShortName == null && profile.posLevel?.posLevelName == null
            ? null
            : `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`,
        oc,

        currentAddress: profile.currentAddress,
        currentSubDistrict: profile.currentSubDistrict?.name ?? null,
        currentDistrict: profile.currentDistrict?.name ?? null,
        currentProvince: profile.currentProvince?.name ?? null,
        currentZipCode: profile.currentZipCode,

        commander: commanderFullname,
        commanderPositionName,
        commanderId,

        root: currentHolder?.orgRoot?.orgRootName ?? null,
        rootId: currentHolder?.orgRootId ?? null,
        rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
        child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
        child1Id: currentHolder?.orgChild1Id ?? null,
        child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
        child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
        child2Id: currentHolder?.orgChild2Id ?? null,
        child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
        child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
        child3Id: currentHolder?.orgChild3Id ?? null,
        child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
        child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
        child4Id: currentHolder?.orgChild4Id ?? null,
        child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
      };

      return new HttpSuccess(mapProfile);
    }

    /* =========================================
     * 2. current holder
     * ========================================= */
    const currentHolder = profile.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );

    /* =================================================
     * 3. หา commander
     * ================================================= */
    const pos = await this.posMasterRepository
      .createQueryBuilder("pos")
      .leftJoinAndSelect("pos.current_holder", "holder")
      .leftJoin("pos.orgRevision", "rev")
      .where("rev.orgRevisionIsCurrent = true")
      .andWhere("rev.orgRevisionIsDraft = false")
      .andWhere("pos.isDirector = true")
      .andWhere("pos.current_holderId IS NOT NULL")
      .andWhere("pos.orgRootId = :root", { root: currentHolder?.orgRootId })
      .andWhere(
        `(pos.orgChild1Id = :c1 OR pos.orgChild1Id IS NULL)
        AND (pos.orgChild2Id = :c2 OR pos.orgChild2Id IS NULL)
        AND (pos.orgChild3Id = :c3 OR pos.orgChild3Id IS NULL)
        AND (pos.orgChild4Id = :c4 OR pos.orgChild4Id IS NULL)`,
        {
          c1: currentHolder?.orgChild1Id,
          c2: currentHolder?.orgChild2Id,
          c3: currentHolder?.orgChild3Id,
          c4: currentHolder?.orgChild4Id,
        },
      )
      .orderBy(
        `(CASE WHEN pos.orgChild4Id IS NULL THEN 1 ELSE 0 END) +
        (CASE WHEN pos.orgChild3Id IS NULL THEN 1 ELSE 0 END) +
        (CASE WHEN pos.orgChild2Id IS NULL THEN 1 ELSE 0 END) +
        (CASE WHEN pos.orgChild1Id IS NULL THEN 1 ELSE 0 END)`,
        "ASC",
      )
      .getOne();

    if (pos?.current_holder) {
      commanderFullname = `${pos.current_holder.prefix}${pos.current_holder.firstName} ${pos.current_holder.lastName}`;
      commanderPositionName = pos.current_holder.position;
      commanderId = pos.current_holder.id;
    }

    /* =========================================
     * 5. position executive
     * ========================================= */
    const position = await this.positionRepository.findOne({
      where: {
        positionIsSelected: true,
        posMaster: {
          orgRevisionId: currentHolder?.orgRevisionId,
          current_holderId: profile.id,
        },
      },
      order: { createdAt: "DESC" },
      relations: { posExecutive: true },
    });

    /* =========================================
     * 6. OC name
     * ========================================= */
    let oc = "";
    if (currentHolder) {
      if (!currentHolder.orgChild1Id) {
        oc = currentHolder.orgRoot?.orgRootName;
      } else if (!currentHolder.orgChild2Id) {
        oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild3Id) {
        oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild4Id) {
        oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else {
        oc = currentHolder.orgChild4?.orgChild4Name;
      }
    }

    /* =========================================
     * 7. position level name
     * ========================================= */
    const positionLeaveName =
      profile.posType &&
      profile.posLevel &&
      (profile.posType.posTypeName === "บริหาร" || profile.posType.posTypeName === "อำนวยการ")
        ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}`
        : profile.posLevel?.posLevelName ?? null;

    /* =========================================
     * 8. map response
     * ========================================= */
    const mapProfile = {
      profileType: "OFFICER",
      id: profile.id,
      keycloak: profile.keycloak,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      email: profile.email,
      phone: profile.phone,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate ?? new Date(),
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.phone,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,

      posLevel: profile.posLevel?.posLevelName ?? null,
      posType: profile.posType?.posTypeName ?? null,
      posExecutiveName: position?.posExecutive?.posExecutiveName ?? null,
      positionLeaveName,
      oc,

      currentAddress: profile.currentAddress,
      currentSubDistrict: profile.currentSubDistrict?.name ?? null,
      currentDistrict: profile.currentDistrict?.name ?? null,
      currentProvince: profile.currentProvince?.name ?? null,
      currentZipCode: profile.currentZipCode,

      commander: commanderFullname,
      commanderPositionName,
      commanderId,

      root: currentHolder?.orgRoot?.orgRootName ?? null,
      rootId: currentHolder?.orgRootId ?? null,
      rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
      child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
      child1Id: currentHolder?.orgChild1Id ?? null,
      child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
      child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
      child2Id: currentHolder?.orgChild2Id ?? null,
      child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
      child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
      child3Id: currentHolder?.orgChild3Id ?? null,
      child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
      child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
      child4Id: currentHolder?.orgChild4Id ?? null,
      child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
    };

    return new HttpSuccess(mapProfile);
  }

  /**
   * API Get Profile For Process Check In
   * @summary API Get Profile For Process Check In
   * @param {string} keycloakId  keycloakId profile
   */
  @Get("check-keycloak/{keycloakId}")
  @Security("internalAuth")
  async GetProfileForProcessCheckInAsync(@Path() keycloakId: string) {
    try {
      // console.log(`[check-keycloak] START - keycloakId=${keycloakId}`);

      /* =========================
       * 1. Load profile (Officer)
       * ========================= */
      const profile = await this.profileRepo.findOne({
        where: { keycloak: keycloakId },
        relations: {
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
      });

      // Employee
      if (!profile) {
        console.log(`[check-keycloak] OFFICER_NOT_FOUND - keycloakId=${keycloakId}, checking EMPLOYEE`);

        const empProfile = await this.profileEmpRepo.findOne({
          where: { keycloak: keycloakId },
          relations: {
            current_holders: {
              orgRevision: true,
              orgRoot: true,
              orgChild1: true,
              orgChild2: true,
              orgChild3: true,
              orgChild4: true,
            },
          },
        });

        if (!empProfile) {
          console.log(`[check-keycloak] EMPLOYEE_NOT_FOUND - keycloakId=${keycloakId}`);
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
        }

        const currentHolder = empProfile.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft === false &&
            x.orgRevision?.orgRevisionIsCurrent === true,
        );

        const mapProfile = {
          profileType: "EMPLOYEE",
          id: empProfile.id,
          keycloak: empProfile.keycloak,
          prefix: empProfile.prefix,
          firstName: empProfile.firstName,
          lastName: empProfile.lastName,
          citizenId: empProfile.citizenId,
          gender: empProfile.gender,

          root: currentHolder?.orgRoot?.orgRootName ?? null,
          rootId: currentHolder?.orgRootId ?? null,
          rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
          child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
          child1Id: currentHolder?.orgChild1Id ?? null,
          child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
          child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
          child2Id: currentHolder?.orgChild2Id ?? null,
          child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
          child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
          child3Id: currentHolder?.orgChild3Id ?? null,
          child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
          child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
          child4Id: currentHolder?.orgChild4Id ?? null,
          child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
        };

        // console.log(
        //   `[check-keycloak] SUCCESS_EMPLOYEE - keycloakId=${keycloakId}, profileType=EMPLOYEE`,
        // );

        return new HttpSuccess(mapProfile);
      }

      // console.log(`[check-keycloak] OFFICER_FOUND - keycloakId=${keycloakId}`);

      /* =========================================
       * 2. current holder (Officer)
       * ========================================= */
      const currentHolder = profile.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
      );

      /* =========================================
       * 3. map response
       * ========================================= */
      const mapProfile = {
        profileType: "OFFICER",
        id: profile.id,
        keycloak: profile.keycloak,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        gender: profile.gender,

        root: currentHolder?.orgRoot?.orgRootName ?? null,
        rootId: currentHolder?.orgRootId ?? null,
        rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
        child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
        child1Id: currentHolder?.orgChild1Id ?? null,
        child1DnaId: currentHolder?.orgChild1?.ancestorDNA ?? null,
        child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
        child2Id: currentHolder?.orgChild2Id ?? null,
        child2DnaId: currentHolder?.orgChild2?.ancestorDNA ?? null,
        child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
        child3Id: currentHolder?.orgChild3Id ?? null,
        child3DnaId: currentHolder?.orgChild3?.ancestorDNA ?? null,
        child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
        child4Id: currentHolder?.orgChild4Id ?? null,
        child4DnaId: currentHolder?.orgChild4?.ancestorDNA ?? null,
      };

      // console.log(
      //   `[check-keycloak] SUCCESS_OFFICER - keycloakId=${keycloakId}, profileType=OFFICER`,
      // );

      return new HttpSuccess(mapProfile);
    } catch (error: any) {
      // Log เฉพาะ unexpected errors (ไม่ใช่ HttpError)
      if (!(error instanceof HttpError)) {
        console.error(`[check-keycloak] Unexpected error: keycloakId=${keycloakId}`, error);
      }
      throw error;
    }
  }

  /**
   * API Get Profile For Logs
   *
   * @summary API Get Profile For Logs
   *
   * @param {string} keycloakId  keycloakId profile
   */
  @Get("user-logs/{keycloakId}")
  @Security("internalAuth")
  async UserLogs(@Path() keycloakId: string) {
    /* =========================
     * 1. Load profile
     * ========================= */
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      relations: {
        current_holders: {
          orgRevision: true,
          orgRoot: true,
        },
      },
    });

    // Employee
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        where: { keycloak: keycloakId },
        relations: {
          current_holders: {
            orgRevision: true,
            orgRoot: true,
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      const currentHolder = profile.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );

      const mapProfile = {
        profileId: profile.id,
        keycloak: profile.keycloak,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        rootId: currentHolder?.orgRootId ?? null,
        rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
      };

      return new HttpSuccess(mapProfile);
    }

    /* =========================================
     * 2. current holder
     * ========================================= */
    const currentHolder = profile.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );

    /* =========================================
     * 8. map response
     * ========================================= */
    const mapProfile = {
      profileId: profile.id,
      keycloak: profile.keycloak,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      rootId: currentHolder?.orgRootId ?? null,
      rootDnaId: currentHolder?.orgRoot?.ancestorDNA ?? null,
    };

    return new HttpSuccess(mapProfile);
  }

  /**
   * 3.	API Get Profile จาก profile id
   *
   * @summary 3. API Get Profile จาก profile id
   *
   * @param {string} profileId  Id profile
   */
  @Get("profile/{profileId}")
  @Security("internalAuth")
  async GetProfileByProfileIdAsync(@Path() profileId: string) {
    const profile = await this.profileRepo.findOne({
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { id: profileId },
    });

    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        relations: [
          "posLevel",
          "posType",
          "current_holders",
          "current_holders.orgRevision",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
        where: { id: profileId },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

      const [latestSalary, latestInsignia] = await Promise.all([
        this.salaryRepo.findOne({
          where: { profileEmployeeId: profile.id },
          order: { commandDateAffect: "DESC" },
        }),
        this.insigniaRepo.findOne({
          where: { profileEmployeeId: profile.id, isDeleted: false },
          order: { receiveDate: "DESC" },
        }),
      ]);

      const org = {
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.id ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.id ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.id ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.id ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.id ?? null,
      };
      let fullname = "";
      let pos = await this.empPosMasterRepository.findOne({
        relations: ["current_holder"],
        where: {
          current_holder: Not(IsNull()),
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
          isDirector: true,
          orgRootId: org?.root ?? "",
          orgChild1Id: org?.child1 ?? "",
          orgChild2Id: org?.child2 ?? "",
          orgChild3Id: org?.child3 ?? "",
          orgChild4Id: org?.child4 ?? "",
        },
      });

      if (pos) {
        fullname =
          pos.current_holder.prefix +
          pos.current_holder.firstName +
          " " +
          pos.current_holder.lastName;
      } else {
        let pos = await this.empPosMasterRepository.findOne({
          relations: ["current_holder"],
          where: {
            current_holder: Not(IsNull()),
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
            isDirector: true,
            orgRootId: org?.root ?? "",
            orgChild1Id: org?.child1 ?? "",
            orgChild2Id: org?.child2 ?? "",
            orgChild3Id: org?.child3 ?? "",
            orgChild4Id: IsNull(),
          },
        });
        if (pos) {
          fullname =
            pos.current_holder.prefix +
            pos.current_holder.firstName +
            " " +
            pos.current_holder.lastName;
        } else {
          let pos = await this.empPosMasterRepository.findOne({
            relations: ["current_holder"],
            where: {
              current_holder: Not(IsNull()),
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
              isDirector: true,
              orgRootId: org?.root ?? "",
              orgChild1Id: org?.child1 ?? "",
              orgChild2Id: org?.child2 ?? "",
              orgChild3Id: IsNull(),
              orgChild4Id: IsNull(),
            },
          });
          if (pos) {
            fullname =
              pos.current_holder.prefix +
              pos.current_holder.firstName +
              " " +
              pos.current_holder.lastName;
          } else {
            let pos = await this.empPosMasterRepository.findOne({
              relations: ["current_holder"],
              where: {
                current_holder: Not(IsNull()),
                orgRevision: {
                  orgRevisionIsCurrent: true,
                  orgRevisionIsDraft: false,
                },
                isDirector: true,
                orgRootId: org?.root ?? "",
                orgChild1Id: org?.child1 ?? "",
                orgChild2Id: IsNull(),
                orgChild3Id: IsNull(),
                orgChild4Id: IsNull(),
              },
            });
            if (pos) {
              fullname =
                pos.current_holder.prefix +
                pos.current_holder.firstName +
                " " +
                pos.current_holder.lastName;
            } else {
              let pos = await this.empPosMasterRepository.findOne({
                relations: ["current_holder"],
                where: {
                  current_holder: Not(IsNull()),
                  orgRevision: {
                    orgRevisionIsCurrent: true,
                    orgRevisionIsDraft: false,
                  },
                  orgRootId: org?.root ?? "",
                  orgChild1Id: IsNull(),
                  orgChild2Id: IsNull(),
                  orgChild3Id: IsNull(),
                  orgChild4Id: IsNull(),
                },
              });
              if (pos) {
                fullname =
                  pos.current_holder.prefix +
                  pos.current_holder.firstName +
                  " " +
                  pos.current_holder.lastName;
              } else {
                fullname = "";
              }
            }
          }
        }
      }

      const mapProfile = {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        position: profile.position,
        posLevelId: profile.posLevelId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender,
        relationship: profile.relationship,
        religion: profile.religion,
        bloodGroup: profile.bloodGroup,
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationZipCode: profile.registrationZipCode,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentZipCode: profile.currentZipCode,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.orgChild1Name ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.orgChild2Name ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.orgChild3Name ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.orgChild4Name ?? null,
        rootId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRootId ?? null,
        child1Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1Id ?? null,
        child2Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2Id ?? null,
        child3Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3Id ?? null,
        child4Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4Id ?? null,
        rootDnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.ancestorDNA ?? null,
        child1DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.ancestorDNA ?? null,
        child2DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.ancestorDNA ?? null,
        child3DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.ancestorDNA ?? null,
        child4DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.ancestorDNA ?? null,
        commander: fullname,
        posLevel:
          (profile.posType == null || profile.posType?.posTypeShortName == null
            ? ""
            : profile.posType?.posTypeShortName + " ") + (profile.posLevel?.posLevelName ?? ""),
        posType: profile.posType?.posTypeName ?? null,
        profileSalary: latestSalary ?? null,
        profileInsignia: latestInsignia ?? null,
        profileType: "EMPLOYEE",
      };

      return new HttpSuccess(mapProfile);
    }

    const [latestSalary, latestInsignia] = await Promise.all([
      this.salaryRepo.findOne({
        where: { profileId: profile.id },
        order: { commandDateAffect: "DESC" },
      }),
      this.insigniaRepo.findOne({
        where: { profileId: profile.id, isDeleted: false },
        order: { receiveDate: "DESC" },
      }),
    ]);

    const org = {
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.id ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.id ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.id ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.id ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.id ?? null,
    };

    let fullname = "";
    let pos = await this.posMasterRepository.findOne({
      relations: ["current_holder"],
      where: {
        current_holder: Not(IsNull()),
        orgRevision: {
          orgRevisionIsCurrent: true,
          orgRevisionIsDraft: false,
        },
        isDirector: true,
        orgRootId: org?.root ?? "",
        orgChild1Id: org?.child1 ?? "",
        orgChild2Id: org?.child2 ?? "",
        orgChild3Id: org?.child3 ?? "",
        orgChild4Id: org?.child4 ?? "",
      },
    });

    if (pos) {
      fullname =
        pos.current_holder.prefix +
        pos.current_holder.firstName +
        " " +
        pos.current_holder.lastName;
    } else {
      let pos = await this.posMasterRepository.findOne({
        relations: ["current_holder"],
        where: {
          current_holder: Not(IsNull()),
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
          isDirector: true,
          orgRootId: org?.root ?? "",
          orgChild1Id: org?.child1 ?? "",
          orgChild2Id: org?.child2 ?? "",
          orgChild3Id: org?.child3 ?? "",
          orgChild4Id: IsNull(),
        },
      });
      if (pos) {
        fullname =
          pos.current_holder.prefix +
          pos.current_holder.firstName +
          " " +
          pos.current_holder.lastName;
      } else {
        let pos = await this.posMasterRepository.findOne({
          relations: ["current_holder"],
          where: {
            current_holder: Not(IsNull()),
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
            isDirector: true,
            orgRootId: org?.root ?? "",
            orgChild1Id: org?.child1 ?? "",
            orgChild2Id: org?.child2 ?? "",
            orgChild3Id: IsNull(),
            orgChild4Id: IsNull(),
          },
        });
        if (pos) {
          fullname =
            pos.current_holder.prefix +
            pos.current_holder.firstName +
            " " +
            pos.current_holder.lastName;
        } else {
          let pos = await this.posMasterRepository.findOne({
            relations: ["current_holder"],
            where: {
              current_holder: Not(IsNull()),
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
              isDirector: true,
              orgRootId: org?.root ?? "",
              orgChild1Id: org?.child1 ?? "",
              orgChild2Id: IsNull(),
              orgChild3Id: IsNull(),
              orgChild4Id: IsNull(),
            },
          });
          if (pos) {
            fullname =
              pos.current_holder.prefix +
              pos.current_holder.firstName +
              " " +
              pos.current_holder.lastName;
          } else {
            let pos = await this.posMasterRepository.findOne({
              relations: ["current_holder"],
              where: {
                current_holder: Not(IsNull()),
                orgRevision: {
                  orgRevisionIsCurrent: true,
                  orgRevisionIsDraft: false,
                },
                orgRootId: org?.root ?? "",
                orgChild1Id: IsNull(),
                orgChild2Id: IsNull(),
                orgChild3Id: IsNull(),
                orgChild4Id: IsNull(),
              },
            });
            if (pos) {
              fullname =
                pos.current_holder.prefix +
                pos.current_holder.firstName +
                " " +
                pos.current_holder.lastName;
            } else {
              fullname = "";
            }
          }
        }
      }
    }

    const mapProfile = {
      id: profile.id,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      rank: profile.rank,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      posLevelId: profile.posLevelId,
      email: profile.email,
      phone: profile.phone,
      keycloak: profile.keycloak,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      leaveReason: profile.leaveReason,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate ?? new Date(),
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.phone,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      registrationAddress: profile.registrationAddress,
      registrationProvinceId: profile.registrationProvinceId,
      registrationDistrictId: profile.registrationDistrictId,
      registrationSubDistrictId: profile.registrationSubDistrictId,
      registrationZipCode: profile.registrationZipCode,
      currentAddress: profile.currentAddress,
      currentProvinceId: profile.currentProvinceId,
      currentSubDistrictId: profile.currentSubDistrictId,
      currentZipCode: profile.currentZipCode,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.orgRootName ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.orgChild1Name ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.orgChild2Name ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.orgChild3Name ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.orgChild4Name ?? null,
      rootId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRootId ?? null,
      child1Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1Id ?? null,
      child2Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2Id ?? null,
      child3Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3Id ?? null,
      child4Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4Id ?? null,
      rootDnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.ancestorDNA ?? null,
      child1DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.ancestorDNA ?? null,
      child2DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.ancestorDNA ?? null,
      child3DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.ancestorDNA ?? null,
      child4DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.ancestorDNA ?? null,
      commander: fullname,
      posLevel: profile.posLevel?.posLevelName ?? null,
      posType: profile.posType?.posTypeName ?? null,
      profileSalary: latestSalary ?? null,
      profileInsignia: latestInsignia ?? null,
      profileType: "OFFICER",
    };

    return new HttpSuccess(mapProfile);
  }

  /**
   * 3.	API Get Profile จาก citizen Id
   *
   * @summary 3. API Get Profile จาก citizen Id
   *
   * @param {string} citizenId  citizen Id
   */
  @Get("citizenId/{citizenId}")
  @Security("internalAuth")
  async GetProfileByCitizenIdAsync(@Path() citizenId: string) {
    const profile = await this.profileRepo.findOne({
      relations: [
        "posLevel",
        "posType",
        "profileSalary",
        "profileInsignias",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { citizenId: citizenId },
      order: {
        profileSalary: {
          commandDateAffect: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });

    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        relations: [
          "posLevel",
          "posType",
          "profileSalary",
          "profileInsignias",
          "current_holders",
          "current_holders.orgRevision",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
        where: { citizenId: citizenId },
        order: {
          profileSalary: {
            commandDateAffect: "DESC",
          },
          profileInsignias: {
            receiveDate: "DESC",
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

      const org = {
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.id ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.id ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.id ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.id ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.id ?? null,
      };
      let fullname = "";
      let pos = await this.posMasterRepository.findOne({
        relations: ["current_holder"],
        where: {
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
          isDirector: true,
          orgRootId: org?.root ?? "",
          orgChild1Id: org?.child1 ?? "",
          orgChild2Id: org?.child2 ?? "",
          orgChild3Id: org?.child3 ?? "",
          orgChild4Id: org?.child4 ?? "",
        },
      });

      if (pos) {
        fullname =
          pos.current_holder.prefix +
          pos.current_holder.firstName +
          " " +
          pos.current_holder.lastName;
      } else {
        let pos = await this.posMasterRepository.findOne({
          relations: ["current_holder"],
          where: {
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
            isDirector: true,
            orgRootId: org?.root ?? "",
            orgChild1Id: org?.child1 ?? "",
            orgChild2Id: org?.child2 ?? "",
            orgChild3Id: org?.child3 ?? "",
            orgChild4Id: IsNull(),
          },
        });
        if (pos) {
          fullname =
            pos.current_holder.prefix +
            pos.current_holder.firstName +
            " " +
            pos.current_holder.lastName;
        } else {
          let pos = await this.posMasterRepository.findOne({
            relations: ["current_holder"],
            where: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
              isDirector: true,
              orgRootId: org?.root ?? "",
              orgChild1Id: org?.child1 ?? "",
              orgChild2Id: org?.child2 ?? "",
              orgChild3Id: IsNull(),
              orgChild4Id: IsNull(),
            },
          });
          if (pos) {
            fullname =
              pos.current_holder.prefix +
              pos.current_holder.firstName +
              " " +
              pos.current_holder.lastName;
          } else {
            let pos = await this.posMasterRepository.findOne({
              relations: ["current_holder"],
              where: {
                orgRevision: {
                  orgRevisionIsCurrent: true,
                  orgRevisionIsDraft: false,
                },
                isDirector: true,
                orgRootId: org?.root ?? "",
                orgChild1Id: org?.child1 ?? "",
                orgChild2Id: IsNull(),
                orgChild3Id: IsNull(),
                orgChild4Id: IsNull(),
              },
            });
            if (pos) {
              fullname =
                pos.current_holder.prefix +
                pos.current_holder.firstName +
                " " +
                pos.current_holder.lastName;
            } else {
              let pos = await this.posMasterRepository.findOne({
                relations: ["current_holder"],
                where: {
                  orgRevision: {
                    orgRevisionIsCurrent: true,
                    orgRevisionIsDraft: false,
                  },
                  orgRootId: org?.root ?? "",
                  orgChild1Id: IsNull(),
                  orgChild2Id: IsNull(),
                  orgChild3Id: IsNull(),
                  orgChild4Id: IsNull(),
                },
              });
              if (pos) {
                fullname =
                  pos.current_holder.prefix +
                  pos.current_holder.firstName +
                  " " +
                  pos.current_holder.lastName;
              } else {
                fullname = "";
              }
            }
          }
        }
      }

      const mapProfile = {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank,
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        position: profile.position,
        posLevelId: profile.posLevelId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender,
        relationship: profile.relationship,
        religion: profile.religion,
        bloodGroup: profile.bloodGroup,
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationZipCode: profile.registrationZipCode,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentZipCode: profile.currentZipCode,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.orgChild1Name ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.orgChild2Name ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.orgChild3Name ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.orgChild4Name ?? null,
        rootId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRootId ?? null,
        child1Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1Id ?? null,
        child2Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2Id ?? null,
        child3Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3Id ?? null,
        child4Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4Id ?? null,
        rootDnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.ancestorDNA ?? null,
        child1DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.ancestorDNA ?? null,
        child2DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.ancestorDNA ?? null,
        child3DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.ancestorDNA ?? null,
        child4DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.ancestorDNA ?? null,
        commander: fullname,
        posLevel: profile.posLevel?.posLevelName ?? null,
        posType: profile.posType?.posTypeName ?? null,
        profileSalary: profile.profileSalary.length > 0 ? profile.profileSalary[0] : null,
        profileInsignia: profile.profileInsignias.length > 0 ? profile.profileInsignias[0] : null,
        profileType: "EMPLOYEE",
      };

      return new HttpSuccess(mapProfile);
    }

    const org = {
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.id ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.id ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.id ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.id ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.id ?? null,
    };

    let fullname = "";
    let pos = await this.posMasterRepository.findOne({
      relations: ["current_holder"],
      where: {
        orgRevision: {
          orgRevisionIsCurrent: true,
          orgRevisionIsDraft: false,
        },
        isDirector: true,
        orgRootId: org?.root ?? "",
        orgChild1Id: org?.child1 ?? "",
        orgChild2Id: org?.child2 ?? "",
        orgChild3Id: org?.child3 ?? "",
        orgChild4Id: org?.child4 ?? "",
      },
    });

    if (pos) {
      fullname =
        pos.current_holder.prefix +
        pos.current_holder.firstName +
        " " +
        pos.current_holder.lastName;
    } else {
      let pos = await this.posMasterRepository.findOne({
        relations: ["current_holder"],
        where: {
          orgRevision: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
          isDirector: true,
          orgRootId: org?.root ?? "",
          orgChild1Id: org?.child1 ?? "",
          orgChild2Id: org?.child2 ?? "",
          orgChild3Id: org?.child3 ?? "",
          orgChild4Id: IsNull(),
        },
      });
      if (pos) {
        fullname =
          pos.current_holder.prefix +
          pos.current_holder.firstName +
          " " +
          pos.current_holder.lastName;
      } else {
        let pos = await this.posMasterRepository.findOne({
          relations: ["current_holder"],
          where: {
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
            isDirector: true,
            orgRootId: org?.root ?? "",
            orgChild1Id: org?.child1 ?? "",
            orgChild2Id: org?.child2 ?? "",
            orgChild3Id: IsNull(),
            orgChild4Id: IsNull(),
          },
        });
        if (pos) {
          fullname =
            pos.current_holder.prefix +
            pos.current_holder.firstName +
            " " +
            pos.current_holder.lastName;
        } else {
          let pos = await this.posMasterRepository.findOne({
            relations: ["current_holder"],
            where: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
              isDirector: true,
              orgRootId: org?.root ?? "",
              orgChild1Id: org?.child1 ?? "",
              orgChild2Id: IsNull(),
              orgChild3Id: IsNull(),
              orgChild4Id: IsNull(),
            },
          });
          if (pos) {
            fullname =
              pos.current_holder.prefix +
              pos.current_holder.firstName +
              " " +
              pos.current_holder.lastName;
          } else {
            let pos = await this.posMasterRepository.findOne({
              relations: ["current_holder"],
              where: {
                orgRevision: {
                  orgRevisionIsCurrent: true,
                  orgRevisionIsDraft: false,
                },
                orgRootId: org?.root ?? "",
                orgChild1Id: IsNull(),
                orgChild2Id: IsNull(),
                orgChild3Id: IsNull(),
                orgChild4Id: IsNull(),
              },
            });
            if (pos) {
              fullname =
                pos.current_holder.prefix +
                pos.current_holder.firstName +
                " " +
                pos.current_holder.lastName;
            } else {
              fullname = "";
            }
          }
        }
      }
    }

    const mapProfile = {
      id: profile.id,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      rank: profile.rank,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      posLevelId: profile.posLevelId,
      email: profile.email,
      phone: profile.phone,
      keycloak: profile.keycloak,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      leaveReason: profile.leaveReason,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate ?? new Date(),
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.phone,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      registrationAddress: profile.registrationAddress,
      registrationProvinceId: profile.registrationProvinceId,
      registrationDistrictId: profile.registrationDistrictId,
      registrationSubDistrictId: profile.registrationSubDistrictId,
      registrationZipCode: profile.registrationZipCode,
      currentAddress: profile.currentAddress,
      currentProvinceId: profile.currentProvinceId,
      currentSubDistrictId: profile.currentSubDistrictId,
      currentZipCode: profile.currentZipCode,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      amount: profile.amount,
      positionSalaryAmount: profile.positionSalaryAmount,
      mouthSalaryAmount: profile.mouthSalaryAmount,
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.orgRootName ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.orgChild1Name ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.orgChild2Name ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.orgChild3Name ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.orgChild4Name ?? null,
      rootId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRootId ?? null,
      child1Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1Id ?? null,
      child2Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2Id ?? null,
      child3Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3Id ?? null,
      child4Id:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4Id ?? null,
      rootDnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.ancestorDNA ?? null,
      child1DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.ancestorDNA ?? null,
      child2DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.ancestorDNA ?? null,
      child3DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.ancestorDNA ?? null,
      child4DnaId:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.ancestorDNA ?? null,
      commander: fullname,
      posLevel: profile.posLevel?.posLevelName ?? null,
      posType: profile.posType?.posTypeName ?? null,
      profileSalary: profile.profileSalary.length > 0 ? profile.profileSalary[0] : null,
      profileInsignia: profile.profileInsignias.length > 0 ? profile.profileInsignias[0] : null,
      profileType: "OFFICER",
    };

    return new HttpSuccess(mapProfile);
  }

  /**
   * 3.	API Get Profile จาก keycloak id
   *
   * @summary 3. API Get Profile จาก keycloak id
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("root/officer/{rootId}")
  @Security("internalAuth")
  async GetProfileByRootIdAsync(@Path() rootId: string) {
    const profiles = await this.profileRepo.find({
      relations: [
        "posLevel",
        "posType",
        "profileSalary",
        "profileInsignias",
        "profileInsignias.insignia",
        "profileDisciplines",
        "profileAssessments",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { current_holders: { orgRootId: rootId } },
      order: {
        profileSalary: {
          commandDateAffect: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });

    const currentYear = new Date().getFullYear();
    const years = [currentYear, currentYear - 1, currentYear - 2, currentYear - 3, currentYear - 4];

    // APR Averages
    const aprAverages: { [year: number]: number | null } = {};
    const aprSums: { [year: number]: number } = {};
    const aprCounts: { [year: number]: number } = {};

    // OCT Averages
    const octAverages: { [year: number]: number | null } = {};
    const octSums: { [year: number]: number } = {};
    const octCounts: { [year: number]: number } = {};

    years.forEach((year) => {
      aprAverages[year] = null;
      aprSums[year] = 0;
      aprCounts[year] = 0;

      octAverages[year] = null;
      octSums[year] = 0;
      octCounts[year] = 0;
    });

    profiles.forEach((profile) => {
      const assessments = profile.profileAssessments || [];

      assessments.forEach((assessment) => {
        const year = Number(assessment.year);

        if (years.includes(year)) {
          if (assessment.period === "APR") {
            aprSums[year] += assessment.pointSum;
            aprCounts[year] += 1;
          }

          if (assessment.period === "OCT") {
            octSums[year] += assessment.pointSum;
            octCounts[year] += 1;
          }
        }
      });
    });

    years.forEach((year) => {
      aprAverages[year] = aprCounts[year] > 0 ? aprSums[year] / aprCounts[year] : null;
      octAverages[year] = octCounts[year] > 0 ? octSums[year] / octCounts[year] : null;
    });

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

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

      return {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank ?? "",
        prefix: profile.prefix ?? "",
        firstName: profile.firstName ?? "",
        lastName: profile.lastName ?? "",
        citizenId: profile.citizenId ?? "",
        position: profile.position ?? "",
        posLevelId: profile.posLevelId,
        posTypeId: profile.posTypeId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender ?? "",
        relationship: profile.relationship ?? "",
        religion: profile.religion ?? "",
        bloodGroup: profile.bloodGroup ?? "",
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationZipCode: profile.registrationZipCode,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentZipCode: profile.currentZipCode,
        dutyTimeId: profile.dutyTimeId,
        dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        posLevel: profile.posLevel?.posLevelName ?? "",
        posType: profile.posType?.posTypeName ?? "",
        // profileSalary: profile.profileSalary,
        profileSalary:
          profile.profileSalary?.map((x) => ({
            ...x,
            date: x.commandDateAffect ?? new Date(),
          })) ?? [],
        // profileInsignia: profile.profileInsignias.map((x) => {
        //   return { ...x, insignia: x.insignia.name };
        // }),
        profileInsignia:
          profile.profileInsignias?.map((x) => ({
            ...x,
            insigniaId: x.insignia?.id ?? null,
            insignia: x.insignia?.name ?? null,
          })) ?? [],
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        profileType: "OFFICER",
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        rootId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRootId ?? null,
        rootDnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.ancestorDNA ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.orgChild1Name ?? null,
        child1Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1Id ?? null,
        child1DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.ancestorDNA ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.orgChild2Name ?? null,
        child2Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2Id ?? null,
        child2DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.ancestorDNA ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.orgChild3Name ?? null,
        child3Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3Id ?? null,
        child3DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.ancestorDNA ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.orgChild4Name ?? null,
        child4Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4Id ?? null,
        child4DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.ancestorDNA ?? null,
        posNo: shortName ?? "",
        markDiscipline: profile.profileDisciplines.length > 0 ? true : false,
        markLeave: false,
        markRate: profile.profileAssessments.length > 0 ? true : false,
        markInsignia: profile.profileInsignias.length > 0 ? true : false,
        apr1: aprAverages[currentYear]
          ? Extension.textPoint(aprAverages[currentYear] as number)
          : null,
        apr2: aprAverages[currentYear - 1]
          ? Extension.textPoint(aprAverages[currentYear - 1] as number)
          : null,
        apr3: aprAverages[currentYear - 2]
          ? Extension.textPoint(aprAverages[currentYear - 2] as number)
          : null,
        apr4: aprAverages[currentYear - 3]
          ? Extension.textPoint(aprAverages[currentYear - 3] as number)
          : null,
        apr5: aprAverages[currentYear - 4]
          ? Extension.textPoint(aprAverages[currentYear - 4] as number)
          : null,
        oct1: octAverages[currentYear]
          ? Extension.textPoint(octAverages[currentYear] as number)
          : null,
        oct2: octAverages[currentYear - 1]
          ? Extension.textPoint(octAverages[currentYear - 1] as number)
          : null,
        oct3: octAverages[currentYear - 2]
          ? Extension.textPoint(octAverages[currentYear - 2] as number)
          : null,
        oct4: octAverages[currentYear - 3]
          ? Extension.textPoint(octAverages[currentYear - 3] as number)
          : null,
        oct5: octAverages[currentYear - 4]
          ? Extension.textPoint(octAverages[currentYear - 4] as number)
          : null,
      };
    });

    return new HttpSuccess(mapProfile);
  }

  /**
   * 3.	API Get Profile จาก keycloak id
   *
   * @summary 3. API Get Profile จาก keycloak id
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("root/employee/{rootId}")
  @Security("internalAuth")
  async GetProfileByRootIdEmpAsync(@Path() rootId: string) {
    const profiles = await this.profileEmpRepo.find({
      relations: [
        "posLevel",
        "posType",
        "profileSalary",
        "profileInsignias",
        "profileInsignias.insignia",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: { current_holders: { orgRootId: rootId } },
      order: {
        profileSalary: {
          commandDateAffect: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });

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

    // const currentYear = new Date().getFullYear();
    // const years = [currentYear, currentYear - 1, currentYear - 2, currentYear - 3, currentYear - 4];

    // // APR Averages
    // const aprAverages: { [year: number]: number | null } = {};
    // const aprSums: { [year: number]: number } = {};
    // const aprCounts: { [year: number]: number } = {};

    // // OCT Averages
    // const octAverages: { [year: number]: number | null } = {};
    // const octSums: { [year: number]: number } = {};
    // const octCounts: { [year: number]: number } = {};

    // years.forEach(year => {
    //   aprAverages[year] = null;
    //   aprSums[year] = 0;
    //   aprCounts[year] = 0;

    //   octAverages[year] = null;
    //   octSums[year] = 0;
    //   octCounts[year] = 0;
    // });

    // profiles.forEach(profile => {
    //   const assessments = profile.profileAssessments || [];

    //   assessments.forEach(assessment => {
    //     const year = Number(assessment.year);

    //     if (years.includes(year)) {
    //       if (assessment.period === 'APR') {
    //         aprSums[year] += assessment.pointSum;
    //         aprCounts[year] += 1;
    //       }

    //       if (assessment.period === 'OCT') {
    //         octSums[year] += assessment.pointSum;
    //         octCounts[year] += 1;
    //       }
    //     }
    //   });
    // });

    // years.forEach(year => {
    //   aprAverages[year] = aprCounts[year] > 0 ? aprSums[year] / aprCounts[year] : null;
    //   octAverages[year] = octCounts[year] > 0 ? octSums[year] / octCounts[year] : null;
    // });

    const mapProfile = profiles.map((profile) => {
      const shortName =
        profile.current_holders.length == 0
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
              profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                null
            ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
            : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                  ?.orgChild3 != null
              ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild2 != null
                ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                      null &&
                    profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild1 != null
                  ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                        null &&
                      profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgRoot != null
                    ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : null;
      return {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank ?? "",
        prefix: profile.prefix ?? "",
        firstName: profile.firstName ?? "",
        lastName: profile.lastName ?? "",
        citizenId: profile.citizenId ?? "",
        position: profile.position ?? "",
        posLevelId: profile.posLevelId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender ?? "",
        relationship: profile.relationship ?? "",
        religion: profile.religion ?? "",
        bloodGroup: profile.bloodGroup ?? "",
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationZipCode: profile.registrationZipCode,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentZipCode: profile.currentZipCode,
        //   dutyTimeId: profile.dutyTimeId,
        //   dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        posLevel:
          (profile.posType == null || profile.posType?.posTypeShortName == null
            ? ""
            : profile.posType?.posTypeShortName + " ") + (profile.posLevel?.posLevelName ?? ""),
        posType: profile.posType?.posTypeName ?? "",
        profileSalary: profile.profileSalary,
        // profileInsignia: profile.profileInsignias.map((x) => {
        //   return { ...x, insignia: x.insignia.name };
        // }),
        profileInsignia:
          profile.profileInsignias?.map((x) => ({
            ...x,
            insigniaId: x.insignia?.id ?? null,
            insignia: x.insignia?.name ?? null,
          })) ?? [],
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        profileType: "EMPLOYEE",
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        rootId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRootId ?? null,
        posNo: shortName ?? "",
        // apr1:aprAverages[currentYear] ? Extension.textPoint(aprAverages[currentYear] as number) : null,
        // apr2:aprAverages[currentYear - 1] ? Extension.textPoint(aprAverages[currentYear - 1] as number) : null,
        // apr3:aprAverages[currentYear - 2] ? Extension.textPoint(aprAverages[currentYear - 2] as number) : null,
        // apr4:aprAverages[currentYear - 3] ? Extension.textPoint(aprAverages[currentYear - 3] as number) : null,
        // apr5:aprAverages[currentYear - 4] ? Extension.textPoint(aprAverages[currentYear - 4] as number) : null,
        // oct1:octAverages[currentYear] ? Extension.textPoint(octAverages[currentYear] as number) : null,
        // oct2:octAverages[currentYear - 1] ? Extension.textPoint(octAverages[currentYear - 1] as number) : null,
        // oct3:octAverages[currentYear - 2] ? Extension.textPoint(octAverages[currentYear - 2] as number) : null,
        // oct4:octAverages[currentYear - 3] ? Extension.textPoint(octAverages[currentYear - 3] as number) : null,
        // oct5:octAverages[currentYear - 4] ? Extension.textPoint(octAverages[currentYear - 4] as number) : null,
      };
    });

    return new HttpSuccess(mapProfile);
  }

  /**
   * 3.	API Get Profile จาก keycloak id
   *
   * @summary 3. API Get Profile จาก keycloak id
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Post("find/employee/position")
  @Security("internalAuth")
  async GetProfileByPositionEmpAsync(
    @Body()
    body: {
      empPosId: string[];
      rootId: string;
    },
  ) {
    const findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    const employeePosDict = await this.employeePosDictRepository.find({
      where: { id: In(body.empPosId) },
    });

    const profiles = await this.profileEmpRepo.find({
      relations: [
        "posLevel",
        "posType",
        "profileSalary",
        "profileInsignias",
        "profileInsignias.insignia",
        "profileDisciplines",
        "profileAssessments",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      where: employeePosDict.map((entry) => ({
        posLevelId: entry.posLevelId,
        posTypeId: entry.posTypeId,
        position: entry.posDictName,
        current_holders: { orgRootId: body.rootId },
      })),
      order: {
        profileSalary: {
          commandDateAffect: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });

    const currentYear = new Date().getFullYear();
    const years = [currentYear, currentYear - 1, currentYear - 2, currentYear - 3, currentYear - 4];

    // APR Averages
    const aprAverages: { [year: number]: number | null } = {};
    const aprSums: { [year: number]: number } = {};
    const aprCounts: { [year: number]: number } = {};

    // OCT Averages
    const octAverages: { [year: number]: number | null } = {};
    const octSums: { [year: number]: number } = {};
    const octCounts: { [year: number]: number } = {};

    years.forEach((year) => {
      aprAverages[year] = null;
      aprSums[year] = 0;
      aprCounts[year] = 0;

      octAverages[year] = null;
      octSums[year] = 0;
      octCounts[year] = 0;
    });

    profiles.forEach((profile) => {
      const assessments = profile.profileAssessments || [];

      assessments.forEach((assessment) => {
        const year = Number(assessment.year);

        if (years.includes(year)) {
          if (assessment.period === "APR") {
            aprSums[year] += assessment.pointSum;
            aprCounts[year] += 1;
          }

          if (assessment.period === "OCT") {
            octSums[year] += assessment.pointSum;
            octCounts[year] += 1;
          }
        }
      });
    });

    years.forEach((year) => {
      aprAverages[year] = aprCounts[year] > 0 ? aprSums[year] / aprCounts[year] : null;
      octAverages[year] = octCounts[year] > 0 ? octSums[year] / octCounts[year] : null;
    });

    const mapProfile = profiles.map((profile) => {
      const shortName =
        profile.current_holders.length == 0
          ? null
          : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
              profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                null
            ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
            : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                  ?.orgChild3 != null
              ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild2 != null
                ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                      null &&
                    profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild1 != null
                  ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                        null &&
                      profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgRoot != null
                    ? `${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${profile.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : null;
      return {
        id: profile.id,
        avatar: profile.avatar,
        avatarName: profile.avatarName,
        rank: profile.rank ?? "",
        prefix: profile.prefix ?? "",
        firstName: profile.firstName ?? "",
        lastName: profile.lastName ?? "",
        citizenId: profile.citizenId ?? "",
        position: profile.position ?? "",
        posLevelId: profile.posLevelId,
        email: profile.email,
        phone: profile.phone,
        keycloak: profile.keycloak,
        isProbation: profile.isProbation,
        isLeave: profile.isLeave,
        leaveReason: profile.leaveReason,
        dateRetire: profile.dateRetire,
        dateAppoint: profile.dateAppoint,
        dateRetireLaw: profile.dateRetireLaw,
        dateStart: profile.dateStart,
        govAgeAbsent: profile.govAgeAbsent,
        govAgePlus: profile.govAgePlus,
        birthDate: profile.birthDate ?? new Date(),
        reasonSameDate: profile.reasonSameDate,
        telephoneNumber: profile.phone,
        nationality: profile.nationality,
        gender: profile.gender ?? "",
        relationship: profile.relationship ?? "",
        religion: profile.religion ?? "",
        bloodGroup: profile.bloodGroup ?? "",
        registrationAddress: profile.registrationAddress,
        registrationProvinceId: profile.registrationProvinceId,
        registrationDistrictId: profile.registrationDistrictId,
        registrationSubDistrictId: profile.registrationSubDistrictId,
        registrationZipCode: profile.registrationZipCode,
        currentAddress: profile.currentAddress,
        currentProvinceId: profile.currentProvinceId,
        currentSubDistrictId: profile.currentSubDistrictId,
        currentZipCode: profile.currentZipCode,
        //   dutyTimeId: profile.dutyTimeId,
        //   dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
        posLevel:
          (profile.posType == null || profile.posType?.posTypeShortName == null
            ? ""
            : profile.posType?.posTypeShortName + " ") + (profile.posLevel?.posLevelName ?? ""),
        posType: profile.posType?.posTypeName ?? "",
        // profileSalary: profile.profileSalary.map((x) => {
        //   return { ...x, date: x.commandDateAffect ?? new Date() };
        // }),
        profileSalary:
          profile.profileSalary?.map((x) => ({
            ...x,
            date: x.commandDateAffect ?? new Date(),
          })) ?? [],
        // profileInsignia: profile.profileInsignias.map((x) => {
        //   return { ...x, insignia: x.insignia.name };
        // }),
        profileInsignia:
          profile.profileInsignias?.map((x) => ({
            ...x,
            insigniaId: x.insignia?.id ?? null,
            insignia: x.insignia?.name ?? null,
          })) ?? [],
        amount: profile.amount,
        positionSalaryAmount: profile.positionSalaryAmount,
        mouthSalaryAmount: profile.mouthSalaryAmount,
        profileType: "EMPLOYEE",
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        rootId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRootId ?? null,
        rootDnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.ancestorDNA ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.orgChild1Name ?? null,
        child1Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1Id ?? null,
        child1DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.ancestorDNA ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.orgChild2Name ?? null,
        child2Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2Id ?? null,
        child2DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.ancestorDNA ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.orgChild3Name ?? null,
        child3Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3Id ?? null,
        child3DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.ancestorDNA ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.orgChild4Name ?? null,
        child4Id:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4Id ?? null,
        child4DnaId:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.ancestorDNA ?? null,
        posNo: shortName ?? "",
        markDiscipline: profile.profileDisciplines.length > 0 ? true : false,
        markLeave: false,
        markRate: profile.profileAssessments.length > 0 ? true : false,
        markInsignia: profile.profileInsignias.length > 0 ? true : false,
        apr1: aprAverages[currentYear]
          ? Extension.textPoint(aprAverages[currentYear] as number)
          : null,
        apr2: aprAverages[currentYear - 1]
          ? Extension.textPoint(aprAverages[currentYear - 1] as number)
          : null,
        apr3: aprAverages[currentYear - 2]
          ? Extension.textPoint(aprAverages[currentYear - 2] as number)
          : null,
        apr4: aprAverages[currentYear - 3]
          ? Extension.textPoint(aprAverages[currentYear - 3] as number)
          : null,
        apr5: aprAverages[currentYear - 4]
          ? Extension.textPoint(aprAverages[currentYear - 4] as number)
          : null,
        oct1: octAverages[currentYear]
          ? Extension.textPoint(octAverages[currentYear] as number)
          : null,
        oct2: octAverages[currentYear - 1]
          ? Extension.textPoint(octAverages[currentYear - 1] as number)
          : null,
        oct3: octAverages[currentYear - 2]
          ? Extension.textPoint(octAverages[currentYear - 2] as number)
          : null,
        oct4: octAverages[currentYear - 3]
          ? Extension.textPoint(octAverages[currentYear - 3] as number)
          : null,
        oct5: octAverages[currentYear - 4]
          ? Extension.textPoint(octAverages[currentYear - 4] as number)
          : null,
      };
    });

    return new HttpSuccess(mapProfile);
  }

  /**
   * 7.1 Get ข้อมูล GetUserFullName
   *
   * @summary 7.1 Get ข้อมูล GetUserFullName
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("user-fullname/{keycloakId}")
  @Security("internalAuth")
  async GetUserFullName(@Path() keycloakId: string) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      select: ["prefix", "firstName", "lastName"],
    });
    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    const fullName = profile ? `${profile.prefix}${profile.firstName} ${profile.lastName}` : "-";
    return new HttpSuccess(fullName);
  }

  /**
   * 7.2 Get ข้อมูล GetUserOCId
   *
   * @summary 7.2 Get ข้อมูล GetUserOCId
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("user-oc/{keycloakId}")
  @Security("internalAuth")
  async getProfileByKeycloak(@Path() keycloakId: string) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      relations: ["posLevel", "posType", "current_holders", "current_holders.orgRoot"],
    });
    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 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 _profile: any = {
      profileId: profile.id,
      prefix: profile.prefix,
      rank: profile.rank,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate ?? new Date(),
      position: profile.position,
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      rootShortName: root == null ? null : root.orgRootShortName,
      rootDnaId: root == null ? null : root.ancestorDNA,
    };
    return new HttpSuccess(_profile);
  }

  /**
   * 7.3 Get ข้อมูล GetUserOCId (all node)
   *
   * @summary 7.3 Get ข้อมูล GetUserOCId (all node)
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("user-oc-all/{keycloakId}")
  @Security("internalAuth")
  async getAllProfileByKeycloak(@Path() keycloakId: string) {
    const profile = await this.profileRepo.findOne({
      where: { keycloak: keycloakId },
      // relations: [
      //   "profileSalary",
      //   "profileEducations",
      //   "current_holders",
      //   "current_holders.orgRoot",
      //   "current_holders.orgChild1",
      //   "current_holders.orgChild2",
      //   "current_holders.orgChild3",
      //   "current_holders.orgChild4",
      // ],
      relations: {
        posType: true,
        posLevel: true,
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
          orgChild2: true,
          orgChild3: true,
          orgChild4: true,
        },
      },
    });
    if (!profile) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    }

    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,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate ?? new Date(),
      position: profile.position,
      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,
      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,
    };

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

  /**
   * 8.	หา root OC Id
   *
   * @summary 8.	หา root OC Id
   *
   * @param {string} ocId  Id หน่วยงาน
   */
  @Get("root-oc/{ocId}")
  @Security("internalAuth")
  async GetRootOcId(@Path() ocId: string) {
    const orgRoot = await this.orgRootRepo.findOne({
      where: { id: ocId },
    });
    if (!orgRoot) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    const root = orgRoot ? orgRoot.id : "";
    return new HttpSuccess(root);
  }

  /**
   * 5.	เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   * @summary 5. เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   */
  @Get("keycloak")
  @Security("internalAuth")
  async GetProfileWithKeycloak() {
    const profile = await this.profileRepo.find({
      where: { keycloak: Not(IsNull()) },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        // "profileSalary",
      ],
      // order: {
      //   profileSalary: {
      //     order: "DESC",
      //   },
      // },
    });

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

    // const profile_ = await Promise.all(
    //   profile.map((item: Profile) => {
    //     const rootName =
    //       item.current_holders.length == 0
    //         ? null
    //         : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot
    //           ?.orgRootName;
    //     const shortName =
    //       item.current_holders.length == 0
    //         ? null
    //         : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
    //           item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
    //           null
    //           ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
    //           : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
    //             item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
    //               ?.orgChild3 != null
    //             ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
    //             : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
    //               item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
    //                 ?.orgChild2 != null
    //               ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
    //               : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
    //                 item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
    //                   ?.orgChild1 != null
    //                 ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
    //                 : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
    //                   null &&
    //                   item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
    //                     ?.orgRoot != null
    //                   ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
    //                   : null;

    //     return {
    //       oc: rootName,
    //       id: item.id,
    //       createdAt: item.createdAt,
    //       createdUserId: item.createdUserId,
    //       lastUpdatedAt: item.lastUpdatedAt,
    //       lastUpdateUserId: item.lastUpdateUserId,
    //       createdFullName: item.createdFullName,
    //       lastUpdateFullName: item.lastUpdateFullName,
    //       avatar: item.avatar,
    //       avatarName: item.avatarName,
    //       rank: item.rank,
    //       prefix: item.prefix,
    //       firstName: item.firstName,
    //       lastName: item.lastName,
    //       citizenId: item.citizenId,
    //       position: item.position,
    //       posLevelId: item.posLevelId,
    //       posTypeId: item.posTypeId,
    //       email: item.email,
    //       phone: item.phone,
    //       keycloak: item.keycloak,
    //       isProbation: item.isProbation,
    //       isLeave: item.isLeave,
    //       leaveReason: item.leaveReason,
    //       dateLeave: item.dateLeave,
    //       dateRetire: item.dateRetire,
    //       dateAppoint: item.dateAppoint,
    //       dateRetireLaw: item.dateRetireLaw,
    //       dateStart: item.dateStart,
    //       govAgeAbsent: item.govAgeAbsent,
    //       govAgePlus: item.govAgePlus,
    //       birthDate: item.birthDate ?? new Date(),
    //       reasonSameDate: item.reasonSameDate,
    //       ethnicity: item.ethnicity,
    //       telephoneNumber: item.phone,
    //       nationality: item.nationality,
    //       gender: item.gender,
    //       relationship: item.relationship,
    //       religion: item.religion,
    //       bloodGroup: item.bloodGroup,
    //       registrationAddress: item.registrationAddress,
    //       registrationProvinceId: item.registrationProvinceId,
    //       registrationDistrictId: item.registrationDistrictId,
    //       registrationSubDistrictId: item.registrationSubDistrictId,
    //       registrationZipCode: item.registrationZipCode,
    //       currentAddress: item.currentAddress,
    //       currentProvinceId: item.currentProvinceId,
    //       currentDistrictId: item.currentDistrictId,
    //       currentSubDistrictId: item.currentSubDistrictId,
    //       currentZipCode: item.currentZipCode,
    //       dutyTimeId: item.dutyTimeId,
    //       dutyTimeEffectiveDate: item.dutyTimeEffectiveDate,
    //       positionLevel: item.posLevel?.posLevelName ?? null,
    //       positionType: item.posType?.posTypeName ?? null,
    //       posNo: shortName,
    //     };
    //   }),
    // );
    const profile_ = profile.map((item: Profile) => {
      const holder = item.current_holders?.find((x) => x.orgRevisionId === findRevision?.id);

      const rootName = holder?.orgRoot?.orgRootName ?? null;

      let shortName: string | null = null;

      if (holder) {
        const posNo = holder.posMasterNo;

        if (holder.orgChild4) {
          shortName = `${holder.orgChild4.orgChild4ShortName} ${posNo}`;
        } else if (holder.orgChild3) {
          shortName = `${holder.orgChild3.orgChild3ShortName} ${posNo}`;
        } else if (holder.orgChild2) {
          shortName = `${holder.orgChild2.orgChild2ShortName} ${posNo}`;
        } else if (holder.orgChild1) {
          shortName = `${holder.orgChild1.orgChild1ShortName} ${posNo}`;
        } else if (holder.orgRoot) {
          shortName = `${holder.orgRoot.orgRootShortName} ${posNo}`;
        }
      }

      return {
        oc: rootName,
        id: item.id,
        createdAt: item.createdAt,
        createdUserId: item.createdUserId,
        lastUpdatedAt: item.lastUpdatedAt,
        lastUpdateUserId: item.lastUpdateUserId,
        createdFullName: item.createdFullName,
        lastUpdateFullName: item.lastUpdateFullName,
        avatar: item.avatar,
        avatarName: item.avatarName,
        rank: item.rank,
        prefix: item.prefix,
        firstName: item.firstName,
        lastName: item.lastName,
        citizenId: item.citizenId,
        position: item.position,
        posLevelId: item.posLevelId,
        posTypeId: item.posTypeId,
        email: item.email,
        phone: item.phone,
        keycloak: item.keycloak,
        isProbation: item.isProbation,
        isLeave: item.isLeave,
        leaveReason: item.leaveReason,
        dateLeave: item.dateLeave,
        dateRetire: item.dateRetire,
        dateAppoint: item.dateAppoint,
        dateRetireLaw: item.dateRetireLaw,
        dateStart: item.dateStart,
        govAgeAbsent: item.govAgeAbsent,
        govAgePlus: item.govAgePlus,
        birthDate: item.birthDate ?? new Date(),
        reasonSameDate: item.reasonSameDate,
        ethnicity: item.ethnicity,
        telephoneNumber: item.phone,
        nationality: item.nationality,
        gender: item.gender,
        relationship: item.relationship,
        religion: item.religion,
        bloodGroup: item.bloodGroup,
        registrationAddress: item.registrationAddress,
        registrationProvinceId: item.registrationProvinceId,
        registrationDistrictId: item.registrationDistrictId,
        registrationSubDistrictId: item.registrationSubDistrictId,
        registrationZipCode: item.registrationZipCode,
        currentAddress: item.currentAddress,
        currentProvinceId: item.currentProvinceId,
        currentDistrictId: item.currentDistrictId,
        currentSubDistrictId: item.currentSubDistrictId,
        currentZipCode: item.currentZipCode,
        dutyTimeId: item.dutyTimeId,
        dutyTimeEffectiveDate: item.dutyTimeEffectiveDate,
        positionLevel: item.posLevel?.posLevelName ?? null,
        positionType: item.posType?.posTypeName ?? null,
        posNo: shortName,
      };
    });

    return new HttpSuccess(profile_);
  }

  /**
   * 5.	เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   * @summary 5. เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   */
  @Get("keycloak-employee")
  @Security("internalAuth")
  async GetProfileWithKeycloakEmployee() {
    const profile = await this.profileEmpRepo.find({
      where: { keycloak: Not(IsNull()) || Not("") },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        // "profileSalary",
      ],
      // order: {
      //   profileSalary: {
      //     order: "DESC",
      //   },
      // },
    });

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

    const profile_ = await Promise.all(
      profile.map((item: ProfileEmployee) => {
        const rootName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot
                ?.orgRootName;
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;

        return {
          oc: rootName,
          id: item.id,
          createdAt: item.createdAt,
          createdUserId: item.createdUserId,
          lastUpdatedAt: item.lastUpdatedAt,
          lastUpdateUserId: item.lastUpdateUserId,
          createdFullName: item.createdFullName,
          lastUpdateFullName: item.lastUpdateFullName,
          avatar: item.avatar,
          avatarName: item.avatarName,
          rank: item.rank,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          position: item.position,
          posLevelId: item.posLevelId,
          posTypeId: item.posTypeId,
          email: item.email,
          phone: item.phone,
          keycloak: item.keycloak,
          isProbation: item.isProbation,
          isLeave: item.isLeave,
          leaveReason: item.leaveReason,
          dateLeave: item.dateLeave,
          dateRetire: item.dateRetire,
          dateAppoint: item.dateAppoint,
          dateRetireLaw: item.dateRetireLaw,
          dateStart: item.dateStart,
          govAgeAbsent: item.govAgeAbsent,
          govAgePlus: item.govAgePlus,
          birthDate: item.birthDate ?? new Date(),
          reasonSameDate: item.reasonSameDate,
          ethnicity: item.ethnicity,
          telephoneNumber: item.phone,
          nationality: item.nationality,
          gender: item.gender,
          relationship: item.relationship,
          religion: item.religion,
          bloodGroup: item.bloodGroup,
          registrationAddress: item.registrationAddress,
          registrationProvinceId: item.registrationProvinceId,
          registrationDistrictId: item.registrationDistrictId,
          registrationSubDistrictId: item.registrationSubDistrictId,
          registrationZipCode: item.registrationZipCode,
          currentAddress: item.currentAddress,
          currentProvinceId: item.currentProvinceId,
          currentDistrictId: item.currentDistrictId,
          currentSubDistrictId: item.currentSubDistrictId,
          currentZipCode: item.currentZipCode,
          dutyTimeId: item.dutyTimeId,
          dutyTimeEffectiveDate: item.dutyTimeEffectiveDate,
          positionLevel: item.posLevel?.posLevelName ?? null,
          positionType: item.posType?.posTypeName ?? null,
          posNo: shortName,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * 5.	เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   * @summary 5. เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   */
  @Post("keycloak-all-officer")
  @Security("internalAuth")
  async PostProfileWithKeycloakAllOfficer(
    @Body()
    body: {
      node: number;
      nodeId: string;
      isAll: boolean;
      isRetirement?: boolean;
      revisionId?: string;
    },
  ) {
    let typeCondition: any = {};
    if (body.isAll == false) {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
          orgChild1Id: IsNull(),
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
          orgChild2Id: IsNull(),
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
          orgChild3Id: IsNull(),
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
          orgChild4Id: IsNull(),
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    } else {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    }
    let profile = await this.profileRepo.find({
      where: { keycloak: Not(IsNull()) || Not(""), isLeave: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });
    if (body.isRetirement) {
      profile = await this.profileRepo.find({
        where: {
          keycloak: Not(IsNull()) || Not(""),
          isLeave: false,
          current_holders: typeCondition,
          isRetirement: true,
        },
        relations: [
          "posType",
          "posLevel",
          "current_holders",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
      });
    }
    let findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map((item: Profile) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName}${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : body.node == 4 && item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : body.node == 3 && item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : body.node == 2 && item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : body.node == 1 && item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : body.node == 0 && item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;
        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel: item.posLevel?.posLevelName ?? null,
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * 5.	เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   * @summary 5. เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   */
  @Post("keycloak-all-officer/date")
  @Security("internalAuth")
  async PostProfileWithKeycloakAllOfficerDate(
    @Body()
    body: {
      node: number;
      nodeId: string;
      isAll: boolean;
      isRetirement?: boolean;
      revisionId?: string;
      startDate: Date;
      endDate: Date;
    },
  ) {
    let typeCondition: any = {};
    // if (body.isAll == false) {
    //   if (body.node === 0) {
    //     typeCondition = {
    //       orgRootId: body.nodeId,
    //       orgChild1Id: IsNull(),
    //     };
    //   } else if (body.node === 1) {
    //     typeCondition = {
    //       orgChild1Id: body.nodeId,
    //       orgChild2Id: IsNull(),
    //     };
    //   } else if (body.node === 2) {
    //     typeCondition = {
    //       orgChild2Id: body.nodeId,
    //       orgChild3Id: IsNull(),
    //     };
    //   } else if (body.node === 3) {
    //     typeCondition = {
    //       orgChild3Id: body.nodeId,
    //       orgChild4Id: IsNull(),
    //     };
    //   } else if (body.node === 4) {
    //     typeCondition = {
    //       orgChild4Id: body.nodeId,
    //     };
    //   }
    // } else {
    if (body.node === 0) {
      typeCondition = {
        orgRootId: body.nodeId,
      };
    } else if (body.node === 1) {
      typeCondition = {
        orgChild1Id: body.nodeId,
      };
    } else if (body.node === 2) {
      typeCondition = {
        orgChild2Id: body.nodeId,
      };
    } else if (body.node === 3) {
      typeCondition = {
        orgChild3Id: body.nodeId,
      };
    } else if (body.node === 4) {
      typeCondition = {
        orgChild4Id: body.nodeId,
      };
    }
    // }
    let profile = await this.profileRepo.find({
      where: { keycloak: Not(IsNull()) || Not(""), isLeave: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });
    const startDate = new Date().getFullYear();
    const endDate = new Date().getFullYear();
    const startOfYear = new Date(startDate, 0, 1); // 1 ม.ค. ปีนี้
    const endOfYear = new Date(endDate, 11, 31, 23, 59, 59, 999); // 31 ธ.ค. ปีนี้
    if (body.isRetirement) {
      profile = await this.profileRepo.find({
        where: {
          keycloak: Not(IsNull()) || Not(""),
          // isLeave: false,
          current_holders: typeCondition,
          // isRetirement: true,
          dateRetire: And(Not(IsNull()), Between(startOfYear, endOfYear)),
        },
        relations: [
          "posType",
          "posLevel",
          "current_holders",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
      });
    }

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

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map((item: Profile) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName}${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : body.node == 4 && item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : body.node == 3 && item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : body.node == 2 && item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : body.node == 1 && item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : body.node == 0 && item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;
        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel: item.posLevel?.posLevelName ?? null,
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * 5.	เอารายชื่อคน ขรก. (none-validate-keycloak)
   *
   * @summary 5. เอารายชื่อคน ขรก. (none-validate-keycloak)
   *
   */
  @Post("none-validate-keycloak-all-officer")
  @Security("internalAuth")
  async PostProfileWithNoneValidateKeycloakAllOfficer(
    @Body()
    body: {
      node: number;
      nodeId: string;
      isAll: boolean;
      isRetirement?: boolean;
      revisionId?: string;
    },
  ) {
    let typeCondition: any = {};
    if (body.isAll == false) {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
          orgChild1Id: IsNull(),
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
          orgChild2Id: IsNull(),
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
          orgChild3Id: IsNull(),
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
          orgChild4Id: IsNull(),
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    } else {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    }
    let profile = await this.profileRepo.find({
      where: { isLeave: false, isRetirement: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });
    if (body.isRetirement) {
      profile = await this.profileRepo.find({
        where: {
          isLeave: false,
          current_holders: typeCondition,
          isRetirement: true,
        },
        relations: [
          "posType",
          "posLevel",
          "current_holders",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
      });
    }
    let findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true },
    });

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map((item: Profile) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : body.node == 4 && item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : body.node == 3 && item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : body.node == 2 && item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : body.node == 1 && item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : body.node == 0 && item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;
        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel: item.posLevel?.posLevelName ?? null,
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * ค้นหาชื่อหน่วยงาน ส่วนราชการ
   *
   * @summary ค้นหาชื่อหน่วยงาน ส่วนราชการ
   *
   */
  @Post("find-node-name")
  @Security("internalAuth")
  async findNodeName(
    @Body()
    body: {
      node: number;
      nodeId: string;
    },
  ) {
    let findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });
    switch (body.node) {
      case 0:
        let orgRoot = await this.orgRootRepo.findOne({
          where: {
            id: body.nodeId,
            orgRevisionId: findRevision?.id,
          },
        });
        return new HttpSuccess({
          rootName: orgRoot?.orgRootName ?? null,
          child1Name: null,
          child2Name: null,
          child3Name: null,
          child4Name: null,
        });

      case 1:
        let orgChild1 = await this.orgChild1Repo.findOne({
          relations: ["orgRoot"],
          where: {
            id: body.nodeId,
            orgRevisionId: findRevision?.id,
          },
        });
        return new HttpSuccess({
          rootName: orgChild1?.orgRoot.orgRootName ?? null,
          child1Name: orgChild1?.orgChild1Name ?? null,
          child2Name: null,
          child3Name: null,
          child4Name: null,
        });

      case 2:
        let orgChild2 = await this.orgChild2Repo.findOne({
          relations: ["orgRoot", "orgChild1"],
          where: {
            id: body.nodeId,
            orgRevisionId: findRevision?.id,
          },
        });
        return new HttpSuccess({
          rootName: orgChild2?.orgRoot.orgRootName ?? null,
          child1Name: orgChild2?.orgChild1.orgChild1Name ?? null,
          child2Name: orgChild2?.orgChild2Name ?? null,
          child3Name: null,
          child4Name: null,
        });

      case 3:
        let orgChild3 = await this.orgChild3Repo.findOne({
          relations: ["orgRoot", "orgChild1", "orgChild2"],
          where: {
            id: body.nodeId,
            orgRevisionId: findRevision?.id,
          },
        });
        return new HttpSuccess({
          rootName: orgChild3?.orgRoot.orgRootName ?? null,
          child1Name: orgChild3?.orgChild1.orgChild1Name ?? null,
          child2Name: orgChild3?.orgChild2.orgChild2Name ?? null,
          child3Name: orgChild3?.orgChild3Name ?? null,
          child4Name: null,
        });

      case 4:
        let orgChild4 = await this.orgChild4Repo.findOne({
          relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3"],
          where: {
            id: body.nodeId,
            orgRevisionId: findRevision?.id,
          },
        });
        return new HttpSuccess({
          rootName: orgChild4?.orgRoot.orgRootName ?? null,
          child1Name: orgChild4?.orgChild1.orgChild1Name ?? null,
          child2Name: orgChild4?.orgChild2.orgChild2Name ?? null,
          child3Name: orgChild4?.orgChild3.orgChild3Name ?? null,
          child4Name: orgChild4?.orgChild4Name ?? null,
        });

      default:
        return new HttpSuccess({
          rootName: null,
          child1Name: null,
          child2Name: null,
          child3Name: null,
          child4Name: null,
        });
    }
  }

  /**
   * รายชื่อขรก. ตามสิทธิ์ admin
   *
   * @summary รายชื่อขรก. ตามสิทธิ์ admin
   *
   */
  @Post("officer-by-admin-role")
  @Security("internalAuth")
  async GetOfficersByAdminRole(
    @Body()
    body: {
      node: number;
      nodeId: string;
      role: string;
      isRetirement?: boolean;
      revisionId?: string;
      reqNode?: number;
      reqNodeId?: string;
    },
  ) {
    let typeCondition: any = {};
    if (body.role === "CHILD" || /*body.role === "PARENT" ||*/ body.role === "BROTHER") {
      if (body.role === "CHILD") {
        switch (body.node) {
          case 0:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 1:
            typeCondition = {
              orgChild1: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 2:
            typeCondition = {
              orgChild2: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 3:
            typeCondition = {
              orgChild3: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 4:
            typeCondition = {
              orgChild4: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      } else if (body.role === "BROTHER") {
        switch (body.node) {
          case 0:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 1:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 2:
            typeCondition = {
              orgChild1: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 3:
            typeCondition = {
              orgChild2: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 4:
            typeCondition = {
              orgChild3: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      }
      // else if (body.role === "PARENT") {
      //   typeCondition = {
      //     orgRoot: {
      //       ancestorDNA: body.nodeId,
      //     },
      //     orgChild1: Not(IsNull()),
      //   };
      // }
    } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") {
      switch (body.reqNode) {
        case 0:
          typeCondition = {
            orgRoot: {
              id: body.reqNodeId,
            },
          };
          break;
        case 1:
          typeCondition = {
            orgChild1: {
              id: body.reqNodeId,
            },
          };
          break;
        case 2:
          typeCondition = {
            orgChild2: {
              id: body.reqNodeId,
            },
          };
          break;
        case 3:
          typeCondition = {
            orgChild3: {
              id: body.reqNodeId,
            },
          };
          break;
        case 4:
          typeCondition = {
            orgChild4: {
              id: body.reqNodeId,
            },
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          typeCondition = {
            orgRoot: {
              ancestorDNA: body.nodeId,
            },
            orgChild1: IsNull(),
          };
          break;
        case 1:
          typeCondition = {
            orgChild1: {
              ancestorDNA: body.nodeId,
            },
            orgChild2: IsNull(),
          };
          break;
        case 2:
          typeCondition = {
            orgChild2: {
              ancestorDNA: body.nodeId,
            },
            orgChild3: IsNull(),
          };
          break;
        case 3:
          typeCondition = {
            orgChild3: {
              ancestorDNA: body.nodeId,
            },
            orgChild4: IsNull(),
          };
          break;
        case 4:
          typeCondition = {
            orgChild4: {
              ancestorDNA: body.nodeId,
            },
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    }

    let profile = await this.profileRepo.find({
      where: { isLeave: false, isRetirement: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      order: {
        current_holders: {
          orgRoot: {
            orgRootOrder: "ASC",
          },
          orgChild1: {
            orgChild1Order: "ASC",
          },
          orgChild2: {
            orgChild2Order: "ASC",
          },
          orgChild3: {
            orgChild3Order: "ASC",
          },
          orgChild4: {
            orgChild4Order: "ASC",
          },
          posMasterNo: "ASC",
        },
      },
    });
    if (body.isRetirement) {
      profile = await this.profileRepo.find({
        where: {
          isLeave: false,
          current_holders: typeCondition,
          isRetirement: true,
        },
        relations: [
          "posType",
          "posLevel",
          "current_holders",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
      });
    }
    let findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map(async (item: Profile) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;

        let _posMaster = await this.posMasterRepository.findOne({
          where: {
            orgRevisionId: findRevision?.id,
            current_holderId: item.id,
          },
        });

        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          dateStart: item.dateStart,
          dateAppoint: item.dateAppoint,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel: item.posLevel?.posLevelName ?? null,
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
          orgRootId: _posMaster?.orgRootId,
          orgChild1Id: _posMaster?.orgChild1Id,
          orgChild2Id: _posMaster?.orgChild2Id,
          orgChild3Id: _posMaster?.orgChild3Id,
          orgChild4Id: _posMaster?.orgChild4Id,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * 5.	เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   * @summary 5. เอารายชื่อคนที่มีการ ,map keycloak id แล้ว
   *
   */
  @Post("keycloak-all-employee")
  @Security("internalAuth")
  async PostProfileWithKeycloakAllEmployee(
    @Body()
    body: {
      node: number;
      nodeId: string;
      isAll: boolean;
      revisionId?: string;
    },
  ) {
    let typeCondition: any = {};
    if (body.isAll == false) {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
          orgChild1Id: IsNull(),
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
          orgChild2Id: IsNull(),
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
          orgChild3Id: IsNull(),
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
          orgChild4Id: IsNull(),
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    } else {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    }
    const profile = await this.profileEmpRepo.find({
      where: { keycloak: Not(IsNull()) || Not(""), isLeave: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });

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

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map((item: ProfileEmployee) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : body.node == 4 && item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : body.node == 3 && item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : body.node == 2 && item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : body.node == 1 && item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : body.node == 0 && item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;
        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel:
            (item.posType == null || item.posType?.posTypeShortName == null
              ? ""
              : item.posType?.posTypeShortName + " ") + (item.posLevel?.posLevelName ?? ""),
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * 5.	เอารายชื่อคน ลูกจ้างประจำ (none-validate-keycloak)
   *
   * @summary 5. เอารายชื่อคน ลูกจ้างประจำ (none-validate-keycloak)
   *
   */
  @Post("none-validate-keycloak-all-employee")
  @Security("internalAuth")
  async PostProfileWithNoneValidateKeycloakAllEmployee(
    @Body()
    body: {
      node: number;
      nodeId: string;
      isAll: boolean;
      revisionId?: string;
    },
  ) {
    let typeCondition: any = {};
    if (body.isAll == false) {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
          orgChild1Id: IsNull(),
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
          orgChild2Id: IsNull(),
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
          orgChild3Id: IsNull(),
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
          orgChild4Id: IsNull(),
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    } else {
      if (body.node === 0) {
        typeCondition = {
          orgRootId: body.nodeId,
        };
      } else if (body.node === 1) {
        typeCondition = {
          orgChild1Id: body.nodeId,
        };
      } else if (body.node === 2) {
        typeCondition = {
          orgChild2Id: body.nodeId,
        };
      } else if (body.node === 3) {
        typeCondition = {
          orgChild3Id: body.nodeId,
        };
      } else if (body.node === 4) {
        typeCondition = {
          orgChild4Id: body.nodeId,
        };
      }
    }
    const profile = await this.profileEmpRepo.find({
      where: { isLeave: false, isRetirement: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
    });

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

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map((item: ProfileEmployee) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : body.node == 4 && item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : body.node == 3 && item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : body.node == 2 && item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : body.node == 1 && item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : body.node == 0 && item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;
        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel:
            (item.posType == null || item.posType?.posTypeShortName == null
              ? ""
              : item.posType?.posTypeShortName + " ") + (item.posLevel?.posLevelName ?? ""),
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * รายชื่อลูกจ้างประจำ ตามสิทธิ์ admin
   *
   * @summary รายชื่อลูกจ้างประจำ ตามสิทธิ์ admin
   *
   */
  @Post("employee-by-admin-role")
  @Security("internalAuth")
  async GetEmployeesByAdminRole(
    @Body()
    body: {
      node: number;
      nodeId: string;
      role: string;
      isRetirement?: boolean;
      revisionId?: string;
      reqNode?: number;
      reqNodeId?: string;
      startDate?: Date;
      endDate?: Date;
    },
  ) {
    let typeCondition: any = {};
    if (body.role === "CHILD" || /*body.role === "PARENT" ||*/ body.role === "BROTHER") {
      if (body.role === "CHILD") {
        switch (body.node) {
          case 0:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 1:
            typeCondition = {
              orgChild1: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 2:
            typeCondition = {
              orgChild2: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 3:
            typeCondition = {
              orgChild3: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 4:
            typeCondition = {
              orgChild4: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      } else if (body.role === "BROTHER") {
        switch (body.node) {
          case 0:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 1:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 2:
            typeCondition = {
              orgChild1: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 3:
            typeCondition = {
              orgChild2: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 4:
            typeCondition = {
              orgChild3: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      }
      // else if (body.role === "PARENT") {
      //   typeCondition = {
      //     orgRoot: {
      //       ancestorDNA: body.nodeId,
      //     },
      //     orgChild1: Not(IsNull()),
      //   };
      // }
    } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") {
      switch (body.reqNode) {
        case 0:
          typeCondition = {
            orgRoot: {
              id: body.reqNodeId,
            },
          };
          break;
        case 1:
          typeCondition = {
            orgChild1: {
              id: body.reqNodeId,
            },
          };
          break;
        case 2:
          typeCondition = {
            orgChild2: {
              id: body.reqNodeId,
            },
          };
          break;
        case 3:
          typeCondition = {
            orgChild3: {
              id: body.reqNodeId,
            },
          };
          break;
        case 4:
          typeCondition = {
            orgChild4: {
              id: body.reqNodeId,
            },
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          typeCondition = {
            orgRoot: {
              ancestorDNA: body.nodeId,
            },
            orgChild1: IsNull(),
          };
          break;
        case 1:
          typeCondition = {
            orgChild1: {
              ancestorDNA: body.nodeId,
            },
            orgChild2: IsNull(),
          };
          break;
        case 2:
          typeCondition = {
            orgChild2: {
              ancestorDNA: body.nodeId,
            },
            orgChild3: IsNull(),
          };
          break;
        case 3:
          typeCondition = {
            orgChild3: {
              ancestorDNA: body.nodeId,
            },
            orgChild4: IsNull(),
          };
          break;
        case 4:
          typeCondition = {
            orgChild4: {
              ancestorDNA: body.nodeId,
            },
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    }

    let profile = await this.profileEmpRepo.find({
      where: { isLeave: false, isRetirement: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      order: {
        current_holders: {
          orgRoot: {
            orgRootOrder: "ASC",
          },
          orgChild1: {
            orgChild1Order: "ASC",
          },
          orgChild2: {
            orgChild2Order: "ASC",
          },
          orgChild3: {
            orgChild3Order: "ASC",
          },
          orgChild4: {
            orgChild4Order: "ASC",
          },
          posMasterNo: "ASC",
        },
      },
    });
    if (body.isRetirement) {
      profile = await this.profileEmpRepo.find({
        where: {
          isLeave: false,
          current_holders: typeCondition,
          isRetirement: true,
        },
        relations: [
          "posType",
          "posLevel",
          "current_holders",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
        ],
      });
    }
    let findRevision = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });

    if (body.revisionId) {
      findRevision = await this.orgRevisionRepo.findOne({
        where: { id: body.revisionId },
      });
    }

    const profile_ = await Promise.all(
      profile.map(async (item: ProfileEmployee) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;

        let _posMaster = await this.empPosMasterRepository.findOne({
          where: {
            orgRevisionId: findRevision?.id,
            current_holderId: item.id,
          },
        });

        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          dateStart: item.dateStart,
          dateAppoint: item.dateAppoint,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel:
            item.posType?.posTypeShortName && item.posLevel?.posLevelName
              ? `${item.posType?.posTypeShortName} ${item.posLevel?.posLevelName}`
              : null,
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
          orgRootId: _posMaster?.orgRootId,
          orgChild1Id: _posMaster?.orgChild1Id,
          orgChild2Id: _posMaster?.orgChild2Id,
          orgChild3Id: _posMaster?.orgChild3Id,
          orgChild4Id: _posMaster?.orgChild4Id,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * รายชื่อลูกจ้างประจำ ตามสิทธิ์ admin
   * @summary รายชื่อลูกจ้างประจำ ตามสิทธิ์ admin
   */
  @Post("employee-by-admin-rolev2")
  @Security("internalAuth")
  async GetEmployeesByAdminRoleV2(
    // @Request() req: RequestWithUser, // ไม่ได้ใช้
    @Body()
    body: {
      node: number;
      nodeId: string;
      role: string;
      isRetirement?: boolean;
      reqNode?: number;
      reqNodeId?: string;
      date: Date;
    },
  ) {
    let typeCondition: any = {};
    if (body.role === "CHILD" || body.role === "BROTHER") {
      if (body.role === "CHILD") {
        switch (body.node) {
          case 0:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 1:
            typeCondition = {
              child1DnaId: body.nodeId,
            };
            break;
          case 2:
            typeCondition = {
              child2DnaId: body.nodeId,
            };
            break;
          case 3:
            typeCondition = {
              child3DnaId: body.nodeId,
            };
            break;
          case 4:
            typeCondition = {
              child4DnaId: body.nodeId,
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      } else if (body.role === "BROTHER") {
        switch (body.node) {
          case 0:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 1:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 2:
            typeCondition = {
              child1DnaId: body.nodeId,
            };
            break;
          case 3:
            typeCondition = {
              child2DnaId: body.nodeId,
            };
            break;
          case 4:
            typeCondition = {
              child3DnaId: body.nodeId,
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      }
    } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") {
      switch (body.reqNode) {
        case 0:
          typeCondition = {
            rootDnaId: body.reqNodeId,
          };
          break;
        case 1:
          typeCondition = {
            child1DnaId: body.reqNodeId,
          };
          break;
        case 2:
          typeCondition = {
            child2DnaId: body.reqNodeId,
          };
          break;
        case 3:
          typeCondition = {
            child3DnaId: body.reqNodeId,
          };
          break;
        case 4:
          typeCondition = {
            child4DnaId: body.reqNodeId,
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          typeCondition = {
            rootDnaId: body.nodeId,
            child1DnaId: IsNull(),
          };
          break;
        case 1:
          typeCondition = {
            child1DnaId: body.nodeId,
            child2DnaId: IsNull(),
          };
          break;
        case 2:
          typeCondition = {
            child2DnaId: body.nodeId,
            child3DnaId: IsNull(),
          };
          break;
        case 3:
          typeCondition = {
            child3DnaId: body.nodeId,
            child4DnaId: IsNull(),
          };
          break;
        case 4:
          typeCondition = {
            child4DnaId: body.nodeId,
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    }
    // set เวลาเป็น 23:59:59 ของวันนั้น
    const date = body.date ? new Date(body.date.toISOString().slice(0, 10)) : new Date();
    date.setHours(23, 59, 59, 999);

    let posEmpHis = await this.posMasterEmployeeHistoryRepository.find({
      where: {
        ...typeCondition,
        createdAt: LessThanOrEqual(date),
      },
      select: [
        "profileEmployeeId",
        "prefix",
        "firstName",
        "lastName",
        "shortName",
        "posMasterNo",
        "position",
        "posType",
        "posLevel",
        "ancestorDNA",
        "rootDnaId",
        "child1DnaId",
        "child2DnaId",
        "child3DnaId",
        "child4DnaId",
        "createdAt",
      ],
      order: {
        firstName: "ASC",
        lastName: "ASC",
        createdAt: "DESC",
      },
    });

    // group1: group by ancestorDNA แล้วเลือก create_at ล่าสุด
    const grouped1 = new Map<string, PosMasterEmployeeHistory>();
    for (const item of posEmpHis) {
      const key = `${item.ancestorDNA}`;
      if (!grouped1.has(key)) {
        grouped1.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped1.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped1.set(key, item);
        }
      }
    }
    // group2: group by shortName-posMasterNo จากค่าที่ได้จาก group1
    const grouped2 = new Map<string, PosMasterEmployeeHistory>();
    for (const item of Array.from(grouped1.values())) {
      const key = `${item.shortName}-${item.posMasterNo}`;
      if (!grouped2.has(key)) {
        grouped2.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped2.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped2.set(key, item);
        }
      }
    }
    // group3: group by firstName-lastName จากค่าที่ได้จาก group2
    const grouped3 = new Map<string, PosMasterEmployeeHistory>();
    for (const item of Array.from(grouped2.values())) {
      const key = `${item.firstName}-${item.lastName}`;
      if (!grouped3.has(key)) {
        grouped3.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped3.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped3.set(key, item);
        }
      }
    }

    const profileEmployeeIds = Array.from(grouped3.values())
      .filter((x) => x.profileEmployeeId != null)
      .map((x) => x.profileEmployeeId);

    const profileEmployees = await this.profileEmpRepo.find({
      where: { id: In(profileEmployeeIds) },
      select: ["id", "citizenId", "dateStart", "dateAppoint", "keycloak"],
    });

    const profileEmployeeMap = new Map(profileEmployees.map((p) => [p.id, p]));

    const profile_ = Array.from(grouped3.values())
      .filter((x) => x.profileEmployeeId != null)
      .map((item: PosMasterEmployeeHistory) => {
        const profileEmp = profileEmployeeMap.get(item.profileEmployeeId);
        return {
          id: item.profileEmployeeId,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: profileEmp?.citizenId ?? null,
          dateStart: profileEmp?.dateStart ?? null,
          dateAppoint: profileEmp?.dateAppoint ?? null,
          keycloak: profileEmp?.keycloak ?? null,
          posNo: `${item.shortName} ${item.posMasterNo}`,
          position: item.position,
          positionLevel: item.posLevel,
          positionType: item.posType,
          orgRootId: item.rootDnaId,
          orgChild1Id: item.child1DnaId,
          orgChild2Id: item.child2DnaId,
          orgChild3Id: item.child3DnaId,
          orgChild4Id: item.child4DnaId,
        };
      });

    return new HttpSuccess(
      (profile_ ?? []).sort((a, b) => a.posNo.localeCompare(b.posNo, undefined, { numeric: true })),
    );
  }

  /**
   * 4.	API Update รอบการลงเวลา ในตาราง profile
   *
   * @summary 4. API Update รอบการลงเวลา ในตาราง profile
   *
   */
  @Put("update-dutytime")
  @Security("bearerAuth")
  async UpdateDutyTimeAsync(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      profileId: string;
      roundId: string;
      effectiveDate: Date;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      where: { id: body.profileId },
    });
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        where: { id: body.profileId },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      Object.assign(profile, body);
      profile.dutyTimeId = body.roundId;
      profile.dutyTimeEffectiveDate = body.effectiveDate;
      profile.lastUpdateUserId = req.user.sub;
      profile.lastUpdateFullName = req.user.name;
      profile.lastUpdatedAt = new Date();
      await this.profileEmpRepo.save(profile);
      return new HttpSuccess();
    }
    Object.assign(profile, body);
    profile.dutyTimeId = body.roundId;
    profile.dutyTimeEffectiveDate = body.effectiveDate;
    profile.lastUpdateUserId = req.user.sub;
    profile.lastUpdateFullName = req.user.name;
    profile.lastUpdatedAt = new Date();
    await this.profileRepo.save(profile);
    return new HttpSuccess();
  }
  /**
   * API เพิ่มข้อมูลเครื่องราชอิสริยาภรณ์
   *
   * @summary ORG_ - เพิ่มข้อมูลเครื่องราชอิสริยาภรณ์ (ADMIN) #
   *
   */
  @Post("insignia/Dumb")
  @Security("bearerAuth")
  public async newInsignia(@Request() req: RequestWithUser, @Body() body: CreateProfileInsignia) {
    if (!body.profileId) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "กรุณากรอก profileId");
    }

    const profile = await this.profileRepo.findOneBy({ id: body.profileId });

    if (!profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }

    // const insignia = await this.insigniaMetaRepo.findOne({
    //   where: { name: body.insigniaId },
    // });
    // const _null: any = null;
    // if (body && body.insigniaId) {
    //   const findPosLevel = await this.insigniaMetaRepo.findOne({
    //     where: { name: body.insigniaId },
    //     select: ["id", "name"],
    //   });
    //   if (findPosLevel) {
    //     body.insigniaId = findPosLevel.id;
    //   } else {
    //     body.insigniaId = _null;
    //   }
    // } else {
    //   body.insigniaId = _null;
    // }

    const data = new ProfileInsignia();

    const meta = {
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
    };

    Object.assign(data, { ...body, ...meta });

    await this.insigniaRepo.save(data);

    return new HttpSuccess();
  }

  /**
   * 2.	API ข้อมูลหน่วยงานตามโครงสร้าง
   *
   * @summary 2. API ข้อมูลหน่วยงานตามโครงสร้าง
   *
   * @param {string} id  Id หน่วยงาน
   */
  @Get("email/{id}")
  async GetEmailById(@Path() id: string) {
    const profile = await this.profileRepo.findOne({
      where: { id: id },
    });
    if (profile != null) return new HttpSuccess(profile.email);
    const profileEmp = await this.profileEmpRepo.findOne({
      where: { id: id },
    });
    if (profileEmp != null) return new HttpSuccess(profileEmp.email);

    return new HttpSuccess(null);
  }

  /**
   * API Get Profile จาก keycloak id (ใช้สำหรับใบลา)
   *
   * @summary API Get Profile จาก keycloak id (ใช้สำหรับใบลา)
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("profile-leave/keycloak/{keycloakId}")
  @Security("internalAuth")
  async GetProfileLeaveByKeycloakIdAsync(@Path() keycloakId: string) {
    const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
    let _currentDate = CURRENT_DATE[0].today;
    const profile = await this.profileRepo.findOne({
      relations: [
        "posLevel",
        "posType",
        "current_holders",
        "current_holders.orgRevision",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
        "profileEducations",
        "currentProvince",
        "currentDistrict",
        "currentSubDistrict",
      ],
      where: {
        keycloak: keycloakId,
      },
      order: {
        profileEducations: {
          level: "ASC",
        },
      },
    });

    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        relations: [
          "posLevel",
          "posType",
          "current_holders",
          "current_holders.orgRevision",
          "current_holders.orgRoot",
          "current_holders.orgChild1",
          "current_holders.orgChild2",
          "current_holders.orgChild3",
          "current_holders.orgChild4",
          "profileEducations",
          "currentProvince",
          "currentDistrict",
          "currentSubDistrict",
        ],
        where: {
          keycloak: keycloakId,
        },
        order: {
          profileEducations: {
            level: "ASC",
          },
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

      const _profileCurrent = profile?.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );
      let oc = "";
      if (_profileCurrent != null) {
        if (_profileCurrent.orgChild1Id === null) {
          oc = _profileCurrent.orgRoot?.orgRootName;
        } else if (_profileCurrent.orgChild2Id === null) {
          oc = `${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
        } else if (_profileCurrent.orgChild3Id === null) {
          oc = `${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
        } else if (_profileCurrent.orgChild4Id === null) {
          oc = `${_profileCurrent.orgChild3?.orgChild3Name} ${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
        } else {
          oc = `${_profileCurrent.orgChild4?.orgChild4Name}`;
        }
      }
      const position = await AppDataSource.query("CALL GetProfileEmployeeSalaryPosition(?, ?)", [
        profile.id,
        _currentDate,
      ]);
      const _position = position.length > 0 ? position[0] : [];

      const mapEmpProfile = {
        birthDate: profile.birthDate ?? "-",
        retireDate: profile.birthDate ? calculateRetireLaw(profile.birthDate) : "-",
        govAge: profile.dateAppoint
          ? `${Extension.CalculateGovAge(profile.dateAppoint, 0, 0)} ปี`
          : "-",
        age: profile.birthDate ? Extension.CalculateAgeStrV2(profile.birthDate, 0, 0, "GET") : "-",
        dateAppoint: profile.dateAppoint,
        dateCurrent: new Date(),
        amount: profile.amount ?? "-",
        telephoneNumber: profile.telephoneNumber ?? "-",
        positionName: profile.position ?? "-",
        posLevel:
          (profile.posType == null || profile.posType?.posTypeShortName == null
            ? ""
            : profile.posType?.posTypeShortName + " ") + (profile.posLevel?.posLevelName ?? ""),
        posType: profile.posType?.posTypeName ?? "-",
        currentAddress:
          profile && profile.currentAddress
            ? profile.currentAddress +
              (profile.currentSubDistrict && profile.currentSubDistrict.name
                ? " ตำบล/แขวง " + profile.currentSubDistrict.name
                : "") +
              (profile.currentDistrict && profile.currentDistrict.name
                ? " อำเภอ/เขต " + profile.currentDistrict.name
                : "") +
              (profile.currentProvince && profile.currentProvince.name
                ? " จังหวัด " + profile.currentProvince.name
                : "") +
              profile.currentZipCode
            : "-",
        oc: oc ?? "-",
        root:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgRoot?.orgRootName ?? null,
        child1:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild1?.orgChild1Name ?? null,
        child2:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild2?.orgChild2Name ?? null,
        child3:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild3?.orgChild3Name ?? null,
        child4:
          profile?.current_holders?.find(
            (x) =>
              x.orgRevision?.orgRevisionIsDraft == false &&
              x.orgRevision?.orgRevisionIsCurrent == true,
          )?.orgChild4?.orgChild4Name ?? null,
        positions:
          _position && _position.length > 0
            ? _position.slice(0, -1).map((x: any, idx: number) => ({
                positionName: x.positionName,
                dateStart: x.commandDateAffect ?? null,
                dateEnd: _position[idx + 1]?.commandDateAffect ?? null,
                positionType: x.positionType,
                positionLevel: x.positionLevel,
                orgRoot: x.orgRoot,
                orgChild1: x.orgChild1,
                orgChild2: x.orgChild2,
                orgChild3: x.orgChild3,
                orgChild4: x.orgChild4,
              }))
            : [],
        educations:
          profile.profileEducations && profile.profileEducations.length > 0
            ? profile.profileEducations.map((x) => ({
                educationLevel: x.educationLevel,
                institute: x.institute ?? "-",
                country: x.country ?? "-",
                finishDate: x.finishDate,
              }))
            : [],
      };
      return new HttpSuccess(mapEmpProfile);
    }
    const _profileCurrent = profile?.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );
    let oc = "";
    if (_profileCurrent != null) {
      if (_profileCurrent.orgChild1Id === null) {
        oc = _profileCurrent.orgRoot?.orgRootName;
      } else if (_profileCurrent.orgChild2Id === null) {
        oc = `${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
      } else if (_profileCurrent.orgChild3Id === null) {
        oc = `${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
      } else if (_profileCurrent.orgChild4Id === null) {
        oc = `${_profileCurrent.orgChild3?.orgChild3Name} ${_profileCurrent.orgChild2?.orgChild2Name} ${_profileCurrent.orgChild1?.orgChild1Name} ${_profileCurrent.orgRoot?.orgRootName}`;
      } else {
        oc = `${_profileCurrent.orgChild4?.orgChild4Name}`;
      }
    }
    if (profile && profile?.isLeave) {
      _currentDate =
        profile && profile.leaveDate ? Extension.toDateOnlyString(profile.leaveDate) : _currentDate;
    }
    const position = await AppDataSource.query("CALL GetProfileSalaryPosition(?, ?)", [
      profile.id,
      _currentDate,
    ]);
    const _position = position.length > 0 ? position[0] : [];

    const mapProfile = {
      birthDate: profile.birthDate ?? "-",
      retireDate: profile.birthDate ? calculateRetireLaw(profile.birthDate) : "-",
      govAge: profile.dateAppoint
        ? `${Extension.CalculateGovAge(profile.dateAppoint, 0, 0)} ปี`
        : "-",
      age: profile.birthDate ? Extension.CalculateAgeStrV2(profile.birthDate, 0, 0, "GET") : "-",
      dateAppoint: profile.dateAppoint,
      dateCurrent: new Date(),
      amount: profile.amount ?? "-",
      telephoneNumber: profile.telephoneNumber ?? "-",
      positionName: profile.position ?? "-",
      posLevel: profile.posLevel?.posLevelName ?? "-",
      posType: profile.posType?.posTypeName ?? "-",
      currentAddress:
        profile && profile.currentAddress
          ? profile.currentAddress +
            (profile.currentSubDistrict && profile.currentSubDistrict.name
              ? " ตำบล/แขวง " + profile.currentSubDistrict.name
              : "") +
            (profile.currentDistrict && profile.currentDistrict.name
              ? " อำเภอ/เขต " + profile.currentDistrict.name
              : "") +
            (profile.currentProvince && profile.currentProvince.name
              ? " จังหวัด " + profile.currentProvince.name
              : "") +
            profile.currentZipCode
          : "-",
      oc: oc ?? "-",
      root:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgRoot?.orgRootName ?? null,
      child1:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild1?.orgChild1Name ?? null,
      child2:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild2?.orgChild2Name ?? null,
      child3:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild3?.orgChild3Name ?? null,
      child4:
        profile?.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft == false &&
            x.orgRevision?.orgRevisionIsCurrent == true,
        )?.orgChild4?.orgChild4Name ?? null,
      positions:
        _position && _position.length > 0
          ? _position.slice(0, -1).map((x: any, idx: number) => ({
              positionName: x.positionName,
              dateStart: x.commandDateAffect ?? null,
              dateEnd: _position[idx + 1]?.commandDateAffect ?? null,
              positionType: x.positionType,
              positionLevel: x.positionLevel,
              orgRoot: x.orgRoot,
              orgChild1: x.orgChild1,
              orgChild2: x.orgChild2,
              orgChild3: x.orgChild3,
              orgChild4: x.orgChild4,
            }))
          : [],
      educations:
        profile.profileEducations && profile.profileEducations.length > 0
          ? profile.profileEducations.map((x) => ({
              educationLevel: x.educationLevel,
              institute: x.institute ?? "-",
              country: x.country ?? "-",
              finishDate: x.finishDate,
            }))
          : [],
    };
    return new HttpSuccess(mapProfile);
  }

  @Post("profile-leave/keycloak")
  @Security("internalAuth")
  async GetProfileLeaveReportByKeycloakIdAsync(
    @Body() body: { keycloakId: string; report?: string },
  ) {
    const profile = await this.profileRepo.findOne({
      relations: {
        currentProvince: true,
        currentDistrict: true,
        currentSubDistrict: true,
        posLevel: true,
        posType: true,
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
          orgChild2: true,
          orgChild3: true,
          orgChild4: true,
        },
      },
      where: {
        keycloak: body.keycloakId,
      },
    });

    // ลูกจ้างประจำ
    if (!profile) {
      const profile = await this.profileEmpRepo.findOne({
        relations: {
          currentProvince: true,
          currentDistrict: true,
          currentSubDistrict: true,
          posLevel: true,
          posType: true,
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
        where: {
          keycloak: body.keycloakId,
        },
      });
      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      /* =========================================
       * current holder
       * ========================================= */
      const currentHolder = profile.current_holders?.find(
        (x) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );

      let oc = "";
      if (currentHolder) {
        if (!currentHolder.orgChild1Id) {
          oc = currentHolder.orgRoot?.orgRootName;
        } else if (!currentHolder.orgChild2Id) {
          oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild3Id) {
          oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else if (!currentHolder.orgChild4Id) {
          oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
        } else {
          oc = currentHolder.orgChild4?.orgChild4Name;
        }
      }
      let _positions: any[] = [];
      let _educations: any[] = [];
      if (body.report && ["LEAVE16", "LEAVE18"].includes(body.report.trim().toUpperCase())) {
        const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
        let _currentDate = CURRENT_DATE[0].today;
        if (profile && profile?.isLeave) {
          _currentDate =
            profile && profile.leaveDate
              ? Extension.toDateOnlyString(profile.leaveDate)
              : _currentDate;
        }
        const positions = await AppDataSource.query("CALL GetProfileEmployeeSalaryPosition(?, ?)", [
          profile!.id,
          _currentDate,
        ]);
        _positions =
          positions[0].length > 0
            ? _positions.slice(0, -1).map((x: any, idx: number) => ({
                positionName: x.positionName,
                dateStart: x.commandDateAffect ?? null,
                dateEnd: _positions[idx + 1]?.commandDateAffect ?? null,
              }))
            : [];

        const profileEducations = await this.educationRepo.find({
          where: { profileEmployeeId: profile!.id, isDeleted: false },
          order: { level: "ASC" },
        });
        _educations =
          profileEducations.length > 0
            ? profileEducations.map((x) => ({
                educationLevel: x.educationLevel,
                institute: x.institute ?? "-",
                country: x.country ?? "-",
                finishDate: x.finishDate,
              }))
            : [];
      }

      const mapProfile = {
        profileType: "EMPLOYEE",
        prefix: profile.prefix,
        firstName: profile.firstName,
        lastName: profile.lastName,
        citizenId: profile.citizenId,
        birthDate: profile.birthDate,
        retireDate: profile.birthDate ? calculateRetireLaw(profile.birthDate) : null,
        govAge: profile.dateAppoint
          ? `${Extension.CalculateGovAge(profile.dateAppoint, 0, 0)} ปี`
          : null,
        age: profile.birthDate ? Extension.CalculateAgeStrV2(profile.birthDate, 0, 0, "GET") : null,
        dateAppoint: profile.dateAppoint,
        dateCurrent: new Date(),
        amount: profile.amount,
        telephoneNumber: profile.telephoneNumber,
        currentAddress:
          profile && profile.currentAddress
            ? profile.currentAddress +
              (profile.currentSubDistrict && profile.currentSubDistrict.name
                ? " ตำบล/แขวง " + profile.currentSubDistrict.name
                : "") +
              (profile.currentDistrict && profile.currentDistrict.name
                ? " อำเภอ/เขต " + profile.currentDistrict.name
                : "") +
              (profile.currentProvince && profile.currentProvince.name
                ? " จังหวัด " + profile.currentProvince.name + " "
                : "") +
              profile.currentZipCode
            : "-",
        position: profile.position,
        posType: profile.posType?.posTypeName,
        posLevel: `${profile.posType?.posTypeShortName} ${profile.posLevel?.posLevelName}`,
        positionLeaveName: null,
        posExecutiveName: null,

        isCommission: currentHolder?.orgRoot?.isCommission ?? false,
        root: currentHolder?.orgRoot?.orgRootName ?? null,
        child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
        child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
        child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
        child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
        oc: oc,

        positions: _positions,
        educations: _educations,
      };
      return new HttpSuccess(mapProfile);
    }

    /* =========================================
     * current holder
     * ========================================= */
    const currentHolder = profile.current_holders?.find(
      (x) =>
        x.orgRevision?.orgRevisionIsDraft === false && x.orgRevision?.orgRevisionIsCurrent === true,
    );

    let oc = "";
    if (currentHolder) {
      if (!currentHolder.orgChild1Id) {
        oc = currentHolder.orgRoot?.orgRootName;
      } else if (!currentHolder.orgChild2Id) {
        oc = `${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild3Id) {
        oc = `${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else if (!currentHolder.orgChild4Id) {
        oc = `${currentHolder.orgChild3?.orgChild3Name} ${currentHolder.orgChild2?.orgChild2Name} ${currentHolder.orgChild1?.orgChild1Name} ${currentHolder.orgRoot?.orgRootName}`;
      } else {
        oc = currentHolder.orgChild4?.orgChild4Name;
      }
    }

    /* =========================================
     * posType + posLevel
     * ========================================= */
    const positionLeaveName =
      profile.posType &&
      profile.posLevel &&
      (profile.posType.posTypeName === "บริหาร" || profile.posType.posTypeName === "อำนวยการ")
        ? `${profile.posType.posTypeName}${profile.posLevel.posLevelName}`
        : profile.posLevel?.posLevelName ?? null;

    /* =========================================
     * position executive
     * ========================================= */
    const _posExec = await this.positionRepository.findOne({
      where: {
        positionIsSelected: true,
        posMaster: {
          orgRevisionId: currentHolder?.orgRevisionId,
          current_holderId: profile.id,
        },
      },
      order: { createdAt: "DESC" },
      relations: { posExecutive: true },
    });

    let _positions: any[] = [];
    let _educations: any[] = [];
    if (body.report && ["LEAVE16", "LEAVE18"].includes(body.report.trim().toUpperCase())) {
      const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
      let _currentDate = CURRENT_DATE[0].today;
      if (profile && profile?.isLeave) {
        _currentDate =
          profile && profile.leaveDate
            ? Extension.toDateOnlyString(profile.leaveDate)
            : _currentDate;
      }
      const positions = await AppDataSource.query("CALL GetProfileSalaryPosition(?, ?)", [
        profile!.id,
        _currentDate,
      ]);
      _positions =
        positions[0].length > 0
          ? _positions.slice(0, -1).map((x: any, idx: number) => ({
              positionName: x.positionName,
              dateStart: x.commandDateAffect ?? null,
              dateEnd: _positions[idx + 1]?.commandDateAffect ?? null,
            }))
          : [];

      const profileEducations = await this.educationRepo.find({
        where: { profileId: profile!.id, isDeleted: false },
        order: { level: "ASC" },
      });
      _educations =
        profileEducations.length > 0
          ? profileEducations.map((x) => ({
              educationLevel: x.educationLevel,
              institute: x.institute ?? "-",
              country: x.country ?? "-",
              finishDate: x.finishDate,
            }))
          : [];
    }

    const mapProfile = {
      profileType: "OFFICER",
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      birthDate: profile.birthDate,
      retireDate: profile.birthDate ? calculateRetireLaw(profile.birthDate) : null,
      govAge: profile.dateAppoint
        ? `${Extension.CalculateGovAge(profile.dateAppoint, 0, 0)} ปี`
        : null,
      age: profile.birthDate ? Extension.CalculateAgeStrV2(profile.birthDate, 0, 0, "GET") : null,
      dateAppoint: profile.dateAppoint,
      dateCurrent: new Date(),
      amount: profile.amount,
      telephoneNumber: profile.telephoneNumber,
      currentAddress:
        profile && profile.currentAddress
          ? profile.currentAddress +
            (profile.currentSubDistrict && profile.currentSubDistrict.name
              ? " ตำบล/แขวง " + profile.currentSubDistrict.name
              : "") +
            (profile.currentDistrict && profile.currentDistrict.name
              ? " อำเภอ/เขต " + profile.currentDistrict.name
              : "") +
            (profile.currentProvince && profile.currentProvince.name
              ? " จังหวัด " + profile.currentProvince.name + " "
              : "") +
            profile.currentZipCode
          : "-",
      position: profile.position ?? "-",
      posLevel: profile.posLevel?.posLevelName ?? "-",
      posType: profile.posType?.posTypeName ?? "-",
      positionLeaveName,
      posExecutiveName: _posExec?.posExecutive?.posExecutiveName ?? null,

      isCommission: currentHolder?.orgRoot?.isCommission ?? false,
      root: currentHolder?.orgRoot?.orgRootName ?? null,
      child1: currentHolder?.orgChild1?.orgChild1Name ?? null,
      child2: currentHolder?.orgChild2?.orgChild2Name ?? null,
      child3: currentHolder?.orgChild3?.orgChild3Name ?? null,
      child4: currentHolder?.orgChild4?.orgChild4Name ?? null,
      oc: oc,

      positions: _positions,
      educations: _educations,
    };
    return new HttpSuccess(mapProfile);
  }

  /**
   * API Get Profile ใช้อัพเดทสถานะ Mark ในระบบเครื่องราช
   *
   * @summary API Get Profile ใช้อัพเดทสถานะ Mark ในระบบเครื่องราช
   *
   * @param {string} type  ประเภท (ข้าราชการ หรือ ลูกจ้าง)
   */
  @Post("find/insignia-requests-profile/{type}")
  @Security("internalAuth")
  async GetInsigniaRequestsProfileAsync(
    @Path() type: string,
    @Body()
    body: {
      profileIds: string[];
    },
  ) {
    let profile;
    if (type.trim().toLocaleUpperCase() == "OFFICER") {
      profile = await this.profileRepo.find({
        relations: [
          // "profileSalary",
          "profileInsignias",
          "profileDisciplines",
          "profileAssessments",
        ],
        where: { id: In(body.profileIds) },
      });
    } else {
      profile = await this.profileEmpRepo.find({
        relations: [
          // "profileSalary",
          "profileInsignias",
          "profileDisciplines",
          "profileAssessments",
        ],
        where: { id: In(body.profileIds) },
      });
    }

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

    const currentYear = new Date().getFullYear();
    const years = [currentYear, currentYear - 1, currentYear - 2, currentYear - 3, currentYear - 4];

    // APR Averages
    const aprAverages: { [year: number]: number | null } = {};
    const aprSums: { [year: number]: number } = {};
    const aprCounts: { [year: number]: number } = {};

    // OCT Averages
    const octAverages: { [year: number]: number | null } = {};
    const octSums: { [year: number]: number } = {};
    const octCounts: { [year: number]: number } = {};

    years.forEach((year) => {
      aprAverages[year] = null;
      aprSums[year] = 0;
      aprCounts[year] = 0;

      octAverages[year] = null;
      octSums[year] = 0;
      octCounts[year] = 0;
    });

    profile.forEach((profile) => {
      const assessments = profile.profileAssessments || [];

      assessments.forEach((assessment) => {
        const year = Number(assessment.year);

        if (years.includes(year)) {
          if (assessment.period === "APR") {
            aprSums[year] += assessment.pointSum;
            aprCounts[year] += 1;
          }

          if (assessment.period === "OCT") {
            octSums[year] += assessment.pointSum;
            octCounts[year] += 1;
          }
        }
      });
    });

    years.forEach((year) => {
      aprAverages[year] = aprCounts[year] > 0 ? aprSums[year] / aprCounts[year] : null;
      octAverages[year] = octCounts[year] > 0 ? octSums[year] / octCounts[year] : null;
    });

    const mapProfile = profile.map((x) => {
      return {
        id: x.id,
        markDiscipline: x.profileDisciplines.length > 0 ? true : false,
        markLeave: false,
        markRate: x.profileAssessments.length > 0 ? true : false,
        markInsignia: x.profileInsignias.length > 0 ? true : false,
        apr1: aprAverages[currentYear]
          ? Extension.textPoint(aprAverages[currentYear] as number)
          : null,
        apr2: aprAverages[currentYear - 1]
          ? Extension.textPoint(aprAverages[currentYear - 1] as number)
          : null,
        apr3: aprAverages[currentYear - 2]
          ? Extension.textPoint(aprAverages[currentYear - 2] as number)
          : null,
        apr4: aprAverages[currentYear - 3]
          ? Extension.textPoint(aprAverages[currentYear - 3] as number)
          : null,
        apr5: aprAverages[currentYear - 4]
          ? Extension.textPoint(aprAverages[currentYear - 4] as number)
          : null,
        oct1: octAverages[currentYear]
          ? Extension.textPoint(octAverages[currentYear] as number)
          : null,
        oct2: octAverages[currentYear - 1]
          ? Extension.textPoint(octAverages[currentYear - 1] as number)
          : null,
        oct3: octAverages[currentYear - 2]
          ? Extension.textPoint(octAverages[currentYear - 2] as number)
          : null,
        oct4: octAverages[currentYear - 3]
          ? Extension.textPoint(octAverages[currentYear - 3] as number)
          : null,
        oct5: octAverages[currentYear - 4]
          ? Extension.textPoint(octAverages[currentYear - 4] as number)
          : null,
      };
    });
    return new HttpSuccess(mapProfile);
  }

  /**
   * รายชื่อขรก. ตามสิทธิ์ admin
   *
   * @summary รายชื่อขรก. ตามสิทธิ์ admin
   *
   */
  @Post("officer-by-admin-rolev2")
  @Security("internalAuth")
  async GetOfficersByAdminRoleV2(
    @Body()
    body: {
      node: number;
      nodeId: string;
      role: string;
      isRetirement?: boolean;
      reqNode?: number;
      reqNodeId?: string;
      date: Date;
    },
  ) {
    let typeCondition: any = {};
    if (body.role === "CHILD" || /*body.role === "PARENT" ||*/ body.role === "BROTHER") {
      if (body.role === "CHILD") {
        switch (body.node) {
          case 0:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 1:
            typeCondition = {
              child1DnaId: body.nodeId,
            };
            break;
          case 2:
            typeCondition = {
              child2DnaId: body.nodeId,
            };
            break;
          case 3:
            typeCondition = {
              child3DnaId: body.nodeId,
            };
            break;
          case 4:
            typeCondition = {
              child4DnaId: body.nodeId,
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      } else if (body.role === "BROTHER") {
        switch (body.node) {
          case 0:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 1:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 2:
            typeCondition = {
              child1DnaId: body.nodeId,
            };
            break;
          case 3:
            typeCondition = {
              child2DnaId: body.nodeId,
            };
            break;
          case 4:
            typeCondition = {
              child3DnaId: body.nodeId,
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      }
      // else if (body.role === "PARENT") {
      //   typeCondition = {
      //     rootDnaId: body.nodeId,
      //     child1DnaId: Not(IsNull()),
      //   };
      // }
    } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") {
      switch (body.reqNode) {
        case 0:
          typeCondition = {
            rootDnaId: body.reqNodeId,
          };
          break;
        case 1:
          typeCondition = {
            child1DnaId: body.reqNodeId,
          };
          break;
        case 2:
          typeCondition = {
            child2DnaId: body.reqNodeId,
          };
          break;
        case 3:
          typeCondition = {
            child3DnaId: body.reqNodeId,
          };
          break;
        case 4:
          typeCondition = {
            child4DnaId: body.reqNodeId,
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          typeCondition = {
            rootDnaId: body.nodeId,
            child1DnaId: IsNull(),
          };
          break;
        case 1:
          typeCondition = {
            child1DnaId: body.nodeId,
            child2DnaId: IsNull(),
          };
          break;
        case 2:
          typeCondition = {
            child2DnaId: body.nodeId,
            child3DnaId: IsNull(),
          };
          break;
        case 3:
          typeCondition = {
            child3DnaId: body.nodeId,
            child4DnaId: IsNull(),
          };
          break;
        case 4:
          typeCondition = {
            child4DnaId: body.nodeId,
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    }
    // set เวลาเป็น 23:59:59 ของวันนั้น
    const date = body.date.setHours(23, 59, 59, 999);

    let profile = await this.posMasterHistoryRepository.find({
      where: {
        ...typeCondition,
        createdAt: LessThanOrEqual(date),
        // firstName: Not("") && Not(IsNull()),
        // lastName: Not("") && Not(IsNull()),
      },
      order: {
        firstName: "ASC",
        lastName: "ASC",
        createdAt: "DESC", // ให้ createdAt ล่าสุดอยู่ข้างบน
      },
    });

    // group by ancestorDNA แล้วเลือก create_at ล่าสุด
    const grouped = new Map<string, PosMasterHistory>();
    for (const item of profile) {
      const key = `${item.shortName}-${item.posMasterNo}`;
      if (!grouped.has(key)) {
        grouped.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped.set(key, item);
        }
      }
    }

    const profile_ = await Promise.all(
      Array.from(grouped.values())
        .filter((x) => x.profileId != null)
        .map(async (item: PosMasterHistory) => {
          let profile = await this.profileRepo.findOne({
            where: { id: item.profileId },
          });

          return {
            id: item.profileId,
            prefix: item.prefix,
            firstName: item.firstName,
            lastName: item.lastName,
            citizenId: profile?.citizenId ?? null,
            dateStart: profile?.dateStart ?? null,
            dateAppoint: profile?.dateAppoint ?? null,
            keycloak: profile?.keycloak ?? null,
            posNo: item.shortName,
            position: item.position,
            positionLevel: item.posLevel,
            positionType: item.posType,
            // oc: Oc,
            orgRootId: item.rootDnaId,
            orgChild1Id: item.child1DnaId,
            orgChild2Id: item.child2DnaId,
            orgChild3Id: item.child3DnaId,
            orgChild4Id: item.child4DnaId,
          };
        }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * รายชื่อขรก. ตามสิทธิ์ admin
   *
   * @summary รายชื่อขรก. ตามสิทธิ์ admin
   *
   */
  @Post("officer-by-admin-rolev3")
  @Security("internalAuth")
  async GetOfficersByAdminRoleV3(
    @Body()
    body: {
      node: number;
      nodeId: string;
      role: string;
      // isRetirement?: boolean;
      // revisionId?: string;
      reqNode?: number;
      reqNodeId?: string;
      startDate: Date;
      endDate: Date;
    },
  ) {
    let typeCondition: any = {};
    if (body.role === "CHILD" || /*body.role === "PARENT" ||*/ body.role === "BROTHER") {
      if (body.role === "CHILD") {
        switch (body.node) {
          case 0:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 1:
            typeCondition = {
              orgChild1: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 2:
            typeCondition = {
              orgChild2: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 3:
            typeCondition = {
              orgChild3: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 4:
            typeCondition = {
              orgChild4: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      } else if (body.role === "BROTHER") {
        switch (body.node) {
          case 0:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 1:
            typeCondition = {
              orgRoot: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 2:
            typeCondition = {
              orgChild1: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 3:
            typeCondition = {
              orgChild2: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          case 4:
            typeCondition = {
              orgChild3: {
                ancestorDNA: body.nodeId,
              },
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      }
      // else if (body.role === "PARENT") {
      //   typeCondition = {
      //     orgRoot: {
      //       ancestorDNA: body.nodeId,
      //     },
      //     orgChild1: Not(IsNull()),
      //   };
      // }
    } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") {
      switch (body.reqNode) {
        case 0:
          typeCondition = {
            orgRoot: {
              id: body.reqNodeId,
            },
          };
          break;
        case 1:
          typeCondition = {
            orgChild1: {
              id: body.reqNodeId,
            },
          };
          break;
        case 2:
          typeCondition = {
            orgChild2: {
              id: body.reqNodeId,
            },
          };
          break;
        case 3:
          typeCondition = {
            orgChild3: {
              id: body.reqNodeId,
            },
          };
          break;
        case 4:
          typeCondition = {
            orgChild4: {
              id: body.reqNodeId,
            },
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          typeCondition = {
            orgRoot: {
              ancestorDNA: body.nodeId,
            },
            orgChild1: IsNull(),
          };
          break;
        case 1:
          typeCondition = {
            orgChild1: {
              ancestorDNA: body.nodeId,
            },
            orgChild2: IsNull(),
          };
          break;
        case 2:
          typeCondition = {
            orgChild2: {
              ancestorDNA: body.nodeId,
            },
            orgChild3: IsNull(),
          };
          break;
        case 3:
          typeCondition = {
            orgChild3: {
              ancestorDNA: body.nodeId,
            },
            orgChild4: IsNull(),
          };
          break;
        case 4:
          typeCondition = {
            orgChild4: {
              ancestorDNA: body.nodeId,
            },
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    }

    let profile = await this.profileRepo.find({
      where: { isLeave: false, isRetirement: false, current_holders: typeCondition },
      relations: [
        "posType",
        "posLevel",
        "current_holders",
        "current_holders.orgRoot",
        "current_holders.orgChild1",
        "current_holders.orgChild2",
        "current_holders.orgChild3",
        "current_holders.orgChild4",
      ],
      order: {
        current_holders: {
          orgRoot: {
            orgRootOrder: "ASC",
          },
          orgChild1: {
            orgChild1Order: "ASC",
          },
          orgChild2: {
            orgChild2Order: "ASC",
          },
          orgChild3: {
            orgChild3Order: "ASC",
          },
          orgChild4: {
            orgChild4Order: "ASC",
          },
          posMasterNo: "ASC",
        },
      },
    });
    // if (body.isRetirement) {
    //   profile = await this.profileRepo.find({
    //     where: {
    //       isLeave: false,
    //       current_holders: typeCondition,
    //       isRetirement: true,
    //     },
    //     relations: [
    //       "posType",
    //       "posLevel",
    //       "current_holders",
    //       "current_holders.orgRoot",
    //       "current_holders.orgChild1",
    //       "current_holders.orgChild2",
    //       "current_holders.orgChild3",
    //       "current_holders.orgChild4",
    //     ],
    //   });
    // }
    // Filter only by date part, not time
    const startDateOnly = new Date(
      body.startDate.getFullYear(),
      body.startDate.getMonth(),
      body.startDate.getDate(),
    );
    const endDateOnly = new Date(
      body.endDate.getFullYear(),
      body.endDate.getMonth(),
      body.endDate.getDate(),
    );
    let findRevision = await this.orgRevisionRepo.findOne({
      where: {
        orgPublishDate: Between(startDateOnly, endDateOnly),
      },
    });

    const profile_ = await Promise.all(
      profile.map(async (item: Profile) => {
        const shortName =
          item.current_holders.length == 0
            ? null
            : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
                  null
              ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
              : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                  item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                    ?.orgChild3 != null
                ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                    item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                      ?.orgChild2 != null
                  ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                  : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
                      item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                        ?.orgChild1 != null
                    ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                    : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
                          null &&
                        item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
                          ?.orgRoot != null
                      ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
                      : null;
        const Oc =
          item.current_holders.length == 0
            ? null
            : item.current_holders[0].orgChild4 != null
              ? `${item.current_holders[0].orgChild4.orgChild4Name}/${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
              : item.current_holders[0].orgChild3 != null
                ? `${item.current_holders[0].orgChild3.orgChild3Name}/${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                : item.current_holders[0].orgChild2 != null
                  ? `${item.current_holders[0].orgChild2.orgChild2Name}/${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                  : item.current_holders[0].orgChild1 != null
                    ? `${item.current_holders[0].orgChild1.orgChild1Name}/${item.current_holders[0].orgRoot.orgRootName}`
                    : item.current_holders[0].orgRoot != null
                      ? `${item.current_holders[0].orgRoot.orgRootName}`
                      : null;

        let _posMaster = await this.posMasterRepository.findOne({
          where: {
            orgRevisionId: findRevision?.id,
            current_holderId: item.id,
          },
        });

        return {
          id: item.id,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: item.citizenId,
          dateStart: item.dateStart,
          dateAppoint: item.dateAppoint,
          keycloak: item.keycloak,
          posNo: shortName,
          position: item.position,
          positionLevel: item.posLevel?.posLevelName ?? null,
          positionType: item.posType?.posTypeName ?? null,
          oc: Oc,
          orgRootId: _posMaster?.orgRootId,
          orgChild1Id: _posMaster?.orgChild1Id,
          orgChild2Id: _posMaster?.orgChild2Id,
          orgChild3Id: _posMaster?.orgChild3Id,
          orgChild4Id: _posMaster?.orgChild4Id,
        };
      }),
    );

    return new HttpSuccess(profile_);
  }

  /**
   * รายชื่อขรก. ตามสิทธิ์ admin
   *
   * @summary รายชื่อขรก. ตามสิทธิ์ admin
   *
   */
  @Post("officer-by-admin-rolev4")
  @Security("internalAuth")
  async GetOfficersByAdminRoleV4(
    @Body()
    body: {
      node: number;
      nodeId: string;
      role: string;
      isRetirement?: boolean;
      reqNode?: number;
      reqNodeId?: string;
      date: Date;
    },
  ) {
    let typeCondition: any = {};
    if (body.role === "CHILD" || /*body.role === "PARENT" ||*/ body.role === "BROTHER") {
      if (body.role === "CHILD") {
        switch (body.node) {
          case 0:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 1:
            typeCondition = {
              child1DnaId: body.nodeId,
            };
            break;
          case 2:
            typeCondition = {
              child2DnaId: body.nodeId,
            };
            break;
          case 3:
            typeCondition = {
              child3DnaId: body.nodeId,
            };
            break;
          case 4:
            typeCondition = {
              child4DnaId: body.nodeId,
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      } else if (body.role === "BROTHER") {
        // nodeId ที่รับมาเป็น DNA ของระดับพ่อแม่ (สูงกว่า 1 ระดับ) จึงต้อง query ด้วย field ของระดับพ่อแม่
        switch (body.node) {
          case 0:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 1:
            typeCondition = {
              rootDnaId: body.nodeId,
            };
            break;
          case 2:
            typeCondition = {
              child1DnaId: body.nodeId,
            };
            break;
          case 3:
            typeCondition = {
              child2DnaId: body.nodeId,
            };
            break;
          case 4:
            typeCondition = {
              child3DnaId: body.nodeId,
            };
            break;
          default:
            typeCondition = {};
            break;
        }
      }
      // else if (body.role === "PARENT") {
      //   typeCondition = {
      //     rootDnaId: body.nodeId,
      //     child1DnaId: Not(IsNull()),
      //   };
      // }
    } else if (body.role === "OWNER" || body.role === "ROOT" || body.role === "PARENT") {
      switch (body.reqNode) {
        case 0:
          typeCondition = {
            rootDnaId: body.reqNodeId,
          };
          break;
        case 1:
          typeCondition = {
            child1DnaId: body.reqNodeId,
          };
          break;
        case 2:
          typeCondition = {
            child2DnaId: body.reqNodeId,
          };
          break;
        case 3:
          typeCondition = {
            child3DnaId: body.reqNodeId,
          };
          break;
        case 4:
          typeCondition = {
            child4DnaId: body.reqNodeId,
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    } else if (body.role === "NORMAL") {
      switch (body.node) {
        case 0:
          typeCondition = {
            rootDnaId: body.nodeId,
            child1DnaId: IsNull(),
          };
          break;
        case 1:
          typeCondition = {
            child1DnaId: body.nodeId,
            child2DnaId: IsNull(),
          };
          break;
        case 2:
          typeCondition = {
            child2DnaId: body.nodeId,
            child3DnaId: IsNull(),
          };
          break;
        case 3:
          typeCondition = {
            child3DnaId: body.nodeId,
            child4DnaId: IsNull(),
          };
          break;
        case 4:
          typeCondition = {
            child4DnaId: body.nodeId,
          };
          break;
        default:
          typeCondition = {};
          break;
      }
    }
    const date = body.date ? new Date(body.date.toISOString().slice(0, 10)) : new Date();
    // set เวลาเป็น 23:59:59 ของวันนั้น
    date.setHours(23, 59, 59, 999);

    let profile = await this.posMasterHistoryRepository.find({
      where: {
        ...typeCondition,
        createdAt: LessThanOrEqual(date),
      },
      select: [
        "profileId",
        "prefix",
        "firstName",
        "lastName",
        "shortName",
        "posMasterNo",
        "position",
        "posType",
        "posLevel",
        "ancestorDNA",
        "rootDnaId",
        "child1DnaId",
        "child2DnaId",
        "child3DnaId",
        "child4DnaId",
        "createdAt",
      ],
      order: {
        firstName: "ASC",
        lastName: "ASC",
        createdAt: "DESC",
      },
    });

    // group1: group by ancestorDNA แล้วเลือก create_at ล่าสุด
    const grouped1 = new Map<string, PosMasterHistory>();
    for (const item of profile) {
      const key = `${item.ancestorDNA}`;
      if (!grouped1.has(key)) {
        grouped1.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped1.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped1.set(key, item);
        }
      }
    }
    // group2: group by shortName-posMasterNo จากค่าที่ได้จาก group1
    const grouped2 = new Map<string, PosMasterHistory>();
    for (const item of Array.from(grouped1.values())) {
      const key = `${item.shortName}-${item.posMasterNo}`;
      if (!grouped2.has(key)) {
        grouped2.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped2.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped2.set(key, item);
        }
      }
    }
    // group3: group by firstName-lastName จากค่าที่ได้จาก group2
    const grouped3 = new Map<string, PosMasterHistory>();
    for (const item of Array.from(grouped2.values())) {
      const key = `${item.firstName}-${item.lastName}`;
      if (!grouped3.has(key)) {
        grouped3.set(key, item);
      } else {
        // ถ้าเจอซ้ำ ให้เลือก createdAt ล่าสุด
        const exist = grouped3.get(key);
        if (exist && item.createdAt > exist.createdAt) {
          grouped3.set(key, item);
        }
      }
    }

    const profileIds = Array.from(grouped3.values())
      .filter((x) => x.profileId != null)
      .map((x) => x.profileId);

    const profiles = await this.profileRepo.find({
      where: { id: In(profileIds) },
      select: ["id", "citizenId", "dateStart", "dateAppoint", "keycloak"],
    });

    const profileMap = new Map(profiles.map((p) => [p.id, p]));

    const profile_ = Array.from(grouped3.values())
      .filter((x) => x.profileId != null)
      .map((item: PosMasterHistory) => {
        const profile = profileMap.get(item.profileId);
        return {
          id: item.profileId,
          prefix: item.prefix,
          firstName: item.firstName,
          lastName: item.lastName,
          citizenId: profile?.citizenId ?? null,
          dateStart: profile?.dateStart ?? null,
          dateAppoint: profile?.dateAppoint ?? null,
          keycloak: profile?.keycloak ?? null,
          posNo: `${item.shortName} ${item.posMasterNo}`,
          position: item.position,
          positionLevel: item.posLevel,
          positionType: item.posType,
          orgRootId: item.rootDnaId,
          orgChild1Id: item.child1DnaId,
          orgChild2Id: item.child2DnaId,
          orgChild3Id: item.child3DnaId,
          orgChild4Id: item.child4DnaId,
        };
      });

    return new HttpSuccess(
      (profile_ ?? []).sort((a, b) => a.posNo.localeCompare(b.posNo, undefined, { numeric: true })),
    );
  }

  /**
   * API ค้นหา กจ.
   *
   * @summary API ค้นหา กจ.
   *
   */
  @Post("find-staff")
  @Security("internalAuth")
  async findHigher(
    @Body()
    requestBody: {
      profileId: string;
      assignId: string;
    },
  ) {
    const profile = await this.profileRepo.findOne({
      where: { id: requestBody.profileId },
      relations: {
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
          orgChild2: true,
          orgChild3: true,
          orgChild4: true
        }
      }
    });

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

    const assign = await this.assignRepository.findOne({
      where: { id: requestBody.assignId.trim().toLocaleUpperCase() },
    });

    if (!assign)
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระบบสิทธิ์หน้าที่ความรับผิดชอบ");

    const currentHolder = profile.current_holders?.find(
      (h) => h.orgRevision?.orgRevisionIsCurrent && !h.orgRevision?.orgRevisionIsDraft,
    );

    if (!currentHolder)
      throw new HttpError(HttpStatus.NOT_FOUND, "โปรไฟล์นี้ไม่ได้ครองตำแหน่งในปัจจุบัน");

    const posMasters = await this.posMasterRepository
      .createQueryBuilder("pm")
      .select([
        "pm.current_holderId AS profileId",
        "profile.keycloak AS keycloak",
        "CONCAT(profile.prefix, profile.firstName, ' ', profile.lastName) AS fullName",
        "pm.orgRootId AS rootId",
        "pm.orgChild1Id AS orgChild1Id",
        "pm.orgChild2Id AS orgChild2Id",
        "pm.orgChild3Id AS orgChild3Id",
        "pm.orgChild4Id AS orgChild4Id",
        "orgRoot.ancestorDNA AS rootDnaId",
        "orgChild1.ancestorDNA AS child1DnaId",
        "orgChild2.ancestorDNA AS child2DnaId",
        "orgChild3.ancestorDNA AS child3DnaId",
        "orgChild4.ancestorDNA AS child4DnaId",
        "authRoleAttr.attrPrivilege AS attrPrivilege",
      ])
      .distinct(true)
      // ต้องมี posMasterAssign
      .innerJoin("posMasterAssign", "assign", "assign.posMasterId = pm.id")
      // INNER JOIN เพื่อเอาเฉพาะที่มี attrPrivilege
      .innerJoin("pm.authRole", "authRole")
      .innerJoin(
        "authRole.authRoles", "authRoleAttr",
        "authRoleAttr.authSysId = :authSysId AND authRoleAttr.attrIsList = :attrIsList",
        { 
          attrIsList: true,
          authSysId: assign.id
        }
      )
      // join เพื่อเอา ancestorDNA
      .leftJoin("pm.orgRoot", "orgRoot")
      .leftJoin("pm.orgChild1", "orgChild1")
      .leftJoin("pm.orgChild2", "orgChild2")
      .leftJoin("pm.orgChild3", "orgChild3")
      .leftJoin("pm.orgChild4", "orgChild4")
      .leftJoin("pm.current_holder", "profile")
      .where("pm.orgRevisionId = :orgRevisionId", {
        orgRevisionId: currentHolder.orgRevisionId,
      })
      .andWhere("pm.orgRootId = :orgRootId", {
        orgRootId: currentHolder.orgRootId,
      })
      .andWhere("pm.current_holderId != :profileId", {
        profileId: profile.id,
      })
      .andWhere("assign.assignId = :assignId", {
        assignId: assign.id,
      })
      .getRawMany();

    // ────────────────────────────────────────────────────────
    // กรองตามสิทธิ์ (NORMAL, CHILD, BROTHER)
    // ROOT และ PARENT ให้ผ่านทุกคน เพราะ filter orgRootId อยู่แล้ว
    // ────────────────────────────────────────────────────────

    // 1. หา User Node
    const userNode = currentHolder.orgChild4Id ? 4
      : currentHolder.orgChild3Id ? 3
      : currentHolder.orgChild2Id ? 2
      : currentHolder.orgChild1Id ? 1
      : 0;

    // 2. หา User DNA แต่ละระดับ
    const userDna = {
      root: currentHolder.orgRoot?.ancestorDNA ?? null,
      child1: currentHolder.orgChild1?.ancestorDNA ?? null,
      child2: currentHolder.orgChild2?.ancestorDNA ?? null,
      child3: currentHolder.orgChild3?.ancestorDNA ?? null,
      child4: currentHolder.orgChild4?.ancestorDNA ?? null,
    };
    
    // 3. กรอง posMasters ตามสิทธิ์
    const filteredPosMasters = posMasters.filter((staff) => {
      const privilege = staff.attrPrivilege;

      // ROOT และ PARENT: ให้ผ่านทุกคน เพราะ filter orgRootId อยู่แล้ว
      if (privilege === "ROOT" || privilege === "PARENT" || privilege === "OWNER") {
        return true;
      }

      // หา Staff Node
      const staffNode = staff.orgChild4Id ? 4
        : staff.orgChild3Id ? 3
        : staff.orgChild2Id ? 2
        : staff.orgChild1Id ? 1
        : 0;

      // หา Staff DNA
      const staffDna = {
        root: staff.rootDnaId,
        child1: staff.child1DnaId,
        child2: staff.child2DnaId,
        child3: staff.child3DnaId,
        child4: staff.child4DnaId,
      };

      // NORMAL: Node เท่ากัน + DNA เหมือนกันทุกตัว
      if (privilege === "NORMAL") {
        return (
          staffNode === userNode &&
          staffDna.root === userDna.root &&
          (staffNode < 1 || staffDna.child1 === userDna.child1) &&
          (staffNode < 2 || staffDna.child2 === userDna.child2) &&
          (staffNode < 3 || staffDna.child3 === userDna.child3) &&
          (staffNode < 4 || staffDna.child4 === userDna.child4)
        );
      }

      // CHILD: Staff เห็น User ที่อยู่ในกิ่งลูก
      if (privilege === "CHILD") {
        // Staff ต้องอยู่บนกว่าหรือเท่ากับ User
        if (staffNode > userNode) return false;

        switch (staffNode) {
          case 0:
            if (staffDna.root !== userDna.root) return false;
            break;
          case 1:
            if (staffDna.root !== userDna.root) return false;
            if (staffDna.child1 !== userDna.child1) return false;
            break;
          case 2:
            if (staffDna.root !== userDna.root) return false;
            if (staffDna.child1 !== userDna.child1) return false;
            if (staffDna.child2 !== userDna.child2) return false;
            break;
          case 3:
            if (staffDna.root !== userDna.root) return false;
            if (staffDna.child1 !== userDna.child1) return false;
            if (staffDna.child2 !== userDna.child2) return false;
            if (staffDna.child3 !== userDna.child3) return false;
            break;
          case 4:
            if (staffDna.root !== userDna.root) return false;
            if (staffDna.child1 !== userDna.child1) return false;
            if (staffDna.child2 !== userDna.child2) return false;
            if (staffDna.child3 !== userDna.child3) return false;
            if (staffDna.child4 !== userDna.child4) return false;
            break;
        }
        return true;
      }

      // BROTHER: Staff เห็น User ที่อยู่ในกิ่งข้างบนและลูก
      if (privilege === "BROTHER") {
        if (userNode < staffNode - 1 || userNode > 4) return false;

        if (staffNode === 0 || staffNode === 1) {
          if (staffDna.root !== userDna.root) return false;
        } /*else if (staffNode === 1) {
          if (staffDna.root !== userDna.root) return false;
          if (staffDna.child1 !== userDna.child1) return false;
        }*/ else if (staffNode === 2) {
          if (staffDna.child1 !== userDna.child1) return false;
          // if (staffDna.child2 !== userDna.child2 && userDna.child2 !== null) return false;
        } else if (staffNode === 3) {
          if (staffDna.child2 !== userDna.child2) return false;
          // if (staffDna.child3 !== userDna.child3 && userDna.child3 !== null) return false;
        } else if (staffNode === 4) {
          if (staffDna.child3 !== userDna.child3) return false;
          // if (staffDna.child4 !== userDna.child4 && userDna.child4 !== null) return false;
        }
        return true;
      }
      // กรณีอื่นๆ ให้ผ่าน
      return true;
    });
    return new HttpSuccess(filteredPosMasters);
  }

  /**
   * API ตรวจสอบสถานะผู้สมัครสอบ 
   * @summary API ตรวจสอบสถานะผู้สมัครสอบ
   */
  @Post("check-isLeave")
  @Security("internalAuth")
  async findProfileIsLeave(
    @Body()
    req: { citizenIds: string[] }
  ) {

    const profiles = await this.profileRepo.find({
      select: { 
        id: true,
        citizenId: true,
        isLeave: true,
        isActive: true 
      },
      where: { 
        citizenId: In(req.citizenIds)
      }
    });

    if (profiles.length === 0) {
      return new HttpSuccess([]);
    }
    
    return new HttpSuccess(
      profiles.map(p => ({
        citizenId: p.citizenId,
        profileId: p.id,
        isLeave: p.isLeave ?? false,
        isActive: p.isActive ?? false
      }))
    );

  }

}
