import {
  Controller,
  Post,
  Put,
  Delete,
  Route,
  Security,
  Tags,
  Body,
  Path,
  Request,
  Response,
  Get,
  Query,
} from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatusCode from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import { Command } from "../entities/Command";
import { Brackets, LessThan, MoreThan, Double, In, Between, IsNull, Not, Like } from "typeorm";
import { CommandType } from "../entities/CommandType";
import { CommandSend } from "../entities/CommandSend";
import { Profile, CreateProfileAllFields } from "../entities/Profile";
import { RequestWithUser } from "../middlewares/user";
import { OrgRevision } from "../entities/OrgRevision";
import { CommandSendCC } from "../entities/CommandSendCC";
import { CommandSalary } from "../entities/CommandSalary";
import { CommandRecive } from "../entities/CommandRecive";
import { CommandOperator } from "../entities/CommandOperator";
import HttpStatus from "../interfaces/http-status";
import Extension from "../interfaces/extension";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import CallAPI from "../interfaces/call-api";
import { ProfileSalary, CreateProfileSalary } from "../entities/ProfileSalary";
import { ProfileSalaryHistory } from "../entities/ProfileSalaryHistory";
import {
  calculateRetireDate,
  calculateRetireLaw,
  commandTypePath,
  removeProfileInOrganize,
  setLogDataDiff,
  checkReturnCommandType,
  checkCommandType,
  removePostMasterAct,
  logPositionIsSelectedChange,
} from "../interfaces/utils";
import { Position } from "../entities/Position";
import { PosMaster } from "../entities/PosMaster";
import { EmployeePosition } from "../entities/EmployeePosition";
import { getPosMasterNo, getOrgFullName } from "../utils/org-formatting";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { ProfileDiscipline } from "../entities/ProfileDiscipline";
import { ProfileDisciplineHistory } from "../entities/ProfileDisciplineHistory";
import { PosMasterAct } from "../entities/PosMasterAct";
import { sendToQueue, sendToQueueCommandNoti } from "../services/rabbitmq";
import { PosLevel } from "../entities/PosLevel";
import { PosType } from "../entities/PosType";
import {
  addUserRoles,
  createUser,
  getRoles,
  deleteUser,
  getUserByUsername,
  getRoleMappings,
  removeUserRoles,
  getToken,
  updateUserAttributes,
} from "../keycloak";
import { ProfileEducation, CreateProfileEducation } from "../entities/ProfileEducation";
import { ProfileEducationHistory } from "../entities/ProfileEducationHistory";
import { CreateProfileCertificate, ProfileCertificate } from "../entities/ProfileCertificate";
import { ProfileCertificateHistory } from "../entities/ProfileCertificateHistory";
import permission from "../interfaces/permission";
import { CommandSign } from "../entities/CommandSign";
import { RoleKeycloak } from "../entities/RoleKeycloak";
import axios from "axios";
import querystring from "querystring";
import { SubDistrict } from "../entities/SubDistrict";
import { District } from "../entities/District";
import { Province } from "../entities/Province";
import { ProfileAssistance } from "../entities/ProfileAssistance";
import { ProfileAssistanceHistory } from "../entities/ProfileAssistanceHistory";
import { ProfileActposition } from "../entities/ProfileActposition";
import { ProfileActpositionHistory } from "../entities/ProfileActpositionHistory";
import { ProfileFamilyFather } from "../entities/ProfileFamilyFather";
import { ProfileFamilyFatherHistory } from "../entities/ProfileFamilyFatherHistory";
import { ProfileFamilyCouple } from "../entities/ProfileFamilyCouple";
import { ProfileFamilyCoupleHistory } from "../entities/ProfileFamilyCoupleHistory";
import { ProfileFamilyMother } from "../entities/ProfileFamilyMother";
import { ProfileFamilyMotherHistory } from "../entities/ProfileFamilyMotherHistory";
import { OrgRoot } from "../entities/OrgRoot";
import { EmployeeTempPosMaster } from "../entities/EmployeeTempPosMaster";
import { ProfileInsignia, CreateProfileInsignia } from "../entities/ProfileInsignia";
import { ProfileInsigniaHistory } from "../entities/ProfileInsigniaHistory";
import { Gender } from "../entities/Gender";
import { ProfileAvatar } from "../entities/ProfileAvatar";
import {
  CreatePosMasterHistoryEmployee,
  CreatePosMasterHistoryEmployeeTemp,
  CreatePosMasterHistoryOfficer,
} from "../services/PositionService";
import { LeaveType } from "../entities/LeaveType";
import { KeycloakAttributeService } from "../services/KeycloakAttributeService";
import { reOrderCommandRecivesAndDelete } from "../services/CommandService";
import { RetirementService } from "../services/RetirementService";
import { promisify } from "util";
const REDIS_HOST = process.env.REDIS_HOST;
const REDIS_PORT = process.env.REDIS_PORT;

@Route("api/v1/org/command")
@Tags("Command")
@Security("bearerAuth")
@Response(
  HttpStatusCode.INTERNAL_SERVER_ERROR,
  "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class CommandController extends Controller {
  private redis = require("redis");
  private commandRepository = AppDataSource.getRepository(Command);
  private commandTypeRepository = AppDataSource.getRepository(CommandType);
  private commandSendRepository = AppDataSource.getRepository(CommandSend);
  private commandSendCCRepository = AppDataSource.getRepository(CommandSendCC);
  private commandSalaryRepository = AppDataSource.getRepository(CommandSalary);
  private commandReciveRepository = AppDataSource.getRepository(CommandRecive);
  private commandOperatorRepository = AppDataSource.getRepository(CommandOperator);
  private profileRepository = AppDataSource.getRepository(Profile);
  private profileEmployeeRepository = AppDataSource.getRepository(ProfileEmployee);
  private orgRevisionRepo = AppDataSource.getRepository(OrgRevision);
  private salaryRepo = AppDataSource.getRepository(ProfileSalary);
  private salaryHistoryRepo = AppDataSource.getRepository(ProfileSalaryHistory);
  private posMasterRepository = AppDataSource.getRepository(PosMaster);
  private positionRepository = AppDataSource.getRepository(Position);
  private employeePosMasterRepository = AppDataSource.getRepository(EmployeePosMaster);
  private employeeTempPosMasterRepository = AppDataSource.getRepository(EmployeeTempPosMaster);
  private employeePositionRepository = AppDataSource.getRepository(EmployeePosition);
  private disciplineRepository = AppDataSource.getRepository(ProfileDiscipline);
  private disciplineHistoryRepository = AppDataSource.getRepository(ProfileDisciplineHistory);
  private posMasterActRepository = AppDataSource.getRepository(PosMasterAct);
  private posLevelRepo = AppDataSource.getRepository(PosLevel);
  private posTypeRepo = AppDataSource.getRepository(PosType);
  private profileEducationRepo = AppDataSource.getRepository(ProfileEducation);
  private profileEducationHistoryRepo = AppDataSource.getRepository(ProfileEducationHistory);
  private certificateRepo = AppDataSource.getRepository(ProfileCertificate);
  private certificateHistoryRepo = AppDataSource.getRepository(ProfileCertificateHistory);
  private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
  private commandSignRepository = AppDataSource.getRepository(CommandSign);
  private roleKeycloakRepo = AppDataSource.getRepository(RoleKeycloak);
  private provinceRepo = AppDataSource.getRepository(Province);
  private districtRepo = AppDataSource.getRepository(District);
  private subDistrictRepo = AppDataSource.getRepository(SubDistrict);
  private assistanceRepository = AppDataSource.getRepository(ProfileAssistance);
  private assistanceHistoryRepository = AppDataSource.getRepository(ProfileAssistanceHistory);
  private actpositionRepository = AppDataSource.getRepository(ProfileActposition);
  private actpositionHistoryRepository = AppDataSource.getRepository(ProfileActpositionHistory);
  private profileFamilyCoupleRepo = AppDataSource.getRepository(ProfileFamilyCouple);
  private profileFamilyCoupleHistoryRepo = AppDataSource.getRepository(ProfileFamilyCoupleHistory);
  private profileFamilyMotherRepo = AppDataSource.getRepository(ProfileFamilyMother);
  private profileFamilyMotherHistoryRepo = AppDataSource.getRepository(ProfileFamilyMotherHistory);
  private profileFamilyFatherRepo = AppDataSource.getRepository(ProfileFamilyFather);
  private profileFamilyFatherHistoryRepo = AppDataSource.getRepository(ProfileFamilyFatherHistory);
  private orgRootRepository = AppDataSource.getRepository(OrgRoot);
  private insigniaRepo = AppDataSource.getRepository(ProfileInsignia);
  private insigniaHistoryRepo = AppDataSource.getRepository(ProfileInsigniaHistory);
  private genderRepo = AppDataSource.getRepository(Gender);
  private avatarRepository = AppDataSource.getRepository(ProfileAvatar);
  private leaveType = AppDataSource.getRepository(LeaveType);
  private keycloakAttributeService = new KeycloakAttributeService();

  /**
   * API  list รายการคำสั่ง
   *
   * @summary API  list รายการคำสั่ง
   *
   */
  @Get("list")
  async GetResult(
    @Request() request: RequestWithUser,
    @Query("sortBy") sortBy?: string,
    @Query("descending") descending?: boolean,
    @Query("page") page: number = 1,
    @Query("pageSize") pageSize: number = 10,
    @Query() keyword: string = "",
    @Query() commandTypeId?: string | null,
    @Query() year?: number,
    @Query() status?: string | null,
  ) {
    await new permission().PermissionList(request, "COMMAND");
    let profilekArray: any = [];

    let _profile = await this.profileRepository.findOne({
      where: { keycloak: request.user.sub },
      relations: ["current_holders", "current_holders.orgRevision"],
    });
    let isDirector =
      _profile?.current_holders?.filter(
        (x) =>
          x.orgRevision?.orgRevisionIsCurrent == true && x.orgRevision?.orgRevisionIsDraft == false,
      )[0]?.isDirector || false;
    let _data: any = {
      root: null,
      child1: null,
      child2: null,
      child3: null,
      child4: null,
    };
    if (request.user.role.includes("STAFF")) {
      // #2523 STAFF + isDirector ให้ล้อสิทธิ์เหมือน CHILD
      if (!isDirector) {
        _data = await new permission().PermissionOrgList(request, "COMMAND");
        
      } else {
        _data = await new permission().PermissionIsDirectorOrgList(request, "COMMAND", isDirector);
      }
    }
    if (isDirector || _data.privilege == "OWNER") {
      const profiles = await this.profileRepository
        .createQueryBuilder("profile")
        .leftJoinAndSelect("profile.current_holders", "current_holders")
        .leftJoinAndSelect("current_holders.orgRoot", "orgRoot")
        .leftJoinAndSelect("current_holders.orgChild1", "orgChild1")
        .leftJoinAndSelect("current_holders.orgChild2", "orgChild2")
        .leftJoinAndSelect("current_holders.orgChild3", "orgChild3")
        .leftJoinAndSelect("current_holders.orgChild4", "orgChild4")
        .andWhere(
          _data.root != undefined && _data.root != null
            ? _data.root[0] != null
              ? `current_holders.orgRootId IN (:...root)`
              : `current_holders.orgRootId is null`
            : "1=1",
          {
            root: _data.root,
          },
        )
        .andWhere(
          _data.child1 != undefined && _data.child1 != null
            ? _data.child1[0] != null
              ? `current_holders.orgChild1Id IN (:...child1)`
              : // : `current_holders.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
                `current_holders.orgChild1Id is null`
            : "1=1",
          {
            child1: _data.child1,
          },
        )
        .andWhere(
          _data.child2 != undefined && _data.child2 != null
            ? _data.child2[0] != null
              ? `current_holders.orgChild2Id IN (:...child2)`
              : `current_holders.orgChild2Id is null`
            : "1=1",
          {
            child2: _data.child2,
          },
        )
        .andWhere(
          _data.child3 != undefined && _data.child3 != null
            ? _data.child3[0] != null
              ? `current_holders.orgChild3Id IN (:...child3)`
              : `current_holders.orgChild3Id is null`
            : "1=1",
          {
            child3: _data.child3,
          },
        )
        .andWhere(
          _data.child4 != undefined && _data.child4 != null
            ? _data.child4[0] != null
              ? `current_holders.orgChild4Id IN (:...child4)`
              : `current_holders.orgChild4Id is null`
            : "1=1",
          {
            child4: _data.child4,
          },
        )
        .select("profile.keycloak", "keycloak")
        .getRawMany();
      profilekArray = profiles.map((p) => p.keycloak);
    }
    //only search command name
    let baseKeyword = keyword;
    let yearKeyword = "";
    const regex = /\/(\d{4})$/;
    const match = keyword.match(regex);
    if (match) {
      baseKeyword = keyword.substring(0, keyword.lastIndexOf("/")).trim();
      yearKeyword = match[1].trim();
    }
    let yearInBC = yearKeyword ? parseInt(yearKeyword) - 543 : null;

    // const [commands, total] = await this.commandRepository
    let query = await this.commandRepository
      .createQueryBuilder("command")
      .leftJoinAndSelect("command.commandType", "commandType")
      .andWhere(
        new Brackets((qb) => {
          qb.orWhere(
            profilekArray.length > 0
              ? "command.createdUserId IN (:...profilekArray)"
              : "command.createdUserId='1'",
            {
              profilekArray: profilekArray,
            },
          ).orWhere("command.createdUserId = :createdUserId", {
            createdUserId: request.user.sub,
          });
        }),
      )
      .andWhere(
        status != null && status != undefined && status != ""
          ? "command.status IN (:...status)"
          : "1=1",
        {
          status:
            status == null || status == undefined || status == ""
              ? null
              : status.trim().toLocaleUpperCase() == "NEW" ||
                  status.trim().toLocaleUpperCase() == "DRAFT"
                ? ["NEW", "DRAFT"]
                : [status.trim().toLocaleUpperCase()],
        },
      )
      .andWhere(
        year != null && year != undefined && year != 0
          ? "command.commandYear = :commandYear"
          : "1=1",
        {
          commandYear: year == null || year == undefined || year == 0 ? null : `${year}`,
        },
      )
      .andWhere(
        commandTypeId != null && commandTypeId != undefined && commandTypeId != ""
          ? "command.commandTypeId = :commandTypeId"
          : "1=1",
        {
          commandTypeId:
            commandTypeId == null || commandTypeId == undefined || commandTypeId == ""
              ? null
              : `${commandTypeId}`,
        },
      )
      .andWhere(
        new Brackets((qb) => {
          qb.where(
            keyword != null && keyword != ""
              ? "TRIM(CONCAT(COALESCE(command.shortName, ''), ' ', command.commandNo, '/', command.commandYear + 543)) LIKE :keyword"
              : "1=1",
            {
              keyword: `%${keyword}%`,
            },
          )
            .orWhere(keyword != null && keyword != "" ? "command.issue LIKE :keyword" : "1=1", {
              keyword: `%${keyword}%`,
            })
            .orWhere(
              keyword != null && keyword != "" ? "command.createdFullName LIKE :keyword" : "1=1",
              {
                keyword: `%${keyword}%`,
              },
            );
        }),
      )
      .orderBy("command.createdAt", "DESC");

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

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

    const data = commands.map((_data) => ({
      id: _data.id,
      commandNo: `${_data.shortName ?? ""} ${_data.commandNo}`.trim(),
      commandYear: _data.commandYear,
      commandAffectDate: _data.commandAffectDate,
      commandExcecuteDate: _data.commandExcecuteDate,
      commandType: _data.commandType ? _data.commandType.code : null,
      assignFullName: null, //xxxxxxxxxxxxxxx
      createdFullName: _data.createdFullName,
      status: _data.status,
      issue: _data.issue,
    }));

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

  /**
   * API สร้างรายการ body คำสั่ง
   *
   * @summary API สร้างรายการ body คำสั่ง
   *
   */
  @Post()
  async Post(
    @Body()
    requestBody: {
      commandTypeId: string;
      commandNo: string | null;
      commandYear: number | null;
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionCreate(request, "COMMAND");
    const command = Object.assign(new Command(), requestBody);

    const commandType = await this.commandTypeRepository.findOne({
      where: { id: requestBody.commandTypeId },
    });

    if (!commandType) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    }
    const now = new Date();
    command.detailHeader = commandType.detailHeader;
    command.detailBody = commandType.detailBody;
    command.detailFooter = commandType.detailFooter;
    command.isAttachment = commandType.isAttachment;
    command.isUploadAttachment = commandType.isUploadAttachment;
    command.status = "NEW";
    command.issue = commandType.name;
    command.createdUserId = request.user.sub;
    command.createdFullName = request.user.name;
    command.createdAt = now;
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = now;
    await this.commandRepository.save(command);
    // insert commandOperator
    if (request.user.sub) {
      const profile = await this.profileRepository.findOne({
        where: { keycloak: request.user.sub },
        relations: {
          posLevel: true,
          posType: true,
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
      });
      if (profile) {
        const currentHolder = profile!.current_holders?.find(
          (x) =>
            x.orgRevision?.orgRevisionIsDraft === false &&
            x.orgRevision?.orgRevisionIsCurrent === true,
        );

        const posNo =
          currentHolder != null && currentHolder.orgChild4 != null
            ? `${currentHolder.orgChild4.orgChild4ShortName} ${currentHolder.posMasterNo}`
            : currentHolder != null && currentHolder.orgChild3 != null
              ? `${currentHolder.orgChild3.orgChild3ShortName} ${currentHolder.posMasterNo}`
              : currentHolder != null && currentHolder.orgChild2 != null
                ? `${currentHolder.orgChild2.orgChild2ShortName} ${currentHolder.posMasterNo}`
                : currentHolder != null && currentHolder.orgChild1 != null
                  ? `${currentHolder.orgChild1.orgChild1ShortName} ${currentHolder.posMasterNo}`
                  : currentHolder != null && currentHolder?.orgRoot != null
                    ? `${currentHolder.orgRoot.orgRootShortName} ${currentHolder.posMasterNo}`
                    : null;

        const position = await this.positionRepository.findOne({
          where: {
            positionIsSelected: true,
            posMaster: {
              orgRevisionId: currentHolder?.orgRevisionId,
              current_holderId: profile!.id,
            },
          },
          order: { createdAt: "DESC" },
          relations: { posExecutive: true },
        });
        const operator = Object.assign(new CommandOperator(), {
          profileId: profile?.id,
          prefix: profile?.prefix,
          firstName: profile?.firstName,
          lastName: profile?.lastName,
          posNo: posNo,
          posType: profile?.posType?.posTypeName ?? null,
          posLevel: profile?.posLevel?.posLevelName ?? null,
          position: position?.positionName ?? null,
          positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
          roleName: "เจ้าหน้าที่ดำเนินการ",
          orderNo: 1,
          commandId: command.id,
          createdUserId: request.user.sub,
          createdFullName: request.user.name,
          createdAt: now,
          lastUpdateUserId: request.user.sub,
          lastUpdateFullName: request.user.name,
          lastUpdatedAt: now,
        });
        await this.commandOperatorRepository.save(operator);
      }
    }
    return new HttpSuccess(command.id);
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab1
   *
   * @summary API รายละเอียดรายการคำสั่ง tab1
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("tab1/{id}")
  async GetByIdTab1(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandType", "commandType.commandTypeSys"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const _command = {
      id: command.id,
      status: command.status,
      shortName: command.shortName ?? "",
      commandNo: command.commandNo,
      commandYear: command.commandYear,
      issue: command.issue,
      detailHeader: command.detailHeader,
      detailBody: command.detailBody,
      detailFooter: command.detailFooter,
      isBangkok: command.isBangkok,
      isAttachment: command.isAttachment,
      isUploadAttachment: command.isUploadAttachment,
      commandAffectDate: command.commandAffectDate,
      commandExcecuteDate: command.commandExcecuteDate,
      commandTypeName: command.commandType?.name || null,
      commandCode: command.commandType?.code || null,
      commandSysId: command.commandType?.commandSysId || null,
      createdUserId: command.createdUserId,
    };
    return new HttpSuccess(_command);
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง Tab1
   *
   * @summary API  แก้ไขรายการ body คำสั่ง Tab1
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("tab1/{id}")
  async PutTab1(
    @Path() id: string,
    @Body()
    requestBody: {
      commandNo: string | null;
      commandYear: number | null;
      issue: string | null;
      detailHeader: string | null;
      detailBody: string | null;
      detailFooter: string | null;
      commandAffectDate: Date | null;
      commandExcecuteDate: Date | null;
      isBangkok: string | null;
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    const data = new Command();
    Object.assign(data, { ...command, ...requestBody });

    // ถ้าเป็น officer (isOfficer == true) ดึง orgRoot.shortName มาใช้
    const userProfile = await this.profileRepository.findOne({
      where: { keycloak: request.user.sub },
      relations: {
        current_holders: {
          orgRevision: true,
          orgRoot: true,
          orgChild1: true,
        },
      },
    });

    if (userProfile) {
      const currentHolder = userProfile.current_holders?.find(
        (x: any) =>
          x.orgRevision?.orgRevisionIsDraft === false &&
          x.orgRevision?.orgRevisionIsCurrent === true,
      );

      if (currentHolder && currentHolder.orgChild1?.isOfficer) {
        data.shortName = 
          requestBody.isBangkok && requestBody.isBangkok === "BANGKOK" 
            ? "กทม." 
            : currentHolder.orgRoot?.orgRootShortName ?? "สนป.";
      }
    }

    data.lastUpdateUserId = request.user.sub;
    data.lastUpdateFullName = request.user.name;
    data.lastUpdatedAt = new Date();
    await this.commandRepository.save(data);
    return new HttpSuccess();
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab2
   *
   * @summary API รายละเอียดรายการคำสั่ง tab2
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("tab2/{id}")
  async GetByIdTab2(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandSalary", "commandRecives"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const _command = {
      id: command.id,
      commandSalaryId: command.commandSalaryId,
      commandSalary: command.commandSalary?.name || null,
      positionDetail: command.positionDetail,
      commandRecives: command.commandRecives
        .sort((a, b) => a.order - b.order)
        .map((x) => ({
          id: x.id,
          citizenId: x.citizenId,
          prefix: x.prefix,
          firstName: x.firstName,
          lastName: x.lastName,
          //   profileId: x.profileId,
          order: x.order,
          remarkVertical: x.remarkVertical,
          remarkHorizontal: x.remarkHorizontal,
          amount: x.amount,
          amountSpecial: x.amountSpecial,
          positionSalaryAmount: x.positionSalaryAmount,
          mouthSalaryAmount: x.mouthSalaryAmount,
          position: x.position,
          posType: x.posType,
          posLevel: x.posLevel,
          posNo: x.posNo,
        })),
    };
    return new HttpSuccess(_command);
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง Tab2
   *
   * @summary API  แก้ไขรายการ body คำสั่ง Tab2
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("tab2/{id}")
  async PutTab2(
    @Path() id: string,
    @Body()
    requestBody: {
      positionDetail: string | null;
      commandSalaryId: string | null;
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    if (requestBody.commandSalaryId != undefined && requestBody.commandSalaryId != null) {
      const commandSalary = await this.commandSalaryRepository.findOne({
        where: { id: requestBody.commandSalaryId },
      });
      if (!commandSalary) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลต้นแบบ");
      }
    }
    const data = new Command();
    Object.assign(data, { ...command, ...requestBody });
    data.lastUpdateUserId = request.user.sub;
    data.lastUpdateFullName = request.user.name;
    data.lastUpdatedAt = new Date();
    await this.commandRepository.save(data);
    return new HttpSuccess();
  }

  @Get("tab2/swap/{direction}/{commandReciveId}")
  public async swapSalary(
    @Path() direction: string,
    commandReciveId: string,
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const source_item = await this.commandReciveRepository.findOne({
      where: { id: commandReciveId },
    });
    if (source_item == null) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    const sourceOrder = source_item.order;
    if (direction.trim().toUpperCase() == "UP") {
      const dest_item = await this.commandReciveRepository.findOne({
        where: { commandId: source_item.commandId, order: LessThan(sourceOrder) },
        order: { order: "DESC" },
      });
      if (dest_item == null) return new HttpSuccess();
      var destOrder = dest_item.order;
      dest_item.order = sourceOrder;
      source_item.order = destOrder;
      await Promise.all([
        this.commandReciveRepository.save(source_item),
        this.commandReciveRepository.save(dest_item),
      ]);
    } else {
      const dest_item = await this.commandReciveRepository.findOne({
        where: { commandId: source_item.commandId, order: MoreThan(sourceOrder) },
        order: { order: "ASC" },
      });
      if (dest_item == null) return new HttpSuccess();
      var destOrder = dest_item.order;
      dest_item.order = sourceOrder;
      source_item.order = destOrder;
      await Promise.all([
        this.commandReciveRepository.save(source_item),
        this.commandReciveRepository.save(dest_item),
      ]);
    }
    return new HttpSuccess();
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง Tab2
   *
   * @summary API  แก้ไขรายการ body คำสั่ง Tab2
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("tab2/recive/{commandReciveId}")
  async PutTab2Recive(
    @Path() commandReciveId: string,
    @Body()
    requestBody: {
      remarkVertical: string | null;
      remarkHorizontal: string | null;
      amount: Double | null;
      amountSpecial: Double | null;
      positionSalaryAmount: Double | null;
      mouthSalaryAmount: Double | null;
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const commandRecive = await this.commandReciveRepository.findOne({
      where: { id: commandReciveId },
    });
    if (!commandRecive) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ได้รับคำสั่ง");
    }
    const data = new CommandRecive();
    Object.assign(data, { ...commandRecive, ...requestBody });
    data.lastUpdateUserId = request.user.sub;
    data.lastUpdateFullName = request.user.name;
    data.lastUpdatedAt = new Date();
    await this.commandReciveRepository.save(data);
    return new HttpSuccess();
  }

  /**
   * API แก้ไขเงินเดือนทั้งกลุ่ม
   *
   * @summary API แก้ไขเงินเดือนทั้งกลุ่ม
   *
   * @param {string} id  Id คำสั่ง
   */
  @Post("tab2/edit-salary")
  async EditSalary(
    @Body()
    requestBody: {
      id: string;
      mouthSalaryAmount?: Double | null;
      positionSalaryAmount?: Double | null;
      amount?: Double | null;
      amountSpecial?: Double | null;
      remarkVertical?: string | null;
      remarkHorizontal?: string | null;
    }[],
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");

    if (!Array.isArray(requestBody)) {
      throw new HttpError(HttpStatusCode.BAD_REQUEST, "รูปแบบข้อมูลไม่ถูกต้อง");
    }

    for (const item of requestBody) {
      if (!item.id) continue;

      const rec = await this.commandReciveRepository.findOne({
        where: { id: item.id },
      });

      if (!rec) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ได้รับคำสั่ง");
      }

      const updated = Object.assign(rec, item);
      updated.lastUpdateUserId = request.user.sub;
      updated.lastUpdateFullName = request.user.name;
      updated.lastUpdatedAt = new Date();

      await this.commandReciveRepository.save(updated);
    }
    return new HttpSuccess();
  }

  /**
   * API ลบรายการผู้ได้รับคำสั่ง
   *
   * @summary API ลบรายการผู้ได้รับคำสั่ง
   *
   * @param {string} id  Id ผู้ได้รับคำสั่ง
   */
  @Delete("tab2/{commandReciveId}")
  async DeleteTab2(@Path() commandReciveId: string, @Request() request: RequestWithUser) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const commandRecive = await this.commandReciveRepository.findOne({
      where: { id: commandReciveId },
      relations: ["command", "command.commandType"],
    });
    if (!commandRecive) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ได้รับคำสั่ง");
    }

    const path = commandTypePath(commandRecive.command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/delete", {
        refIds: [commandRecive.refId],
      })
      .then(async (res) => {})
      .catch(() => {});

    const commandId = commandRecive.commandId;
    await this.commandReciveRepository.delete(commandRecive.id);

    const commandReciveList = await this.commandReciveRepository.find({
      where: {
        commandId: commandId,
      },
      order: { order: "ASC" },
    });
    commandReciveList.map(async (p, i) => {
      p.order = i + 1;
      await this.commandReciveRepository.save(p);
    });

    return new HttpSuccess();
  }

  /**
   * API ลบรายการผู้ได้รับคำสั่ง
   *
   * @summary API ลบรายการผู้ได้รับคำสั่ง
   *
   * @param {string} id  Id ผู้ได้รับคำสั่ง
   */
  @Delete("tab2Cancel17/{refId}")
  async DeleteTab2Cancel17(@Path() refId: string, @Request() request: RequestWithUser) {
    // await new permission().PermissionUpdate(request, "COMMAND");
    const commandRecive = await this.commandReciveRepository.findOne({
      where: { refId: refId, command: { commandType: { code: "C-PM-17" } } },
      relations: ["command", "command.commandType"],
    });
    if (!commandRecive) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ได้รับคำสั่ง");
    }

    const path = commandTypePath(commandRecive.command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/delete", {
        refIds: [commandRecive.refId],
      })
      .then(async (res) => {})
      .catch(() => {});

    const commandId = commandRecive.commandId;
    await this.commandReciveRepository.delete(commandRecive.id);

    const commandReciveList = await this.commandReciveRepository.find({
      where: {
        commandId: commandId,
      },
      order: { order: "ASC" },
    });
    commandReciveList.map(async (p, i) => {
      p.order = i + 1;
      await this.commandReciveRepository.save(p);
    });

    return new HttpSuccess();
  }

  /**
   * API ลบรายการผู้ได้รับคำสั่ง
   *
   * @summary API ลบรายการผู้ได้รับคำสั่ง
   *
   * @param {string} id  Id ผู้ได้รับคำสั่ง
   */
  @Delete("tab2Cancel23/{refId}")
  async DeleteTab2Cancel23(@Path() refId: string, @Request() request: RequestWithUser) {
    // await new permission().PermissionUpdate(request, "COMMAND");
    const commandRecive = await this.commandReciveRepository.findOne({
      where: { refId: refId, command: { commandType: { code: "C-PM-23" } } },
      relations: ["command", "command.commandType"],
    });
    if (!commandRecive) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ได้รับคำสั่ง");
    }

    const path = commandTypePath(commandRecive.command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/delete", {
        refIds: [commandRecive.refId],
      })
      .then(async (res) => {})
      .catch(() => {});

    const commandId = commandRecive.commandId;
    await this.commandReciveRepository.delete(commandRecive.id);

    const commandReciveList = await this.commandReciveRepository.find({
      where: {
        commandId: commandId,
      },
      order: { order: "ASC" },
    });
    commandReciveList.map(async (p, i) => {
      p.order = i + 1;
      await this.commandReciveRepository.save(p);
    });

    return new HttpSuccess();
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab3
   *
   * @summary API รายละเอียดรายการคำสั่ง tab3
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("tab3/{id}")
  async GetByIdTab3(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      order: {
        commandSends: {
          createdAt: "ASC",
        },
      },
      relations: ["commandSends", "commandSends.commandSendCCs"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const _command = command.commandSends.map((item) => ({
      id: item.id,
      citizenId: item.citizenId,
      prefix: item.prefix,
      firstName: item.firstName,
      lastName: item.lastName,
      position: item.position,
      org: item.org,
      sendCC: item.commandSendCCs.sort((a, b) => a.name.localeCompare(b.name)).map((x) => x.name),
      profileId: item.profileId,
    }));
    return new HttpSuccess(_command);
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง Tab3
   *
   * @summary API  แก้ไขรายการ body คำสั่ง Tab3
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("tab3-add/{id}")
  async PutTab3Add(
    @Path() id: string,
    @Body()
    requestBody: {
      profileId: string[];
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    let _null: any = null;

    await Promise.all(
      requestBody.profileId.map(async (item) => {
        const commandSendCheck = await this.commandSendRepository.findOne({
          where: { profileId: item, commandId: command.id },
        });
        if (commandSendCheck) return;

        let profile = await this.profileRepository.findOne({
          where: { id: item },
          relations: ["current_holders", "current_holders.orgRoot"],
        });
        if (!profile) return;

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

        const commandSend = new CommandSend();
        commandSend.citizenId = profile.citizenId;
        commandSend.prefix =
          profile.rank != null && profile.rank != "" ? profile.rank : profile.prefix;
        commandSend.firstName = profile.firstName;
        commandSend.lastName = profile.lastName;
        commandSend.position = profile.position;
        commandSend.org =
          profile.current_holders?.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot
            ?.orgRootName || _null;
        commandSend.profileId = profile.id;
        commandSend.commandId = command.id;
        commandSend.createdUserId = request.user.sub;
        commandSend.createdFullName = request.user.name;
        commandSend.createdAt = new Date();
        commandSend.lastUpdateUserId = request.user.sub;
        commandSend.lastUpdateFullName = request.user.name;
        commandSend.lastUpdatedAt = new Date();
        await this.commandSendRepository.save(commandSend);
        if (commandSend && commandSend.id) {
          let _ccName = new Array("EMAIL", "INBOX");
          let _dataSendCC = new Array();
          for (let i = 0; i < _ccName.length; i++) {
            _dataSendCC.push({
              commandSendId: commandSend.id,
              name: _ccName[i],
              createdUserId: request.user.sub,
              createdFullName: request.user.name,
              createdAt: new Date(),
              lastUpdateUserId: request.user.sub,
              lastUpdateFullName: request.user.name,
              lastUpdatedAt: new Date(),
            });
          }
          await this.commandSendCCRepository.save(_dataSendCC);
        }
      }),
    );

    return new HttpSuccess();
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง Tab3
   *
   * @summary API  แก้ไขรายการ body คำสั่ง Tab3
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("tab3/{id}")
  async PutTab3Update(
    @Path() id: string,
    @Body()
    requestBody: {
      commandSend: {
        id: string;
        sendCC: string[];
      }[];
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    await Promise.all(
      requestBody.commandSend.map(async (item) => {
        const commandSendCC = await this.commandSendCCRepository.find({
          where: { commandSendId: item.id },
        });
        await this.commandSendCCRepository.remove(commandSendCC);

        await Promise.all(
          item.sendCC.map(async (item1) => {
            const _commandSendCC = new CommandSendCC();
            _commandSendCC.name = item1;
            _commandSendCC.commandSendId = item.id;
            _commandSendCC.createdUserId = request.user.sub;
            _commandSendCC.createdFullName = request.user.name;
            _commandSendCC.createdAt = new Date();
            _commandSendCC.lastUpdateUserId = request.user.sub;
            _commandSendCC.lastUpdateFullName = request.user.name;
            _commandSendCC.lastUpdatedAt = new Date();
            await this.commandSendCCRepository.save(_commandSendCC);
          }),
        );
      }),
    );

    return new HttpSuccess();
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง Tab3
   *
   * @summary API  แก้ไขรายการ body คำสั่ง Tab3
   *
   * @param {string} id  Id คำสั่ง
   */
  @Delete("tab3/{commandSendId}")
  async DeleteTab3Update(
    @Path() commandSendId: string,
    @Body()
    requestBody: { reason?: string | null },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandSendRepository.findOne({ where: { id: commandSendId } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ได้รับสำเนาคำสั่ง");
    }
    await this.commandSendCCRepository.delete({ commandSendId: commandSendId });
    await this.commandSendRepository.delete(commandSendId);
    return new HttpSuccess();
  }

  /**
   * API  คัดลอก
   *
   * @summary API  คัดลอก
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("copy/{id}")
  async PutCopy(
    @Path() id: string,
    @Body()
    requestBody: { commandNo?: string | null; commandYear?: number | null },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id: id },
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    const copy = new Command();
    Object.assign(copy, { ...command, ...requestBody, id: undefined });
    const _null: any = null;
    copy.status = "NEW";
    copy.commandAffectDate = _null;
    copy.commandExcecuteDate = _null;
    copy.isSignature = _null;
    copy.isDraft = false;
    copy.isSign = false;
    copy.createdUserId = request.user.sub;
    copy.createdFullName = request.user.name;
    copy.createdAt = new Date();
    copy.lastUpdateUserId = request.user.sub;
    copy.lastUpdateFullName = request.user.name;
    copy.lastUpdatedAt = new Date();
    await this.commandRepository.save(copy);

    return new HttpSuccess(copy.id);
  }

  /**
   * API  ยกเลิก
   *
   * @summary API  ยกเลิก
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("cancel/{id}")
  async PutCancel(
    @Path() id: string,
    @Body()
    requestBody: { reason?: string | null },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id: id },
      relations: ["commandType", "commandRecives"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const path = commandTypePath(command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/delete", {
        refIds: command.commandRecives.map((x) => x.refId),
      })
      .then(async (res) => {})
      .catch(() => {});

    await this.commandReciveRepository.delete({ commandId: command.id });
    command.status = "CANCEL";
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();
    await this.commandRepository.save(command);
    return new HttpSuccess();
  }

  /**
   * API  ทำคำสั่งใหม่
   *
   * @summary API  ทำคำสั่งใหม่
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("resume/{id}")
  async PutDraft(
    @Path() id: string,
    @Body()
    requestBody: { reason?: string | null },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    command.status = "DRAFT";
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();
    await this.commandRepository.save(command);
    return new HttpSuccess();
  }

  /**
   * API ลบรายการคำสั่งถาวร
   *
   * @summary API ลบรายการคำสั่งถาวร
   *
   * @param {string} id  Id คำสั่ง
   */
  @Delete("{id}")
  async Delete(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionDelete(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id: id },
      relations: ["commandType", "commandRecives"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    const commandSend = await this.commandSendRepository.find({
      where: { commandId: id },
    });

    const path = commandTypePath(command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/delete", {
        refIds: command.commandRecives.map((x) => x.refId),
      })
      .then(async (res) => {})
      .catch(() => {});

    await this.commandSendCCRepository.delete({ commandSendId: In(commandSend.map((x) => x.id)) });
    await this.commandReciveRepository.delete({ commandId: command.id });
    await this.commandSendRepository.delete({ commandId: command.id });
    await this.commandOperatorRepository.delete({ commandId: command.id });
    await this.commandRepository.delete(command.id);
    return new HttpSuccess();
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab0
   *
   * @summary API รายละเอียดรายการคำสั่ง tab0
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("tab0/{id}")
  async GetByIdTab0(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandType"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const _command = {
      id: command.id,
      isSignature: command.isSignature,
      status: command.status,
      isDraft: command.isDraft,
      isSign: command.isSign,
      isAttachment: command.isAttachment,
      isUploadAttachment: command.isUploadAttachment,
      isSalary: command.commandType ? command.commandType.isSalary : null,
    };
    return new HttpSuccess(_command);
  }

  /**
   * API  ทำคำสั่งใหม่
   *
   * @summary API  ทำคำสั่งใหม่
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("sign/{id}")
  async PutSelectSign(
    @Path() id: string,
    @Body()
    requestBody: { sign: boolean },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    command.isSignature = requestBody.sign;
    command.status = "DRAFT";
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();
    await this.commandRepository.save(command);
    return new HttpSuccess();
  }

  /**
   * API  ทำคำสั่งใหม่
   *
   * @summary API  ทำคำสั่งใหม่
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("draft/{id}")
  async PutSelectDraft(
    @Path() id: string,
    @Body()
    requestBody: { sign: boolean },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    command.isDraft = requestBody.sign;
    command.status = "PENDING";
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();
    await this.commandRepository.save(command);
    return new HttpSuccess();
  }

  /**
   * API  ทำคำสั่งใหม่
   *
   * @summary API  ทำคำสั่งใหม่
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("pending-check/{id}")
  async PutSelectPending_Check(
    @Path() id: string,
    @Body()
    requestBody: { sign?: boolean },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    command.isSign = true;
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();
    await this.commandRepository.save(command);
    return new HttpSuccess();
  }

  /**
   * API  ออกคำสั่ง
   *
   * @summary API  ออกคำสั่ง
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("pending/{id}")
  async PutSelectPending(
    @Path() id: string,
    @Body()
    requestBody: { sign?: boolean },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id: id },
      relations: ["commandType", "commandRecives", "commandSends", "commandSends.commandSendCCs"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    command.isSign = true;
    if (command.commandExcecuteDate == null)
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบวันที่คำสั่งมีผล");

    let profiles =
      command && command.commandRecives.length > 0
        ? command.commandRecives
            .filter((x) => x.profileId != null)
            .map((x) => ({
              receiverUserId: x.profileId,
              notiLink: "",
            }))
        : [];

    const msgNoti = {
      data: {
        command: command,
        profiles: profiles,
      },
      user: request.user,
      token: request.headers["authorization"],
    };
    sendToQueueCommandNoti(msgNoti);

    if (
      new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()) <
      new Date(
        command.commandExcecuteDate.getFullYear(),
        command.commandExcecuteDate.getMonth(),
        command.commandExcecuteDate.getDate(),
      )
    ) {
      command.status = "WAITING";
      command.lastUpdateUserId = request.user.sub;
      command.lastUpdateFullName = request.user.name;
      command.lastUpdatedAt = new Date();
      const path = commandTypePath(command.commandType.code);
      if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
      await new CallAPI()
        .PostData(request, path, {
          refIds: command.commandRecives.filter((x) => x.refId != null).map((x) => x.refId),
          status: "WAITING",
        })
        .then(async (res) => {})
        .catch(() => {});
      await this.commandRepository.save(command);
    } else {
      const path = commandTypePath(command.commandType.code);
      if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
      const msg = {
        data: {
          id: command.id,
          status: "REPORTED",
          lastUpdateUserId: request.user.sub,
          lastUpdateFullName: request.user.name,
          lastUpdatedAt: new Date(),
        },
        user: request.user,
        token: request.headers["authorization"],
      };
      sendToQueue(msg);
    }
    return new HttpSuccess();
  }

  async cronjobCommand(@Request() request?: RequestWithUser) {
    const today = new Date();
    today.setUTCHours(0, 0, 0, 0);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);

    const command = await this.commandRepository.find({
      relations: ["commandType", "commandRecives"],
      where: {
        commandExcecuteDate: Between(today, tomorrow),
        status: "WAITING",
      },
    });

    let body = {
      client_id: "gettoken",
      client_secret: process.env.AUTH_ACCOUNT_SECRET,
      grant_type: "client_credentials",
    };

    const postData = querystring.stringify(body);

    // get admin token
    const response = await axios.post(
      `${process.env.KC_URL}/realms/${process.env.KC_REALMS}/protocol/openid-connect/token`,
      postData,
      {
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
          api_key: process.env.API_KEY,
        },
      },
    );

    const adminToken = response.data.access_token;

    command.forEach(async (x) => {
      const path = commandTypePath(x.commandType.code);
      if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
      const msg = {
        data: {
          id: x.id,
          status: "REPORTED",
          lastUpdateUserId: "system",
          lastUpdateFullName: "system",
          // lastUpdateUserId: _data.user.sub,
          // lastUpdateFullName: _data.user.name,
          lastUpdatedAt: new Date(),
        },
        // user: _data.user,
        token: adminToken,
      };
      sendToQueue(msg);
    });

    return new HttpSuccess();
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab3
   *
   * @summary API รายละเอียดรายการคำสั่ง tab3
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("run/cronjob/retirement")
  async CreateCronjobUpdateRetirementStatus(@Request() request: RequestWithUser) {
    let body = {
      client_id: "gettoken",
      client_secret: process.env.AUTH_ACCOUNT_SECRET,
      grant_type: "client_credentials",
    };
    const postData = querystring.stringify(body);
    const response = await axios.post(
      `${process.env.KC_URL}/realms/${process.env.KC_REALMS}/protocol/openid-connect/token`,
      postData,
      {
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
          api_key: process.env.API_KEY,
        },
      },
    );
    const adminToken = response.data.access_token;
    const today = new Date();
    today.setUTCHours(0, 0, 0, 0);
    let type: string = "OFFICER";
    try {
      const response_ = await axios.get(
        process.env.API_URL + `/retirement/update-status/${type}/${today.getFullYear()}`,
        {
          headers: {
            Authorization: `Bearer ${adminToken}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        },
      );
      if (response && response_.data.result.length > 0) {
        let profiles: Profile[] = [];
        await Promise.all(
          response_.data.result.map(async (x: any) => {
            const _profile = await this.profileRepository.findOneBy({ id: x.profileId });
            if (_profile) {
              _profile.isRetirement = true;
              _profile.isLeave = true;
              _profile.leaveType = "RETIRE";
              _profile.leaveDate = new Date();
              _profile.dateLeave = new Date();
              _profile.lastUpdatedAt = new Date();
              profiles.push(_profile);
            }
          }),
        );
        await this.profileRepository.save(profiles);
      }
    } catch {}

    type = "EMPLOYEE";
    try {
      const response_ = await axios.get(
        process.env.API_URL + `/retirement/update-status/${type}/${today.getFullYear()}`,
        {
          headers: {
            Authorization: `Bearer ${adminToken}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        },
      );
      if (response && response_.data.result.length > 0) {
        let profiles: ProfileEmployee[] = [];
        await Promise.all(
          response_.data.result.map(async (x: any) => {
            const _profileEmp = await this.profileEmployeeRepository.findOneBy({ id: x.profileId });
            if (_profileEmp) {
              _profileEmp.isRetirement = true;
              _profileEmp.isLeave = true;
              _profileEmp.leaveType = "RETIRE";
              _profileEmp.leaveDate = new Date();
              _profileEmp.dateLeave = new Date();
              _profileEmp.lastUpdatedAt = new Date();
              profiles.push(_profileEmp);
            }
          }),
        );
        await this.profileEmployeeRepository.save(profiles);
      }
    } catch {}

    return new HttpSuccess();
  }
  async cronjobUpdateRetirementStatus() {
    const adminToken = (await getToken()) ?? "";
    const today = new Date();
    today.setUTCHours(0, 0, 0, 0);
    let type: string = "OFFICER";
    let _Date = new Date();
    try {
      const response_ = await axios.get(
        process.env.API_URL + `/retirement/update-status/${type}/${today.getFullYear()}`,
        {
          headers: {
            Authorization: `Bearer ${adminToken}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        },
      );
      if (response_ && response_.data.result) {
        let signDate: string = "";
        if (response_.data.result.signDate != null) {
          signDate = Extension.ToThaiShortDate_noPrefix(new Date(response_.data.result.signDate));
        } else {
          signDate = Extension.ToThaiShortDate_noPrefix(_Date);
        }

        await Promise.all(
          response_.data.result.profiles.map(async (x: any) => {
            const _profile = await this.profileRepository.findOne({
              where: { id: x.profileId },
              relations: ["roleKeycloaks"],
            });
            if (_profile) {
              // console.log("1. บันทึกลงประวัติตำแหน่ง")
              await this.profileSalaryRetire(x.profileId, type, signDate, _Date);
              // console.log("2. ปลดออกจากโครงสร้าง")
              await this.posMasterRetire(x.profileId, type, _Date);
              // console.log("3. แก้ไขสถานะในทะเบียนประวัติ")
              _profile.isRetirement = true;
              _profile.isLeave = true;
              _profile.isActive = false;
              _profile.leaveType = "RETIRE";
              _profile.leaveReason = "เกษียณอายุราชการ";
              _profile.leaveDate = _Date;
              _profile.dateLeave = _Date;
              _profile.lastUpdatedAt = _Date;
              if (
                _profile.keycloak != null &&
                _profile.keycloak != "" &&
                _profile.isDelete === false
              ) {
                // console.log("4. disable keycloak/authen")
                const delUserKeycloak = await deleteUser(_profile.keycloak, adminToken);
                if (delUserKeycloak) {
                  // Task #228
                  // _profile.keycloak = "";
                  _profile.isDelete = true;
                  _profile.roleKeycloaks = [];
                }
              }
              // console.log("5. save profile ",_profile)
              await this.profileRepository.save(_profile);
            }
          }),
        );
      }
    } catch {}

    type = "EMPLOYEE";
    try {
      const response_ = await axios.get(
        process.env.API_URL + `/retirement/update-status/${type}/${today.getFullYear()}`,
        {
          headers: {
            Authorization: `Bearer ${adminToken}`,
            "Content-Type": "application/json",
            api_key: process.env.API_KEY,
          },
        },
      );
      if (response_ && response_.data.result) {
        let signDate: string = "";
        if (response_.data.result.signDate != null) {
          signDate = Extension.ToThaiShortDate_noPrefix(new Date(response_.data.result.signDate));
        } else {
          signDate = Extension.ToThaiShortDate_noPrefix(_Date);
        }

        await Promise.all(
          response_.data.result.profiles.map(async (x: any) => {
            const _profileEmp = await this.profileEmployeeRepository.findOne({
              where: { id: x.profileId },
              relations: ["roleKeycloaks"],
            });
            if (_profileEmp) {
              // บันทึกลงประวัติตำแหน่ง
              await this.profileSalaryRetire(x.profileId, type, signDate, _Date);
              // ปลดออกจากโครงสร้าง
              await this.posMasterRetire(x.profileId, type, _Date);
              // แก้ไขสถานะในทะเบียนประวัติ
              _profileEmp.isRetirement = true;
              _profileEmp.isLeave = true;
              _profileEmp.isActive = false;
              _profileEmp.leaveType = "RETIRE";
              _profileEmp.leaveReason = "เกษียณอายุราชการ";
              _profileEmp.leaveDate = _Date;
              _profileEmp.dateLeave = _Date;
              _profileEmp.lastUpdatedAt = _Date;
              if (
                _profileEmp.keycloak != null &&
                _profileEmp.keycloak != "" &&
                _profileEmp.isDelete === false
              ) {
                // disable keycloak/authen
                const delUserKeycloak = await deleteUser(_profileEmp.keycloak, adminToken);
                if (delUserKeycloak) {
                  // Task #228
                  // _profileEmp.keycloak = "";
                  _profileEmp.isDelete = true;
                  _profileEmp.roleKeycloaks = [];
                }
              }
              await this.profileEmployeeRepository.save(_profileEmp);
            }
          }),
        );
      }
    } catch {}

    return new HttpSuccess();
  }

  async profileSalaryRetire(profileId: string, type: string, signDate: string, _Date: Date) {
    const whereKey =
      type == "OFFICER" ? { profileId: profileId } : { profileEmployeeId: profileId };
    const maxOrder = await this.salaryRepo.findOne({
      select: { order: true },
      where: whereKey,
      order: { order: "DESC" },
    });
    const data: any = {
      order: maxOrder ? maxOrder.order + 1 : 1,
      amount: null,
      positionSalaryAmount: null,
      mouthSalaryAmount: null,
      posNo: null,
      positionExecutive: null,
      positionType: null,
      positionLevel: null,
      amountSpecial: null,
      orgRoot: null,
      orgChild1: null,
      orgChild2: null,
      orgChild3: null,
      orgChild4: null,
      commandYear: _Date.getFullYear() + 543,
      commandDateAffect: _Date,
      commandCode: "16",
      commandName: "พ้นจากราชการ",
      posNoAbb: null,
      isEntry: false,
      positionName: "เกษียณอายุราชการ",
      createdUserId: "",
      createdFullName: "System Administrator",
      lastUpdateUserId: "",
      lastUpdateFullName: "System Administrator",
      createdAt: _Date,
      lastUpdatedAt: _Date,
      remark: `ประกาศคณะอนุกรรมการสามัญข้าราชการกรุงเทพมหานครสามัญ ลว. ${signDate}`, // script เกษียณจริง ๆ ให้เอา “วันที่ประกาศเกษียณฉบับแรก” มาลงในเอกสารอ้างอิง
      isGovernment: false,
    };
    const history = new ProfileSalaryHistory();
    Object.assign(history, { ...data, id: undefined });
    data.dateGovernment = _Date;
    if (type == "OFFICER") {
      data.profileId = profileId;
      data.profileEmployeeId = null;
    } else if (type == "EMPLOYEE") {
      data.profileEmployeeId = profileId;
      data.profileId = null;
    }
    const savedData = await this.salaryRepo.save(data);
    history.profileSalaryId = savedData.id;
    await this.salaryHistoryRepo.save(history);
  }

  async posMasterRetire(profileId: string, type: string, _Date: Date) {
    const revisionIsCurrent = await this.orgRevisionRepo.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });
    if (revisionIsCurrent) {
      let _posMaster: any = null;
      if (type == "OFFICER") {
        _posMaster = await this.posMasterRepository.findOne({
          where: {
            orgRevisionId: revisionIsCurrent.id,
            current_holderId: profileId,
          },
        });
        if (_posMaster) {
          await this.positionRepository.update(
            {
              posMasterId: _posMaster.id,
              positionIsSelected: true,
            },
            {
              positionIsSelected: false,
              lastUpdateFullName: "System Administrator",
              lastUpdatedAt: _Date,
            },
          );
          _posMaster.isSit = false;
          _posMaster.current_holderId = null;
          _posMaster.lastUpdateFullName = "System Administrator";
          _posMaster.lastUpdatedAt = _Date;
          await this.posMasterRepository.save(_posMaster);
          await CreatePosMasterHistoryOfficer(_posMaster.id, null);
        }
        const revisionIsDraft = await this.orgRevisionRepo.findOne({
          where: { orgRevisionIsCurrent: false, orgRevisionIsDraft: true },
        });
        if (revisionIsDraft) {
          _posMaster = null;
          _posMaster = await this.posMasterRepository.findOne({
            where: {
              orgRevisionId: revisionIsDraft.id,
              next_holderId: profileId,
            },
          });
          if (_posMaster) {
            await this.positionRepository.update(
              {
                posMasterId: _posMaster.id,
                positionIsSelected: true,
              },
              {
                positionIsSelected: false,
                lastUpdateFullName: "System Administrator",
                lastUpdatedAt: _Date,
              },
            );
            _posMaster.isSit = false;
            _posMaster.next_holderId = null;
            _posMaster.lastUpdateFullName = "System Administrator";
            _posMaster.lastUpdatedAt = _Date;
            await this.posMasterRepository.save(_posMaster);
            await CreatePosMasterHistoryOfficer(_posMaster.id, null);
          }
          // console.log("clear posMaster & position 'Draf' success")
        }
      } else if (type == "EMPLOYEE") {
        _posMaster = await this.employeePosMasterRepository.findOne({
          where: {
            orgRevisionId: revisionIsCurrent.id,
            current_holderId: profileId,
          },
        });
        if (_posMaster) {
          await this.employeePositionRepository.update(
            {
              posMasterId: _posMaster.id,
              positionIsSelected: true,
            },
            {
              positionIsSelected: false,
              lastUpdateFullName: "System Administrator",
              lastUpdatedAt: _Date,
            },
          );
          _posMaster.isSit = false;
          _posMaster.current_holderId = null;
          _posMaster.lastUpdateFullName = "System Administrator";
          _posMaster.lastUpdatedAt = _Date;
          await this.employeePosMasterRepository.save(_posMaster);
          await CreatePosMasterHistoryEmployee(_posMaster.id, null);
        }
      }
      // console.log("clear posMaster & position 'Current' success")
    }
  }

  @Get("cornjob/cronjobUpdateRetirementStatus")
  async runCronjobUpdateRetirementStatus() {
    await this.cronjobUpdateRetirementStatus();
    return new HttpSuccess();
  }

  /**
   * API ทดสอบ cronjobPostRetireToExprofile
   * @summary ทดสอบส่งข้อมูลผู้เกษียณไปยังระบบพ้นราชการ (Exprofile)
   */
  @Get("cronjob/cronjobPostRetireToExprofile")
  async runCronjobPostRetireToExprofile() {
    try {
      const retirementService = new RetirementService();
      const result = await retirementService.cronjobPostRetireToExprofile();
      return new HttpSuccess(result);
    } catch (error: any) {
      throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, error.message || "เกิดข้อผิดพลาด");
    }
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab4 คำสั่ง
   *
   * @summary API รายละเอียดรายการคำสั่ง tab4 คำสั่ง
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("tab4/cover/{id}")
  async GetByIdTab4Cover(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandType", "commandRecives"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    let issue =
      command.isBangkok == "OFFICE"
        ? "สำนักปลัดกรุงเทพมหานคร"
        : command.isBangkok == "BANGKOK"
          ? "กรุงเทพมหานคร"
          : null;
    let orgRevisionActive: any = {
      id: null,
    };
    if (issue == null) {
      orgRevisionActive = await this.orgRevisionRepository.findOne({
        where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        relations: ["posMasters", "posMasters.orgRoot"],
      });
      if (orgRevisionActive != null) {
        const profile = await this.profileRepository.findOne({
          where: {
            keycloak: command.createdUserId.toString(),
          },
        });
        if (profile != null) {
          issue =
            orgRevisionActive?.posMasters?.filter((x: any) => x.current_holderId == profile.id)[0]
              ?.orgRoot?.orgRootName || null;
        }
      }
    }
    if (issue == null) issue = "...................................";

    let res: any[] = [];
    if (command.commandRecives.length > 0) {
      await new CallAPI()
        .GetData(request, `/probation/report/command10/appoints/${command.commandRecives[0].refId}`)
        .then((x) => {
          res = x;
        })
        .catch((x) => {});
    }

    let _command;
    let commandCode = command && command.commandType ? command.commandType.code : "";
    if (!["C-PM-21", "C-PM-23"].includes(commandCode)) {
      _command = {
        issue: issue,
        commandNo: command.commandNo == null ? "" : Extension.ToThaiNumber(command.commandNo),
        commandYear:
          command.commandYear == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiYear(command.commandYear).toString()),
        commandTitle: command.issue,
        detailHeader: command.detailHeader,
        detailBody: command.detailBody,
        detailFooter: command.detailFooter,
        commandDate:
          command.commandAffectDate == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandAffectDate)),
        commandExcecuteDate:
          command.commandExcecuteDate == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandExcecuteDate)),
        name: "...................................",
        position: "...................................",
        authorizedUserFullName: "...................................",
        authorizedPosition: "...................................",
        commandAffectDate: "...................................",
        name1:
          res && res.length > 0
            ? `๑. ${res[0].name}.........${res[0].role}`
            : "๑. ..........................ประธาน",
        name2:
          res && res.length > 1
            ? `๒. ${res[1].name}.........${res[1].role}`
            : "๒. ..........................กรรมการ",
        name3:
          res && res.length > 2
            ? `๓. ${res[2].name}.........${res[2].role}`
            : "๓. ..........................กรรมการ",
        name4:
          res && res.length > 3
            ? `๔. ${res[3].name}.........${res[3].role}`
            : "๔. ..........................กรรมการ",
      };
    } else {
      let _persons: any;
      _persons = await Promise.all(
        command.commandRecives.map(async (x, idx) => {
          const profile = await this.profileEmployeeRepository.findOne({
            where: {
              id: x.profileId,
            },
            relations: [
              "posLevel",
              "posType",
              "current_holders",
              "current_holders.orgRevision",
              "current_holders.orgRoot",
              "current_holders.orgChild1",
              "current_holders.orgChild2",
              "current_holders.orgChild3",
              "current_holders.orgChild4",
              "profileSalary",
            ],
            order: {
              profileSalary: {
                order: "DESC",
                createdAt: "DESC",
              },
            },
          });
          const shortName =
            profile?.current_holders.length == 0
              ? null
              : profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) !=
                    null &&
                  profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                    ?.orgChild4 != null
                ? `${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild4.orgChild4ShortName} ${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.posMasterNo}`
                : profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id) !=
                      null &&
                    profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                      ?.orgChild3 != null
                  ? `${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild3.orgChild3ShortName} ${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.posMasterNo}`
                  : profile?.current_holders.find(
                        (x) => x.orgRevisionId == orgRevisionActive?.id,
                      ) != null &&
                      profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)
                        ?.orgChild2 != null
                    ? `${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild2.orgChild2ShortName} ${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.posMasterNo}`
                    : profile?.current_holders.find(
                          (x) => x.orgRevisionId == orgRevisionActive?.id,
                        ) != null &&
                        profile?.current_holders.find(
                          (x) => x.orgRevisionId == orgRevisionActive?.id,
                        )?.orgChild1 != null
                      ? `${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgChild1.orgChild1ShortName} ${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.posMasterNo}`
                      : profile?.current_holders.find(
                            (x) => x.orgRevisionId == orgRevisionActive?.id,
                          ) != null &&
                          profile?.current_holders.find(
                            (x) => x.orgRevisionId == orgRevisionActive?.id,
                          )?.orgRoot != null
                        ? `${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.orgRoot.orgRootShortName} ${profile?.current_holders.find((x) => x.orgRevisionId == orgRevisionActive?.id)?.posMasterNo}`
                        : null;

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

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

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

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

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

          let _root = root?.orgRootName;
          let _child1 = child1?.orgChild1Name;
          let _child2 = child2?.orgChild2Name;
          let _child3 = child3?.orgChild3Name;
          let _child4 = child4?.orgChild4Name;
          let _OrgLeave: any = [];
          if (profile?.isLeave && profile?.profileSalary.length > 0) {
            _OrgLeave = [
              profile?.profileSalary[0].orgChild4 ? profile?.profileSalary[0].orgChild4 : null,
              profile?.profileSalary[0].orgChild3 ? profile?.profileSalary[0].orgChild3 : null,
              profile?.profileSalary[0].orgChild2 ? profile?.profileSalary[0].orgChild2 : null,
              profile?.profileSalary[0].orgChild1 ? profile?.profileSalary[0].orgChild1 : null,
              profile?.profileSalary[0].orgRoot ? profile?.profileSalary[0].orgRoot : null,
            ];
          }
          const orgLeave = _OrgLeave.filter((x: any) => x !== undefined && x !== null).join("\n");
          let profileTemp = {
            org: "-",
            position: "-",
            posLevel: "-",
            posNo: "-",
          };
          if (commandCode == "C-PM-21") {
            profileTemp.position = profile?.positionTemp ?? "-";
            profileTemp.posLevel = profile?.posLevelNameTemp ?? "-";
            profileTemp.org =
              (profile?.child4Temp == null ? "" : profile?.child4Temp + "\n") +
              (profile?.child3Temp == null ? "" : profile?.child3Temp + "\n") +
              (profile?.child2Temp == null ? "" : profile?.child2Temp + "\n") +
              (profile?.child1Temp == null ? "" : profile?.child1Temp + "\n") +
              (profile?.rootTemp == null ? "" : profile?.rootTemp);
            if (profile?.nodeTemp) {
              switch (profile?.nodeTemp) {
                case "4":
                  profileTemp.posNo = `${profile.child4ShortNameTemp} ${profile?.posMasterNoTemp}`;
                  break;
                case "3":
                  profileTemp.posNo = `${profile.child3ShortNameTemp} ${profile?.posMasterNoTemp}`;
                  break;
                case "2":
                  profileTemp.posNo = `${profile.child2ShortNameTemp} ${profile?.posMasterNoTemp}`;
                  break;
                case "1":
                  profileTemp.posNo = `${profile.child1ShortNameTemp} ${profile?.posMasterNoTemp}`;
                  break;
                case "0":
                  profileTemp.posNo = `${profile.rootShortNameTemp} ${profile?.posMasterNoTemp}`;
                  break;
                default:
                  break;
              }
            }
          }
          return {
            no: Extension.ToThaiNumber((idx + 1).toString()),
            org:
              commandCode != "C-PM-21"
                ? profile?.isLeave == false
                  ? (_child4 == null ? "" : _child4 + "\n") +
                    (_child3 == null ? "" : _child3 + "\n") +
                    (_child2 == null ? "" : _child2 + "\n") +
                    (_child1 == null ? "" : _child1 + "\n") +
                    (_root == null ? "" : _root)
                  : orgLeave
                : profileTemp.org,
            fullName: `${x.prefix}${x.firstName} ${x.lastName}`,
            citizenId: Extension.ToThaiNumber(x.citizenId),
            position:
              commandCode != "C-PM-21"
                ? profile?.position
                  ? profile?.position
                  : "-"
                : profileTemp.position,
            posLevel:
              commandCode != "C-PM-21"
                ? profile?.posType && profile?.posLevel
                  ? Extension.ToThaiNumber(
                      `${profile?.posType.posTypeShortName} ${profile?.posLevel.posLevelName}`,
                    )
                  : "-"
                : Extension.ToThaiNumber(profileTemp.posLevel),
            posNo:
              commandCode != "C-PM-21"
                ? shortName
                  ? Extension.ToThaiNumber(shortName)
                  : "-"
                : Extension.ToThaiNumber(profileTemp.posNo),
            amount: x.amount ? Extension.ToThaiNumber(x.amount.toLocaleString()) : "-",
            dateRetire: profile?.dateRetire
              ? Extension.ToThaiNumber(Extension.ToThaiShortDate_monthYear(profile?.dateRetire))
              : profile?.birthDate && commandCode == "C-PM-21"
                ? Extension.ToThaiNumber(
                    Extension.ToThaiShortDate_monthYear(
                      new Date(
                        profile.birthDate.getFullYear() + 60,
                        profile.birthDate.getMonth(),
                        profile.birthDate.getDate(),
                      ),
                    ),
                  )
                : "-",
            dateExecute: command.commandExcecuteDate
              ? Extension.ToThaiNumber(
                  Extension.ToThaiShortDate_monthYear(command.commandExcecuteDate),
                )
              : "-",
            remark: x.remarkVertical ? x.remarkVertical : "-",
          };
        }),
      );
      _command = {
        issue: issue,
        commandNo: command.commandNo == null ? "" : Extension.ToThaiNumber(command.commandNo),
        commandYear:
          command.commandYear == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiYear(command.commandYear).toString()),
        commandTitle: command.issue,
        detailHeader: command.detailHeader,
        detailBody: command.detailBody,
        detailFooter: command.detailFooter,
        commandDate:
          command.commandAffectDate == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandAffectDate)),
        commandExcecuteDate:
          command.commandExcecuteDate == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandExcecuteDate)),
        name: "...................................",
        position: "...................................",
        authorizedUserFullName: "...................................",
        authorizedPosition: "...................................",
        commandAffectDate: "...................................",
        name1:
          res && res.length > 0
            ? `๑. ${res[0].name}.........${res[0].role}`
            : "๑. ..........................ประธาน",
        name2:
          res && res.length > 1
            ? `๒. ${res[1].name}.........${res[1].role}`
            : "๒. ..........................กรรมการ",
        name3:
          res && res.length > 2
            ? `๓. ${res[2].name}.........${res[2].role}`
            : "๓. ..........................กรรมการ",
        name4:
          res && res.length > 3
            ? `๔. ${res[3].name}.........${res[3].role}`
            : "๔. ..........................กรรมการ",
        persons: _persons,
      };
    }

    return new HttpSuccess({
      template: command.commandType.fileCover,
      reportName: "docx-report",
      data: _command,
    });
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab4 แนบท้าย
   *
   * @summary API รายละเอียดรายการคำสั่ง tab4 แนบท้าย
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("tab4/attachment/{id}")
  async GetByIdTab4Attachment(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandType", "commandRecives"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    let _command: any = [];
    const path = commandTypePath(command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/attachment", {
        refIds: command.commandRecives
          .filter((x) => x.refId != null)
          .map((x) => ({
            refId: x.refId,
            Sequence: x.order,
            CitizenId: x.citizenId,
            Prefix: x.prefix,
            FirstName: x.firstName,
            LastName: x.lastName,
            Amount: x.amount,
            PositionSalaryAmount: x.positionSalaryAmount,
            MouthSalaryAmount: x.mouthSalaryAmount,
            RemarkHorizontal: x.remarkHorizontal,
            RemarkVertical: x.remarkVertical,
            CommandYear: command.commandYear,
            CommandExcecuteDate: command.commandExcecuteDate,
          })),
      })
      .then(async (res) => {
        _command = res;
      })
      .catch(() => {});

    let issue =
      command.isBangkok == "OFFICE"
        ? "สำนักปลัดกรุงเทพมหานคร"
        : command.isBangkok == "BANGKOK"
          ? "กรุงเทพมหานคร"
          : null;
    if (issue == null) {
      const orgRevisionActive = await this.orgRevisionRepository.findOne({
        where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        relations: ["posMasters", "posMasters.orgRoot"],
      });
      if (orgRevisionActive != null) {
        const profile = await this.profileRepository.findOne({
          where: {
            keycloak: command.createdUserId.toString(),
          },
        });
        if (profile != null) {
          issue =
            orgRevisionActive?.posMasters?.filter((x) => x.current_holderId == profile.id)[0]
              ?.orgRoot?.orgRootName || null;
        }
      }
    }
    if (issue == null) issue = "...................................";

    const operators = await this.commandOperatorRepository.find({
      select: {
        prefix: true,
        firstName: true,
        lastName: true,
        roleName: true,
        orderNo: true,
      },
      where: { commandId: command.id },
      order: { orderNo: "ASC" },
    });

    return new HttpSuccess({
      template: command.commandType.fileAttachment,
      reportName: "xlsx-report",
      data: {
        data: _command,
        issuerOrganizationName: issue,
        commandNo: command.commandNo == null ? "" : Extension.ToThaiNumber(command.commandNo),
        commandYear:
          command.commandYear == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiYear(command.commandYear).toString()),
        commandExcecuteDate:
          command.commandAffectDate == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandAffectDate)),
        operators:
          operators.length > 0
            ? operators.map((x) => ({
                fullName: `${x.prefix ?? ""}${x.firstName ?? ""} ${x.lastName ?? ""}`,
                roleName: x.roleName,
              }))
            : [
                {
                  fullName: "",
                  roleName: "เจ้าหน้าที่ดำเนินการ",
                },
              ],
      },
    });
  }

  /**
   * API รายละเอียดรายการคำสั่ง step
   *
   * @summary API รายละเอียดรายการคำสั่ง step
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("step/{id}")
  async GetByIdStep(@Path() id: string, @Request() request: RequestWithUser) {
    await new permission().PermissionGet(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandSigns"],
      order: {
        commandSigns: {
          createdAt: "ASC",
        },
      },
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const _command = command.commandSigns.map((item) => ({
      id: item.id,
      prefix: item.prefix,
      firstName: item.firstName,
      lastName: item.lastName,
      position: item.position,
      profileId: item.profileId,
      comment: item.comment,
      isSignatory: item.isSignatory,
    }));
    return new HttpSuccess(_command);
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง step
   *
   * @summary API  แก้ไขรายการ body คำสั่ง step
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("step-add/{id}")
  async PutStepAdd(
    @Path() id: string,
    @Body()
    requestBody: {
      profileId: string;
      isSignatory: boolean;
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({ where: { id: id } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    const profile = await this.profileRepository.findOne({ where: { id: requestBody.profileId } });
    if (!profile) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งานนี้");
    }
    command.status = "PENDING";
    command.isDraft = true;
    const commandSign = new CommandSign();
    commandSign.prefix = profile.prefix;
    commandSign.firstName = profile.firstName;
    commandSign.lastName = profile.lastName;
    commandSign.position = profile.position;
    commandSign.isSignatory = requestBody.isSignatory;
    commandSign.profileId = requestBody.profileId;
    commandSign.commandId = command.id;
    commandSign.createdUserId = request.user.sub;
    commandSign.createdFullName = request.user.name;
    commandSign.createdAt = new Date();
    commandSign.lastUpdateUserId = request.user.sub;
    commandSign.lastUpdateFullName = request.user.name;
    commandSign.lastUpdatedAt = new Date();
    await this.commandSignRepository.save(commandSign);
    await this.commandRepository.save(command);

    return new HttpSuccess();
  }

  /**
   * API  แก้ไขรายการ body คำสั่ง step-comment
   *
   * @summary API  แก้ไขรายการ body คำสั่ง step-comment
   *
   * @param {string} id  Id คำสั่ง
   */
  @Put("step-comment/{id}")
  async PutStepComment(
    @Path() id: string,
    @Body()
    requestBody: {
      comment: string;
    },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const commandSign = await this.commandSignRepository.findOne({
      where: { id: id },
      relations: ["command"],
    });
    if (!commandSign) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    commandSign.comment = requestBody.comment;
    commandSign.lastUpdateUserId = request.user.sub;
    commandSign.lastUpdateFullName = request.user.name;
    commandSign.lastUpdatedAt = new Date();
    await this.commandSignRepository.save(commandSign);
    if (commandSign.isSignatory == true)
      await this.PutSelectPending(commandSign.commandId, { sign: true }, request);

    return new HttpSuccess();
  }

  /**
   * API แก้ไขเปลี่ยนผู้สร้างคำสั่ง
   * @summary API แก้ไขเปลี่ยนผู้สร้างคำสั่ง
   * @param {string} id  Id คำสั่ง
   */
  @Put("change-creator/{id}")
  async ChangeCreator(
    @Path() id: string,
    @Body() req: { assignId: string },
    @Request() request: RequestWithUser,
  ) {
    await new permission().PermissionUpdate(request, "COMMAND");
    const command = await this.commandRepository.findOne({
      where: { id: id },
    });

    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    command.createdUserId = req.assignId;
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();

    await this.commandRepository.save(command);
    return new HttpSuccess();
  }

  /**
   * API สร้างรายการ body คำสั่ง
   *
   * @summary API สร้างรายการ body คำสั่ง
   *
   */
  @Post("person")
  async PostPerson(
    @Body()
    requestBody: {
      commandTypeId?: string | null;
      commandNo?: string | null;
      commandYear?: number | null;
      commandId?: string | null;
      commandAffectDate?: Date | null;
      commandExcecuteDate?: Date | null;
      persons: {
        refId: string;
        profileId?: string | null;
        citizenId?: string | null;
        prefix?: string | null;
        firstName?: string | null;
        lastName?: string | null;
        remarkVertical?: string | null;
        remarkHorizontal?: string | null;
        rootId?: string | null;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        position?: string | null;
        posType?: string | null;
        posLevel?: string | null;
      }[];
    },
    @Request() request: RequestWithUser,
  ) {
    const now = new Date();
    let command = new Command();
    let commandCode: string = "";
    let commandSysId: string = "";
    let _null: any = null;
    let userProfile: any = null;
    if (
      requestBody.commandId != undefined &&
      requestBody.commandId != null &&
      requestBody.commandId != ""
    ) {
      const _command = await this.commandRepository.findOne({
        where: { id: requestBody.commandId },
        relations: ["commandRecives", "commandType"],
        order: {
          commandRecives: {
            order: "DESC",
          },
        },
      });
      if (!_command) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบคำสั่งนี้ในระบบ");
      }
      commandSysId = _command.commandType.commandSysId;
      commandCode = _command.commandType.code;
      command = _command;
    } else {
      command = Object.assign(new Command(), requestBody);
      if (!requestBody.commandTypeId) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่ง");
      }
      const commandType = await this.commandTypeRepository.findOne({
        where: { id: requestBody.commandTypeId },
      });

      if (!commandType) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
      }
      commandSysId = commandType.commandSysId;
      commandCode = commandType.code;
      command.detailHeader = commandType.detailHeader;
      command.detailBody = commandType.detailBody;
      command.detailFooter = commandType.detailFooter;
      command.isAttachment = commandType.isAttachment;
      command.isUploadAttachment = commandType.isUploadAttachment;
      // ถ้าเป็นคำสั่งโปรดเกล้าฯ "C-PM-47" ให้เปิดถึงรออัปโหลดไฟล์ #1780
      if (commandCode === "C-PM-47") {
        command.isSignature = true;
        command.isDraft = true;
        command.isSign = true;
        command.status = "PENDING";
      } else {
        command.status = "NEW";
      }
      command.issue = commandType.name;
      (command.commandAffectDate = requestBody.commandAffectDate
        ? new Date(requestBody.commandAffectDate)
        : _null),
        (command.commandExcecuteDate = requestBody.commandExcecuteDate
          ? new Date(requestBody.commandExcecuteDate)
          : _null),
        (command.createdUserId = request.user.sub);
      command.createdFullName = request.user.name;
      command.createdAt = now;
      command.lastUpdateUserId = request.user.sub;
      command.lastUpdateFullName = request.user.name;
      command.lastUpdatedAt = now;

      // Query profile ครั้งเดียว ใช้ร่วมกันทั้ง shortName และ CommandOperator
      userProfile = await this.profileRepository.findOne({
        where: { keycloak: request.user.sub },
        relations: {
          posLevel: true,
          posType: true,
          current_holders: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        },
      });

      // เช็คถ้าไม่ใช่ กสจ. ดึง root.shortName มาปั๊ม
      if (userProfile) {
        const currentHolder = userProfile.current_holders?.find(
          (x: any) =>
            x.orgRevision?.orgRevisionIsDraft === false &&
            x.orgRevision?.orgRevisionIsCurrent === true,
        );

        if (currentHolder && !currentHolder.orgChild1?.isOfficer) {
          command.shortName = currentHolder.orgRoot?.orgRootShortName ?? null;
        }
      }

      await this.commandRepository.save(command);
    }
    // insert commandOperator
    const checkCommandOperator = await this.commandOperatorRepository.findOne({
      where: { commandId: command.id, roleName: "เจ้าหน้าที่ดำเนินการ" },
    });
    if (!checkCommandOperator) {
      if (request.user.sub) {
        // ใช้ userProfile ที่ query ไปแล้วถ้ามี ถ้าไม่มีค่อย query ใหม่
        let profile = userProfile;
        if (!profile) {
          profile = await this.profileRepository.findOne({
            where: { keycloak: request.user.sub },
            relations: {
              posLevel: true,
              posType: true,
              current_holders: {
                orgRevision: true,
                orgRoot: true,
                orgChild1: true,
                orgChild2: true,
                orgChild3: true,
                orgChild4: true,
              },
            },
          });
        }
        if (profile) {
          const currentHolder = profile!.current_holders?.find(
            (x: any) =>
              x.orgRevision?.orgRevisionIsDraft === false &&
              x.orgRevision?.orgRevisionIsCurrent === true,
          );

          const posNo =
            currentHolder != null && currentHolder.orgChild4 != null
              ? `${currentHolder.orgChild4.orgChild4ShortName} ${currentHolder.posMasterNo}`
              : currentHolder != null && currentHolder.orgChild3 != null
                ? `${currentHolder.orgChild3.orgChild3ShortName} ${currentHolder.posMasterNo}`
                : currentHolder != null && currentHolder.orgChild2 != null
                  ? `${currentHolder.orgChild2.orgChild2ShortName} ${currentHolder.posMasterNo}`
                  : currentHolder != null && currentHolder.orgChild1 != null
                    ? `${currentHolder.orgChild1.orgChild1ShortName} ${currentHolder.posMasterNo}`
                    : currentHolder != null && currentHolder?.orgRoot != null
                      ? `${currentHolder.orgRoot.orgRootShortName} ${currentHolder.posMasterNo}`
                      : null;

          const position = await this.positionRepository.findOne({
            where: {
              positionIsSelected: true,
              posMaster: {
                orgRevisionId: currentHolder?.orgRevisionId,
                current_holderId: profile!.id,
              },
            },
            order: { createdAt: "DESC" },
            relations: { posExecutive: true },
          });
          const operator = Object.assign(new CommandOperator(), {
            profileId: profile?.id,
            prefix: profile?.prefix,
            firstName: profile?.firstName,
            lastName: profile?.lastName,
            posNo: posNo,
            posType: profile?.posType?.posTypeName ?? null,
            posLevel: profile?.posLevel?.posLevelName ?? null,
            position: position?.positionName ?? null,
            positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
            roleName: "เจ้าหน้าที่ดำเนินการ",
            orderNo: 1,
            commandId: command.id,
            createdUserId: request.user.sub,
            createdFullName: request.user.name,
            createdAt: now,
            lastUpdateUserId: request.user.sub,
            lastUpdateFullName: request.user.name,
            lastUpdatedAt: now,
          });
          await this.commandOperatorRepository.save(operator);
        }
      }
    }

    const path = commandTypePath(commandCode);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    if (commandSysId && commandSysId.toLocaleUpperCase().trim() !== "DISCIPLINE") {
      await new CallAPI()
        .PostData(request, path, {
          refIds: requestBody.persons.filter((x) => x.refId != null).map((x) => x.refId),
          status: "REPORT",
        })
        .then(async (res) => {})
        .catch(() => {});
    } else {
      await new CallAPI()
        .PostData(request, path, {
          refIds: requestBody.persons.filter((x) => x.refId != null).map((x) => x.refId),
          status: "REPORT",
          commandTypeId: requestBody.commandTypeId,
          commandCode: commandCode,
        })
        .then(async (res) => {})
        .catch(() => {});
    }
    let order =
      command.commandRecives == null || command.commandRecives.length <= 0
        ? 0
        : command.commandRecives[0].order;
    await Promise.all(
      requestBody.persons.map(async (item) => {
        const _commandRecive = await this.commandReciveRepository.findOne({
          where: {
            commandId: command.id,
            refId: item.refId,
          },
        });
        if (_commandRecive) return;
        order = order + 1;
        let commandRecive = new CommandRecive();
        commandRecive = Object.assign(new CommandRecive(), item);
        commandRecive.order = order;
        let salaryData = _null;

        // const excludedCommands = ["C-PM-33", "C-PM-34", "C-PM-35", "C-PM-36", "C-PM-37"];
        // if (!excludedCommands.includes(commandCode)) {
        if (item.profileId) {
          salaryData = await this.profileRepository.findOne({
            where: {
              id: item.profileId,
            },
          });
          let _setZero: any = 0;
          if (!salaryData) {
            salaryData = await this.profileEmployeeRepository.findOne({
              where: {
                id: item.profileId,
              },
            });
          }
          commandRecive.amount = item.amount ?? (salaryData ? salaryData.amount : _setZero);
          commandRecive.amountSpecial =
            item.amountSpecial ?? (salaryData ? salaryData.amountSpecial : _setZero);
          commandRecive.positionSalaryAmount =
            item.positionSalaryAmount ?? (salaryData ? salaryData.positionSalaryAmount : _setZero);
          commandRecive.mouthSalaryAmount =
            item.mouthSalaryAmount ?? (salaryData ? salaryData.mouthSalaryAmount : _setZero);
        } else {
          commandRecive.amount = _null;
          commandRecive.amountSpecial = _null;
          commandRecive.positionSalaryAmount = _null;
          commandRecive.mouthSalaryAmount = _null;
        }

        commandRecive.remarkVertical = item.remarkVertical == null ? _null : item.remarkVertical;
        commandRecive.remarkHorizontal =
          item.remarkHorizontal == null ? _null : item.remarkHorizontal;
        commandRecive.commandId = command.id;
        commandRecive.createdUserId = request.user.sub;
        commandRecive.createdFullName = request.user.name;
        commandRecive.createdAt = now;
        commandRecive.lastUpdateUserId = request.user.sub;
        commandRecive.lastUpdateFullName = request.user.name;
        commandRecive.lastUpdatedAt = now;

        if (commandCode == "C-PM-40") {
          const posMasterAct = await this.posMasterActRepository.findOne({
            where: { id: item.refId },
            relations: [
              "posMaster",
              "posMaster.positions",
              "posMaster.orgRoot",
              "posMaster.orgChild1",
              "posMaster.orgChild2",
              "posMaster.orgChild3",
              "posMaster.orgChild4",
            ],
          });

          if (posMasterAct) {
            commandRecive.remarkVertical =
              "ลำดับที่ " + Extension.ToThaiNumber(posMasterAct?.posMasterOrder?.toString() ?? "");
            const selectedPosition = posMasterAct?.posMaster?.positions?.find(
              (x) => x.positionIsSelected === true,
            );
            commandRecive.position = selectedPosition?.positionName ?? _null;

            const orgShortName =
              [
                posMasterAct.posMaster?.orgChild4?.orgChild4ShortName,
                posMasterAct.posMaster?.orgChild3?.orgChild3ShortName,
                posMasterAct.posMaster?.orgChild2?.orgChild2ShortName,
                posMasterAct.posMaster?.orgChild1?.orgChild1ShortName,
                posMasterAct.posMaster?.orgRoot?.orgRootShortName,
              ].find(Boolean) ?? "";
            commandRecive.posNo =
              orgShortName && posMasterAct.posMaster?.posMasterNo
                ? `${orgShortName} ${posMasterAct.posMaster?.posMasterNo}`
                : posMasterAct.posMaster?.posMasterNo?.toString() ?? "-";
          }
        }
        await this.commandReciveRepository.save(commandRecive);
      }),
    );
    if (
      [
        "C-PM-01",
        "C-PM-02",
        "C-PM-03",
        "C-PM-04",
        "C-PM-05",
        "C-PM-07",
        "C-PM-08",
        "C-PM-09",
        "C-PM-13",
        "C-PM-14",
        "C-PM-15",
        "C-PM-16",
        "C-PM-21",
        "C-PM-22",
        "C-PM-24",
        "C-PM-39",
      ].includes(commandCode)
    ) {
      const _posMasterCommission = await this.posMasterRepository.findOne({
        where: {
          orgRoot: {
            isCommission: true,
          },
          isDirector: true,
          orgChild1: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          current_holderId: Not(IsNull()),
        },
        relations: ["current_holder", "orgRoot", "positions"],
        order: { posMasterOrder: "ASC" },
      });
      let _commandSend = await this.commandSendRepository.findOne({
        where: {
          commandId: command.id,
          profileId: _posMasterCommission?.current_holderId ?? _null,
        },
      });
      if (!_commandSend && _posMasterCommission != null) {
        let commandSend = new CommandSend();
        commandSend.citizenId = _posMasterCommission?.current_holder.citizenId ?? _null;
        commandSend.prefix = _posMasterCommission?.current_holder.prefix ?? _null;
        commandSend.firstName = _posMasterCommission?.current_holder.firstName ?? _null;
        commandSend.lastName = _posMasterCommission?.current_holder.lastName ?? _null;
        commandSend.position = _posMasterCommission?.current_holder.position ?? _null;
        commandSend.org =
          _posMasterCommission && _posMasterCommission.orgRoot
            ? _posMasterCommission.orgRoot.orgRootName
            : _null;
        commandSend.profileId = _posMasterCommission?.current_holderId ?? _null;
        commandSend.commandId = command.id;
        commandSend.createdUserId = request.user.sub;
        commandSend.createdFullName = request.user.name;
        commandSend.createdAt = now;
        commandSend.lastUpdateUserId = request.user.sub;
        commandSend.lastUpdateFullName = request.user.name;
        commandSend.lastUpdatedAt = now;
        await this.commandSendRepository.save(commandSend);
        if (commandSend && commandSend.id) {
          let _ccName = new Array("EMAIL", "INBOX");
          let _dataSendCC = new Array();
          for (let i = 0; i < _ccName.length; i++) {
            _dataSendCC.push({
              commandSendId: commandSend.id,
              name: _ccName[i],
              createdUserId: request.user.sub,
              createdFullName: request.user.name,
              createdAt: now,
              lastUpdateUserId: request.user.sub,
              lastUpdateFullName: request.user.name,
              lastUpdatedAt: now,
            });
          }
          await this.commandSendCCRepository.save(_dataSendCC);
        }
      }
      const _posMasterInformation = await this.posMasterRepository.findOne({
        where: {
          orgChild1: {
            isInformation: true,
          },
          isDirector: true,
          orgChild2: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          current_holderId: Not(IsNull()),
        },
        relations: ["current_holder", "orgRoot", "positions"],
        order: { posMasterOrder: "ASC" },
      });
      _commandSend = await this.commandSendRepository.findOne({
        where: {
          commandId: command.id,
          profileId: _posMasterInformation?.current_holderId ?? _null,
        },
      });
      if (!_commandSend && _posMasterInformation != null) {
        let commandSend = new CommandSend();
        commandSend.citizenId = _posMasterInformation?.current_holder.citizenId ?? _null;
        commandSend.prefix = _posMasterInformation?.current_holder.prefix ?? _null;
        commandSend.firstName = _posMasterInformation?.current_holder.firstName ?? _null;
        commandSend.lastName = _posMasterInformation?.current_holder.lastName ?? _null;
        commandSend.position = _posMasterInformation?.current_holder.position ?? _null;
        commandSend.org =
          _posMasterInformation && _posMasterInformation.orgRoot
            ? _posMasterInformation.orgRoot.orgRootName
            : _null;
        commandSend.profileId = _posMasterInformation?.current_holderId ?? _null;
        commandSend.commandId = command.id;
        commandSend.createdUserId = request.user.sub;
        commandSend.createdFullName = request.user.name;
        commandSend.createdAt = now;
        commandSend.lastUpdateUserId = request.user.sub;
        commandSend.lastUpdateFullName = request.user.name;
        commandSend.lastUpdatedAt = now;
        await this.commandSendRepository.save(commandSend);
        if (commandSend && commandSend.id) {
          let _ccName = new Array("EMAIL", "INBOX");
          let _dataSendCC = new Array();
          for (let i = 0; i < _ccName.length; i++) {
            _dataSendCC.push({
              commandSendId: commandSend.id,
              name: _ccName[i],
              createdUserId: request.user.sub,
              createdFullName: request.user.name,
              createdAt: now,
              lastUpdateUserId: request.user.sub,
              lastUpdateFullName: request.user.name,
              lastUpdatedAt: now,
            });
          }
          await this.commandSendCCRepository.save(_dataSendCC);
        }
      }
      const _posMasterOfficer = await this.posMasterRepository.findOne({
        where: {
          orgChild1: {
            isOfficer: true,
          },
          isDirector: true,
          orgChild2: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          current_holderId: Not(IsNull()),
        },
        relations: ["current_holder", "orgRoot", "positions"],
        order: { posMasterOrder: "ASC" },
      });
      _commandSend = await this.commandSendRepository.findOne({
        where: {
          commandId: command.id,
          profileId: _posMasterOfficer?.current_holderId ?? _null,
        },
      });
      if (!_commandSend && _posMasterOfficer != null) {
        let commandSend = new CommandSend();
        commandSend.citizenId = _posMasterOfficer?.current_holder.citizenId ?? _null;
        commandSend.prefix = _posMasterOfficer?.current_holder.prefix ?? _null;
        commandSend.firstName = _posMasterOfficer?.current_holder.firstName ?? _null;
        commandSend.lastName = _posMasterOfficer?.current_holder.lastName ?? _null;
        commandSend.position = _posMasterOfficer?.current_holder.position ?? _null;
        commandSend.org =
          _posMasterOfficer && _posMasterOfficer.orgRoot
            ? _posMasterOfficer.orgRoot.orgRootName
            : _null;
        commandSend.profileId = _posMasterOfficer?.current_holderId ?? _null;
        commandSend.commandId = command.id;
        commandSend.createdUserId = request.user.sub;
        commandSend.createdFullName = request.user.name;
        commandSend.createdAt = now;
        commandSend.lastUpdateUserId = request.user.sub;
        commandSend.lastUpdateFullName = request.user.name;
        commandSend.lastUpdatedAt = now;
        await this.commandSendRepository.save(commandSend);
        if (commandSend && commandSend.id) {
          let _ccName = new Array("EMAIL", "INBOX");
          let _dataSendCC = new Array();
          for (let i = 0; i < _ccName.length; i++) {
            _dataSendCC.push({
              commandSendId: commandSend.id,
              name: _ccName[i],
              createdUserId: request.user.sub,
              createdFullName: request.user.name,
              createdAt: now,
              lastUpdateUserId: request.user.sub,
              lastUpdateFullName: request.user.name,
              lastUpdatedAt: now,
            });
          }
          await this.commandSendCCRepository.save(_dataSendCC);
        }
      }
    }
    if (!["C-PM-10"].includes(commandCode)) {
      if (requestBody.persons != undefined && requestBody.persons.length > 0) {
        let _orgRoot: any = [];
        let _orgChild1: any = [];
        let _orgChild2: any = [];
        let _orgChild3: any = [];
        let _orgChild4: any = [];
        if (
          [
            "C-PM-21",
            "C-PM-22",
            "C-PM-23",
            "C-PM-24",
            "C-PM-36",
            "C-PM-37",
            "C-PM-42",
            "C-PM-43",
            "C-PM-45",
            "C-PM-46",
          ].includes(commandCode)
        ) {
          let posMaster = await this.employeePosMasterRepository.find({
            where: {
              current_holderId: In(requestBody.persons.map((x) => x.profileId)),
              orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
            },
            select: ["orgRootId", "orgChild1Id", "orgChild2Id", "orgChild3Id", "orgChild4Id"],
          });
          _orgRoot = posMaster
            .filter((x) => x.orgRootId != null && x.orgRootId != "")
            .map((x) => x.orgRootId);
          _orgChild1 = posMaster
            .filter((x) => x.orgChild1Id != null && x.orgChild1Id != "")
            .map((x) => x.orgChild1Id);
          _orgChild2 = posMaster
            .filter((x) => x.orgChild2Id != null && x.orgChild2Id != "")
            .map((x) => x.orgChild2Id);
          _orgChild3 = posMaster
            .filter((x) => x.orgChild3Id != null && x.orgChild3Id != "")
            .map((x) => x.orgChild3Id);
          _orgChild4 = posMaster
            .filter((x) => x.orgChild4Id != null && x.orgChild4Id != "")
            .map((x) => x.orgChild4Id);
        } else {
          var posMasterOfficer = await this.posMasterRepository.find({
            where: {
              current_holderId: In(requestBody.persons.map((x) => x.profileId)),
              orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
            },
            select: ["orgRootId", "orgChild1Id", "orgChild2Id", "orgChild3Id", "orgChild4Id"],
          });
          var posMasterEmployee = await this.employeePosMasterRepository.find({
            where: {
              current_holderId: In(requestBody.persons.map((x) => x.profileId)),
              orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
            },
            select: ["orgRootId", "orgChild1Id", "orgChild2Id", "orgChild3Id", "orgChild4Id"],
          });
          let posMaster = [...posMasterOfficer, ...posMasterEmployee];
          _orgRoot = posMaster
            .filter((x) => x.orgRootId != null && x.orgRootId != "")
            .map((x) => x.orgRootId);
          _orgChild1 = posMaster
            .filter((x) => x.orgChild1Id != null && x.orgChild1Id != "")
            .map((x) => x.orgChild1Id);
          _orgChild2 = posMaster
            .filter((x) => x.orgChild2Id != null && x.orgChild2Id != "")
            .map((x) => x.orgChild2Id);
          _orgChild3 = posMaster
            .filter((x) => x.orgChild3Id != null && x.orgChild3Id != "")
            .map((x) => x.orgChild3Id);
          _orgChild4 = posMaster
            .filter((x) => x.orgChild4Id != null && x.orgChild4Id != "")
            .map((x) => x.orgChild4Id);
        }

        let _posMaster: any;
        if (["C-PM-38", "C-PM-40"].includes(commandCode)) {
          _posMaster = await this.posMasterRepository.find({
            where: {
              orgRootId: In(_orgRoot),
              orgChild1: IsNull(),
              orgChild2: IsNull(),
              orgChild3: IsNull(),
              orgChild4: IsNull(),
              orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
              isDirector: true,
              current_holderId: Not(IsNull()),
            },
            relations: ["current_holder", "orgRoot"],
          });
        } else {
          _posMaster = await this.posMasterRepository.find({
            where: [
              {
                orgRootId: In(_orgRoot),
                orgChild1: IsNull(),
                orgChild2: IsNull(),
                orgChild3: IsNull(),
                orgChild4: IsNull(),
                orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
                isDirector: true,
                current_holderId: Not(IsNull()),
              },
              {
                orgChild1: In(_orgChild1),
                orgChild2: IsNull(),
                orgChild3: IsNull(),
                orgChild4: IsNull(),
                orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
                isDirector: true,
                current_holderId: Not(IsNull()),
              },
              {
                orgChild2: In(_orgChild2),
                orgChild3: IsNull(),
                orgChild4: IsNull(),
                orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
                isDirector: true,
                current_holderId: Not(IsNull()),
              },
              {
                orgChild3: In(_orgChild3),
                orgChild4: IsNull(),
                orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
                isDirector: true,
                current_holderId: Not(IsNull()),
              },
              {
                orgChild4: In(_orgChild4),
                orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
                isDirector: true,
                current_holderId: Not(IsNull()),
              },
            ],
            relations: ["current_holder", "orgRoot"],
          });
        }
        await Promise.all(
          _posMaster.map(async (item: any) => {
            const _commandSend = await this.commandSendRepository.findOne({
              where: {
                commandId: command.id,
                profileId: item.current_holderId,
              },
            });
            if (!_commandSend) {
              let commandSend = new CommandSend();
              commandSend.citizenId = item.current_holder.citizenId;
              commandSend.prefix = item.current_holder.prefix;
              commandSend.firstName = item.current_holder.firstName;
              commandSend.lastName = item.current_holder.lastName;
              commandSend.position = item.current_holder.position;
              commandSend.org = item.orgRoot.orgRootName;
              commandSend.profileId = item.current_holderId;
              commandSend.commandId = command.id;
              commandSend.createdUserId = request.user.sub;
              commandSend.createdFullName = request.user.name;
              commandSend.createdAt = now;
              commandSend.lastUpdateUserId = request.user.sub;
              commandSend.lastUpdateFullName = request.user.name;
              commandSend.lastUpdatedAt = now;
              await this.commandSendRepository.save(commandSend);
              if (commandSend && commandSend.id) {
                let _ccName = new Array("EMAIL", "INBOX");
                let _dataSendCC = new Array();
                for (let i = 0; i < _ccName.length; i++) {
                  _dataSendCC.push({
                    commandSendId: commandSend.id,
                    name: _ccName[i],
                    createdUserId: request.user.sub,
                    createdFullName: request.user.name,
                    createdAt: now,
                    lastUpdateUserId: request.user.sub,
                    lastUpdateFullName: request.user.name,
                    lastUpdatedAt: now,
                  });
                }
                await this.commandSendCCRepository.save(_dataSendCC);
              }
            }
          }),
        );

        const _posMasterNext = await this.posMasterRepository.find({
          where: {
            orgRootId: In(
              requestBody.persons
                .filter((x) => x.rootId != undefined && x.rootId != null && x.rootId != "")
                .map((x) => x.rootId),
            ),
            orgChild1: IsNull(),
            orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
            isDirector: true,
            current_holderId: Not(IsNull()),
          },
          relations: ["current_holder", "orgRoot"],
        });
        await Promise.all(
          _posMasterNext.map(async (item: any) => {
            const _commandSend = await this.commandSendRepository.findOne({
              where: {
                commandId: command.id,
                profileId: item.current_holderId,
              },
            });
            // if (_commandSend) return;
            if (!_commandSend) {
              let commandSend = new CommandSend();
              commandSend.citizenId = item.current_holder.citizenId;
              commandSend.prefix = item.current_holder.prefix;
              commandSend.firstName = item.current_holder.firstName;
              commandSend.lastName = item.current_holder.lastName;
              commandSend.position = item.current_holder.position;
              commandSend.org = item.orgRoot.orgRootName;
              commandSend.profileId = item.current_holderId;
              commandSend.commandId = command.id;
              commandSend.createdUserId = request.user.sub;
              commandSend.createdFullName = request.user.name;
              commandSend.createdAt = now;
              commandSend.lastUpdateUserId = request.user.sub;
              commandSend.lastUpdateFullName = request.user.name;
              commandSend.lastUpdatedAt = now;
              await this.commandSendRepository.save(commandSend);
              if (commandSend && commandSend.id) {
                let _ccName = new Array("EMAIL", "INBOX");
                let _dataSendCC = new Array();
                for (let i = 0; i < _ccName.length; i++) {
                  _dataSendCC.push({
                    commandSendId: commandSend.id,
                    name: _ccName[i],
                    createdUserId: request.user.sub,
                    createdFullName: request.user.name,
                    createdAt: now,
                    lastUpdateUserId: request.user.sub,
                    lastUpdateFullName: request.user.name,
                    lastUpdatedAt: now,
                  });
                }
                await this.commandSendCCRepository.save(_dataSendCC);
              }
            }
          }),
        );
      }
    }
    if (["C-PM-10", "C-PM-40"].includes(commandCode)) {
      await Promise.all(
        requestBody.persons.map(async (item: any) => {
          const _posMasterDirector = await this.posMasterRepository.findOne({
            where: {
              orgRootId: item.rootId,
              orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
              current_holderId: item.profileId,
            },
            relations: ["current_holder", "orgRoot", "positions"],
          });
          const _commandSend = await this.commandSendRepository.findOne({
            where: {
              commandId: command.id,
              profileId: item.profileId ?? _null,
            },
          });
          if (!_commandSend) {
            let commandSend = new CommandSend();
            commandSend.citizenId = item.citizenId;
            commandSend.prefix = item.prefix;
            commandSend.firstName = item.firstName;
            commandSend.lastName = item.lastName;
            commandSend.position = _posMasterDirector?.current_holder.position ?? _null;
            commandSend.org =
              _posMasterDirector && _posMasterDirector.orgRoot
                ? _posMasterDirector.orgRoot.orgRootName
                : _null;
            commandSend.profileId = item.profileId;
            commandSend.commandId = command.id;
            commandSend.createdUserId = request.user.sub;
            commandSend.createdFullName = request.user.name;
            commandSend.createdAt = now;
            commandSend.lastUpdateUserId = request.user.sub;
            commandSend.lastUpdateFullName = request.user.name;
            commandSend.lastUpdatedAt = now;
            await this.commandSendRepository.save(commandSend);
            if (commandSend && commandSend.id) {
              let _ccName = new Array("EMAIL", "INBOX");
              let _dataSendCC = new Array();
              for (let i = 0; i < _ccName.length; i++) {
                _dataSendCC.push({
                  commandSendId: commandSend.id,
                  name: _ccName[i],
                  createdUserId: request.user.sub,
                  createdFullName: request.user.name,
                  createdAt: now,
                  lastUpdateUserId: request.user.sub,
                  lastUpdateFullName: request.user.name,
                  lastUpdatedAt: now,
                });
              }
              await this.commandSendCCRepository.save(_dataSendCC);
            }
          }
        }),
      );
    }
    return new HttpSuccess(command.id);
  }

  /**
   * API ค้นหา กก. สกจ. และหัวหน้า
   *
   * @summary API ค้นหา กก. สกจ. และหัวหน้า
   *
   */
  @Post("find-higher")
  async findHigher(
    @Body()
    requestBody: {
      persons: {
        profileId?: string | null;
      }[];
    },
    @Request() request: RequestWithUser,
  ) {
    let _null: any = null;
    let _data = new Array();
    const _posMasterCommission = await this.posMasterRepository.findOne({
      where: {
        orgRoot: {
          isCommission: true,
        },
        isDirector: true,
        orgChild1: IsNull(),
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
        current_holderId: Not(IsNull()),
      },
      relations: ["current_holder", "orgRoot", "positions"],
      order: { posMasterOrder: "ASC" },
    });
    if (_posMasterCommission) {
      _data.push({
        citizenId: _posMasterCommission?.current_holder.citizenId ?? _null,
        prefix: _posMasterCommission?.current_holder.prefix,
        firstName: _posMasterCommission?.current_holder.firstName,
        lastName: _posMasterCommission?.current_holder.lastName,
        organizationName: _posMasterCommission.orgRoot
          ? _posMasterCommission.orgRoot.orgRootName
          : _null,
        positionName: _posMasterCommission?.current_holder.position ?? _null,
        profileId: _posMasterCommission?.current_holder.id ?? _null,
      });
    }
    const _posMasterOfficer = await this.posMasterRepository.findOne({
      where: {
        orgChild1: {
          isOfficer: true,
        },
        isDirector: true,
        orgChild2: IsNull(),
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
        current_holderId: Not(IsNull()),
      },
      relations: ["current_holder", "orgRoot", "orgChild1", "positions"],
      order: { posMasterOrder: "ASC" },
    });
    if (_posMasterOfficer) {
      _data.push({
        citizenId: _posMasterOfficer?.current_holder.citizenId ?? _null,
        prefix: _posMasterOfficer?.current_holder.prefix,
        firstName: _posMasterOfficer?.current_holder.firstName,
        lastName: _posMasterOfficer?.current_holder.lastName,
        // organizationName: _posMasterOfficer.orgRoot ? _posMasterOfficer.orgRoot.orgRootName : _null,
        organizationName: _posMasterOfficer.orgChild1
          ? _posMasterOfficer.orgChild1.orgChild1Name + "\n" + _posMasterOfficer.orgRoot.orgRootName
          : _posMasterOfficer.orgChild1 == null && _posMasterOfficer.orgRoot
            ? _posMasterOfficer.orgRoot.orgRootName
            : _null,
        positionName: _posMasterOfficer?.current_holder.position ?? _null,
        profileId: _posMasterOfficer?.current_holder.id ?? _null,
      });
    }
    let _orgRoot: any = [];
    let _orgChild1: any = [];
    let _orgChild2: any = [];
    let _orgChild3: any = [];
    let _orgChild4: any = [];

    var posMasterOfficer = await this.posMasterRepository.find({
      where: {
        current_holderId: In(requestBody.persons.map((x) => x.profileId)),
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
      select: ["orgRootId", "orgChild1Id", "orgChild2Id", "orgChild3Id", "orgChild4Id"],
    });
    var posMasterEmployee = await this.employeePosMasterRepository.find({
      where: {
        current_holderId: In(requestBody.persons.map((x) => x.profileId)),
        orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
      },
      select: ["orgRootId", "orgChild1Id", "orgChild2Id", "orgChild3Id", "orgChild4Id"],
    });

    let posMaster = [...posMasterOfficer, ...posMasterEmployee];
    _orgRoot = posMaster
      .filter((x) => x.orgRootId != null && x.orgRootId != "")
      .map((x) => x.orgRootId);
    _orgChild1 = posMaster
      .filter((x) => x.orgChild1Id != null && x.orgChild1Id != "")
      .map((x) => x.orgChild1Id);
    _orgChild2 = posMaster
      .filter((x) => x.orgChild2Id != null && x.orgChild2Id != "")
      .map((x) => x.orgChild2Id);
    _orgChild3 = posMaster
      .filter((x) => x.orgChild3Id != null && x.orgChild3Id != "")
      .map((x) => x.orgChild3Id);
    _orgChild4 = posMaster
      .filter((x) => x.orgChild4Id != null && x.orgChild4Id != "")
      .map((x) => x.orgChild4Id);

    let _posMaster: any;
    _posMaster = await this.posMasterRepository.find({
      where: [
        {
          orgRootId: In(_orgRoot),
          orgChild1: IsNull(),
          orgChild2: IsNull(),
          orgChild3: IsNull(),
          orgChild4: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          isDirector: true,
          current_holderId: Not(IsNull()),
          id: Not(In([_posMasterCommission?.id])),
        },
        {
          orgChild1: In(_orgChild1),
          orgChild2: IsNull(),
          orgChild3: IsNull(),
          orgChild4: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          isDirector: true,
          current_holderId: Not(IsNull()),
          id: Not(In([_posMasterOfficer?.id])),
        },
        {
          orgChild2: In(_orgChild2),
          orgChild3: IsNull(),
          orgChild4: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          isDirector: true,
          current_holderId: Not(IsNull()),
        },
        {
          orgChild3: In(_orgChild3),
          orgChild4: IsNull(),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          isDirector: true,
          current_holderId: Not(IsNull()),
        },
        {
          orgChild4: In(_orgChild4),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          isDirector: true,
          current_holderId: Not(IsNull()),
        },
      ],
      relations: ["current_holder", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
    });
    if (_posMaster.length > 0) {
      _posMaster.forEach((x: any) => {
        _data.push({
          citizenId: x?.current_holder.citizenId ?? _null,
          prefix: x?.current_holder.prefix,
          firstName: x?.current_holder.firstName,
          lastName: x?.current_holder.lastName,
          // organizationName: x.orgRoot ? x.orgRoot.orgRootName : _null,
          organizationName:
            x.orgChild1 == null
              ? x.orgRoot.orgRootName
              : x.orgChild2 == null
                ? x.orgChild1.orgChild1Name + "\n" + x.orgRoot.orgRootName
                : x.orgChild3 == null
                  ? x.orgChild2.orgChild2Name +
                    "\n" +
                    x.orgChild1.orgChild1Name +
                    "\n" +
                    x.orgRoot.orgRootName
                  : x.orgChild4 == null
                    ? x.orgChild3.orgChild3Name +
                      "\n" +
                      x.orgChild2.orgChild2Name +
                      "\n" +
                      x.orgChild1.orgChild1Name +
                      "\n" +
                      x.orgRoot.orgRootName
                    : x.orgChild4.orgChild4Name +
                      "\n" +
                      x.orgChild3.orgChild3Name +
                      "\n" +
                      x.orgChild2.orgChild2Name +
                      "\n" +
                      x.orgChild1.orgChild1Name +
                      "\n" +
                      x.orgRoot.orgRootName,
          positionName: x?.current_holder.position ?? _null,
          profileId: x?.current_holder.id ?? _null,
        });
      });
    }

    return new HttpSuccess(_data);
  }

  /**
   * API อัพเดทสถานะ CANCEL คำสั่งยกเลิกการลาออก, คำสั่งยกเลิกการลาออกลูกจ้าง
   *
   * @summary API อัพเดทสถานะ CANCEL คำสั่งยกเลิกการลาออก, คำสั่งยกเลิกการลาออกลูกจ้าง
   *
   */
  @Post("cancel-resign")
  public async command41Excecute(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      resignId: string[];
    },
  ) {
    const _refId = Array.from(new Set(body.resignId));
    // 1. ดึง commandRecive ที่ refId ตรงกับ resignId
    const commandRecives = await this.commandReciveRepository.find({
      select: ["commandId"],
      where: { refId: In(_refId) },
    });
    // 2. ดึง commandId ที่ไม่ซ้ำ
    const commandIds = Array.from(new Set(commandRecives.map((x) => x.commandId).filter(Boolean)));
    // 3. อัปเดต status ของ command
    if (commandIds.length > 0) {
      await this.commandRepository.update({ id: In(commandIds) }, { status: "CANCEL" });
    }
    return new HttpSuccess();
  }

  @Post("excexute/salary-current")
  public async newSalaryAndUpdateCurrent(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        positionExecutive: string | null;
        positionExecutiveField?: string | null;
        positionArea?: string | null;
        positionType: string | null;
        positionLevel: string | null;
        positionTypeId?: string | null;
        positionLevelId?: string | null;
        posmasterId: string;
        positionId: string;
        posExecutiveId?: string | null;
        positionField?: string | null;
        commandId?: string | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        commandNo: string | null;
        commandYear: number | null;
        posNo: string | null;
        posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.data.map(async (item) => {
        const profile: any = await this.profileRepository.findOneBy({ id: item.profileId });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }
        let _null: any = null;
        const dest_item = await this.salaryRepo.findOne({
          where: { profileId: item.profileId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();

        const meta = {
          order: dest_item == null ? 1 : dest_item.order + 1,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
        };
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        Object.assign(data, { ...item, ...meta });
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });
        await this.salaryRepo.save(data, { data: req });
        setLogDataDiff(req, { before, after: data });
        history.commandId = item.commandId ?? _null;
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history, { data: req });

        // STEP 1: หา posMaster ที่จะใช้งานตาม id ที่ส่งมา
        let posMaster = await this.posMasterRepository.findOne({
          where: { id: item.posmasterId },
          relations: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        });

        // เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่
        const isCurrent =
          posMaster?.orgRevision?.orgRevisionIsCurrent === true &&
          posMaster?.orgRevision?.orgRevisionIsDraft === false;

        // ถ้าไม่อยู่ในโครงสร้างปัจจุบัน ให้หาตัวใหม่จาก ancestorDNA
        if (!isCurrent && posMaster?.ancestorDNA) {
          posMaster = await this.posMasterRepository.findOne({
            where: {
              ancestorDNA: posMaster.ancestorDNA,
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
            relations: {
              orgRevision: true,
              orgRoot: true,
              orgChild1: true,
              orgChild2: true,
              orgChild3: true,
              orgChild4: true,
            },
          });
        }

        if (posMaster == null) {
          console.error(
            `[CommandController] PosMaster not found - posMasterId: ${item.posmasterId}, `
          );
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
        }

        const posMasterOld = await this.posMasterRepository.findOne({
          where: {
            current_holderId: item.profileId,
            orgRevisionId: posMaster.orgRevisionId,
          },
        });
        if (posMasterOld != null) {
          posMasterOld.current_holderId = null;
          posMasterOld.lastUpdatedAt = new Date();
        }

        const positionOld = await this.positionRepository.findOne({
          where: {
            posMasterId: posMasterOld?.id,
            positionIsSelected: true,
          },
        });
        if (positionOld != null) {
          logPositionIsSelectedChange(positionOld.id, positionOld.positionIsSelected, false, {
            posMasterId: posMasterOld?.id,
            userId: req.user.sub,
            endpoint: "updateMaster",
            action: "command_change_reset_old_position",
          });

          positionOld.positionIsSelected = false;
          await this.positionRepository.save(positionOld);
        }

        const checkPosition = await this.positionRepository.find({
          where: {
            posMasterId: posMaster!.id, // ใช้ posMaster ตัวใหม่ (ที่อาจจะเปลี่ยนจาก ancestorDNA)
            positionIsSelected: true,
          },
        });
        if (checkPosition.length > 0) {
          console.log(
            `[positionIsSelected-DEBUG] Command change: clearing ${checkPosition.length} positions (posMasterId: ${posMaster!.id}, userId: ${req.user.sub}, endpoint: updateMaster)`
          );

          const clearPosition = checkPosition.map((positions) => {
            logPositionIsSelectedChange(positions.id, positions.positionIsSelected, false, {
              posMasterId: posMaster!.id,
              userId: req.user.sub,
              endpoint: "updateMaster",
              action: "command_change_clear_positions",
            });

            return {
              ...positions,
              positionIsSelected: false,
            };
          });
          await this.positionRepository.save(clearPosition);
        }

        posMaster.current_holderId = item.profileId;
        posMaster.lastUpdatedAt = new Date();
        // posMaster.conditionReason = _null;
        // posMaster.isCondition = false;
        if (posMasterOld != null) {
          await this.posMasterRepository.save(posMasterOld);
          await CreatePosMasterHistoryOfficer(posMasterOld.id, req);
        }
        await this.posMasterRepository.save(posMaster);

        // STEP 2: กำหนด position ใหม่
        // Match position ตามลำดับ priority:
        // Condition 1: match จาก positionId
        // Condition 2: match 7 ฟิลด์ (positionName, posTypeId, posLevelId, positionField, positionArea, positionExecutiveField, posExecutiveId)
        // Condition 3: match 3 ฟิลด์ (positionName, posTypeId, posLevelId)
        // Fallback: เลือก position แรกใน posMaster

        let positionNew: Position | null = null;

        // Resolve ID: ใช้ positionTypeId/positionLevelId ก่อน ถ้าไม่มี fallback เป็น positionType/positionLevel
        const posTypeId = item.positionTypeId || item.positionType;
        const posLevelId = item.positionLevelId || item.positionLevel;

        // ═══════════════════════════════════════════════════════════
        // CONDITION 1: เช็คจาก positionId ตรง
        // ═══════════════════════════════════════════════════════════
        if (item.positionId) {
          const positionById = await this.positionRepository.findOne({
            where: {
              id: item.positionId,
              posMasterId: posMaster.id, // ต้องอยู่ใน posMaster ที่ถูกต้อง
            },
            relations: ["posExecutive"],
          });

          if (positionById) {
            positionNew = positionById;
          }
        }

        // ═══════════════════════════════════════════════════════════
        // CONDITION 2: Match 7 ฟิลด์ (ถ้า Condition 1 ไม่ match)
        // ═══════════════════════════════════════════════════════════
        if (!positionNew && item.positionName && posTypeId && posLevelId) {
          // สร้าง where clause แบบ dynamic - ใส่เฉพาะฟิลด์ที่มีค่า
          const whereCondition: any = {
            posMasterId: posMaster.id,
            positionName: item.positionName,
            posTypeId: posTypeId,
            posLevelId: posLevelId,
          };

          // เพิ่มเฉพาะฟิลด์ที่มีค่า (ไม่ใช่ null, undefined, หรือ string ว่าง)
          if (item.positionField) {
            whereCondition.positionField = item.positionField;
          }
          if (item.posExecutiveId) {
            whereCondition.posExecutiveId = item.posExecutiveId;
          }
          if (item.positionExecutiveField) {
            whereCondition.positionExecutiveField = item.positionExecutiveField;
          }
          if (item.positionArea) {
            whereCondition.positionArea = item.positionArea;
          }

          const positionBy7Fields = await this.positionRepository.findOne({
            where: whereCondition,
            relations: ["posExecutive"],
            order: { orderNo: "ASC" }
          });

          if (positionBy7Fields) {
            positionNew = positionBy7Fields;
          }
        }

        // ═══════════════════════════════════════════════════════════
        // CONDITION 3: Match 3 ฟิลด์ (ถ้า Condition 2 ไม่ match)
        // ═══════════════════════════════════════════════════════════
        if (!positionNew && item.positionName && posTypeId && posLevelId) {
          const positionBy3Fields = await this.positionRepository.findOne({
            where: {
              posMasterId: posMaster.id,
              positionName: item.positionName,
              posTypeId: posTypeId,
              posLevelId: posLevelId,
            },
            relations: ["posExecutive"],
            order: { orderNo: "ASC" }
          });

          if (positionBy3Fields) {
            positionNew = positionBy3Fields;
          }
        }

        // // ═══════════════════════════════════════════════════════════
        // // FALLBACK: ถ้าทั้ง 3 ไม่ match ให้เลือก position แรกใน posMaster
        // // ═══════════════════════════════════════════════════════════
        // if (!positionNew) {
        //   const fallbackPositions = await this.positionRepository.find({
        //     where: {
        //       posMasterId: posMaster.id,
        //     },
        //     relations: ["posExecutive"],
        //     order: {
        //       orderNo: "ASC",
        //     },
        //     take: 1,
        //   });

        //   if (fallbackPositions.length > 0) {
        //     positionNew = fallbackPositions[0];
        //   }
        // }

        // ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
        if (positionNew != null) {
          positionNew.positionIsSelected = true;
          // อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
          profile.posMasterNo = getPosMasterNo(posMaster);
          profile.org = getOrgFullName(posMaster);
          if (!posMaster.isSit) {
            profile.posLevelId = positionNew.posLevelId;
            profile.posTypeId = positionNew.posTypeId;
            profile.position = positionNew.positionName;
            profile.positionField = positionNew.positionField ?? null;
            profile.posExecutive = positionNew.posExecutive?.posExecutiveName ?? null;
            profile.positionArea = positionNew.positionArea ?? null;
            profile.positionExecutiveField = positionNew.positionExecutiveField ?? null;
          }
          profile.amount = item.amount ?? null;
          profile.amountSpecial = item.amountSpecial ?? null;
          await this.profileRepository.save(profile);
          await this.positionRepository.save(positionNew);
        }
        await CreatePosMasterHistoryOfficer(posMaster.id, req);
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee-current")
  public async newSalaryEmployeeAndUpdateCurrent(
    @Request() req: RequestWithUser,
    @Body()
    body: { 
      data: {
        profileId: string;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        positionType: string | null;
        positionLevel: string | null;
        posmasterId: string;
        positionId: string;
        commandId?: string | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        commandNo: string | null;
        commandYear: number | null;
        posNo: string | null;
        posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.data.map(async (item) => {
        const profile: any = await this.profileEmployeeRepository.findOneBy({ id: item.profileId });
        if (!profile) {
          throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
        }

        const dest_item = await this.salaryRepo.findOne({
          where: { profileEmployeeId: item.profileId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        const meta = {
          order: dest_item == null ? 1 : dest_item.order + 1,
          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, {
          ...item,
          ...meta,
          profileEmployeeId: item.profileId,
          profileId: undefined,
        });
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });

        await this.salaryRepo.save(data, { data: req });
        setLogDataDiff(req, { before, after: data });
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history, { data: req });

        const posMaster = await this.employeePosMasterRepository.findOne({
          where: { id: item.posmasterId },
          relations: ["orgRoot"],
        });
        if (posMaster == null)
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");

        const posMasterOld = await this.employeePosMasterRepository.findOne({
          where: {
            current_holderId: item.profileId,
            orgRevisionId: posMaster.orgRevisionId,
          },
        });
        if (posMasterOld != null) {
          posMasterOld.current_holderId = null;
          posMasterOld.lastUpdatedAt = new Date();
        }
        // if (posMasterOld != null) posMasterOld.next_holderId = null;

        const positionOld = await this.employeePositionRepository.findOne({
          where: {
            posMasterId: posMasterOld?.id,
            positionIsSelected: true,
          },
        });
        if (positionOld != null) {
          positionOld.positionIsSelected = false;
          await this.employeePositionRepository.save(positionOld);
        }

        const checkPosition = await this.employeePositionRepository.find({
          where: {
            posMasterId: item.posmasterId,
            positionIsSelected: true,
          },
        });
        if (checkPosition.length > 0) {
          const clearPosition = checkPosition.map((positions) => ({
            ...positions,
            positionIsSelected: false,
          }));
          await this.employeePositionRepository.save(clearPosition);
        }

        posMaster.current_holderId = item.profileId;
        posMaster.lastUpdatedAt = new Date();
        posMaster.next_holderId = null;
        if (posMasterOld != null) {
          await this.employeePosMasterRepository.save(posMasterOld);
          await CreatePosMasterHistoryEmployee(posMasterOld.id, req);
        }
        await this.employeePosMasterRepository.save(posMaster);
        const positionNew = await this.employeePositionRepository.findOne({
          where: {
            id: item.positionId,
            posMasterId: item.posmasterId,
          },
        });
        if (positionNew != null) {
          positionNew.positionIsSelected = true;
          profile.posLevelId = positionNew.posLevelId;
          profile.posTypeId = positionNew.posTypeId;
          profile.position = positionNew.positionName;
          profile.employeeOc = posMaster?.orgRoot?.orgRootName ?? null;
          profile.positionEmployeePositionId = positionNew.positionName;
          profile.amount = item.amount ?? null;
          profile.amountSpecial = item.amountSpecial ?? null;
          await this.profileEmployeeRepository.save(profile);
          await this.employeePositionRepository.save(positionNew);
        }
        await CreatePosMasterHistoryEmployee(posMaster.id, req);
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-leave")
  public async newSalaryAndUpdateLeave(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        positionExecutive: string | null;
        positionExecutiveField?: string | null;
        positionArea?: string | null;
        positionType: string | null;
        positionLevel: string | null;
        isLeave: boolean;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        posExecutiveId?: string | null;
        positionField?: string | null;
        commandId?: string | null;
        isGovernment?: boolean | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        commandNo: string | null;
        commandYear: number | null;
        posNo: string | null;
        posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
        positionId?: string | null;
        positionTypeNew?: string | null;
        positionLevelNew?: string | null;
        positionNameNew?: string | null;
        posmasterId?: string | null;
        posTypeNameNew?: string | null;
        posLevelNameNew?: string | null;
        posNoNew?: string | null;
        posNoAbbNew?: string | null;
        orgRootNew?: string | null;
        orgChild1New?: string | null;
        orgChild2New?: string | null;
        orgChild3New?: string | null;
        orgChild4New?: string | null;
        resignId?: string | null;
      }[];
    },
  ) {
    const roleKeycloak = await this.roleKeycloakRepo.findOne({
      where: { name: Like("USER") },
    });
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      relations: ["commandType"],
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    const today = new Date().setHours(0, 0, 0, 0);
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          where: { id: item.profileId },
          relations: {
            roleKeycloaks: true
          },
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }
        //ลบตำแหน่งที่รักษาการแทน
        const code = _command?.commandType?.code;
        if (code && ["C-PM-08", "C-PM-17", "C-PM-18", "C-PM-48"].includes(code)) {
          removePostMasterAct(profile.id);
        }
        //ออกคำสั่งยกเลิกลาออก ลบเฉพาะคนที่ขอยกเลิกลาออก
        else if (item.resignId && code && ["C-PM-41"].includes(code)) {
          const commandResign = await this.commandReciveRepository.findOne({
            where: { refId: item.resignId },
            relations: { command: true },
          });
          const executeDate = commandResign
            ? new Date(commandResign.command.commandExcecuteDate).setHours(0, 0, 0, 0)
            : today;
          if (
            commandResign &&
            _command.status !== "REPORTED" &&
            (_command.status !== "WAITING" || today < executeDate)
          ) {
            await reOrderCommandRecivesAndDelete(commandResign!.id);
          }
        }
        let _commandYear = item.commandYear;
        if (item.commandYear) {
          _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
        }
        const returnWork = await checkReturnCommandType(String(item.commandId));
        const dest_item = await this.salaryRepo.findOne({
          where: { profileId: item.profileId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        data.dateGovernment = item.commandDateAffect ?? new Date();
        data.order = dest_item == null ? 1 : dest_item.order + 1;
        const meta = {
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
        };
        if (!returnWork) {
          Object.assign(data, { ...item, ...meta });
          const history = new ProfileSalaryHistory();
          Object.assign(history, { ...data, id: undefined });
          await this.salaryRepo.save(data, { data: req });
          setLogDataDiff(req, { before, after: data });
          history.profileSalaryId = data.id;
          await this.salaryHistoryRepo.save(history, { data: req });
        }
        const _null: any = null;
        profile.isLeave = item.isLeave;
        profile.leaveReason = item.leaveReason ?? _null;
        profile.dateLeave = item.dateLeave ?? _null;
        profile.lastUpdateUserId = req.user.sub;
        profile.lastUpdateFullName = req.user.name;
        profile.lastUpdatedAt = new Date();
        const clearProfile = await checkCommandType(String(item.commandId));

        //ปั๊มประวัติก่อนลบตำแหน่ง
        const curRevision = await this.orgRevisionRepo.findOne({
          where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        });
        let orgRootRef = null;
        let orgChild1Ref = null;
        let orgChild2Ref = null;
        let orgChild3Ref = null;
        let orgChild4Ref = null;
        if (curRevision) {
          const curPosMaster = await this.posMasterRepository.findOne({
            where: {
              current_holderId: profile.id,
              orgRevisionId: curRevision.id,
            },
            relations: {
              orgRoot: true,
              orgChild1: true,
              orgChild2: true,
              orgChild3: true,
              orgChild4: true,
            },
          });
          orgRootRef = curPosMaster?.orgRoot ?? null;
          orgChild1Ref = curPosMaster?.orgChild1 ?? null;
          orgChild2Ref = curPosMaster?.orgChild2 ?? null;
          orgChild3Ref = curPosMaster?.orgChild3 ?? null;
          orgChild4Ref = curPosMaster?.orgChild4 ?? null;
          if (curPosMaster && clearProfile.LeaveType != "RETIRE_OUT_EMP") {
            await CreatePosMasterHistoryOfficer(curPosMaster.id, req, "DELETE");
          }
        }

        //ลบตำแหน่ง
        if (item.isLeave == true) {
          await removeProfileInOrganize(profile.id, "OFFICER");
        }
        if (clearProfile.status) {
          if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
            const delUserKeycloak = await deleteUser(profile.keycloak);
            if (delUserKeycloak) {
              // Task #228
              // profile.keycloak = _null;
              profile.roleKeycloaks = [];
              profile.isActive = false;
              profile.isDelete = true;
            }
          }
          profile.leaveCommandId = item.commandId ?? _null;
          profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
          profile.leaveRemark = clearProfile.leaveRemark ?? _null;
          profile.leaveDate = item.commandDateAffect ?? _null;
          profile.leaveType = clearProfile.LeaveType ?? _null;
          //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
          // profile.position = _null;
          // profile.posTypeId = _null;
          // profile.posLevelId = _null;
        }

        if (item.isGovernment == true) {
          if (returnWork) {
            //ปลดตำแหน่งเดิมที่ไม่ถูกปลดออกจากกิ่งครั้งเมื่อออกคำสั่งพักราชการหรือออกราชการไว้
            await removeProfileInOrganize(profile.id, "OFFICER");
            //ปั๊มตำแหน่งใหม่
            // หา posMaster และเช็ค orgRevisionIsCurrent
            let posMaster = await this.posMasterRepository.findOne({
              where: { id: item.posmasterId?.toString() },
              relations: {
                orgRevision: true,
                orgRoot: true,
                orgChild1: true,
                orgChild2: true,
                orgChild3: true,
                orgChild4: true,
              },
            });

            // เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่
            const isCurrent =
              posMaster?.orgRevision?.orgRevisionIsCurrent === true &&
              posMaster?.orgRevision?.orgRevisionIsDraft === false;

            // ถ้าไม่อยู่ในโครงสร้างปัจจุบัน ให้หาตัวใหม่จาก ancestorDNA
            if (!isCurrent && posMaster?.ancestorDNA) {
              posMaster = await this.posMasterRepository.findOne({
                where: {
                  ancestorDNA: posMaster.ancestorDNA,
                  orgRevision: {
                    orgRevisionIsCurrent: true,
                    orgRevisionIsDraft: false,
                  },
                },
                relations: {
                  orgRevision: true,
                  orgRoot: true,
                  orgChild1: true,
                  orgChild2: true,
                  orgChild3: true,
                  orgChild4: true,
                },
              });
            }

            if (posMaster) {
              const checkPosition = await this.positionRepository.find({
                where: {
                  posMasterId: posMaster.id,
                  positionIsSelected: true,
                },
              });
              if (checkPosition.length > 0) {
                const clearPosition = checkPosition.map((positions) => ({
                  ...positions,
                  positionIsSelected: false,
                }));
                await this.positionRepository.save(clearPosition);
              }
              posMaster.current_holderId = profile.id;
              posMaster.lastUpdatedAt = new Date();
              // posMaster.conditionReason = _null;
              // posMaster.isCondition = false;
              await this.posMasterRepository.save(posMaster);

              // Match position ตามลำดับ priority:
              //   Condition 1: match จาก positionId
              //   Condition 2: match 7 ฟิลด์ (positionName, posTypeId, posLevelId, positionField, positionArea, positionExecutiveField, posExecutiveId)
              //   Condition 3: match 3 ฟิลด์ (positionName, posTypeId, posLevelId)
              //   Fallback: เลือก position แรกใน posMaster

              let positionNew: Position | null = null;

              // ═══════════════════════════════════════════════════════════
              // CONDITION 1: เช็คจาก positionId ตรง
              // ═══════════════════════════════════════════════════════════
              if (item.positionId) {
                const positionById = await this.positionRepository.findOne({
                  where: {
                    id: item.positionId,
                    posMasterId: posMaster.id, // ต้องอยู่ใน posMaster ที่ถูกต้อง
                  },
                  relations: ["posExecutive"],
                });

                if (positionById) {
                  positionNew = positionById;
                }
              }

              // ═══════════════════════════════════════════════════════════
              // CONDITION 2: Match 7 ฟิลด์ (ถ้า Condition 1 ไม่ match)
              // ═══════════════════════════════════════════════════════════
              if (!positionNew && item.positionNameNew && item.positionTypeNew && item.positionLevelNew) {
                // สร้าง where clause แบบ dynamic - ใส่เฉพาะฟิลด์ที่มีค่า
                const whereCondition: any = {
                  posMasterId: posMaster.id,
                  positionName: item.positionNameNew,
                  posTypeId: item.positionTypeNew,
                  posLevelId: item.positionLevelNew,
                };

                if (item.positionField) {
                  whereCondition.positionField = item.positionField;
                }
                if (item.posExecutiveId) {
                  whereCondition.posExecutiveId = item.posExecutiveId;
                }
                if (item.positionExecutiveField) {
                  whereCondition.positionExecutiveField = item.positionExecutiveField;
                }
                if (item.positionArea) {
                  whereCondition.positionArea = item.positionArea;
                }

                const positionBy7Fields = await this.positionRepository.findOne({
                  where: whereCondition,
                  relations: ["posExecutive"],
                  order: { orderNo: "ASC" }
                });

                if (positionBy7Fields) {
                  positionNew = positionBy7Fields;
                }
              }

              // ═══════════════════════════════════════════════════════════
              // CONDITION 3: Match 3 ฟิลด์ (ถ้า Condition 2 ไม่ match)
              // ═══════════════════════════════════════════════════════════
              if (!positionNew && item.positionNameNew && item.positionTypeNew && item.positionLevelNew) {
                const positionBy3Fields = await this.positionRepository.findOne({
                  where: {
                    posMasterId: posMaster.id,
                    positionName: item.positionNameNew,
                    posTypeId: item.positionTypeNew,
                    posLevelId: item.positionLevelNew,
                  },
                  relations: ["posExecutive"],
                  order: { orderNo: "ASC" }
                });

                if (positionBy3Fields) {
                  positionNew = positionBy3Fields;
                }
              }

              // // FALLBACK: เลือก position แรก (ถ้าไม่เจอทั้ง 2 condition)
              // if (!positionNew) {
              //   const fallbackPositions = await this.positionRepository.find({
              //     where: {
              //       posMasterId: posMaster.id,
              //     },
              //     relations: ["posExecutive"],
              //     order: {
              //       orderNo: "ASC",
              //     },
              //     take: 1,
              //   });

              //   if (fallbackPositions.length > 0) {
              //     positionNew = fallbackPositions[0];
              //   }
              // }

              if (positionNew) {
                positionNew.positionIsSelected = true;
                await this.positionRepository.save(positionNew, { data: req });
              }
              await CreatePosMasterHistoryOfficer(posMaster.id, req);
              profile.posMasterNo = getPosMasterNo(posMaster);
              profile.org = getOrgFullName(posMaster);
            }
            const newMapProfileSalary = {
              profileId: profile.id,
              commandId: item.commandId,
              positionName: item.positionNameNew ?? null,
              positionType: item.posTypeNameNew ?? null,
              positionLevel: item.posLevelNameNew ?? null,
              amount: item.amount ? item.amount : null,
              positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
              amountSpecial: item.amountSpecial ? item.amountSpecial : null,
              mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
              posNo: item.posNoNew,
              posNoAbb: item.posNoAbbNew,
              orgRoot: item.orgRootNew,
              orgChild1: item.orgChild1New,
              orgChild2: item.orgChild2New,
              orgChild3: item.orgChild3New,
              orgChild4: item.orgChild4New,
              isGovernment: item.isGovernment,
              commandNo: item.commandNo,
              commandYear: item.commandYear,
              commandDateAffect: item.commandDateAffect,
              commandDateSign: item.commandDateSign,
              commandCode: item.commandCode,
              commandName: item.commandName,
              remark: item.remark,
            };
            Object.assign(data, { ...newMapProfileSalary, ...meta });
            const history = new ProfileSalaryHistory();
            Object.assign(history, { ...data, id: undefined });
            await this.salaryRepo.save(data);
            history.profileSalaryId = data.id;
            await this.salaryHistoryRepo.save(history);
            profile.leaveReason = _null;
            profile.leaveCommandId = _null;
            profile.leaveCommandNo = _null;
            profile.leaveRemark = _null;
            profile.leaveDate = _null;
            profile.leaveType = _null;
            profile.position = item.positionNameNew ?? _null;
            profile.posTypeId = item.positionTypeNew ?? _null;
            profile.posLevelId = item.positionLevelNew ?? _null;
          }
          let userKeycloakId;
          const checkUser = await getUserByUsername(profile.citizenId);
          //ถ้ายังไม่มี user keycloak ให้สร้างใหม่
          if (checkUser.length == 0) {
            let password = profile.citizenId;
            if (profile.birthDate != null) {
              // const gregorianYear = profile.birthDate.getFullYear() + 543;

              // const formattedDate =
              //   profile.birthDate.toISOString().slice(8, 10) +
              //   profile.birthDate.toISOString().slice(5, 7) +
              //   gregorianYear;
              // password = formattedDate;
              const _date = new Date(profile.birthDate.toDateString())
                .getDate()
                .toString()
                .padStart(2, "0");
              const _month = (new Date(profile.birthDate.toDateString()).getMonth() + 1)
                .toString()
                .padStart(2, "0");
              const _year = new Date(profile.birthDate.toDateString()).getFullYear() + 543;
              password = `${_date}${_month}${_year}`;
            }
            // กรอง "." ออกจาก firstName ก่อนส่งไป keycloak
            const sanitizedFirstName = profile.firstName?.replace(/\./g, "") ?? "";
            userKeycloakId = await createUser(profile.citizenId, password, {
              firstName: sanitizedFirstName,
              lastName: profile.lastName,
            });
            const list = await getRoles();
            let result = false;
            if (Array.isArray(list) && userKeycloakId) {
              result = await addUserRoles(
                userKeycloakId,
                list
                  .filter((v) => v.name === "USER")
                  .map((x) => ({
                    id: x.id,
                    name: x.name,
                  })),
              );
            }
            profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
            profile.keycloak =
              userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : "";
          }
          //ถ้ามีอยู่แล้วให้ใช้อันเดิม
          else {
            const rolesData = await getRoleMappings(checkUser[0].id);
            if (rolesData) {
              const _roleKeycloak = await this.roleKeycloakRepo.find({
                where: { name: In(rolesData.map((x: any) => x.name)) },
              });
              profile.roleKeycloaks =
                _roleKeycloak && _roleKeycloak.length > 0 ? _roleKeycloak : [];
            }
            profile.keycloak = checkUser[0].id;
          }
          profile.amount = item.amount ?? _null;
          profile.amountSpecial = item.amountSpecial ?? _null;
          profile.isActive = true;
          profile.isDelete = false;
        }
        await this.profileRepository.save(profile);

        // if (profile.id) {
        //   await this.keycloakAttributeService.clearOrgDnaAttributes(
        //     [profile.id],
        //     "PROFILE",
        //   );
        // }

        // update user attribute in keycloak
        await updateUserAttributes(profile.keycloak ?? "", {
          profileId: [profile.id],
          prefix: [profile.prefix || ""],
        });

        // Task #2190
        if (code && ["C-PM-17", "C-PM-18", "C-PM-48"].includes(code)) {
          let organizeName = "";
          if (orgRootRef) {
            const names = [
              orgChild4Ref?.orgChild4Name,
              orgChild3Ref?.orgChild3Name,
              orgChild2Ref?.orgChild2Name,
              orgChild1Ref?.orgChild1Name,
              orgRootRef?.orgRootName,
            ].filter(Boolean);
            organizeName = names.join(" ");
          }

        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee-leave")
  public async newSalaryEmployeeAndUpdateLeave(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        positionType: string | null;
        positionLevel: string | null;
        isLeave: boolean;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        isGovernment?: boolean | null;
        commandId?: string | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        positionExecutive?: string | null;
        positionExecutiveField?: string | null;
        positionArea?: string | null;
        commandNo: string | null;
        commandYear: number | null;
        posNo: string | null;
        posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
        resignId: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
      relations: { commandType: true },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    const today = new Date().setHours(0, 0, 0, 0);
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileEmployeeRepository.findOne({
          where: { id: item.profileId },
          // relations: ["roleKeycloaks"],
          relations: {
            roleKeycloaks: true,
            posType: true,
            posLevel: true,
          },
        });
        if (!profile) {
          throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
        }
        const code = _command?.commandType?.code;
        //ออกคำสั่งยกเลิกลาออก ลบเฉพาะคนที่ขอยกเลิกลาออก
        if (item.resignId && code && ["C-PM-42"].includes(code)) {
          const commandResign = await this.commandReciveRepository.findOne({
            where: { refId: item.resignId },
            relations: { command: true },
          });
          const executeDate = commandResign
            ? new Date(commandResign.command.commandExcecuteDate).setHours(0, 0, 0, 0)
            : today;
          if (
            commandResign &&
            _command.status !== "REPORTED" &&
            (_command.status !== "WAITING" || today < executeDate)
          ) {
            await reOrderCommandRecivesAndDelete(commandResign!.id);
          }
        }
        let _commandYear = item.commandYear;
        if (item.commandYear) {
          _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
        }
        const dest_item = await this.salaryRepo.findOne({
          where: { profileEmployeeId: item.profileId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        const meta = {
          order: dest_item == null ? 1 : dest_item.order + 1,
          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, {
          ...item,
          ...meta,
          profileEmployeeId: item.profileId,
          profileId: undefined,
        });
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });
        data.dateGovernment = item.commandDateAffect ?? meta.createdAt;
        await this.salaryRepo.save(data, { data: req });
        setLogDataDiff(req, { before, after: data });
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history, { data: req });

        const _null: any = null;
        profile.isLeave = item.isLeave;
        profile.leaveReason = item.leaveReason ?? _null;
        profile.dateLeave = item.dateLeave ?? _null;
        profile.lastUpdateUserId = req.user.sub;
        profile.lastUpdateFullName = req.user.name;
        profile.lastUpdatedAt = new Date();
        // บันทึกประวัติก่อนลบตำแหน่ง
        const clearProfile = await checkCommandType(String(item.commandId));
        const curRevision = await this.orgRevisionRepo.findOne({
          where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        });
        let orgRootRef = null;
        let orgChild1Ref = null;
        let orgChild2Ref = null;
        let orgChild3Ref = null;
        let orgChild4Ref = null;
        if (curRevision) {
          const curPosMaster = await this.employeePosMasterRepository.findOne({
            where: {
              current_holderId: profile.id,
              orgRevisionId: curRevision.id,
            },
            relations: {
              orgRoot: true,
              orgChild1: true,
              orgChild2: true,
              orgChild3: true,
              orgChild4: true,
            },
          });
          orgRootRef = curPosMaster?.orgRoot ?? null;
          orgChild1Ref = curPosMaster?.orgChild1 ?? null;
          orgChild2Ref = curPosMaster?.orgChild2 ?? null;
          orgChild3Ref = curPosMaster?.orgChild3 ?? null;
          orgChild4Ref = curPosMaster?.orgChild4 ?? null;
          if (curPosMaster) {
            await CreatePosMasterHistoryEmployee(curPosMaster.id, req, "DELETE");
          }
        }

        // ลบตำแหน่ง
        if (item.isLeave == true) {
          await removeProfileInOrganize(profile.id, "EMPLOYEE");
        }

        if (clearProfile.status) {
          if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
            const delUserKeycloak = await deleteUser(profile.keycloak);
            if (delUserKeycloak) {
              // Task #228
              // profile.keycloak = _null;
              profile.roleKeycloaks = [];
              profile.isActive = false;
              profile.isDelete = true;
            }
          }
          profile.leaveCommandId = item.commandId ?? _null;
          profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
          profile.leaveRemark = clearProfile.leaveRemark ?? _null;
          profile.leaveDate = item.commandDateAffect ?? _null;
          profile.leaveType = clearProfile.LeaveType ?? _null;
          //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
          // profile.position = _null;
          // profile.posTypeId = _null;
          // profile.posLevelId = _null;
        }
        await this.profileEmployeeRepository.save(profile);

        // if (profile.id) {
        //   await this.keycloakAttributeService.clearOrgDnaAttributes(
        //     [profile.id],
        //     "PROFILE_EMPLOYEE",
        //   );
        // }

        // Task #2190
        if (code && ["C-PM-23", "C-PM-43"].includes(code)) {
          let organizeName = "";
          if (orgRootRef) {
            const names = [
              orgChild4Ref?.orgChild4Name,
              orgChild3Ref?.orgChild3Name,
              orgChild2Ref?.orgChild2Name,
              orgChild1Ref?.orgChild1Name,
              orgRootRef?.orgRootName,
            ].filter(Boolean);
            organizeName = names.join(" ");
          }
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary")
  public async newSalaryAndUpdate(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        positionExecutive: string | null;
        positionExecutiveField?: string | null;
        positionArea?: string | null;
        positionType: string | null;
        positionLevel: string | null;
        commandId?: string | null;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        isLeave?: boolean;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        officerOrg?: string | null;
        dateStart?: Date | null;
        dateEnd?: Date | null;
        commandNo: string | null;
        commandYear: number | null;
        posNo: string | null;
        posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
        refId?: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      relations: ["commandType"],
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.data.map(async (item) => {
        const profile: any = await this.profileRepository.findOne({
          where: { id: item.profileId },
          // relations: ["roleKeycloaks"],
          relations: {
            roleKeycloaks: true,
            posType: true,
            posLevel: true,
          },
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }
        const posMaster: any = await this.posMasterRepository.findOne({
          where: {
            current_holderId: item.profileId,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: {
            orgRevision: true,
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        });

        const orgRevisionRef = posMaster ? posMaster.id : null;
        const orgRootRef = orgRevisionRef?.orgRoot ?? null;
        const orgChild1Ref = orgRevisionRef?.orgChild1 ?? null;
        const orgChild2Ref = orgRevisionRef?.orgChild2 ?? null;
        const orgChild3Ref = orgRevisionRef?.orgChild3 ?? null;
        const orgChild4Ref = orgRevisionRef?.orgChild4 ?? null;

        //ลบตำแหน่งที่รักษาการแทน
        const code = _command?.commandType?.code;
        if (code && ["C-PM-13"].includes(code)) {
          removePostMasterAct(profile.id);
        }

        let _commandYear = item.commandYear;
        if (item.commandYear) {
          _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
        }
        const dest_item = await this.salaryRepo.findOne({
          where: { profileId: item.profileId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        const meta = {
          order: dest_item == null ? 1 : dest_item.order + 1,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
        };
        if (item.isLeave != undefined && item.isLeave == true) {
          await CreatePosMasterHistoryOfficer(orgRevisionRef, req, "DELETE");
          await removeProfileInOrganize(profile.id, "OFFICER");
        }
        const clearProfile = await checkCommandType(String(item.commandId));
        const _null: any = null;
        if (clearProfile.status) {
          if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
            const delUserKeycloak = await deleteUser(profile.keycloak);
            if (delUserKeycloak) {
              // Task #228
              // profile.keycloak = _null;
              profile.roleKeycloaks = [];
              profile.isActive = false;
              profile.isDelete = true;
            }
          }
          profile.isLeave = item.isLeave;
          profile.leaveCommandId = item.commandId ?? _null;
          profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
          profile.leaveRemark = clearProfile.leaveRemark ?? _null;
          profile.leaveDate = item.commandDateAffect ?? _null;
          profile.leaveType = clearProfile.LeaveType ?? _null;
          //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
          // profile.position = _null;
          // profile.posTypeId = _null;
          // profile.posLevelId = _null;
          profile.leaveReason = item.leaveReason ?? _null;
          profile.dateLeave = item.dateLeave ?? _null;
          profile.amount = item.amount ?? _null;
          profile.amountSpecial = item.amountSpecial ?? _null;
          await this.profileRepository.save(profile, { data: req });

          // if (profile.id) {
          //   await this.keycloakAttributeService.clearOrgDnaAttributes(
          //     [profile.id],
          //     "PROFILE",
          //   );
          // }
        }
        Object.assign(data, { ...item, ...meta });
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });

        await this.salaryRepo.save(data, { data: req });
        setLogDataDiff(req, { before, after: data });
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history, { data: req });

        if (_command) {
          /*
          const command = await this.commandRepository.findOne({
            where: { id: item.commandId },
            relations: ["commandType"],
          });
          */
          if (["C-PM-15", "C-PM-16"].includes(_command.commandType.code)) {
            // ประวัติคำสั่งให้ช่วยราชการ
            const dataAssis = new ProfileAssistance();

            const metaAssis = {
              profileId: item.profileId,
              agency: item.officerOrg,
              dateStart: item.dateStart,
              dateEnd: item.dateEnd,
              commandNo: `${item.commandNo}/${_commandYear}`,
              commandName: item.commandName,
              refId: item.refId,
              refCommandDate: new Date(),
              commandId: item.commandId,
              createdUserId: req.user.sub,
              createdFullName: req.user.name,
              lastUpdateUserId: req.user.sub,
              lastUpdateFullName: req.user.name,
              createdAt: new Date(),
              lastUpdatedAt: new Date(),
              status: _command.commandType.code == "C-PM-15" ? "PENDING" : "DONE",
            };

            Object.assign(dataAssis, metaAssis);
            const historyAssis = new ProfileAssistanceHistory();
            Object.assign(historyAssis, { ...dataAssis, id: undefined });

            await this.assistanceRepository.save(dataAssis);
            historyAssis.profileAssistanceId = dataAssis.id;
            await this.assistanceHistoryRepository.save(historyAssis);
          }
          // Task #2190
          else if (_command.commandType.code == "C-PM-13") {
            let organizeName = "";
            if (orgRootRef) {
              const names = [
                orgChild4Ref?.orgChild4Name,
                orgChild3Ref?.orgChild3Name,
                orgChild2Ref?.orgChild2Name,
                orgChild1Ref?.orgChild1Name,
                orgRootRef?.orgRootName,
              ].filter(Boolean);
              organizeName = names.join(" ");
            }
          }
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee")
  public async newSalaryEmployeeAndUpdate(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        positionType: string | null;
        positionLevel: string | null;
        commandId?: string | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        officerOrg?: string | null;
        dateStart?: Date | null;
        dateEnd?: Date | null;
        commandNo: string | null;
        commandYear: number | null;
        posNo: string | null;
        posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
        refId?: string | null;
      }[];
    },
  ) {
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileEmployeeRepository.findOneBy({ id: item.profileId });
        if (!profile) {
          throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
        }

        const dest_item = await this.salaryRepo.findOne({
          where: { profileEmployeeId: item.profileId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();

        const meta = {
          order: dest_item == null ? 1 : dest_item.order + 1,
          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, {
          ...item,
          ...meta,
          profileEmployeeId: item.profileId,
          profileId: undefined,
        });
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });

        await this.salaryRepo.save(data, { data: req });
        setLogDataDiff(req, { before, after: data });
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history, { data: req });
        if (item.commandId) {
          const command = await this.commandRepository.findOne({
            where: { id: item.commandId },
            relations: ["commandType"],
          });
          if (
            command != null &&
            (command.commandType.code == "C-PM-15" || command.commandType.code == "C-PM-16")
          ) {
            // ประวัติคำสั่งให้ช่วยราชการ
            const dataAssis = new ProfileAssistance();

            const metaAssis = {
              profileId: item.profileId,
              agency: item.officerOrg,
              dateStart: item.dateStart,
              dateEnd: item.dateEnd,
              commandNo: `${item.commandNo}/${item.commandYear}`,
              commandName: item.commandName,
              refId: item.refId,
              refCommandDate: new Date(),
              commandId: item.commandId,
              createdUserId: req.user.sub,
              createdFullName: req.user.name,
              lastUpdateUserId: req.user.sub,
              lastUpdateFullName: req.user.name,
              createdAt: new Date(),
              lastUpdatedAt: new Date(),
            };

            Object.assign(dataAssis, metaAssis);
            const historyAssis = new ProfileAssistanceHistory();
            Object.assign(historyAssis, { ...dataAssis, id: undefined });

            await this.assistanceRepository.save(dataAssis);
            historyAssis.profileAssistanceId = dataAssis.id;
            await this.assistanceHistoryRepository.save(historyAssis);
          }
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-leave-discipline")
  public async newSalaryAndUpdateLeaveDiscipline(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        profileType?: string | null;
        isLeave: boolean | null;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        detail?: string | null;
        level?: string | null;
        unStigma?: string | null;
        commandId?: string | null;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        isGovernment?: boolean | null;
        commandNo: string | null;
        commandYear: number | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        posNo?: string | null;
        posNoAbb?: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      relations: ["commandType"],
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.data.map(async (item) => {
        let _commandYear = item.commandYear;
        if (item.commandYear) {
          _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
        }
        const orgRevision = await this.orgRevisionRepo.findOne({
          where: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
        });
        let orgRootRef = null;
        let orgChild1Ref = null;
        let orgChild2Ref = null;
        let orgChild3Ref = null;
        let orgChild4Ref = null;
        let profile;
        let isEmployee: boolean = false;
        let retireTypeName: string = "";
        // ขรก.
        if (item.profileType && item.profileType.trim().toUpperCase() == "OFFICER") {
          profile = await this.profileRepository.findOne({
            relations: [
              // "profileSalary",
              "posLevel",
              "posType",
              "current_holders",
              "current_holders.orgRoot",
              "current_holders.orgChild1",
              "current_holders.orgChild2",
              "current_holders.orgChild3",
              "current_holders.orgChild4",
              "current_holders.positions",
              "current_holders.positions.posExecutive",
              "roleKeycloaks",
            ],
            where: { id: item.profileId },
            // order: {
            //   profileSalary: {
            //     order: "DESC",
            //   },
            // },
          });
          if (!profile) {
            throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
          }
          const lastSalary = await this.salaryRepo.findOne({
            where: { profileId: item.profileId },
            select: ["order"],
            order: { order: "DESC" },
          });
          const nextOrder = lastSalary ? lastSalary.order + 1 : 1;
          //ลบตำแหน่งที่รักษาการแทน
          const code = _command?.commandType?.code;
          if (code && ["C-PM-19", "C-PM-20"].includes(code)) {
            removePostMasterAct(profile.id);
          }

          const orgRevisionRef =
            profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null;
          orgRootRef = orgRevisionRef?.orgRoot ?? null;
          orgChild1Ref = orgRevisionRef?.orgChild1 ?? null;
          orgChild2Ref = orgRevisionRef?.orgChild2 ?? null;
          orgChild3Ref = orgRevisionRef?.orgChild3 ?? null;
          orgChild4Ref = orgRevisionRef?.orgChild4 ?? null;

          let position =
            profile.current_holders
              .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
              ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
          // ประวัติตำแหน่ง
          const data = new ProfileSalary();
          data.posNumCodeSit = _posNumCodeSit;
          data.posNumCodeSitAbb = _posNumCodeSitAbb;
          const meta = {
            profileId: profile.id,
            commandId: item.commandId,
            position: profile.position,
            positionName: profile.position,
            positionType: profile?.posType?.posTypeName ?? null,
            positionLevel: profile?.posLevel?.posLevelName ?? null,
            positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
            amount: item.amount ? item.amount : null,
            positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
            amountSpecial: item.amountSpecial ? item.amountSpecial : null,
            mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
            // order:
            //   profile.profileSalary.length >= 0
            //     ? profile.profileSalary.length > 0
            //       ? profile.profileSalary[0].order + 1
            //       : 1
            //     : null,
            order: nextOrder,
            orgRoot: item.orgRoot,
            orgChild1: item.orgChild1,
            orgChild2: item.orgChild2,
            orgChild3: item.orgChild3,
            orgChild4: item.orgChild4,
            createdUserId: req.user.sub,
            createdFullName: req.user.name,
            lastUpdateUserId: req.user.sub,
            lastUpdateFullName: req.user.name,
            createdAt: new Date(),
            lastUpdatedAt: new Date(),
            dateGovernment: item.commandDateAffect ?? new Date(),
            isGovernment: item.isGovernment,
            commandNo: item.commandNo,
            commandYear: item.commandYear,
            posNo: item.posNo,
            posNoAbb: item.posNoAbb,
            commandDateAffect: item.commandDateAffect,
            commandDateSign: item.commandDateSign,
            commandCode: item.commandCode,
            commandName: item.commandName,
            remark: item.remark,
          };

          Object.assign(data, meta);
          const history = new ProfileSalaryHistory();
          Object.assign(history, { ...data, id: undefined });

          await this.salaryRepo.save(data);
          history.profileSalaryId = data.id;
          await this.salaryHistoryRepo.save(history);

          // ประวัติวินัย
          const dataDis = new ProfileDiscipline();

          const metaDis = {
            date: item.commandDateAffect,
            refCommandDate: item.commandDateSign,
            refCommandNo: `${item.commandNo}/${item.commandYear}`,
            refCommandId: item.commandId,
            createdUserId: req.user.sub,
            createdFullName: req.user.name,
            lastUpdateUserId: req.user.sub,
            lastUpdateFullName: req.user.name,
            createdAt: new Date(),
            lastUpdatedAt: new Date(),
          };

          Object.assign(dataDis, { ...item, ...metaDis });
          const historyDis = new ProfileDisciplineHistory();
          Object.assign(historyDis, { ...dataDis, id: undefined });

          await this.disciplineRepository.save(dataDis);
          historyDis.profileDisciplineId = dataDis.id;
          await this.disciplineHistoryRepository.save(historyDis);

          // ทะเบียนประวัติ
          if (item.isLeave != null) {
            const _profile = await this.profileRepository.findOne({
              where: { id: item.profileId },
              relations: ["roleKeycloaks"],
            });
            if (!_profile) {
              throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
            }
            const _null: any = null;
            _profile.isLeave = item.isLeave;
            _profile.leaveReason = item.leaveReason ?? _null;
            _profile.dateLeave = item.dateLeave ?? _null;
            _profile.lastUpdateUserId = req.user.sub;
            _profile.lastUpdateFullName = req.user.name;
            _profile.lastUpdatedAt = new Date();
            if (item.isLeave == true) {
              if (orgRevisionRef) {
                await CreatePosMasterHistoryOfficer(orgRevisionRef.id, req, "DELETE");
              }
              await removeProfileInOrganize(_profile.id, "OFFICER");
            }
            const clearProfile = await checkCommandType(String(item.commandId));
            if (clearProfile.status) {
              retireTypeName = clearProfile.retireTypeName ?? "";
              if (
                _profile.keycloak != null &&
                _profile.keycloak != "" &&
                _profile.isDelete === false
              ) {
                const delUserKeycloak = await deleteUser(_profile.keycloak);
                if (delUserKeycloak) {
                  // Task #228
                  // _profile.keycloak = _null;
                  _profile.roleKeycloaks = [];
                  _profile.isActive = false;
                  _profile.isDelete = true;
                }
              }
              _profile.leaveCommandId = item.commandId ?? _null;
              _profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
              _profile.leaveRemark = clearProfile.leaveRemark ?? _null;
              _profile.leaveDate = item.commandDateAffect ?? _null;
              _profile.leaveType = clearProfile.LeaveType ?? _null;
              //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
              // _profile.position = _null;
              // _profile.posTypeId = _null;
              // _profile.posLevelId = _null;
            }
            await this.profileRepository.save(_profile);
            // if (_profile.id) {
            //   await this.keycloakAttributeService.clearOrgDnaAttributes(
            //     [_profile.id],
            //     "PROFILE",
            //   );
            // }
          }
        }
        // ลูกจ้าง
        else {
          isEmployee = true;
          profile = await this.profileEmployeeRepository.findOne({
            relations: [
              // "profileSalary",
              "posLevel",
              "posType",
              "current_holders",
              "current_holders.orgRoot",
              "current_holders.orgChild1",
              "current_holders.orgChild2",
              "current_holders.orgChild3",
              "current_holders.orgChild4",
              "roleKeycloaks",
            ],
            where: { id: item.profileId },
            // order: {
            //   profileSalary: {
            //     order: "DESC",
            //   },
            // },
          });
          if (!profile) {
            throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
          }
          const lastSalary = await this.salaryRepo.findOne({
            where: { profileEmployeeId: item.profileId },
            select: ["order"],
            order: { order: "DESC" },
          });
          const nextOrder = lastSalary ? lastSalary.order + 1 : 1;
          const orgRevisionRef =
            profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null;
          orgRootRef = orgRevisionRef?.orgRoot ?? null;
          orgChild1Ref = orgRevisionRef?.orgChild1 ?? null;
          orgChild2Ref = orgRevisionRef?.orgChild2 ?? null;
          orgChild3Ref = orgRevisionRef?.orgChild3 ?? null;
          orgChild4Ref = orgRevisionRef?.orgChild4 ?? null;

          // ประวัติตำแหน่ง
          const data = new ProfileSalary();
          data.posNumCodeSit = _posNumCodeSit;
          data.posNumCodeSitAbb = _posNumCodeSitAbb;
          const meta = {
            profileEmployeeId: profile.id,
            commandId: item.commandId,
            position: profile.position,
            positionName: profile.position,
            positionType: profile?.posType?.posTypeName ?? null,
            positionLevel:
              profile?.posType && profile?.posLevel
                ? `${profile?.posType?.posTypeShortName} ${profile?.posLevel?.posLevelName}`
                : null,
            amount: item.amount ? item.amount : null,
            positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
            mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
            // order:
            //   profile.profileSalary.length >= 0
            //     ? profile.profileSalary.length > 0
            //       ? profile.profileSalary[0].order + 1
            //       : 1
            //     : null,
            order: nextOrder,
            orgRoot: item.orgRoot,
            orgChild1: item.orgChild1,
            orgChild2: item.orgChild2,
            orgChild3: item.orgChild3,
            orgChild4: item.orgChild4,
            createdUserId: req.user.sub,
            createdFullName: req.user.name,
            lastUpdateUserId: req.user.sub,
            lastUpdateFullName: req.user.name,
            createdAt: new Date(),
            lastUpdatedAt: new Date(),
            dateGovernment: item.commandDateAffect ?? new Date(),
            isGovernment: item.isGovernment,
            commandNo: item.commandNo,
            commandYear: item.commandYear,
            posNo: item.posNo,
            posNoAbb: item.posNoAbb,
            commandDateAffect: item.commandDateAffect,
            commandDateSign: item.commandDateSign,
            commandCode: item.commandCode,
            commandName: item.commandName,
            remark: item.remark,
          };

          Object.assign(data, meta);
          const history = new ProfileSalaryHistory();
          Object.assign(history, { ...data, id: undefined });

          await this.salaryRepo.save(data);
          history.profileSalaryId = data.id;
          await this.salaryHistoryRepo.save(history);

          // ประวัติวินัย
          const dataDis = new ProfileDiscipline();

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

          Object.assign(dataDis, {
            ...item,
            ...metaDis,
            date: item.commandDateAffect,
            refCommandDate: item.commandDateSign,
            refCommandNo: item.commandNo,
            profileEmployeeId: item.profileId,
            profileId: undefined,
          });
          const historyDis = new ProfileDisciplineHistory();
          Object.assign(historyDis, { ...dataDis, id: undefined });

          await this.disciplineRepository.save(dataDis);
          historyDis.profileDisciplineId = dataDis.id;
          await this.disciplineHistoryRepository.save(historyDis);

          // ทะเบียนประวัติ
          if (item.isLeave != null) {
            const _profile = await this.profileEmployeeRepository.findOne({
              where: { id: item.profileId },
              relations: ["roleKeycloaks"],
            });
            if (!_profile) {
              throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
            }
            const _null: any = null;
            _profile.isLeave = item.isLeave;
            _profile.leaveReason = item.leaveReason ?? _null;
            _profile.dateLeave = item.dateLeave ?? _null;
            _profile.lastUpdateUserId = req.user.sub;
            _profile.lastUpdateFullName = req.user.name;
            _profile.lastUpdatedAt = new Date();
            if (item.isLeave == true) {
              // บันทึกประวัติก่อนลบตำแหน่ง
              const curRevision = await this.orgRevisionRepo.findOne({
                where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
              });
              if (curRevision) {
                const curPosMaster = await this.employeePosMasterRepository.findOne({
                  where: {
                    current_holderId: _profile.id,
                    orgRevisionId: curRevision.id,
                  },
                });
                if (curPosMaster) {
                  await CreatePosMasterHistoryEmployee(curPosMaster.id, req, "DELETE");
                }
              }
              await removeProfileInOrganize(_profile.id, "EMPLOYEE");
            }
            const clearProfile = await checkCommandType(String(item.commandId));
            if (clearProfile.status) {
              retireTypeName = clearProfile.retireTypeName ?? "";
              if (
                _profile.keycloak != null &&
                _profile.keycloak != "" &&
                _profile.isDelete === false
              ) {
                const delUserKeycloak = await deleteUser(_profile.keycloak);
                if (delUserKeycloak) {
                  // Task #228
                  // _profile.keycloak = _null;
                  _profile.roleKeycloaks = [];
                  _profile.isActive = false;
                  _profile.isDelete = true;
                }
              }
              _profile.leaveCommandId = item.commandId ?? _null;
              _profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
              _profile.leaveRemark = clearProfile.leaveRemark ?? _null;
              _profile.leaveDate = item.commandDateAffect ?? _null;
              _profile.leaveType = clearProfile.LeaveType ?? _null;
              //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
              // _profile.position = _null;
              // _profile.posTypeId = _null;
              // _profile.posLevelId = _null;
            }
            await this.profileEmployeeRepository.save(_profile);
            // if (_profile.id) {
            //   await this.keycloakAttributeService.clearOrgDnaAttributes(
            //     [_profile.id],
            //     "PROFILE_EMPLOYEE",
            //   );
            // }
          }
        }
        // Task #2190
        if (_command && ["C-PM-19", "C-PM-20"].includes(_command.commandType.code)) {
          let organizeName = "";
          if (orgRootRef) {
            const names = [
              orgChild4Ref?.orgChild4Name,
              orgChild3Ref?.orgChild3Name,
              orgChild2Ref?.orgChild2Name,
              orgChild1Ref?.orgChild1Name,
              orgRootRef?.orgRootName,
            ].filter(Boolean);
            organizeName = names.join(" ");
          }
          let _posLevelName: string = !isEmployee
            ? `${profile.posLevel?.posLevelName}`
            : `${profile.posType?.posTypeName} ${profile.posLevel?.posLevelName}`;
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee-leave-discipline")
  public async newSalaryEmployeeAndUpdateLeaveDiscipline(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        isLeave: boolean | null;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        detail?: string | null;
        level?: string | null;
        unStigma?: string | null;
        commandId?: string | null;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        isGovernment?: boolean | null;
        commandNo: string | null;
        commandYear: number | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
        orgRoot?: string | null;
        orgChild1?: string | null;
        orgChild2?: string | null;
        orgChild3?: string | null;
        orgChild4?: string | null;
        posNo?: string | null;
        posNoAbb?: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileEmployeeRepository.findOne({
          relations: [
            // "profileSalary",
            "posLevel",
            "posType",
            "current_holders",
            "current_holders.orgRoot",
            "current_holders.orgChild1",
            "current_holders.orgChild2",
            "current_holders.orgChild3",
            "current_holders.orgChild4",
            "roleKeycloaks",
          ],
          where: { id: item.profileId },
          // order: {
          //   profileSalary: {
          //     order: "DESC",
          //   },
          // },
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }
        const lastSalary = await this.salaryRepo.findOne({
          where: { profileEmployeeId: item.profileId },
          select: ["order"],
          order: { order: "DESC" },
        });
        const nextOrder = lastSalary ? lastSalary.order + 1 : 1;
        let _commandYear = item.commandYear;
        if (item.commandYear) {
          _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
        }
        // const orgRevision = await this.orgRevisionRepo.findOne({
        //   where: {
        //     orgRevisionIsCurrent: true,
        //     orgRevisionIsDraft: false,
        //   },
        // });
        // const orgRevisionRef =
        //   profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null;
        // const orgRootRef = orgRevisionRef?.orgRoot ?? null;
        // const orgChild1Ref = orgRevisionRef?.orgChild1 ?? null;
        // const orgChild2Ref = orgRevisionRef?.orgChild2 ?? null;
        // const orgChild3Ref = orgRevisionRef?.orgChild3 ?? null;
        // const orgChild4Ref = orgRevisionRef?.orgChild4 ?? null;
        // const shortName =
        //   !profile.current_holders || profile.current_holders.length == 0
        //     ? null
        //     : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null &&
        //         profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        //           ?.orgChild4 != null
        //       ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4.orgChild4ShortName}`
        //       : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null &&
        //           profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        //             ?.orgChild3 != null
        //         ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3.orgChild3ShortName}`
        //         : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null &&
        //             profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        //               ?.orgChild2 != null
        //           ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2.orgChild2ShortName}`
        //           : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) !=
        //                 null &&
        //               profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        //                 ?.orgChild1 != null
        //             ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1.orgChild1ShortName}`
        //             : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) !=
        //                   null &&
        //                 profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
        //                   ?.orgRoot != null
        //               ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot.orgRootShortName}`
        //               : null;
        // const posNo = `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`;
        // let position =
        //   profile.current_holders
        //     .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
        //     ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
        // ประวัติตำแหน่ง
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        const meta = {
          profileEmployeeId: profile.id,
          commandId: item.commandId,
          position: profile.position,
          positionType: profile?.posType?.posTypeName ?? null,
          positionLevel:
            profile?.posType && profile?.posLevel
              ? `${profile?.posType?.posTypeShortName} ${profile?.posLevel?.posLevelName}`
              : null,
          amount: item.amount ? item.amount : null,
          amountSpecial: item.amountSpecial ? item.amountSpecial : null,
          positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
          mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
          // order:
          //   profile.profileSalary.length >= 0
          //     ? profile.profileSalary.length > 0
          //       ? profile.profileSalary[0].order + 1
          //       : 1
          //     : null,
          order: nextOrder,
          orgRoot: item.orgRoot,
          orgChild1: item.orgChild1,
          orgChild2: item.orgChild2,
          orgChild3: item.orgChild3,
          orgChild4: item.orgChild4,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          dateGovernment: item.commandDateAffect ?? new Date(),
          isGovernment: item.isGovernment,
          commandNo: item.commandNo,
          commandYear: item.commandYear,
          posNo: item.posNo,
          posNoAbb: item.posNoAbb,
          commandDateAffect: item.commandDateAffect,
          commandDateSign: item.commandDateSign,
          commandCode: item.commandCode,
          commandName: item.commandName,
          remark: item.remark,
        };

        Object.assign(data, meta);
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });

        await this.salaryRepo.save(data);
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history);

        // ประวัติวินัย
        const dataDis = new ProfileDiscipline();

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

        Object.assign(dataDis, {
          ...item,
          ...metaDis,
          date: item.commandDateAffect,
          refCommandDate: item.commandDateSign,
          refCommandNo: `${item.commandNo}/${item.commandYear}`,
          refCommandId: item.commandId,
          profileEmployeeId: item.profileId,
          profileId: undefined,
        });
        const historyDis = new ProfileDisciplineHistory();
        Object.assign(historyDis, { ...dataDis, id: undefined });

        await this.disciplineRepository.save(dataDis);
        historyDis.profileDisciplineId = dataDis.id;
        await this.disciplineHistoryRepository.save(historyDis);

        // ทะเบียนประวัติ
        if (item.isLeave != null) {
          const _profile = await this.profileEmployeeRepository.findOne({
            where: { id: item.profileId },
            relations: ["roleKeycloaks"],
          });
          if (!_profile) {
            throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
          }
          const _null: any = null;
          _profile.isLeave = item.isLeave;
          _profile.leaveReason = item.leaveReason ?? _null;
          _profile.dateLeave = item.dateLeave ?? _null;
          _profile.lastUpdateUserId = req.user.sub;
          _profile.lastUpdateFullName = req.user.name;
          _profile.lastUpdatedAt = new Date();
          if (item.isLeave == true) {
            // บันทึกประวัติก่อนลบตำแหน่ง
            const curRevision = await this.orgRevisionRepo.findOne({
              where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
            });
            if (curRevision) {
              const curPosMaster = await this.employeePosMasterRepository.findOne({
                where: {
                  current_holderId: _profile.id,
                  orgRevisionId: curRevision.id,
                },
              });
              if (curPosMaster) {
                await CreatePosMasterHistoryEmployee(curPosMaster.id, req, "DELETE");
              }
            }
            await removeProfileInOrganize(_profile.id, "EMPLOYEE");
          }
          const clearProfile = await checkCommandType(String(item.commandId));
          if (clearProfile.status) {
            if (
              _profile.keycloak != null &&
              _profile.keycloak != "" &&
              _profile.isDelete === false
            ) {
              const delUserKeycloak = await deleteUser(_profile.keycloak);
              if (delUserKeycloak) {
                // Task #228
                // _profile.keycloak = _null;
                _profile.roleKeycloaks = [];
                _profile.isActive = false;
                _profile.isDelete = true;
              }
            }
            _profile.leaveCommandId = item.commandId ?? _null;
            _profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
            _profile.leaveRemark = clearProfile.leaveRemark ?? _null;
            _profile.leaveDate = item.commandDateAffect ?? _null;
            _profile.leaveType = clearProfile.LeaveType ?? _null;
            //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
            // _profile.position = _null;
            // _profile.posTypeId = _null;
            // _profile.posLevelId = _null;
          }
          await this.profileEmployeeRepository.save(_profile);

          // if (_profile.id) {
          //   await this.keycloakAttributeService.clearOrgDnaAttributes(
          //     [_profile.id],
          //     "PROFILE_EMPLOYEE",
          //   );
          // }
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-probation")
  public async newSalaryAndUpdateLeaveDisciplinefgh(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        commandId?: string | null;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        commandNo: string | null;
        commandYear: number | null;
        // posNo: string | null;
        // posNoAbb: string | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        positionName?: string | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    let commandType: any = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      commandType = await this.commandTypeRepository.findOne({
        select: { code: true },
        where: { id: _command.commandTypeId },
      });
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    // const leaveType = await this.leaveType.findOne({
    //   select: { id: true, limit: true, code: true },
    //   where: { code: "LV-005" }
    // });
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          relations: [
            "posType",
            "posLevel",
            "current_holders",
            "current_holders.orgRoot",
            "current_holders.orgChild1",
            "current_holders.orgChild2",
            "current_holders.orgChild3",
            "current_holders.orgChild4",
          ],
          where: { id: item.profileId },
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }
        const lastSalary = await this.salaryRepo.findOne({
          where: { profileId: item.profileId },
          select: ["order"],
          order: { order: "DESC" },
        });
        const nextOrder = lastSalary ? lastSalary.order + 1 : 1;
        const orgRevision = await this.orgRevisionRepo.findOne({
          where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        });

        const orgRevisionRef =
          profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null;
        const shortName =
          orgRevisionRef?.orgChild4?.orgChild4ShortName ??
          orgRevisionRef?.orgChild3?.orgChild3ShortName ??
          orgRevisionRef?.orgChild2?.orgChild2ShortName ??
          orgRevisionRef?.orgChild1?.orgChild1ShortName ??
          orgRevisionRef?.orgRoot?.orgRootShortName ??
          null;
        const posNo = orgRevisionRef?.posMasterNo?.toString() ?? null;
        let position =
          profile.current_holders
            .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
            ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
        // ประวัติตำแหน่ง
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        const meta = {
          profileId: item.profileId,
          commandId: item.commandId,
          positionName: profile.position,
          positionType: profile?.posType?.posTypeName ?? null,
          positionLevel: profile?.posLevel?.posLevelName ?? null,
          positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
          amount: item.amount ? item.amount : null,
          amountSpecial: item.amountSpecial ? item.amountSpecial : null,
          positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
          mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
          order: nextOrder,
          orgRoot: orgRevisionRef?.orgRoot?.orgRootName ?? null,
          orgChild1: orgRevisionRef?.orgChild1?.orgChild1Name ?? null,
          orgChild2: orgRevisionRef?.orgChild2?.orgChild2Name ?? null,
          orgChild3: orgRevisionRef?.orgChild3?.orgChild3Name ?? null,
          orgChild4: orgRevisionRef?.orgChild4?.orgChild4Name ?? null,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          commandNo: item.commandNo,
          commandYear: item.commandYear,
          posNo: posNo,
          posNoAbb: shortName,
          commandDateAffect: item.commandDateAffect,
          commandDateSign: item.commandDateSign,
          commandCode: item.commandCode,
          commandName: item.commandName,
          remark: item.remark,
        };
        Object.assign(data, meta);
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });

        await this.salaryRepo.save(data);
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history);
      }),
    );

    if (commandType && String(commandType.code) == "C-PM-11") {
      const profileIds = body.data.map((x) => x.profileId);
      await this.profileRepository.update({ id: In(profileIds) }, { isProbation: false });
      // // Task #2304 อัปเดตจำนวนสิทธิ์การลา เมื่อผ่านทดลองงานฯ
      // if (leaveType != null) {
      //   await Promise.all(
      //     body.data.map((item) =>
      //       new CallAPI().PutData(req, `/leave-beginning/schedule`, {
      //         profileId: item.profileId,
      //         leaveTypeId: leaveType.id,
      //         leaveYear: item.commandYear,
      //         leaveDays: leaveType.limit,
      //         leaveDaysUsed: 0,
      //         leaveCount: 0,
      //         beginningLeaveDays: 0,
      //         beginningLeaveCount: 0,
      //       })
      //       .then(() => {})
      //       .catch(() => {})
      //     )
      //   );
      // }
    }
    return new HttpSuccess();
  }

  @Post("excexute/salary-probation-leave")
  async ExecuteCommand12Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        commandId?: string | null;
        amount?: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        isGovernment?: boolean | null;
        commandNo: string | null;
        commandYear: number | null;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          relations: [
            // "profileSalary",
            "posType",
            "posLevel",
            "current_holders",
            "current_holders.orgRoot",
            "current_holders.orgChild1",
            "current_holders.orgChild2",
            "current_holders.orgChild3",
            "current_holders.orgChild4",
            "current_holders.positions",
            "current_holders.positions.posExecutive",
          ],
          where: { id: item.profileId },
          // order: {
          //   profileSalary: {
          //     order: "DESC",
          //   },
          // },
        });
        if (!profile) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
        }
        const lastSalary = await this.salaryRepo.findOne({
          where: { profileId: item.profileId },
          select: ["order"],
          order: { order: "DESC" },
        });
        const nextOrder = lastSalary ? lastSalary.order + 1 : 1;
        let _commandYear = item.commandYear;
        if (item.commandYear) {
          _commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
        }
        const _profile = await this.profileRepository.findOne({
          where: { id: item.profileId },
          relations: ["roleKeycloaks"],
        });
        if (!_profile) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
        }
        let dateLeave_: any = item.commandDateAffect;
        _profile.isLeave = true;
        _profile.leaveReason =
          "คำสั่งให้ข้าราชการออกจากราชการเพราะผลการทดลองปฏิบัติหน้าที่ราชการต่ำกว่ามาตรฐานที่กำหนด";
        _profile.dateLeave = dateLeave_;
        _profile.lastUpdateUserId = req.user.sub;
        _profile.lastUpdateFullName = req.user.name;
        _profile.lastUpdatedAt = new Date();

        const orgRevision = await this.orgRevisionRepo.findOne({
          where: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
        });
        const orgRevisionRef =
          profile?.current_holders?.find((x) => x.orgRevisionId == orgRevision?.id) ?? null;
        const orgRootRef = orgRevisionRef?.orgRoot ?? null;
        const orgChild1Ref = orgRevisionRef?.orgChild1 ?? null;
        const orgChild2Ref = orgRevisionRef?.orgChild2 ?? null;
        const orgChild3Ref = orgRevisionRef?.orgChild3 ?? null;
        const orgChild4Ref = orgRevisionRef?.orgChild4 ?? null;
        const shortName =
          !profile.current_holders || profile.current_holders.length == 0
            ? null
            : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null &&
                profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
                  ?.orgChild4 != null
              ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild4.orgChild4ShortName}`
              : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null &&
                  profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
                    ?.orgChild3 != null
                ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild3.orgChild3ShortName}`
                : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) != null &&
                    profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
                      ?.orgChild2 != null
                  ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild2.orgChild2ShortName}`
                  : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) !=
                        null &&
                      profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
                        ?.orgChild1 != null
                    ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgChild1.orgChild1ShortName}`
                    : profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id) !=
                          null &&
                        profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)
                          ?.orgRoot != null
                      ? `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.orgRoot.orgRootShortName}`
                      : null;
        const posNo = `${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`;
        let position =
          profile.current_holders
            .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
            ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
        const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
          profileId: item.profileId,
          commandId: item.commandId,
          positionName: profile.position,
          positionType: profile?.posType?.posTypeName ?? null,
          positionLevel: profile?.posLevel?.posLevelName ?? null,
          positionExecutive: position?.posExecutive?.posExecutiveName ?? null,
          amount: item.amount ? item.amount : null,
          amountSpecial: item.amountSpecial ? item.amountSpecial : null,
          positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
          mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
          // order:
          //   profile.profileSalary.length >= 0
          //     ? profile.profileSalary.length > 0
          //       ? profile.profileSalary[0].order + 1
          //       : 1
          //     : null,
          order: nextOrder,
          orgRoot: orgRootRef?.orgRootName ?? null,
          orgChild1: orgChild1Ref?.orgChild1Name ?? null,
          orgChild2: orgChild2Ref?.orgChild2Name ?? null,
          orgChild3: orgChild3Ref?.orgChild3Name ?? null,
          orgChild4: orgChild4Ref?.orgChild4Name ?? null,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          dateGovernment: item.commandDateAffect ?? new Date(),
          isGovernment: item.isGovernment,
          commandNo: item.commandNo,
          commandYear: item.commandYear,
          posNo: posNo,
          posNoAbb: shortName,
          commandDateAffect: item.commandDateAffect,
          commandDateSign: item.commandDateSign,
          commandCode: item.commandCode,
          commandName: item.commandName,
          remark: item.remark,
          posNumCodeSit: _posNumCodeSit,
          posNumCodeSitAbb: _posNumCodeSitAbb,
        });
        if (orgRevisionRef) {
          await CreatePosMasterHistoryOfficer(orgRevisionRef.id, req, "DELETE");
        }
        await removeProfileInOrganize(profile.id, "OFFICER");
        const clearProfile = await checkCommandType(String(item.commandId));
        const _null: any = null;
        if (clearProfile.status) {
          if (_profile.keycloak != null && _profile.keycloak != "" && _profile.isDelete === false) {
            const delUserKeycloak = await deleteUser(_profile.keycloak);
            if (delUserKeycloak) {
              // Task #228
              // _profile.keycloak = _null;
              _profile.roleKeycloaks = [];
              _profile.isActive = false;
              _profile.isDelete = true;
            }
          }
          _profile.leaveCommandId = item.commandId ?? _null;
          _profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
          _profile.leaveRemark = clearProfile.leaveRemark ?? _null;
          _profile.leaveDate = item.commandDateAffect ?? _null;
          _profile.leaveType = clearProfile.LeaveType ?? _null;
          //ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
          // _profile.position = _null;
          // _profile.posTypeId = _null;
          // _profile.posLevelId = _null;
        }
        await Promise.all([
          this.profileRepository.save(_profile),
          this.salaryRepo.save(profileSalary),
        ]);

        // if (profile.id) {
        //   await this.keycloakAttributeService.clearOrgDnaAttributes(
        //     [profile.id],
        //     "PROFILE",
        //   );
        // }

        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...profileSalary, id: undefined });
        history.profileSalaryId = profileSalary.id;
        await this.salaryHistoryRepo.save(history);
        // Task #2190
        let organizeName = "";
        if (orgRootRef) {
          const names = [
            orgChild4Ref?.orgChild4Name,
            orgChild3Ref?.orgChild3Name,
            orgChild2Ref?.orgChild2Name,
            orgChild1Ref?.orgChild1Name,
            orgRootRef?.orgRootName,
          ].filter(Boolean);
          organizeName = names.join(" ");
        }
      }),
    );
    return new HttpSuccess();
  }

  @Post("excexute/create-officer-profile")
  public async CreateOfficeProfileExcecute(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        bodyProfile: CreateProfileAllFields;
        bodyEducations?: CreateProfileEducation[];
        bodyCertificates?: CreateProfileCertificate[];
        bodySalarys?: CreateProfileSalary | null;
        bodyPosition?: {
          posmasterId: string;
          positionId: string;
          positionName: string;
          posTypeId: string;
          posLevelId: string;
          posExecutiveId: string | null;
          positionField: string | null;
          positionExecutiveField: string | null;
          positionArea: string | null;
        } | null;
        bodyMarry?: {
          marry?: boolean | null;
          marryPrefix?: string | null;
          marryFirstName?: string | null;
          marryLastName?: string | null;
          marryOccupation?: string | null;
          marryNationality?: string | null;
        } | null;
        bodyFather?: {
          fatherPrefix?: string | null;
          fatherFirstName?: string | null;
          fatherLastName?: string | null;
          fatherOccupation?: string | null;
          fatherNationality?: string | null;
        } | null;
        bodyMother?: {
          motherPrefix?: string | null;
          motherFirstName?: string | null;
          motherLastName?: string | null;
          motherOccupation?: string | null;
          motherNationality?: string | null;
        } | null;
      }[];
    },
  ) {
    console.log("[Excexute/CreateOfficerProfile] Starting CreateOfficeProfileExcecute");
    console.log("[Excexute/CreateOfficerProfile] Request body count:", body.data?.length);
    const roleKeycloak = await this.roleKeycloakRepo.findOne({
      where: { name: Like("USER") },
    });
    console.log("[Excexute/CreateOfficerProfile] roleKeycloak found:", !!roleKeycloak);
    const list = await getRoles();
    console.log("[Excexute/CreateOfficerProfile] Roles list retrieved, length:", Array.isArray(list) ? list.length : "not array");
    if (!Array.isArray(list)) {
      console.error("[Excexute/CreateOfficerProfile] Failed - Cannot get role(s) data from the server");
      throw new Error("Failed. Cannot get role(s) data from the server.");
    }
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    console.log("[Excexute/CreateOfficerProfile] Getting command data");
    const _command = await this.commandRepository.findOne({
      where: { id: body.data.find((x) => x.bodySalarys?.commandId)?.bodySalarys?.commandId ?? "" },
    });
    console.log("[Excexute/CreateOfficerProfile] Command found:", !!_command, "isBangkok:", _command?.isBangkok);
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        console.log("[Excexute/CreateOfficerProfile] Setting position codes for OFFICE");
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
        console.log("[Excexute/CreateOfficerProfile] OFFICE position codes set:", _posNumCodeSit, _posNumCodeSitAbb);
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        console.log("[Excexute/CreateOfficerProfile] Setting position codes for BANGKOK");
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
        console.log("[Excexute/CreateOfficerProfile] BANGKOK position codes set:", _posNumCodeSit, _posNumCodeSitAbb);
      } else {
        console.log("[Excexute/CreateOfficerProfile] Setting position codes from admin profile");
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
        console.log("[Excexute/CreateOfficerProfile] Admin profile position codes set:", _posNumCodeSit, _posNumCodeSitAbb);
      }
    }
    const before = null;
    const meta = {
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
    };
    console.log("[Excexute/CreateOfficerProfile] Starting to process", body.data.length, "profile(s)");
    await Promise.all(
      body.data.map(async (item, index) => {
        console.log("[Excexute/CreateOfficerProfile] Processing item", index + 1, "of", body.data.length);
        const _null: any = null;
        if (item.bodyProfile.posLevelId === "") item.bodyProfile.posLevelId = null;
        if (item.bodyProfile.posTypeId === "") item.bodyProfile.posTypeId = null;
        if (
          item.bodyProfile.posLevelId &&
          !(await this.posLevelRepo.findOneBy({ id: item.bodyProfile.posLevelId }))
        ) {
          console.error("[Excexute/CreateOfficerProfile] ไม่พบข้อมูลระดับตำแหน่งนี้ posLevelId:", item.bodyProfile.posLevelId);
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้");
        }
        if (
          item.bodyProfile.posTypeId &&
          !(await this.posTypeRepo.findOneBy({ id: item.bodyProfile.posTypeId }))
        ) {
          console.error("[Excexute/CreateOfficerProfile] ไม่พบข้อมูลประเภทตำแหน่งนี้ posTypeId:", item.bodyProfile.posTypeId);
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
        }

        console.log("[Excexute/CreateOfficerProfile] Processing citizenId:", item.bodyProfile.citizenId);
        let registrationProvinceId = await this.provinceRepo.findOneBy({
          id: item.bodyProfile.registrationProvinceId ?? "",
        });
        let registrationDistrictId = await this.districtRepo.findOneBy({
          id: item.bodyProfile.registrationDistrictId ?? "",
        });
        let registrationSubDistrictId = await this.subDistrictRepo.findOneBy({
          id: item.bodyProfile.registrationSubDistrictId ?? "",
        });
        let currentProvinceId = await this.provinceRepo.findOneBy({
          id: item.bodyProfile.currentProvinceId ?? "",
        });
        let currentDistrictId = await this.districtRepo.findOneBy({
          id: item.bodyProfile.currentDistrictId ?? "",
        });
        let currentSubDistrictId = await this.subDistrictRepo.findOneBy({
          id: item.bodyProfile.currentSubDistrictId ?? "",
        });
        console.log("[Excexute/CreateOfficerProfile] Address validation completed");

        let _dateRetire =
          item.bodyProfile.birthDate == null
            ? _null
            : calculateRetireDate(item.bodyProfile.birthDate);
        let _dateRetireLaw =
          item.bodyProfile.birthDate == null
            ? _null
            : calculateRetireLaw(item.bodyProfile.birthDate);

        let userKeycloakId: any;
        let result: any;
        console.log("[Excexute/CreateOfficerProfile] Checking Keycloak user for citizenId:", item.bodyProfile.citizenId);
        const checkUser = await getUserByUsername(item.bodyProfile.citizenId);
        console.log("[Excexute/CreateOfficerProfile] Keycloak user exists:", checkUser.length > 0);
        if (checkUser.length == 0) {
          console.log("[Excexute/CreateOfficerProfile] Creating new Keycloak user");
          let password = item.bodyProfile.citizenId;
          if (item.bodyProfile.birthDate != null) {
            const _date = new Date(item.bodyProfile.birthDate.toDateString())
              .getDate()
              .toString()
              .padStart(2, "0");
            const _month = (new Date(item.bodyProfile.birthDate.toDateString()).getMonth() + 1)
              .toString()
              .padStart(2, "0");
            const _year = new Date(item.bodyProfile.birthDate.toDateString()).getFullYear() + 543;
            password = `${_date}${_month}${_year}`;
          }
          console.log("[Excexute/CreateOfficerProfile] Calling createUser for:", item.bodyProfile.citizenId);
          console.log("[Excexute/CreateOfficerProfile] createUser data - firstName:", item.bodyProfile.firstName, "lastName:", item.bodyProfile.lastName);
          // กรอง "." ออกจาก firstName ก่อนส่งไป keycloak (ป้องกัน . หรืออักขระอื่นๆ)
          const sanitizedFirstName = item.bodyProfile.firstName?.replace(/\./g, "") ?? "";
          userKeycloakId = await createUser(item.bodyProfile.citizenId, password, {
            firstName: sanitizedFirstName,
            lastName: item.bodyProfile.lastName,
          });
          if (userKeycloakId && typeof userKeycloakId === "object" && userKeycloakId.errorMessage) {
            console.error("[Excexute/CreateOfficerProfile] createUser FAILED - field:", userKeycloakId.field, "errorMessage:", userKeycloakId.errorMessage, "params:", userKeycloakId.params);
            throw new HttpError(HttpStatus.BAD_REQUEST, `Keycloak validation failed: ${userKeycloakId.field} - ${userKeycloakId.errorMessage}`);
          }
          console.log("[Excexute/CreateOfficerProfile] User created in Keycloak, userKeycloakId:", userKeycloakId);
          result = await addUserRoles(
            userKeycloakId,
            list
              .filter((v) => v.name === "USER")
              .map((x) => ({
                id: x.id,
                name: x.name,
              })),
          );
          console.log("[Excexute/CreateOfficerProfile] USER role assigned to new user, result:", result);
        } else {
          console.log("[Excexute/CreateOfficerProfile] Updating existing Keycloak user");
          userKeycloakId = checkUser[0].id;
          console.log("[Excexute/CreateOfficerProfile] Existing userKeycloakId:", userKeycloakId);
          const rolesData = await getRoleMappings(userKeycloakId);
          if (rolesData) {
            const _delRole = rolesData.map((x: any) => ({
              id: x.id,
              name: x.name,
            }));
            console.log("[Excexute/CreateOfficerProfile] Removing old roles:", _delRole.length);
            await removeUserRoles(userKeycloakId, _delRole);
          }
          result = await addUserRoles(
            userKeycloakId,
            list
              .filter((v) => v.name === "USER")
              .map((x) => ({
                id: x.id,
                name: x.name,
              })),
          );
          console.log("[Excexute/CreateOfficerProfile] USER role assigned to existing user");
        }

        let profile: any = await this.profileRepository.findOne({
          where: { citizenId: item.bodyProfile.citizenId /*, isActive: true */ },
          relations: ["roleKeycloaks", "profileInsignias", "profileAvatars"],
        });
        console.log("[Excexute/CreateOfficerProfile] Profile found:", !!profile, "for citizenId:", item.bodyProfile.citizenId);
        let _oldInsigniaIds: string[] = [];
        let _oldSalaries: any[] = [];
        //ลูกจ้างประจำ หรือ บุคคลภายนอก
        if (!profile) {
          console.log("[Excexute/CreateOfficerProfile] No existing profile found, creating new profile");
          //กรณีลูกจ้างประจำมาสอบเป็นข้าราชการ ต้อง update สถานะโปรไฟล์เดิม
          let profileEmployee: any = await this.profileEmployeeRepository.findOne({
            where: { citizenId: item.bodyProfile.citizenId },
            relations: ["profileInsignias", "roleKeycloaks"],
          });
          console.log("[Excexute/CreateOfficerProfile] Employee profile found:", !!profileEmployee);
          if (profileEmployee) {
            console.log("[Excexute/CreateOfficerProfile] Converting employee profile to officer profile");
            const _order = await this.salaryRepo.findOne({
              where: { profileEmployeeId: profileEmployee.id },
              order: { order: "DESC" },
            });
            const profileEmpSalary = new ProfileSalary();
            profileEmpSalary.posNumCodeSit = _posNumCodeSit;
            profileEmpSalary.posNumCodeSitAbb = _posNumCodeSitAbb;
            profileEmpSalary.order = _order == null ? 1 : _order.order + 1;
            Object.assign(profileEmpSalary, {
              ...item.bodySalarys,
              ...meta,
              profileEmployeeId: profileEmployee.id,
              profileId: undefined,
            });
            const history = new ProfileSalaryHistory();
            Object.assign(history, { ...profileEmpSalary, id: undefined });
            profileEmpSalary.dateGovernment = item.bodySalarys?.commandDateAffect ?? meta.createdAt;
            (profileEmpSalary.profileId = _null),
              await this.salaryRepo.save(profileEmpSalary, { data: req });
            setLogDataDiff(req, { before, after: profileEmpSalary });
            history.profileSalaryId = profileEmpSalary.id;
            await this.salaryHistoryRepo.save(history, { data: req });

            if (profileEmployee.profileInsignias.length > 0) {
              _oldInsigniaIds = profileEmployee.profileInsignias?.map((x: any) => x.id) ?? [];
            }
            await removeProfileInOrganize(profileEmployee.id, "EMPLOYEE");
            if (profileEmployee.keycloak != null) {
              // const delUserKeycloak = await deleteUser(profileEmployee.keycloak);
              // if (delUserKeycloak) {
              // Task #228
              // profileEmployee.keycloak = _null;
              profileEmployee.roleKeycloaks = [];
              profileEmployee.isActive = false;
              // }
            }
            profileEmployee.isLeave = true;
            profileEmployee.leaveReason = "บรรจุข้าราชการ";
            profileEmployee.lastUpdateUserId = req.user.sub;
            profileEmployee.lastUpdateFullName = req.user.name;
            profileEmployee.lastUpdatedAt = new Date();
            await this.profileEmployeeRepository.save(profileEmployee);
            setLogDataDiff(req, { before, after: profileEmployee });
          }
          profile = Object.assign({ ...item.bodyProfile, ...meta });
          profile.dateRetire = _dateRetire;
          profile.dateRetireLaw = _dateRetireLaw;
          profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
          profile.keycloak =
            userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : "";
          profile.registrationAddress = item.bodyProfile.registrationAddress;
          profile.registrationProvinceId = registrationProvinceId
            ? registrationProvinceId.id
            : _null;
          profile.registrationDistrictId = registrationDistrictId
            ? registrationDistrictId.id
            : _null;
          profile.registrationSubDistrictId = registrationSubDistrictId
            ? registrationSubDistrictId.id
            : _null;
          profile.registrationZipCode = item.bodyProfile.registrationZipCode;
          profile.currentAddress = item.bodyProfile.currentAddress;
          profile.currentProvinceId = currentProvinceId ? currentProvinceId.id : _null;
          profile.currentDistrictId = currentDistrictId ? currentDistrictId.id : _null;
          profile.currentSubDistrictId = currentSubDistrictId ? currentSubDistrictId.id : _null;
          profile.currentZipCode = item.bodyProfile.currentZipCode;
          profile.email = item.bodyProfile.email;
          profile.dateStart = item.bodyProfile.dateStart;
          profile.amount = item.bodyProfile.amount ?? null;
          profile.amountSpecial = item.bodyProfile.amountSpecial ?? null;
          profile.isProbation = item.bodyProfile.isProbation;
          //เพิ่มใหม่จากรับโอน
          profile.rank = item?.bodyProfile?.rank || null;
          profile.prefix = item?.bodyProfile?.rank || item?.bodyProfile?.prefix || null;
          profile.prefixMain = item?.bodyProfile?.prefix ?? null;
          profile.firstName = item.bodyProfile.firstName ?? null;
          profile.lastName = item.bodyProfile.lastName ?? null;
          profile.birthDate = item.bodyProfile.birthDate ?? null;
          profile.gender = item.bodyProfile.gender ?? null;
          profile.relationship = item.bodyProfile.relationship ?? null;
          profile.religion = item.bodyProfile.religion ?? null;
          profile.ethnicity = item.bodyProfile.ethnicity;
          profile.nationality = item.bodyProfile.nationality ?? null;
          profile.bloodGroup = item.bodyProfile.bloodGroup ?? null;
          profile.phone = item.bodyProfile.phone ?? null;

          console.log("[Excexute/CreateOfficerProfile] Saving new profile");
          await this.profileRepository.save(profile);
          console.log("[Excexute/CreateOfficerProfile] New profile saved, profileId:", profile.id);
          // update user attribute in keycloak
          await updateUserAttributes(profile.keycloak ?? "", {
            profileId: [profile.id],
            prefix: [profile.prefix || ""],
          });
          console.log("[Excexute/CreateOfficerProfile] Keycloak attributes updated");
          setLogDataDiff(req, { before, after: profile });
        }
        //ขรก.ในระบบ หรือ ขรก.ในระบบที่สถานะพ้นจากราชการ
        else {
          console.log("[Excexute/CreateOfficerProfile] Existing profile found, isLeave:", profile.isLeave, "leaveType:", profile.leaveType);
          //สร้างโปรไฟล์ใหม่ ถ้าสถานะพ้นราชการ คำสั่งโอนออกหรือคำสั่งขอลาออก
          if (
            profile.isLeave &&
            ["PLACEMENT_TRANSFER", "RETIRE_RESIGN"].includes(profile.leaveType)
          ) {
            console.log("[Excexute/CreateOfficerProfile] Profile is leaving with eligible leave type, creating new profile record");
            //ดึง profileSalary เดิม
            _oldSalaries = await this.salaryRepo.find({
              where: { profileId: profile.id },
              order: { order: "ASC" },
            });
            if (profile.profileInsignias.length > 0) {
              _oldInsigniaIds = profile.profileInsignias?.map((x: any) => x.id) ?? [];
            }
            profile = Object.assign({ ...item.bodyProfile, ...meta });
            profile.dateRetire = _dateRetire;
            profile.dateRetireLaw = _dateRetireLaw;
            profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
            profile.keycloak =
              userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : "";
            profile.registrationAddress = item.bodyProfile.registrationAddress;
            profile.registrationProvinceId = registrationProvinceId
              ? registrationProvinceId.id
              : _null;
            profile.registrationDistrictId = registrationDistrictId
              ? registrationDistrictId.id
              : _null;
            profile.registrationSubDistrictId = registrationSubDistrictId
              ? registrationSubDistrictId.id
              : _null;
            profile.registrationZipCode = item.bodyProfile.registrationZipCode;
            profile.currentAddress = item.bodyProfile.currentAddress;
            profile.currentProvinceId = currentProvinceId ? currentProvinceId.id : _null;
            profile.currentDistrictId = currentDistrictId ? currentDistrictId.id : _null;
            profile.currentSubDistrictId = currentSubDistrictId ? currentSubDistrictId.id : _null;
            profile.currentZipCode = item.bodyProfile.currentZipCode;
            profile.email = item.bodyProfile.email;
            profile.dateStart = item.bodyProfile.dateStart;
            profile.amount = item.bodyProfile.amount ?? null;
            profile.amountSpecial = item.bodyProfile.amountSpecial ?? null;
            profile.isProbation = item.bodyProfile.isProbation;
            profile.rank = item?.bodyProfile?.rank || null;
            profile.prefix = item?.bodyProfile?.rank || item?.bodyProfile?.prefix || null;
            profile.prefixMain = item?.bodyProfile?.prefix ?? null;
            profile.firstName = item.bodyProfile.firstName ?? null;
            profile.lastName = item.bodyProfile.lastName ?? null;
            profile.birthDate = item.bodyProfile.birthDate ?? null;
            profile.gender = item.bodyProfile.gender ?? null;
            profile.relationship = item.bodyProfile.relationship ?? null;
            profile.religion = item.bodyProfile.religion ?? null;
            profile.ethnicity = item.bodyProfile.ethnicity;
            profile.nationality = item.bodyProfile.nationality ?? null;
            profile.bloodGroup = item.bodyProfile.bloodGroup ?? null;
            profile.phone = item.bodyProfile.phone ?? null;
            await this.profileRepository.save(profile);
            console.log("[Excexute/CreateOfficerProfile] New profile record saved for leaving officer, profileId:", profile.id);
            setLogDataDiff(req, { before, after: profile });
          } else {
            console.log("[Excexute/CreateOfficerProfile] Updating existing active profile");
            profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
            profile.keycloak =
              userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : "";
            profile.isProbation = item.bodyProfile.isProbation;
            profile.isLeave = item.bodyProfile.isLeave;
            profile.isRetirement = false;
            profile.isActive = true;
            profile.isDelete = false;
            profile.dateLeave = _null;
            profile.dateRetire = _dateRetire;
            profile.dateRetireLaw = _dateRetireLaw;
            profile.registrationAddress = item.bodyProfile.registrationAddress;
            profile.registrationProvinceId = registrationProvinceId
              ? registrationProvinceId.id
              : _null;
            profile.registrationDistrictId = registrationDistrictId
              ? registrationDistrictId.id
              : _null;
            profile.registrationSubDistrictId = registrationSubDistrictId
              ? registrationSubDistrictId.id
              : _null;
            profile.registrationZipCode = item.bodyProfile.registrationZipCode;
            profile.currentAddress = item.bodyProfile.currentAddress;
            profile.currentProvinceId = currentProvinceId ? currentProvinceId.id : _null;
            profile.currentDistrictId = currentDistrictId ? currentDistrictId.id : _null;
            profile.currentSubDistrictId = currentSubDistrictId ? currentSubDistrictId.id : _null;
            profile.currentZipCode = item.bodyProfile.currentZipCode;
            profile.email = item.bodyProfile.email;
            profile.telephoneNumber = item.bodyProfile.telephoneNumber;
            profile.phone = item.bodyProfile.phone;
            profile.dateStart = item.bodyProfile.dateStart;
            profile.amount = item.bodyProfile.amount ?? null;
            profile.amountSpecial = item.bodyProfile.amountSpecial ?? null;
            profile.leaveCommandId = _null;
            profile.leaveCommandNo = _null;
            profile.leaveRemark = _null;
            profile.leaveDate = _null;
            profile.leaveType = _null;
            profile.leaveReason = _null;
            profile.lastUpdateUserId = req.user.sub;
            profile.lastUpdateFullName = req.user.name;
            profile.lastUpdatedAt = new Date();
            //เพิ่มใหม่จากรับโอน
            profile.rank = item?.bodyProfile?.rank || null;
            profile.prefix = item?.bodyProfile?.rank || item?.bodyProfile?.prefix || null;
            profile.prefixMain = item?.bodyProfile?.prefix ?? null;
            profile.firstName =
              item.bodyProfile.firstName && item.bodyProfile.firstName != ""
                ? item.bodyProfile.firstName
                : profile.firstName;
            profile.lastName =
              item.bodyProfile.lastName && item.bodyProfile.lastName != ""
                ? item.bodyProfile.lastName
                : profile.lastName;
            profile.birthDate = item.bodyProfile.birthDate
              ? item.bodyProfile.birthDate
              : profile.birthDate;
            profile.gender =
              item.bodyProfile.gender && item.bodyProfile.gender != ""
                ? item.bodyProfile.gender
                : profile.gender;
            profile.relationship =
              item.bodyProfile.relationship && item.bodyProfile.relationship != ""
                ? item.bodyProfile.relationship
                : profile.relationship;
            profile.religion =
              item.bodyProfile.religion && item.bodyProfile.religion != ""
                ? item.bodyProfile.religion
                : profile.religion;
            profile.ethnicity =
              item.bodyProfile.ethnicity && item.bodyProfile.ethnicity != ""
                ? item.bodyProfile.ethnicity
                : profile.ethnicity;
            profile.nationality =
              item.bodyProfile.nationality && item.bodyProfile.nationality != ""
                ? item.bodyProfile.nationality
                : profile.nationality;
            profile.bloodGroup =
              item.bodyProfile.bloodGroup && item.bodyProfile.bloodGroup != ""
                ? item.bodyProfile.bloodGroup
                : profile.bloodGroup;
            profile.phone =
              item.bodyProfile.phone && item.bodyProfile.phone != ""
                ? item.bodyProfile.phone
                : profile.phone;
            await this.profileRepository.save(profile);
            console.log("[Excexute/CreateOfficerProfile] Existing active profile updated, profileId:", profile.id);
            setLogDataDiff(req, { before, after: profile });
          }
        }

        if (profile && profile.id) {
          console.log("[Excexute/CreateOfficerProfile] Processing additional data for profileId:", profile.id);
          //Educations
          if (item.bodyEducations && item.bodyEducations.length > 0) {
            console.log("[Excexute/CreateOfficerProfile] Processing educations, count:", item.bodyEducations.length);
            await Promise.all(
              item.bodyEducations.map(async (education) => {
                const profileEdu = new ProfileEducation();
                Object.assign(profileEdu, { ...education, ...meta });
                const eduHistory = new ProfileEducationHistory();
                Object.assign(eduHistory, { ...profileEdu, id: undefined });
                profileEdu.profileId = profile.id;
                const educationLevel = await this.profileEducationRepo.findOne({
                  select: ["id", "level", "profileId"],
                  where: { profileId: profile.id, isDeleted: false },
                  order: { level: "DESC" },
                });
                profileEdu.level = educationLevel == null ? 1 : educationLevel.level + 1;
                await this.profileEducationRepo.save(profileEdu, { data: req });
                setLogDataDiff(req, { before, after: profileEdu });
                eduHistory.profileEducationId = profileEdu.id;
                await this.profileEducationHistoryRepo.save(eduHistory, { data: req });
              }),
            );
          }
          //Certificates
          if (item.bodyCertificates && item.bodyCertificates.length > 0) {
            console.log("[Excexute/CreateOfficerProfile] Processing certificates, count:", item.bodyCertificates.length);
            await Promise.all(
              item.bodyCertificates.map(async (cer) => {
                const profileCer = new ProfileCertificate();
                Object.assign(profileCer, { ...cer, ...meta });
                const cerHistory = new ProfileCertificateHistory();
                Object.assign(cerHistory, { ...profileCer, id: undefined });
                profileCer.profileId = profile.id;
                await this.certificateRepo.save(profileCer, { data: req });
                setLogDataDiff(req, { before, after: profileCer });
                cerHistory.profileCertificateId = profileCer.id;
                await this.certificateHistoryRepo.save(cerHistory, { data: req });
              }),
            );
          }
          //FamilyCouple
          if (item.bodyMarry != null) {
            console.log("[Excexute/CreateOfficerProfile] Processing couple/marry data");
            const profileCouple = new ProfileFamilyCouple();
            const data = {
              profileId: profile.id,
              couple: item.bodyMarry.marry,
              couplePrefix: item.bodyMarry.marryPrefix,
              coupleFirstName: item.bodyMarry.marryFirstName,
              coupleLastName: item.bodyMarry.marryLastName,
              coupleCareer: item.bodyMarry.marryOccupation,
              coupleLive: true,
            };
            Object.assign(profileCouple, { ...data, ...meta });
            const coupleHistory = new ProfileFamilyCoupleHistory();
            Object.assign(coupleHistory, { ...profileCouple, id: undefined });
            profileCouple.profileId = profile.id;
            await this.profileFamilyCoupleRepo.save(profileCouple, { data: req });
            setLogDataDiff(req, { before, after: profileCouple });
            coupleHistory.profileFamilyCoupleId = profileCouple.id;
            await this.profileFamilyCoupleHistoryRepo.save(coupleHistory, { data: req });
          }
          //FamilyFather
          if (item.bodyFather != null) {
            console.log("[Excexute/CreateOfficerProfile] Processing father data");
            const profileFather = new ProfileFamilyFather();
            const data = {
              profileId: profile.id,
              fatherPrefix: item.bodyFather.fatherPrefix,
              fatherFirstName: item.bodyFather.fatherFirstName,
              fatherLastName: item.bodyFather.fatherLastName,
              fatherCareer: item.bodyFather.fatherOccupation,
              fatherLive: true,
            };
            Object.assign(profileFather, { ...data, ...meta });
            const fatherHistory = new ProfileFamilyFatherHistory();
            Object.assign(fatherHistory, { ...profileFather, id: undefined });
            profileFather.profileId = profile.id;
            await this.profileFamilyFatherRepo.save(profileFather, { data: req });
            setLogDataDiff(req, { before, after: profileFather });
            fatherHistory.profileFamilyFatherId = profileFather.id;
            await this.profileFamilyFatherHistoryRepo.save(fatherHistory, { data: req });
          }
          //FamilyMother
          if (item.bodyMother != null) {
            console.log("[Excexute/CreateOfficerProfile] Processing mother data");
            const profileMother = new ProfileFamilyMother();
            const data = {
              profileId: profile.id,
              motherPrefix: item.bodyMother.motherPrefix,
              motherFirstName: item.bodyMother.motherFirstName,
              motherLastName: item.bodyMother.motherLastName,
              motherCareer: item.bodyMother.motherOccupation,
              motherLive: true,
            };
            Object.assign(profileMother, { ...data, ...meta });
            const motherHistory = new ProfileFamilyMotherHistory();
            Object.assign(motherHistory, { ...profileMother, id: undefined });
            profileMother.profileId = profile.id;
            await this.profileFamilyMotherRepo.save(profileMother, { data: req });
            setLogDataDiff(req, { before, after: profileMother });
            motherHistory.profileFamilyMotherId = profileMother.id;
            await this.profileFamilyMotherHistoryRepo.save(motherHistory, { data: req });
          }
          //Salary
          //insert profileSalary อันเก่า กรณีพ้นราชการแล้วกลับมาบรรจุ
          if (_oldSalaries.length > 0) {
            console.log("[Excexute/CreateOfficerProfile] Restoring old salaries, count:", _oldSalaries.length);
            await Promise.all(
              _oldSalaries.map(async (oldSal) => {
                const profileSal: any = new ProfileSalary();
                Object.assign(profileSal, { ...oldSal, ...meta });
                const salaryHistory = new ProfileSalaryHistory();
                Object.assign(salaryHistory, { ...profileSal, id: undefined });
                profileSal.profileId = profile.id;
                await this.salaryRepo.save(profileSal, { data: req });
                setLogDataDiff(req, { before, after: profileSal });
                salaryHistory.profileSalaryId = profileSal.id;
                await this.salaryHistoryRepo.save(salaryHistory, { data: req });
              }),
            );
          }
          //insert item.bodySalarys ต่อจากที่ insert เดิมไปแล้ว
          if (item.bodySalarys && item.bodySalarys != null) {
            console.log("[Excexute/CreateOfficerProfile] Processing new salary data");
            const dest_item = await this.salaryRepo.findOne({
              where: { profileId: profile.id },
              order: { order: "DESC" },
            });
            const profileSal: any = new ProfileSalary();
            profileSal.posNumCodeSit = _posNumCodeSit;
            profileSal.posNumCodeSitAbb = _posNumCodeSitAbb;
            Object.assign(profileSal, { ...item.bodySalarys, ...meta });
            const salaryHistory = new ProfileSalaryHistory();
            Object.assign(salaryHistory, { ...profileSal, id: undefined });
            profileSal.order = dest_item == null ? 1 : dest_item.order + 1;
            profileSal.profileId = profile.id;
            profileSal.dateGovernment = item.bodySalarys.commandDateAffect ?? meta.createdAt;
            profileSal.amount = item.bodySalarys.amount ?? null;
            profileSal.amountSpecial = item.bodySalarys.amountSpecial ?? null;
            profileSal.positionSalaryAmount = item.bodySalarys.positionSalaryAmount ?? null;
            profileSal.mouthSalaryAmount = item.bodySalarys.mouthSalaryAmount ?? null;
            await this.salaryRepo.save(profileSal, { data: req });
            setLogDataDiff(req, { before, after: profileSal });
            salaryHistory.profileSalaryId = profileSal.id;
            await this.salaryHistoryRepo.save(salaryHistory, { data: req });
          }
          //Position
          if (item.bodyPosition && item.bodyPosition != null) {
            console.log("[Excexute/CreateOfficerProfile] Processing position assignment");
            // STEP 1: หา posMaster ที่จะใช้งานตาม id ที่ส่งมา (อาจเป็นตำแหน่งเก่าหรือใหม่ก็ได้)
            console.log("[Excexute/CreateOfficerProfile] STEP 1: Finding posMaster, posmasterId:", item.bodyPosition.posmasterId);
            let posMaster = await this.posMasterRepository.findOne({
              where: {
                id: item.bodyPosition.posmasterId,
              },
              relations: {
                orgRevision: true,
                orgRoot: true,
                orgChild1: true,
                orgChild2: true,
                orgChild3: true,
                orgChild4: true,
              },
            });
            console.log("[Excexute/CreateOfficerProfile] posMaster found:", !!posMaster);

            // เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่
            const isCurrent =
              posMaster?.orgRevision?.orgRevisionIsCurrent === true &&
              posMaster?.orgRevision?.orgRevisionIsDraft === false;
            console.log("[Excexute/CreateOfficerProfile] posMaster isCurrent:", isCurrent);

            // ถ้าไม่อยู่ในโครงสร้างปัจจุบัน ให้หาตัวใหม่จาก ancestorDNA
            if (!isCurrent && posMaster?.ancestorDNA) {
              console.log("[Excexute/CreateOfficerProfile] Finding current posMaster from ancestorDNA");
              posMaster = await this.posMasterRepository.findOne({
                where: {
                  ancestorDNA: posMaster.ancestorDNA,
                  orgRevision: {
                    orgRevisionIsCurrent: true,
                    orgRevisionIsDraft: false,
                  },
                },
                relations: {
                  orgRevision: true,
                  orgRoot: true,
                  orgChild1: true,
                  orgChild2: true,
                  orgChild3: true,
                  orgChild4: true,
                },
              });
              console.log("[Excexute/CreateOfficerProfile] Current posMaster from ancestorDNA found:", !!posMaster);
            }

            if (posMaster == null) {
              console.error(
                `[Excexute/CreateOfficerProfile] not found posMasterId: ${item.bodyPosition.posmasterId}`
              );
              throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
            }

            // STEP 2: เคลียร์ข้อมูลตำแหน่งเก่าที่ครองอยู่ ในโครงสร้างปัจจุบัน
            console.log("[Excexute/CreateOfficerProfile] STEP 2: Clearing old position data");
            const posMasterOld = await this.posMasterRepository.findOne({
              where: {
                current_holderId: profile.id,
                orgRevisionId: posMaster.orgRevisionId,
              },
            });
            if (posMasterOld != null) {
              // เคลียร์คนครองเก่าออกจากตำแหน่งเดิม
              posMasterOld.current_holderId = null;
              posMasterOld.lastUpdatedAt = new Date();
            }

            // หา position เก่าที่เลือกไว้ แล้วเคลียร์การเลือก
            const positionOld = await this.positionRepository.findOne({
              where: {
                posMasterId: posMasterOld?.id,
                positionIsSelected: true,
              },
            });
            if (positionOld != null) {
              positionOld.positionIsSelected = false;
              await this.positionRepository.save(positionOld);
            }

            // STEP 3: เคลียร์ position ที่เลือกไว้อื่นๆ ใน posMaster ตัวใหม่
            console.log("[Excexute/CreateOfficerProfile] STEP 3: Clearing other selected positions in new posMaster");
            const checkPosition = await this.positionRepository.find({
              where: {
                posMasterId: posMaster.id,
                positionIsSelected: true,
              },
            });
            if (checkPosition.length > 0) {
              const clearPosition = checkPosition.map((positions) => ({
                ...positions,
                positionIsSelected: false,
              }));
              await this.positionRepository.save(clearPosition);
            }

            // STEP 4: กำหนดคนครองใหม่ให้กับ posMaster
            console.log("[Excexute/CreateOfficerProfile] STEP 4: Assigning new holder to posMaster");
            posMaster.current_holderId = profile.id;
            posMaster.lastUpdatedAt = new Date();
            // posMaster.conditionReason = _null;
            // posMaster.isCondition = false;
            if (posMasterOld != null) {
              await this.posMasterRepository.save(posMasterOld);
              await CreatePosMasterHistoryOfficer(posMasterOld.id, req);
            }
            await this.posMasterRepository.save(posMaster);
            console.log("[Excexute/CreateOfficerProfile] posMaster saved with new holder");

            // STEP 5: กำหนด position ใหม่
            console.log("[Excexute/CreateOfficerProfile] STEP 5: Determining position to assign");
            // Match position ตามลำดับ priority:
            // Condition 1: match จาก positionId
            // Condition 2: match 7 ฟิลด์ (positionName, posTypeId, posLevelId, positionField, positionArea, positionExecutiveField, posExecutiveId)
            // Condition 3: match 3 ฟิลด์ (positionName, posTypeId, posLevelId)
            // Fallback: เลือก position แรกใน posMaster

            let positionNew: Position | null = null;

            // ═══════════════════════════════════════════════════════════
            // CONDITION 1: เช็คจาก positionId ตรง
            // ═══════════════════════════════════════════════════════════
            console.log("[Excexute/CreateOfficerProfile] CONDITION 1: Checking by positionId:", item.bodyPosition?.positionId);
            if (item.bodyPosition?.positionId) {
              const positionById = await this.positionRepository.findOne({
                where: {
                  id: item.bodyPosition.positionId,
                  posMasterId: posMaster.id, // ต้องอยู่ใน posMaster ที่ถูกต้อง
                },
                relations: ["posExecutive"],
              });

              if (positionById) {
                positionNew = positionById;
                console.log("[Excexute/CreateOfficerProfile] CONDITION 1 matched, positionId:", positionById.id);
              }
            }

            // ═══════════════════════════════════════════════════════════
            // CONDITION 2: Match 7 ฟิลด์ (ถ้า Condition 1 ไม่ match)
            // ═══════════════════════════════════════════════════════════
            if (!positionNew && item.bodyPosition) {
              console.log("[Excexute/CreateOfficerProfile] CONDITION 1 not matched, trying CONDITION 2: Match 7 fields");
              // สร้าง where clause แบบ dynamic - ใส่เฉพาะฟิลด์ที่ไม่ใช่ null
              const whereCondition: any = {
                posMasterId: posMaster.id,
                positionName: item.bodyPosition.positionName,
                posTypeId: item.bodyPosition.posTypeId,
                posLevelId: item.bodyPosition.posLevelId,
              };

              if (item.bodyPosition.positionField) {
                whereCondition.positionField = item.bodyPosition.positionField;
              }
              if (item.bodyPosition.posExecutiveId) {
                whereCondition.posExecutiveId = item.bodyPosition.posExecutiveId;
              }
              if (item.bodyPosition.positionExecutiveField) {
                whereCondition.positionExecutiveField = item.bodyPosition.positionExecutiveField;
              }
              if (item.bodyPosition.positionArea) {
                whereCondition.positionArea = item.bodyPosition.positionArea;
              }

              const positionBy7Fields = await this.positionRepository.findOne({
                where: whereCondition,
                relations: ["posExecutive"],
                order: { orderNo: "ASC" }
              });

              if (positionBy7Fields) {
                positionNew = positionBy7Fields;
                console.log("[Excexute/CreateOfficerProfile] CONDITION 2 matched with 7 fields, positionId:", positionBy7Fields.id);
              }
            }

            // ═══════════════════════════════════════════════════════════
            // CONDITION 3: Match 3 ฟิลด์ (ถ้า Condition 2 ไม่ match)
            // ═══════════════════════════════════════════════════════════
            if (!positionNew && item.bodyPosition) {
              console.log("[Excexute/CreateOfficerProfile] CONDITION 2 not matched, trying CONDITION 3: Match 3 fields");
              const positionBy3Fields = await this.positionRepository.findOne({
                where: {
                  posMasterId: posMaster.id,
                  positionName: item.bodyPosition.positionName,
                  posTypeId: item.bodyPosition.posTypeId,
                  posLevelId: item.bodyPosition.posLevelId,
                },
                relations: ["posExecutive"],
                order: { orderNo: "ASC" }
              });

              if (positionBy3Fields) {
                positionNew = positionBy3Fields;
                console.log("[Excexute/CreateOfficerProfile] CONDITION 3 matched with 3 fields, positionId:", positionBy3Fields.id);
              } else {
                console.log("[Excexute/CreateOfficerProfile] No position matched for profileId:", profile.id);
              }
            }

            // // ═══════════════════════════════════════════════════════════
            // // FALLBACK: ถ้าทั้ง 3 ไม่ match ให้เลือก position แรกใน posMaster
            // // ═══════════════════════════════════════════════════════════
            // if (!positionNew) {
            //   const fallbackPositions = await this.positionRepository.find({
            //     where: {
            //       posMasterId: posMaster.id,
            //     },
            //     relations: ["posExecutive"],
            //     order: {
            //       orderNo: "ASC",
            //     },
            //     take: 1,
            //   });

            //   if (fallbackPositions.length > 0) {
            //     positionNew = fallbackPositions[0];
            //   }
            // }

            // อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
            profile.posMasterNo = getPosMasterNo(posMaster);
            profile.org = getOrgFullName(posMaster);
            // ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
            if (positionNew != null) {
              console.log("[Excexute/CreateOfficerProfile] Final position assignment, isSit:", posMaster.isSit, "positionId:", positionNew.id);
              positionNew.positionIsSelected = true;
              if (!posMaster.isSit) {
                profile.posLevelId = positionNew.posLevelId;
                profile.posTypeId = positionNew.posTypeId;
                profile.position = positionNew.positionName;
                profile.positionField = positionNew.positionField ?? null;
                profile.posExecutive = positionNew.posExecutive?.posExecutiveName ?? null;
                profile.positionArea = positionNew.positionArea ?? null;
                profile.positionExecutiveField = positionNew.positionExecutiveField ?? null;
                // profile.dateStart = new Date();
              }
              await this.positionRepository.save(positionNew, { data: req });
            } else if (!posMaster.isSit) {
              // fallback: ตำแหน่งในโครงสร้างถูกแก้ไข ใช้ข้อมูลตำแหน่งที่สมัครสอบมา
              console.log("[Excexute/CreateOfficerProfile] positionNew is null, using bodyPosition data as fallback");
              profile.position = item.bodyPosition.positionName ?? null;
              profile.posTypeId = item.bodyPosition.posTypeId ?? null;
              profile.posLevelId = item.bodyPosition.posLevelId ?? null;
              profile.positionField = item.bodyPosition.positionField ?? null;
              profile.positionArea = item.bodyPosition.positionArea ?? null;
              profile.positionExecutiveField = item.bodyPosition.positionExecutiveField ?? null;
            }
            await this.profileRepository.save(profile, { data: req });
            setLogDataDiff(req, { before, after: profile });
            // await CreatePosMasterHistoryOfficer(posMaster.id, req);
            await CreatePosMasterHistoryOfficer(posMaster.id, req, null, {
              positionId: positionNew?.id,
            });
          }
          // Insignia
          if (_oldInsigniaIds.length > 0) {
            console.log("[Excexute/CreateOfficerProfile] Processing old insignias, count:", _oldInsigniaIds.length);
            const _insignias = await this.insigniaRepo.find({
              where: { id: In(_oldInsigniaIds), isDeleted: false },
              order: { createdAt: "ASC" },
            });
            for (const oldInsignia of _insignias) {
              const newInsigniaData: CreateProfileInsignia = {
                profileId: profile.id,
                year: oldInsignia.year,
                no: oldInsignia.no,
                volume: oldInsignia.volume,
                section: oldInsignia.section,
                page: oldInsignia.page,
                receiveDate: oldInsignia.receiveDate,
                insigniaId: oldInsignia.insigniaId,
                dateAnnounce: oldInsignia.dateAnnounce,
                issue: oldInsignia.issue,
                volumeNo: oldInsignia.volumeNo,
                refCommandDate: oldInsignia.refCommandDate,
                refCommandNo: oldInsignia.refCommandNo,
                note: oldInsignia.note,
                isUpload: oldInsignia.isUpload,
              };
              const insignia = new ProfileInsignia();
              Object.assign(insignia, { ...newInsigniaData, ...meta });
              const history = new ProfileInsigniaHistory();
              Object.assign(history, { ...insignia, id: undefined });
              await this.insigniaRepo.save(insignia, { data: req });
              setLogDataDiff(req, { before, after: insignia });
              history.profileInsigniaId = insignia.id;
              await this.insigniaHistoryRepo.save(history, { data: req });
            }
          }
          // เพิ่มรูปภาพโปรไฟล์
          if (item.bodyProfile.objectRefId) {
            console.log("[Excexute/CreateOfficerProfile] Processing profile avatar image, objectRefId:", item.bodyProfile.objectRefId);
            const _profileAvatar = new ProfileAvatar();
            Object.assign(_profileAvatar, {
              ...meta,
              profileId: profile.id,
              profileEmployeeId: undefined,
            });
            if (profile.profileAvatars && profile.profileAvatars.length > 0) {
              await Promise.all(
                profile.profileAvatars.map(async (item: any) => {
                  item.isActive = false;
                  await this.avatarRepository.save(item);
                }),
              );
            }
            await this.avatarRepository.save(_profileAvatar);
            let avatar = `ทะเบียนประวัติ/โปรไฟล์/${profile.id}`;
            let fileName = `profile-${_profileAvatar.id}`;
            _profileAvatar.isActive = true;
            _profileAvatar.avatar = avatar;
            _profileAvatar.avatarName = fileName;
            await this.avatarRepository.save(_profileAvatar, { data: req });
            profile.avatar = avatar;
            profile.avatarName = fileName;
            await this.profileRepository.save(profile, { data: req });
            const checkAvatar = await this.avatarRepository.findOne({
              where: { avatar: avatar, avatarName: fileName },
            });
            if (checkAvatar && checkAvatar.profileId == null) {
              checkAvatar.profileId = profile.id;
              await this.avatarRepository.save(checkAvatar);
            }
            //duplicate รูปภาพโปรไฟล์โดยอิงจากรูปภาพเดิม
            await new CallAPI()
              .PostData(req, `/salary/file/avatar/${item.bodyProfile.objectRefId}`, {
                prefix: avatar,
                fileName: fileName,
              })
              .then(() => {})
              .catch(() => {});
          }
        }
      }),
    );
    console.log("[Excexute/CreateOfficerProfile] CreateOfficeProfileExcecute completed successfully");
    return new HttpSuccess();
  }

  @Post("command21/employee/report")
  public async command21SalaryEmployee(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: string[];
      status: string;
    },
  ) {
    const profile = await this.profileEmployeeRepository.find({ where: { id: In(body.refIds) } });
    const data = profile.map((_data) => ({
      ..._data,
      statusTemp: body.status,
    }));
    await this.profileEmployeeRepository.save(data);
    return new HttpSuccess();
  }

  @Post("command38/officer/report")
  public async command38SalaryOfficer(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: string[];
      status: string;
    },
  ) {
    const posMasters = await this.posMasterRepository.find({ where: { id: In(body.refIds) } });
    const data = posMasters.map((_data) => ({
      ..._data,
      statusReport: body.status,
    }));
    await this.posMasterRepository.save(data);
    if (posMasters && posMasters.length > 0) {
      const orgRevision = await this.orgRevisionRepo.findOne({
        where: { id: posMasters[0].orgRevisionId },
      });
      if (orgRevision != null && orgRevision.isLock == false) {
        await this.orgRevisionRepo.update(orgRevision.id, {
          isLock: true,
        });
      }
    }
    return new HttpSuccess();
  }

  @Post("command40/officer/report")
  public async command40SalaryOfficer(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: string[];
      status: string;
    },
  ) {
    const posMasters = await this.posMasterActRepository.find({ where: { id: In(body.refIds) } });
    const data = posMasters.map((_data) => ({
      ..._data,
      statusReport: body.status,
    }));
    await this.posMasterActRepository.save(data);
    return new HttpSuccess();
  }

  @Post("command21/employee/report/excecute")
  public async command21SalaryEmployeeExcecute(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: {
        refId: string;
        commandId?: string | null;
        amount: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount: Double | null;
        mouthSalaryAmount: Double | null;
        commandNo: string | null;
        commandYear: number;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    let _reqBody: any[] = [];
    const roleKeycloak = await this.roleKeycloakRepo.findOne({
      where: { name: Like("USER") },
    });
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.refIds.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.refIds.map(async (item) => {
        const profile = await this.profileEmployeeRepository.findOne({
          where: { id: item.refId },
          relations: ["roleKeycloaks"],
        });
        if (!profile) {
          throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
        }
        const orgRevision = await this.orgRevisionRepository.findOne({
          where: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
        });
        const _posMaster = await this.employeePosMasterRepository.findOne({
          where: {
            orgRevisionId: orgRevision?.id,
            id: profile.posmasterIdTemp,
            // current_holderId: profile.id
          },
          relations: {
            orgRoot: true,
            orgChild1: true,
            orgChild2: true,
            orgChild3: true,
            orgChild4: true,
          },
        });
        const orgRootRef = _posMaster?.orgRoot ?? null;
        const orgChild1Ref = _posMaster?.orgChild1 ?? null;
        const orgChild2Ref = _posMaster?.orgChild2 ?? null;
        const orgChild3Ref = _posMaster?.orgChild3 ?? null;
        const orgChild4Ref = _posMaster?.orgChild4 ?? null;
        let orgShortName = "";
        if (_posMaster != null) {
          if (_posMaster.orgChild1Id === null) {
            orgShortName = _posMaster.orgRoot?.orgRootShortName;
          } else if (_posMaster.orgChild2Id === null) {
            orgShortName = _posMaster.orgChild1?.orgChild1ShortName;
          } else if (_posMaster.orgChild3Id === null) {
            orgShortName = _posMaster.orgChild2?.orgChild2ShortName;
          } else if (_posMaster.orgChild4Id === null) {
            orgShortName = _posMaster.orgChild3?.orgChild3ShortName;
          } else {
            orgShortName = _posMaster.orgChild4?.orgChild4ShortName;
          }
        }
        const dest_item = await this.salaryRepo.findOne({
          where: { profileEmployeeId: item.refId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();
        data.posNumCodeSit = _posNumCodeSit;
        data.posNumCodeSitAbb = _posNumCodeSitAbb;
        const meta = {
          profileEmployeeId: profile.id,
          amount: item.amount,
          amountSpecial: item.amountSpecial,
          commandId: item.commandId,
          positionSalaryAmount: item.positionSalaryAmount,
          mouthSalaryAmount: item.mouthSalaryAmount,
          position: profile.positionTemp,
          positionName: profile.positionTemp,
          positionType: profile.posTypeNameTemp,
          positionLevel: profile.posLevelNameTemp,
          order: dest_item == null ? 1 : dest_item.order + 1,
          orgRoot: orgRootRef?.orgRootName ?? null,
          orgChild1: orgChild1Ref?.orgChild1Name ?? null,
          orgChild2: orgChild2Ref?.orgChild2Name ?? null,
          orgChild3: orgChild3Ref?.orgChild3Name ?? null,
          orgChild4: orgChild4Ref?.orgChild4Name ?? null,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          commandNo: item.commandNo,
          commandYear: item.commandYear,
          posNo: profile.posMasterNoTemp ?? "",
          posNoAbb: orgShortName,
          commandDateAffect: item.commandDateAffect,
          commandDateSign: item.commandDateSign,
          commandCode: item.commandCode,
          commandName: item.commandName,
          remark: item.remark,
        };

        Object.assign(data, meta);
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });

        await this.salaryRepo.save(data, { data: req });
        setLogDataDiff(req, { before, after: data });
        history.profileSalaryId = data.id;
        await this.salaryHistoryRepo.save(history, { data: req });

        const posMaster = await this.employeePosMasterRepository.findOne({
          where: { id: profile.posmasterIdTemp },
          relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
        });
        if (posMaster == null)
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");

        const posMasterOld = await this.employeePosMasterRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: posMaster.orgRevisionId,
          },
        });
        if (posMasterOld != null) {
          posMasterOld.current_holderId = null;
          posMasterOld.lastUpdatedAt = new Date();
        }
        // if (posMasterOld != null) posMasterOld.next_holderId = null;

        const positionOld = await this.employeePositionRepository.findOne({
          where: {
            posMasterId: posMasterOld?.id,
            positionIsSelected: true,
          },
        });
        if (positionOld != null) {
          positionOld.positionIsSelected = false;
          await this.employeePositionRepository.save(positionOld);
        }

        const checkPosition = await this.employeePositionRepository.find({
          where: {
            posMasterId: profile.posmasterIdTemp,
            positionIsSelected: true,
          },
        });
        if (checkPosition.length > 0) {
          const clearPosition = checkPosition.map((positions) => ({
            ...positions,
            positionIsSelected: false,
          }));
          await this.employeePositionRepository.save(clearPosition);
        }

        posMaster.current_holderId = profile.id;
        posMaster.lastUpdatedAt = new Date();
        posMaster.next_holderId = null;
        if (posMasterOld != null) {
          await this.employeePosMasterRepository.save(posMasterOld);
          await CreatePosMasterHistoryEmployee(posMasterOld.id, req);
        }
        await this.employeePosMasterRepository.save(posMaster);
        await CreatePosMasterHistoryEmployee(posMaster.id, req);

        const clsTempPosmaster = await this.employeeTempPosMasterRepository.find({
          where: {
            current_holderId: profile.id,
            orgRevisionId: posMaster.orgRevisionId,
          },
        });

        if (clsTempPosmaster.length > 0) {
          const clearTempPosmaster = clsTempPosmaster.map((posMasterTemp) => ({
            ...posMasterTemp,
            current_holderId: null,
            next_holderId: null,
          }));
          await this.employeeTempPosMasterRepository.save(clearTempPosmaster);

          const checkTempPosition = await this.employeePositionRepository.find({
            where: {
              posMasterTempId: In(clearTempPosmaster.map((x) => x.id)),
              positionIsSelected: true,
            },
          });
          if (checkTempPosition.length > 0) {
            const clearTempPosition = checkTempPosition.map((positions) => ({
              ...positions,
              positionIsSelected: false,
            }));
            await this.employeePositionRepository.save(clearTempPosition);
          }
          await Promise.all(
            clsTempPosmaster.map(
              async (posMasterTemp) =>
                await CreatePosMasterHistoryEmployeeTemp(posMasterTemp.id, req),
            ),
          );
        }

        const positionNew = await this.employeePositionRepository.findOne({
          where: {
            id: profile.positionIdTemp,
            posMasterId: profile.posmasterIdTemp,
          },
        });

        if (positionNew != null) {
          // Create Keycloak
          const checkUser = await getUserByUsername(profile.citizenId);
          if (checkUser.length == 0) {
            let password = profile.citizenId;
            if (profile.birthDate != null) {
              // const gregorianYear = profile.birthDate.getFullYear() + 543;

              // const formattedDate =
              //   profile.birthDate.toISOString().slice(8, 10) +
              //   profile.birthDate.toISOString().slice(5, 7) +
              //   gregorianYear;
              // password = formattedDate;
              const _date = new Date(profile.birthDate.toDateString())
                .getDate()
                .toString()
                .padStart(2, "0");
              const _month = (new Date(profile.birthDate.toDateString()).getMonth() + 1)
                .toString()
                .padStart(2, "0");
              const _year = new Date(profile.birthDate.toDateString()).getFullYear() + 543;
              password = `${_date}${_month}${_year}`;
            }
            // กรอง "." ออกจาก firstName ก่อนส่งไป keycloak
            const sanitizedFirstName = profile.firstName?.replace(/\./g, "") ?? "";
            const userKeycloakId = await createUser(profile.citizenId, password, {
              firstName: sanitizedFirstName,
              lastName: profile.lastName,
              // email: profile.email,
            });
            // if (typeof userKeycloakId !== "string") {
            //   throw new Error(userKeycloakId.errorMessage);
            // }
            const list = await getRoles();
            if (!Array.isArray(list))
              throw new Error("Failed. Cannot get role(s) data from the server.");
            const result = await addUserRoles(
              userKeycloakId,
              list
                .filter((v) => v.name === "USER")
                .map((x) => ({
                  id: x.id,
                  name: x.name,
                })),
            );
            // if (!result) throw new Error("Failed. Cannot set user's role.");
            profile.keycloak =
              userKeycloakId && typeof userKeycloakId == "string" ? userKeycloakId : "";
            profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
            // End Create Keycloak
          } else {
            const rolesData = await getRoleMappings(checkUser[0].id);
            if (rolesData) {
              const _roleKeycloak = await this.roleKeycloakRepo.find({
                where: { name: In(rolesData.map((x: any) => x.name)) },
              });
              profile.roleKeycloaks =
                _roleKeycloak && _roleKeycloak.length > 0 ? _roleKeycloak : [];
            }
            profile.keycloak = checkUser[0].id;
          }
          positionNew.positionIsSelected = true;
          profile.posLevelId = positionNew.posLevelId;
          profile.posTypeId = positionNew.posTypeId;
          profile.position = positionNew.positionName;
          profile.employeeOc = posMaster?.orgRoot?.orgRootName ?? null;
          profile.positionEmployeePositionId = positionNew.positionName;
          profile.statusTemp = "DONE";
          profile.employeeClass = "PERM";
          const _null: any = null;
          profile.employeeWage = item.amount == null ? _null : item.amount.toString();
          profile.dateStart = _command ? _command.commandExcecuteDate : new Date();
          profile.dateAppoint = _command ? _command.commandExcecuteDate : new Date();
          profile.amount = item.amount == null ? _null : item.amount;
          profile.amountSpecial = item.amountSpecial == null ? _null : item.amountSpecial;
          _reqBody.push({
            profileId: profile.id,
            prefix: profile.prefix,
            firstName: profile.firstName,
            lastName: profile.lastName,
            citizenId: profile.citizenId,
            root: posMaster.orgRoot.orgRootName,
            rootId: posMaster.orgRootId,
            rootShortName: posMaster.orgRoot.orgRootShortName,
            rootDnaId: posMaster.orgRoot?.ancestorDNA ?? _null,
            child1DnaId: posMaster.orgChild1?.ancestorDNA ?? _null,
            child2DnaId: posMaster.orgChild2?.ancestorDNA ?? _null,
            child3DnaId: posMaster.orgChild3?.ancestorDNA ?? _null,
            child4DnaId: posMaster.orgChild4?.ancestorDNA ?? _null,
          });
          await this.profileEmployeeRepository.save(profile);
          await this.employeePositionRepository.save(positionNew);
          await CreatePosMasterHistoryEmployee(posMaster.id, req);
          //ลบออกคนออกจากโครงสร้างลูกจ้างชั่วคราว
          const posMasterTemp = await this.employeeTempPosMasterRepository.findOne({
            where: {
              orgRevisionId: orgRevision?.id,
              current_holderId: profile.id,
            },
          });
          if (posMasterTemp) {
            await this.employeeTempPosMasterRepository.update(posMasterTemp.id, {
              current_holderId: _null,
            });
            await CreatePosMasterHistoryEmployeeTemp(posMasterTemp.id, req);
          }
        }
      }),
    );
    await new CallAPI()
      .PostData(req, "/placement/appointment/employee-appoint-21/report/excecute", {
        profileEmps: _reqBody,
      })
      .catch((error) => {
        throw new Error("Failed. Cannot update status. ", error);
      });
    return new HttpSuccess();
  }

  @Post("command21/employee/report/delete")
  public async command21SalaryEmployeeDelete(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: string[];
    },
  ) {
    const profile = await this.profileEmployeeRepository.find({ where: { id: In(body.refIds) } });
    const data = profile.map((_data) => ({
      ..._data,
      statusTemp: "PENDING",
    }));
    await this.profileEmployeeRepository.save(data);
    return new HttpSuccess();
  }

  @Post("command40/officer/report/excecute")
  public async command40SalaryOfficerExcecute(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: {
        refId: string;
        commandId?: string | null;
        amount: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount: Double | null;
        mouthSalaryAmount: Double | null;
        commandNo: string | null;
        commandYear: number;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    // 1. Bulk update status
    await this.posMasterActRepository.update(
      { id: In(body.refIds.map((x) => x.refId)) },
      { statusReport: "DONE" },
    );

    // 2. ดึงข้อมูลครบทุก relation ที่จำเป็น
    const posMasters = await this.posMasterActRepository.find({
      where: { id: In(body.refIds.map((x) => x.refId)) },
      relations: [
        "posMasterChild",
        "posMasterChild.current_holder",
        "posMaster",
        "posMaster.current_holder",
        "posMaster.positions",
        "posMaster.orgRoot",
        "posMaster.orgChild1",
        "posMaster.orgChild2",
        "posMaster.orgChild3",
        "posMaster.orgChild4",
      ],
    });

    // 3. ตรวจสอบว่ามี body.refIds[0] หรือไม่
    const firstRef = body.refIds[0];
    if (!firstRef) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบข้อมูล refIds");
    }

    const profileIdsToClearCache = new Set<string>();

    await Promise.all(
      posMasters.map(async (item) => {
        // 4. ตรวจสอบข้อมูลที่จำเป็นทั้งหมด
        if (!item.posMasterChild?.current_holderId || !item.posMaster) {
          console.warn(`ข้ามรายการ ${item.id}: ข้อมูลไม่ครบ`);
          return;
        }

        if (item.posMasterChild.current_holderId) {
          profileIdsToClearCache.add(item.posMasterChild.current_holderId);
        }

        // 5. สร้าง orgShortName แบบปลอดภัย
        const orgShortName =
          [
            item.posMaster?.orgChild4?.orgChild4ShortName,
            item.posMaster?.orgChild3?.orgChild3ShortName,
            item.posMaster?.orgChild2?.orgChild2ShortName,
            item.posMaster?.orgChild1?.orgChild1ShortName,
            item.posMaster?.orgRoot?.orgRootShortName,
          ].find(Boolean) ?? "";

        // 6. หา position ที่ถูกเลือกแบบปลอดภัย
        const selectedPosition = item.posMaster?.positions;
        const positionName =
          selectedPosition
            ?.map((pos) => pos.positionName)
            .filter(Boolean)
            .join(", ") ?? "-";

        // 7. สร้าง metaAct แบบปลอดภัย
        const metaAct = {
          profileId: item.posMasterChild.current_holderId,
          dateStart: firstRef.commandDateAffect ?? null,
          dateEnd: null,
          position: positionName,
          status: true,
          commandId: firstRef.commandId ?? null,
          createdUserId: req.user?.sub ?? null,
          createdFullName: req.user?.name ?? null,
          lastUpdateUserId: req.user?.sub ?? null,
          lastUpdateFullName: req.user?.name ?? null,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          commandNo: firstRef.commandNo ?? null,
          refCommandNo: `${firstRef.commandNo ?? ""}/${firstRef.commandYear ? Extension.ToThaiYear(firstRef.commandYear) : ""}`,
          commandYear: firstRef.commandYear ? Extension.ToThaiYear(firstRef.commandYear) : null,
          posNo:
            orgShortName && item.posMaster?.posMasterNo
              ? `${orgShortName} ${item.posMaster.posMasterNo}`
              : item.posMaster?.posMasterNo ?? "-",
          posNoAbb: orgShortName,
          commandDateAffect: firstRef.commandDateAffect ?? null,
          commandDateSign: firstRef.commandDateSign ?? null,
          commandCode: firstRef.commandCode ?? null,
          commandName: firstRef.commandName ?? null,
          remark: firstRef.remark ?? null,
        };

        try {
          // 8. ปิดสถานะรักษาการ
          const existingActPositions = await this.actpositionRepository.find({
            where: {
              profileId: item.posMasterChild.current_holderId,
              status: true,
              isDeleted: false,
            },
          });

          if (existingActPositions.length > 0) {
            const updatedActPositions = existingActPositions.map((_data) => ({
              ..._data,
              status: false,
              dateEnd: new Date(),
            }));

            await this.actpositionRepository.save(updatedActPositions);
          }

          // 9. บันทึกข้อมูลใหม่
          const dataAct = new ProfileActposition();
          Object.assign(dataAct, metaAct);

          const historyAct = new ProfileActpositionHistory();
          Object.assign(historyAct, { ...dataAct, id: undefined });

          await this.actpositionRepository.save(dataAct);
          historyAct.profileActpositionId = dataAct.id;
          await this.actpositionHistoryRepository.save(historyAct);
        } catch (error) {
          console.error(`Error processing item ${item.id}:`, error);
          throw new HttpError(
            HttpStatus.INTERNAL_SERVER_ERROR,
            `เกิดข้อผิดพลาดในการประมวลผลรายการ ${item.id}`,
          );
        }
      }),
    );

    if (profileIdsToClearCache.size > 0) {
      await Promise.all(
        Array.from(profileIdsToClearCache).map(async (profileId) => {
          const redisClient = await this.redis.createClient({
            host: REDIS_HOST,
            port: REDIS_PORT,
          });

          const delAsync = promisify(redisClient.del).bind(redisClient);
          await delAsync("role_" + profileId);
          await delAsync("menu_" + profileId);

          redisClient.quit();
        }),
      );
    }

    return new HttpSuccess();
  }

  @Post("command40/officer/report/delete")
  public async command40SalaryOfficerDelete(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: string[];
    },
  ) {
    const posMasters = await this.posMasterActRepository.find({ where: { id: In(body.refIds) } });
    const data = posMasters.map((_data) => ({
      ..._data,
      statusReport: "PENDING",
    }));
    await this.posMasterActRepository.save(data);
    return new HttpSuccess();
  }
  @Post("command40/officer/report/attachment")
  public async command40SalaryOfficerAttachment(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: {
        refId?: string;
        Sequence?: any | null;
        CitizenId?: any | null;
        Prefix?: any | null;
        FirstName?: any | null;
        LastName?: any | null;
        Amount?: any | null;
        amountSpecial?: Double | null;
        PositionSalaryAmount?: any | null;
        MouthSalaryAmount?: any | null;
        RemarkHorizontal?: any | null;
        RemarkVertical?: any | null;
        CommandYear?: any | null;
        CommandExcecuteDate?: Date | null;
      }[];
    },
  ) {
    let data: any = [];
    await Promise.all(
      body.refIds.map(async (item, i) => {
        const posMasterAct = await this.posMasterActRepository.findOne({
          relations: [
            "posMaster",
            "posMaster.orgRoot",
            "posMaster.orgChild1",
            "posMaster.orgChild2",
            "posMaster.orgChild3",
            "posMaster.orgChild4",
            "posMaster.current_holder",
            "posMasterChild",
            "posMasterChild.orgRoot",
            "posMasterChild.orgChild1",
            "posMasterChild.orgChild2",
            "posMasterChild.orgChild3",
            "posMasterChild.orgChild4",
            "posMasterChild.current_holder",
            "posMasterChild.current_holder.posLevel",
            "posMasterChild.current_holder.posType",
          ],
          where: {
            id: item.refId,
          },
        });
        if (!posMasterAct) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
        }
        const organization = [
          posMasterAct.posMasterChild?.current_holder?.position ?? null,
          posMasterAct.posMasterChild?.orgChild4?.orgChild4Name ?? null,
          posMasterAct.posMasterChild?.orgChild3?.orgChild3Name ?? null,
          posMasterAct.posMasterChild?.orgChild2?.orgChild2Name ?? null,
          posMasterAct.posMasterChild?.orgChild1?.orgChild1Name ?? null,
          posMasterAct.posMasterChild?.orgRoot?.orgRootName ?? null,
        ];
        const _organization = organization
          .filter((part) => part !== undefined && part !== null)
          .join(" ");

        const organizationNew = [
          posMasterAct.posMaster?.current_holder?.position ?? null,
          posMasterAct.posMaster?.orgChild4?.orgChild4Name ?? null,
          posMasterAct.posMaster?.orgChild3?.orgChild3Name ?? null,
          posMasterAct.posMaster?.orgChild2?.orgChild2Name ?? null,
          posMasterAct.posMaster?.orgChild1?.orgChild1Name ?? null,
          posMasterAct.posMaster?.orgRoot?.orgRootName ?? null,
        ];
        const _organizationNew = organizationNew
          .filter((part) => part !== undefined && part !== null)
          .join(" ");
        var _data = {
          no: Extension.ToThaiNumber((i + 1).toString()),
          fullName: `${item.Prefix ?? ""}${item.FirstName ?? ""} ${item.LastName ?? ""}`,
          oc:
            /*(posMasterAct.posMasterChild?.current_holder?.position ?? "-") +
            "/" +*/
            _organization ?? "-",
          postype: posMasterAct?.posMasterChild?.current_holder?.posType?.posTypeName ?? "-",
          poslevel: posMasterAct?.posMasterChild?.current_holder?.posLevel?.posLevelName ?? "-",
          organizationNew:
            /*(posMasterAct.posMaster?.current_holder?.position ?? "-") +
            "/" +*/
            _organizationNew ?? "-",
          //   date: Extension.ToThaiShortDate_noPrefix(new Date()),
          dateStart: item.CommandExcecuteDate
            ? Extension.ToThaiShortDate(item.CommandExcecuteDate)
            : "-",
          dateEnd: "-",
          remarkVertical: item.RemarkVertical ? Extension.ToThaiNumber(item.RemarkVertical) : "-",
          remarkHorizontal: item.RemarkHorizontal
            ? Extension.ToThaiNumber(item.RemarkHorizontal)
            : "-",
          order:
            posMasterAct.posMasterOrder == null
              ? "-"
              : "ลำดับที่ " + Extension.ToThaiNumber(posMasterAct.posMasterOrder.toString()),
        };
        data.push(_data);
      }),
    );

    return new HttpSuccess(data);
  }

  @Post("command38/officer/report/excecute")
  public async command38SalaryOfficerExcecute(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: {
        refId: string;
        commandId?: string | null;
        amount: Double | null;
        amountSpecial?: Double | null;
        positionSalaryAmount: Double | null;
        mouthSalaryAmount: Double | null;
        commandNo: string | null;
        commandYear: number;
        commandDateAffect?: Date | null;
        commandDateSign?: Date | null;
        commandCode?: string | null;
        commandName?: string | null;
        remark: string | null;
      }[];
    },
  ) {
    let _posNumCodeSit: string = "";
    let _posNumCodeSitAbb: string = "";
    const _command = await this.commandRepository.findOne({
      where: { id: body.refIds.find((x) => x.commandId)?.commandId ?? "" },
    });
    if (_command) {
      if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
        const orgRootDeputy = await this.orgRootRepository.findOne({
          where: {
            isDeputy: true,
            orgRevision: {
              orgRevisionIsCurrent: true,
              orgRevisionIsDraft: false,
            },
          },
          relations: ["orgRevision"],
        });
        _posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
        _posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
      } else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
        _posNumCodeSit = "กรุงเทพมหานคร";
        _posNumCodeSitAbb = "กทม.";
      } else {
        let _profileAdmin = await this.profileRepository.findOne({
          where: {
            keycloak: _command?.createdUserId.toString(),
            current_holders: {
              orgRevision: {
                orgRevisionIsCurrent: true,
                orgRevisionIsDraft: false,
              },
            },
          },
          relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
        });
        _posNumCodeSit =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
          "";
        _posNumCodeSitAbb =
          _profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
            .orgRootShortName ?? "";
      }
    }
    await Promise.all(
      body.refIds.map(async (item) => {
        const posMaster = await this.posMasterRepository.findOne({
          where: { id: item.refId },
          relations: [
            "orgRoot",
            "orgChild1",
            "orgChild2",
            "orgChild3",
            "orgChild4",
            "current_holder",
            "current_holder.posLevel",
            "current_holder.posType",
          ],
        });
        if (!posMaster) {
          throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบตำแหน่งดังกล่าว");
        }
        if (posMaster.next_holderId != null) {
          const orgRootRef = posMaster?.orgRoot ?? null;
          const orgChild1Ref = posMaster?.orgChild1 ?? null;
          const orgChild2Ref = posMaster?.orgChild2 ?? null;
          const orgChild3Ref = posMaster?.orgChild3 ?? null;
          const orgChild4Ref = posMaster?.orgChild4 ?? null;
          const shortName =
            posMaster != null && posMaster.orgChild4 != null
              ? `${posMaster.orgChild4.orgChild4ShortName}`
              : posMaster != null && posMaster.orgChild3 != null
                ? `${posMaster.orgChild3.orgChild3ShortName}`
                : posMaster != null && posMaster.orgChild2 != null
                  ? `${posMaster.orgChild2.orgChild2ShortName}`
                  : posMaster != null && posMaster.orgChild1 != null
                    ? `${posMaster.orgChild1.orgChild1ShortName}`
                    : posMaster != null && posMaster?.orgRoot != null
                      ? `${posMaster.orgRoot.orgRootShortName}`
                      : null;
          const profile = await this.profileRepository.findOne({
            where: { id: posMaster.next_holderId },
          });
          const position = await this.positionRepository.findOne({
            where: {
              posMasterId: posMaster.id,
              positionIsSelected: true,
            },
            relations: ["posType", "posLevel"],
          });
          const dest_item = await this.salaryRepo.findOne({
            where: { profileId: profile?.id },
            order: { order: "DESC" },
          });
          const before = null;
          const data = new ProfileSalary();
          data.posNumCodeSit = _posNumCodeSit;
          data.posNumCodeSitAbb = _posNumCodeSitAbb;
          const meta = {
            profileId: profile?.id,
            date: new Date(),
            amount: item.amount,
            commandId: item.commandId,
            positionSalaryAmount: item.positionSalaryAmount,
            mouthSalaryAmount: item.mouthSalaryAmount,
            position: position?.positionName ?? null,
            positionType: position?.posType?.posTypeName ?? null,
            positionLevel: position?.posLevel?.posLevelName ?? null,
            order: dest_item == null ? 1 : dest_item.order + 1,
            orgRoot: orgRootRef?.orgRootName ?? null,
            orgChild1: orgChild1Ref?.orgChild1Name ?? null,
            orgChild2: orgChild2Ref?.orgChild2Name ?? null,
            orgChild3: orgChild3Ref?.orgChild3Name ?? null,
            orgChild4: orgChild4Ref?.orgChild4Name ?? null,
            createdUserId: req.user.sub,
            createdFullName: req.user.name,
            lastUpdateUserId: req.user.sub,
            lastUpdateFullName: req.user.name,
            createdAt: new Date(),
            lastUpdatedAt: new Date(),
            commandNo: item.commandNo,
            commandYear: item.commandYear,
            posNo: posMaster.posMasterNo,
            posNoAbb: shortName,
            commandDateAffect: item.commandDateAffect,
            commandDateSign: item.commandDateSign,
            commandCode: item.commandCode,
            commandName: item.commandName,
            remark: item.remark,
          };
          Object.assign(data, meta);
          const history = new ProfileSalaryHistory();
          Object.assign(history, { ...data, id: undefined });

          await this.salaryRepo.save(data, { data: req });
          setLogDataDiff(req, { before, after: data });
          history.profileSalaryId = data.id;
          await this.salaryHistoryRepo.save(history, { data: req });

          //   if (profile != null) {
          //     profile.position = position?.positionName ?? "";
          //     profile.posTypeId = position?.posTypeId ?? "";
          //     profile.posLevelId = position?.posLevelId ?? "";
          //     profile.lastUpdateUserId = req.user.sub;
          //     profile.lastUpdateFullName = req.user.name;
          //     profile.lastUpdatedAt = new Date();
          //     await this.profileRepository.save(profile);
          //   }
        }
      }),
    );
    // const posMasters = await this.posMasterRepository.find({
    //   where: { id: In(body.refIds.map((x) => x.refId)) },
    // });
    // const data = posMasters.map((_data) => ({
    //   ..._data,
    //   current_holderId: _data.next_holderId,
    //   next_holderId: null,
    //   statusReport: "PENDING",
    // }));
    // await this.posMasterRepository.save(data);
    return new HttpSuccess();
  }

  @Post("command38/officer/report/delete")
  public async command38SalaryOfficerDelete(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: string[];
    },
  ) {
    const posMasters = await this.posMasterRepository.find({
      where: { id: In(body.refIds) },
    });
    const data = posMasters.map((_data) => ({
      ..._data,
      statusReport: "PENDING",
    }));
    await this.posMasterRepository.save(data);
    if (data && data.length > 0) {
      const revisionId = data[0].orgRevisionId;
      const orgRevision = await this.orgRevisionRepo.findOne({
        where: { id: revisionId },
        relations: ["posMasters"],
      });
      if (
        orgRevision != null &&
        !["REPORT", "DONE"].includes(
          orgRevision.posMasters.find(
            (x) => x.statusReport === "REPORT" || x.statusReport === "DONE",
          )?.statusReport || "",
        )
      ) {
        await this.orgRevisionRepo.update(orgRevision.id, {
          isLock: false,
        });
      }
    }
    return new HttpSuccess();
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab0
   *
   * @summary API รายละเอียดรายการคำสั่ง tab0
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("register-tab0/{id}")
  async GetByIdTab0Register(@Path() id: string) {
    const command = await this.commandRepository.findOne({
      where: { id },
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    const _command = {
      id: command.id,
      isSignature: command.isSignature,
      status: command.status,
      isDraft: command.isDraft,
      isSign: command.isSign,
      isAttachment: command.isAttachment,
      isUploadAttachment: command.isUploadAttachment,
    };
    return new HttpSuccess(_command);
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab4 คำสั่ง
   *
   * @summary API รายละเอียดรายการคำสั่ง tab4 คำสั่ง
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("register-tab4/cover/{id}")
  async GetByIdTab4CoverRegister(@Path() id: string, @Request() request: RequestWithUser) {
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandType"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    let issue =
      command.isBangkok == "OFFICE"
        ? "สำนักปลัดกรุงเทพมหานคร"
        : command.isBangkok == "BANGKOK"
          ? "กรุงเทพมหานคร"
          : null;
    if (issue == null) {
      const orgRevisionActive = await this.orgRevisionRepository.findOne({
        where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        relations: ["posMasters", "posMasters.orgRoot"],
      });
      if (orgRevisionActive != null) {
        const profile = await this.profileRepository.findOne({
          where: {
            keycloak: command.createdUserId.toString(),
          },
        });
        if (profile != null) {
          issue =
            orgRevisionActive?.posMasters?.filter((x) => x.current_holderId == profile.id)[0]
              ?.orgRoot?.orgRootName || null;
        }
      }
    }
    if (issue == null) issue = "...................................";
    const _command = {
      issue: issue,
      commandNo: command.commandNo == null ? "" : Extension.ToThaiNumber(command.commandNo),
      commandYear:
        command.commandYear == null
          ? ""
          : Extension.ToThaiNumber(Extension.ToThaiYear(command.commandYear).toString()),
      commandTitle: command.issue,
      detailHeader: command.detailHeader,
      detailBody: command.detailBody,
      detailFooter: command.detailFooter,
      commandDate:
        command.commandAffectDate == null
          ? ""
          : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandAffectDate)),
      commandExcecuteDate:
        command.commandExcecuteDate == null
          ? ""
          : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandExcecuteDate)),
      name: "...................................",
      position: "...................................",
      authorizedUserFullName: "...................................",
      authorizedPosition: "...................................",
      commandAffectDate: "...................................",
    };
    return new HttpSuccess({
      template: command.commandType.fileCover,
      reportName: "docx-report",
      data: _command,
    });
  }

  /**
   * API รายละเอียดรายการคำสั่ง tab4 แนบท้าย
   *
   * @summary API รายละเอียดรายการคำสั่ง tab4 แนบท้าย
   *
   * @param {string} id  Id  คำสั่ง
   */
  @Get("register-tab4/attachment/{id}")
  async GetByIdTab4AttachmentRegister(@Path() id: string, @Request() request: RequestWithUser) {
    const command = await this.commandRepository.findOne({
      where: { id },
      relations: ["commandType", "commandRecives"],
    });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }

    let _command: any = [];
    const path = commandTypePath(command.commandType.code);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path + "/attachment", {
        refIds: command.commandRecives
          .filter((x) => x.refId != null)
          .map((x) => ({
            refId: x.refId,
            Sequence: x.order,
            CitizenId: x.citizenId,
            Prefix: x.prefix,
            FirstName: x.firstName,
            LastName: x.lastName,
            Amount: x.amount,
            PositionSalaryAmount: x.positionSalaryAmount,
            MouthSalaryAmount: x.mouthSalaryAmount,
            RemarkHorizontal: x.remarkHorizontal,
            RemarkVertical: x.remarkVertical,
            CommandYear: command.commandYear,
          })),
      })
      .then(async (res) => {
        _command = res;
      })
      .catch(() => {});

    let issue =
      command.isBangkok == "OFFICE"
        ? "สำนักปลัดกรุงเทพมหานคร"
        : command.isBangkok == "BANGKOK"
          ? "กรุงเทพมหานคร"
          : null;
    if (issue == null) {
      const orgRevisionActive = await this.orgRevisionRepository.findOne({
        where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
        relations: ["posMasters", "posMasters.orgRoot"],
      });
      if (orgRevisionActive != null) {
        const profile = await this.profileRepository.findOne({
          where: {
            keycloak: command.createdUserId.toString(),
          },
        });
        if (profile != null) {
          issue =
            orgRevisionActive?.posMasters?.filter((x) => x.current_holderId == profile.id)[0]
              ?.orgRoot?.orgRootName || null;
        }
      }
    }
    if (issue == null) issue = "...................................";
    return new HttpSuccess({
      template: command.commandType.fileAttachment,
      reportName: "xlsx-report",
      data: {
        data: _command,
        issuerOrganizationName: issue,
        commandNo: command.commandNo == null ? "" : Extension.ToThaiNumber(command.commandNo),
        commandYear:
          command.commandYear == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiYear(command.commandYear).toString()),
        commandExcecuteDate:
          command.commandExcecuteDate == null
            ? ""
            : Extension.ToThaiNumber(Extension.ToThaiFullDate2(command.commandExcecuteDate)),
      },
    });
  }
}
