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 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,
  checkExceptCommandType,
  checkCommandType,
} from "../interfaces/utils";
import { Position } from "../entities/Position";
import { PosMaster } from "../entities/PosMaster";
import { EmployeePosition } from "../entities/EmployeePosition";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { ProfileDiscipline } from "../entities/ProfileDiscipline";
import { ProfileDisciplineHistory } from "../entities/ProfileDisciplineHistory";
import { PosMasterAct } from "../entities/PosMasterAct";
import { sendToQueue } from "../services/rabbitmq";
import { PosLevel } from "../entities/PosLevel";
import { PosType } from "../entities/PosType";
import { addUserRoles, createUser, getRoles, deleteUser, enableStatus } 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";

@Route("api/v1/org/command")
@Tags("Command")
@Security("bearerAuth")
@Response(
  HttpStatusCode.INTERNAL_SERVER_ERROR,
  "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class CommandController extends Controller {
  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 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 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);

  /**
   * API  list รายการคำสั่ง
   *
   * @summary API  list รายการคำสั่ง
   *
   */
  @Get("list")
  async GetResult(
    @Request() request: RequestWithUser,
    @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;
    if (isDirector) {
      let _data: any = {
        root: null,
        child1: null,
        child2: null,
        child3: null,
        child4: null,
      };
      if (!request.user.role.includes("SUPER_ADMIN")) {
        _data = await new permission().PermissionOrgList(request, "COMMAND");
      }
      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 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);
    }

    const [commands, total] = await this.commandRepository
      .createQueryBuilder("command")
      .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 != "" ? "command.commandNo 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")
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    const data = commands.map((_data) => ({
      id: _data.id,
      commandNo: _data.commandNo,
      commandYear: _data.commandYear,
      commandAffectDate: _data.commandAffectDate,
      commandExcecuteDate: _data.commandExcecuteDate,
      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, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    }
    command.detailHeader = commandType.detailHeader;
    command.detailBody = commandType.detailBody;
    command.detailFooter = commandType.detailFooter;
    command.isAttachment = commandType.isAttachment;
    command.status = "NEW";
    command.issue = commandType.name;
    command.createdUserId = request.user.sub;
    command.createdFullName = request.user.name;
    command.createdAt = new Date();
    command.lastUpdateUserId = request.user.sub;
    command.lastUpdateFullName = request.user.name;
    command.lastUpdatedAt = new Date();
    await this.commandRepository.save(command);
    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,
      commandNo: command.commandNo,
      commandYear: command.commandYear,
      issue: command.issue,
      detailHeader: command.detailHeader,
      detailBody: command.detailBody,
      detailFooter: command.detailFooter,
      isBangkok: command.isBangkok,
      isAttachment: command.isAttachment,
      commandAffectDate: command.commandAffectDate,
      commandExcecuteDate: command.commandExcecuteDate,
      commandTypeName: command.commandType?.name || null,
      commandCode: command.commandType?.code || null,
      commandSysId: command.commandType?.commandSysId || null,
    };
    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 });
    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,
          positionSalaryAmount: x.positionSalaryAmount,
          mouthSalaryAmount: x.mouthSalaryAmount,
        })),
    };
    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;
      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 ผู้ได้รับคำสั่ง
   */
  @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 รายละเอียดรายการคำสั่ง 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 },
      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.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);
      }),
    );

    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 } });
    if (!command) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้");
    }
    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.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 },
    });
    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,
    };
    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: "",
            }))
        : [];

    await new CallAPI()
      .PostData(request, "/placement/noti/profiles", {
        subject: `${command.issue}`,
        body: `${command.issue}`,
        receiverUserIds: profiles,
        payload: "", //แนบไฟล์
        isSendMail: true,
        isSendInbox: true,
        isSendNotification: true,
      })
      .catch((error) => {
        console.error("Error calling API:", error);
      });
    let profilesSend =
      command && command.commandSends.length > 0
        ? command.commandSends
            .filter((x) => x.profileId != null)
            .map((x) => ({
              receiverUserId: x.profileId,
              notiLink: "",
              isSendMail: x.commandSendCCs.map((x) => x.name == "EMAIL").length > 0 ? true : false,
              isSendInbox: x.commandSendCCs.map((x) => x.name == "INBOX").length > 0 ? true : false,
              isSendNotification: true,
            }))
        : [];

    await new CallAPI()
      .PostData(request, "/placement/noti/profiles-send", {
        subject: `${command.issue}`,
        body: `${command.issue}`,
        receiverUserIds: profilesSend,
        payload: "", //แนบไฟล์
      })
      .catch((error) => {
        console.error("Error calling API:", error);
      });
    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();
      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();
  }

 /**
   * API  ออกคำสั่ง
   *
   * @summary API  ออกคำสั่ง
   *
   * @param {string} id  Id คำสั่ง
   */
 @Put("testRabbit/{id}")
 async testRabbit(
   @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",],
   });
   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: "",
           }))
       : [];

   await new CallAPI()
     .PostData(request, "/placement/noti/profiles", {
       subject: `${command.issue}`,
       body: `${command.issue}`,
       receiverUserIds: profiles,
       payload: "", //แนบไฟล์
       isSendMail: true,
       isSendInbox: true,
       isSendNotification: true,
     })
     .catch((error) => {
       console.error("Error calling API:", error);
     });

   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();
     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",
      },
    });

    const data = {
      client_id: "gettoken",
      client_secret: process.env.AUTH_ACCOUNT_SECRET,
      grant_type: "password",
      requested_token_type: "urn:ietf:params:oauth:token-type:refresh_token",
      username: process.env.USERNAME_,
      password: process.env.PASSWORD_,
    };
    let _data: any = null;
    await Promise.all([
      await new CallAPI()
        .PostDataKeycloak("/realms/bma-ehr/protocol/openid-connect/token", data)
        .then(async (x) => {
          _data = x;
        })
        .catch(async (x) => {
          throw new HttpError(HttpStatus.UNAUTHORIZED, "ชื่อผู้ใช้งานหรือรหัสผ่านไม่ถูกต้อง");
        }),
    ]);
    if (_data == null) {
      return new HttpError(HttpStatus.UNAUTHORIZED, "ชื่อผู้ใช้งานหรือรหัสผ่านไม่ถูกต้อง");
    }

    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: _data.access_token,
      };
      sendToQueue(msg);
    });

    return new HttpSuccess();
  }

  /**
   * 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;
    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 = "...................................";

    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 = {
      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}`
          : "๔. ..........................กรรมการ",
    };

    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 = "...................................";
    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)),
      },
    });
  }

  /**
   * 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 สร้างรายการ 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;
      }[];
    },
    @Request() request: RequestWithUser,
  ) {
    let command = new Command();
    let commandCode = null;
    let null_: 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, "ไม่พบคำสั่งนี้ในระบบ");
      }
      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, "ไม่พบประเภทคำสั่งนี้ในระบบ");
      }
      commandCode = commandType.code;
      command.detailHeader = commandType.detailHeader;
      command.detailBody = commandType.detailBody;
      command.detailFooter = commandType.detailFooter;
      command.isAttachment = commandType.isAttachment;
      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 = new Date();
      command.lastUpdateUserId = request.user.sub;
      command.lastUpdateFullName = request.user.name;
      command.lastUpdatedAt = new Date();
      await this.commandRepository.save(command);
    }

    const path = commandTypePath(commandCode);
    if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
    await new CallAPI()
      .PostData(request, path, {
        refIds: requestBody.persons.filter((x) => x.refId != null).map((x) => x.refId),
      })
      .then(async (res) => {
        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_;
            if (item.profileId) {
              salaryData = await this.profileRepository.findOne({
                where: {
                  id: item.profileId,
                },
              });
              let null_: any = 0;
              if (!salaryData) {
                salaryData = await this.profileEmployeeRepository.findOne({
                  where: {
                    id: item.profileId,
                  },
                });
              }
              commandRecive.amount = salaryData ? salaryData.amount : null_;
              commandRecive.positionSalaryAmount = salaryData
                ? salaryData.positionSalaryAmount
                : null_;
              commandRecive.mouthSalaryAmount = salaryData ? salaryData.mouthSalaryAmount : null_;
            } else {
              commandRecive.amount = null_;
              commandRecive.positionSalaryAmount = null_;
              commandRecive.mouthSalaryAmount = null_;
            }
            commandRecive.remarkVertical =
              item.remarkVertical == null ? null_ : item.remarkVertical;
            commandRecive.remarkHorizontal =
              item.remarkHorizontal == null ? null_ : item.remarkHorizontal;
            commandRecive.order = order;
            commandRecive.commandId = command.id;
            commandRecive.createdUserId = request.user.sub;
            commandRecive.createdFullName = request.user.name;
            commandRecive.createdAt = new Date();
            commandRecive.lastUpdateUserId = request.user.sub;
            commandRecive.lastUpdateFullName = request.user.name;
            commandRecive.lastUpdatedAt = new Date();
            await this.commandReciveRepository.save(commandRecive);
          }),
        );
      })
      .catch(() => {});

    if (requestBody.persons != undefined && requestBody.persons.length > 0) {
      const posMaster = await this.posMasterRepository.find({
        where: {
          current_holderId: In(requestBody.persons.map((x) => x.profileId)),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
        },
        select: ["orgRootId"],
      });
      let _posMaster: any;
      if (["C-PM-38", "C-PM-40"].includes(commandCode)) {
        _posMaster = await this.posMasterRepository.find({
          where: {
            orgRootId: In(posMaster.map((x) => x.orgRootId)),
            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(posMaster.map((x) => x.orgRootId)),
            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_holder.id,
            },
          });
          if (_commandSend) return;
          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_holder.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);
        }),
      );

      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),
          ),
          orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
          isDirector: true,
          current_holderId: Not(IsNull()),
        },
        relations: ["current_holder", "orgRoot"],
      });
      await Promise.all(
        _posMasterNext.map(async (item) => {
          const _commandSend = await this.commandSendRepository.findOne({
            where: {
              commandId: command.id,
              profileId: item.current_holder.id,
            },
          });
          if (_commandSend) return;
          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_holder.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);
        }),
      );
    }
    return new HttpSuccess(command.id);
  }

  @Post("excexute/salary-current")
  public async newSalaryAndUpdateCurrent(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        posNo: string | null;
        position: string | null;
        positionLine: string | null;
        positionPathSide: string | null;
        positionExecutive: string | null;
        positionType: string | null;
        positionLevel: string | null;
        refCommandNo: string | null;
        templateDoc: string | null;
        posmasterId: string;
        positionId: string;
        commandId?: string | null;
      }[];
    },
  ) {
    await Promise.all(
      body.data.map(async (item) => {
        const profile = 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(),
        };

        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 });

        const posMaster = await this.posMasterRepository.findOne({
          where: { id: item.posmasterId },
        });
        if (posMaster == null)
          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;

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

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

        posMaster.current_holderId = item.profileId;
        if (posMasterOld != null) await this.posMasterRepository.save(posMasterOld);
        await this.posMasterRepository.save(posMaster);

        const positionNew = await this.positionRepository.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;
          await this.profileRepository.save(profile);
          await this.positionRepository.save(positionNew);
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee-current")
  public async newSalaryEmployeeAndUpdateCurrent(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        posNo: string | null;
        position: string | null;
        positionType: string | null;
        positionLevel: string | null;
        refCommandNo: string | null;
        templateDoc: string | null;
        posmasterId: string;
        positionId: string;
        commandId?: 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 });

        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;
        // 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.next_holderId = null;
        if (posMasterOld != null) await this.employeePosMasterRepository.save(posMasterOld);
        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;

          await this.profileEmployeeRepository.save(profile);
          await this.employeePositionRepository.save(positionNew);
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-leave")
  public async newSalaryAndUpdateLeave(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        posNo: string | null;
        position: string | null;
        positionLine: string | null;
        positionPathSide: string | null;
        positionExecutive: string | null;
        positionType: string | null;
        positionLevel: string | null;
        refCommandNo: string | null;
        templateDoc: string | null;
        isLeave: boolean;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        commandId?: string | null;
        isGovernment?: boolean | null;
      }[];
    },
  ) {
    const roleKeycloak = await this.roleKeycloakRepo.findOne({
      where: { name: Like("USER") },
    });
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          where: { id: item.profileId },
          relations: ["roleKeycloaks"],
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }

        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(),
        };

        Object.assign(data, { ...item, ...meta });
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...data, id: undefined });
        data.dateGovernment = 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();
        // profile.dateStart = new Date();
        if (item.isLeave == true) {
          await removeProfileInOrganize(profile.id, "OFFICER");
        }
        const clearProfile = await checkCommandType(String(item.commandId));
        if (clearProfile) {
          if (profile.keycloak != null) {
            const delUserKeycloak = await deleteUser(profile.keycloak);
            if (delUserKeycloak) profile.keycloak = _null;
            profile.roleKeycloaks = [];
          }
          profile.position = _null;
          profile.posTypeId = _null;
          profile.posLevelId = _null;
        }
        const returnWork = await checkReturnCommandType(String(item.commandId));
        if (returnWork && item.isGovernment) {
          if (profile.keycloak != null) {
            const enableActive = await enableStatus(profile.keycloak, true);
            if (!enableActive) throw new Error("Failed. Cannot change enable status.");
          } else {
            const userKeycloakId = await createUser(profile.citizenId, profile.citizenId, {
              firstName: profile.firstName,
              lastName: profile.lastName,
            });
            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;
          }
          profile.isActive = true;
          profile.roleKeycloaks = profile.roleKeycloaks ?? [roleKeycloak];
        }
        await this.profileRepository.save(profile);
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee-leave")
  public async newSalaryEmployeeAndUpdateLeave(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        posNo: string | null;
        position: string | null;
        positionType: string | null;
        positionLevel: string | null;
        refCommandNo: string | null;
        templateDoc: string | null;
        isLeave: boolean;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        isGovernment?: boolean | null;
        commandId?: string | null;
      }[];
    },
  ) {
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileEmployeeRepository.findOne({
          where: { id: item.profileId },
          relations: ["roleKeycloaks"],
        });
        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 });
        data.dateGovernment = 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();
        if (item.isLeave == true) {
          await removeProfileInOrganize(profile.id, "EMPLOYEE");
        }
        const clearProfile = await checkCommandType(String(item.commandId));
        if (clearProfile) {
          if (profile.keycloak != null) {
            const delUserKeycloak = await deleteUser(profile.keycloak);
            if (delUserKeycloak) profile.keycloak = _null;
            profile.roleKeycloaks = [];
            profile.isActive = false;
          }
          profile.position = _null;
          profile.posTypeId = _null;
          profile.posLevelId = _null;
        }
        await this.profileEmployeeRepository.save(profile);
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary")
  public async newSalaryAndUpdate(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        posNo: string | null;
        position: string | null;
        positionLine: string | null;
        positionPathSide: string | null;
        positionExecutive: string | null;
        positionType: string | null;
        positionLevel: string | null;
        refCommandNo: string | null;
        templateDoc: string | null;
        commandId?: string | null;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        isLeave?: boolean;
      }[];
    },
  ) {
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          where: { id: item.profileId },
          relations: ["roleKeycloaks"],
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }

        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(),
        };
        if (item.isLeave != undefined && item.isLeave == true) {
          await removeProfileInOrganize(profile.id, "OFFICER");
        }
        const clearProfile = await checkCommandType(String(item.commandId));
        const _null: any = null;
        if (clearProfile) {
          if (profile.keycloak != null) {
            const delUserKeycloak = await deleteUser(profile.keycloak);
            if (delUserKeycloak) profile.keycloak = _null;
            profile.roleKeycloaks = [];
          }
          profile.position = _null;
          profile.posTypeId = _null;
          profile.posLevelId = _null;
          profile.leaveReason = item.leaveReason ?? _null;
          profile.dateLeave = item.dateLeave ?? _null;
          await this.profileRepository.save(profile, { data: req });
        }
        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 });
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-employee")
  public async newSalaryEmployeeAndUpdate(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        posNo: string | null;
        position: string | null;
        positionType: string | null;
        positionLevel: string | null;
        refCommandNo: string | null;
        templateDoc: 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 });
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-leave-discipline")
  public async newSalaryAndUpdateLeaveDiscipline(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        refCommandNo?: string | null;
        salaryRef?: string | null;
        isLeave: boolean | null;
        leaveReason?: string | null;
        dateLeave?: Date | null;
        refCommandDate?: Date | null;
        detail?: string | null;
        level?: string | null;
        unStigma?: string | null;
        commandId?: string | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        isGovernment?: boolean | null;
      }[];
    },
  ) {
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          relations: ["profileSalary", "posLevel", "posType", "current_holders", "roleKeycloaks"],
          where: { id: item.profileId },
          order: {
            profileSalary: {
              order: "DESC",
            },
          },
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }
        const orgRevision = await this.orgRevisionRepo.findOne({
          where: {
            orgRevisionIsCurrent: true,
            orgRevisionIsDraft: false,
          },
        });
        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)?.posMasterNo}`
              : 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)?.posMasterNo}`
                : 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)?.posMasterNo}`
                  : 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)?.posMasterNo}`
                    : 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}${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`
                      : 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();
        const meta = {
          profileId: profile.id,
          commandId: item.commandId,
          date: item.date,
          refCommandNo: item.refCommandNo,
          templateDoc: item.salaryRef,
          position: profile.position,
          positionType: profile.posType.posTypeName,
          positionLevel: profile.posLevel.posLevelName,
          posNo: shortName ? shortName : "-",
          positionLine: position?.positionField ?? "-",
          positionPathSide: position?.positionArea ?? "-",
          positionExecutive: position?.posExecutive?.posExecutiveName ?? "-",
          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,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          dateGovernment: new Date(),
          isGovernment: item.isGovernment,
        };

        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, { ...body, ...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 },
          });
          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();
          const exceptClear = await checkExceptCommandType(String(item.commandId));
          if (item.isLeave == true && !exceptClear) {
            await removeProfileInOrganize(_profile.id, "OFFICER");
          } else if (item.isLeave == true && exceptClear && _profile.keycloak != null) {
            const enableActive = await enableStatus(_profile.keycloak, false);
            if (!enableActive) throw new Error("Failed. Cannot change enable status.");
            _profile.isActive = false;
          }
          const clearProfile = await checkCommandType(String(item.commandId));
          if (clearProfile) {
            if (_profile.keycloak != null) {
              const delUserKeycloak = await deleteUser(_profile.keycloak);
              if (delUserKeycloak) _profile.keycloak = _null;
              _profile.roleKeycloaks = [];
            }
            _profile.position = _null;
            _profile.posTypeId = _null;
            _profile.posLevelId = _null;
          }
          await this.profileRepository.save(_profile);
        }
      }),
    );

    return new HttpSuccess();
  }

  @Post("excexute/salary-probation")
  public async newSalaryAndUpdateLeaveDisciplinefgh(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        refCommandNo?: string | null;
        salaryRef?: string | null;
        commandId?: string | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
      }[];
    },
  ) {
    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",
          ],
          where: { id: item.profileId },
          order: {
            profileSalary: {
              order: "DESC",
            },
          },
        });
        if (!profile) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
        }

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

        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)?.posMasterNo}`
              : 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)?.posMasterNo}`
                : 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)?.posMasterNo}`
                  : 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)?.posMasterNo}`
                    : 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}${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`
                      : 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();
        const meta = {
          profileId: item.profileId,
          date: item.date,
          refCommandNo: item.refCommandNo,
          templateDoc: item.salaryRef,
          commandId: item.commandId,
          position: profile.position,
          positionType: profile.posType.posTypeName,
          positionLevel: profile.posLevel.posLevelName,
          posNo: shortName ? shortName : "-",
          positionLine: position?.positionField ?? "-",
          positionPathSide: position?.positionArea ?? "-",
          positionExecutive: position?.posExecutive?.posExecutiveName ?? "-",
          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,
          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, 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 checkCommandType = await this.commandRepository.findOne({
      where: { id: body.data.length > 0 ? body.data[0].commandId?.toString() : "" },
      relations: ["commandType"],
    });
    if (checkCommandType?.commandType.code == "C-PM-11") {
      const profile = await this.profileRepository.find({
        where: { id: In(body.data.map((x) => x.profileId)) },
      });
      const data = profile.map((x) => ({
        ...x,
        isProbation: false,
      }));
      await this.profileRepository.save(data);
    }
    return new HttpSuccess();
  }

  @Post("excexute/salary-probation-leave")
  async ExecuteCommand12Async(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      data: {
        profileId: string;
        date?: Date | null;
        refCommandNo?: string | null;
        salaryRef?: string | null;
        commandId?: string | null;
        amount?: Double | null;
        positionSalaryAmount?: Double | null;
        mouthSalaryAmount?: Double | null;
        isGovernment?: boolean | null;
      }[];
    },
  ) {
    await Promise.all(
      body.data.map(async (item) => {
        const profile = await this.profileRepository.findOne({
          relations: [
            "profileSalary",
            "posType",
            "posLevel",
            "current_holders",
            "current_holders.positions",
            "current_holders.positions.posExecutive",
          ],
          where: { id: item.profileId },
          order: {
            profileSalary: {
              order: "DESC",
            },
          },
        });
        if (!profile) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
        }
        const _profile = await this.profileRepository.findOne({
          where: { id: item.profileId },
          relations: ["roleKeycloaks"],
        });
        if (!_profile) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลโปรไฟล์");
        }
        let dateLeave_: any = item.date;
        _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 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)?.posMasterNo}`
              : 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)?.posMasterNo}`
                : 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)?.posMasterNo}`
                  : 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)?.posMasterNo}`
                    : 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}${profile.current_holders.find((x) => x.orgRevisionId == orgRevision?.id)?.posMasterNo}`
                      : null;
        let position =
          profile.current_holders
            .filter((x) => x.orgRevisionId == orgRevision?.id)[0]
            ?.positions?.filter((pos) => pos.positionIsSelected === true)[0] ?? null;
        const profileSalary: ProfileSalary = Object.assign(new ProfileSalary(), {
          profileId: item.profileId,
          date: item.date,
          refCommandNo: item.refCommandNo,
          templateDoc: item.salaryRef,
          commandId: item.commandId,
          position: profile.position,
          positionType: profile.posType.posTypeName,
          positionLevel: profile.posLevel.posLevelName,
          posNo: shortName,
          positionLine: position?.positionField ?? "-",
          positionPathSide: position?.positionArea ?? "-",
          positionExecutive: position?.posExecutive?.posExecutiveName ?? "-",
          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,
          createdUserId: req.user.sub,
          createdFullName: req.user.name,
          lastUpdateUserId: req.user.sub,
          lastUpdateFullName: req.user.name,
          createdAt: new Date(),
          lastUpdatedAt: new Date(),
          dateGovernment: new Date(),
          isGovernment: item.isGovernment,
        });
        await removeProfileInOrganize(profile.id, "OFFICER");
        const clearProfile = await checkCommandType(String(item.commandId));
        const _null: any = null;
        if (clearProfile) {
          if (_profile.keycloak != null) {
            const delUserKeycloak = await deleteUser(_profile.keycloak);
            if (delUserKeycloak) _profile.keycloak = _null;
            _profile.roleKeycloaks = [];
          }
          _profile.position = _null;
          _profile.posTypeId = _null;
          _profile.posLevelId = _null;
        }
        await Promise.all([
          this.profileRepository.save(_profile),
          this.salaryRepo.save(profileSalary),
        ]);
        const history = new ProfileSalaryHistory();
        Object.assign(history, { ...profileSalary, id: undefined });
        history.profileSalaryId = profileSalary.id;
        await this.salaryHistoryRepo.save(history);
      }),
    );

    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;
        } | null;
      }[];
    },
  ) {
    const roleKeycloak = await this.roleKeycloakRepo.findOne({
      where: { name: Like("USER") },
    });
    await Promise.all(
      body.data.map(async (item) => {
        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(),
        };
        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 }))
        ) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้");
        }
        if (
          item.bodyProfile.posTypeId &&
          !(await this.posTypeRepo.findOneBy({ id: item.bodyProfile.posTypeId }))
        ) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้");
        }

        let profile: any = await this.profileRepository.findOne({
          where: { citizenId: item.bodyProfile.citizenId },
          relations: ["roleKeycloaks"],
        });
        if (!profile) {
          profile = Object.assign({ ...item.bodyProfile, ...meta });
          profile.dateRetire =
            item.bodyProfile.birthDate == null
              ? _null
              : calculateRetireDate(item.bodyProfile.birthDate);
          profile.dateRetireLaw =
            item.bodyProfile.birthDate == null
              ? _null
              : calculateRetireLaw(item.bodyProfile.birthDate);
          const userKeycloakId = await createUser(profile.citizenId, profile.citizenId, {
            firstName: profile.firstName,
            lastName: profile.lastName,
          });
          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;
          profile.roleKeycloaks = roleKeycloak ? [roleKeycloak] : [];
          profile.email = item.bodyProfile.email;
          profile.dateStart = item.bodyProfile.dateStart;
          await this.profileRepository.save(profile);
          setLogDataDiff(req, { before, after: profile });
        }
        if (profile && profile.id) {
          //Educations
          if (item.bodyEducations && item.bodyEducations.length > 0) {
            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;
                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) {
            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 });
              }),
            );
          }
          //Salary
          if (item.bodySalarys && item.bodySalarys != null) {
            const dest_item = await this.salaryRepo.findOne({
              where: { profileId: profile.id },
              order: { order: "DESC" },
            });
            const profileSal = new ProfileSalary();
            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 = meta.createdAt;
            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) {
            const posMaster = await this.posMasterRepository.findOne({
              where: { id: item.bodyPosition.posmasterId },
            });
            if (posMaster == null)
              throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");

            const posMasterOld = await this.posMasterRepository.findOne({
              where: {
                current_holderId: profile.id,
                orgRevisionId: posMaster.orgRevisionId,
              },
            });
            if (posMasterOld != null) posMasterOld.current_holderId = null;

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

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

            posMaster.current_holderId = profile.id;
            if (posMasterOld != null) await this.posMasterRepository.save(posMasterOld);
            await this.posMasterRepository.save(posMaster);

            const positionNew = await this.positionRepository.findOne({
              where: {
                id: item.bodyPosition.positionId,
                posMasterId: item.bodyPosition.posmasterId,
              },
            });
            if (positionNew != null) {
              positionNew.positionIsSelected = true;
              profile.posLevelId = positionNew.posLevelId;
              profile.posTypeId = positionNew.posTypeId;
              profile.position = positionNew.positionName;
              profile.dateStart = new Date();
              await this.profileRepository.save(profile, { data: req });
              setLogDataDiff(req, { before, after: profile });
              await this.positionRepository.save(positionNew, { data: req });
            }
          }
        }
      }),
    );
    return new HttpSuccess();
  }

  @Post("command21/employee/report")
  public async command21SalaryEmployee(
    @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: "REPORT",
    }));
    await this.profileEmployeeRepository.save(data);
    return new HttpSuccess();
  }

  @Post("command38/officer/report")
  public async command38SalaryOfficer(
    @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: "REPORT",
    }));
    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[];
    },
  ) {
    const posMasters = await this.posMasterActRepository.find({ where: { id: In(body.refIds) } });
    const data = posMasters.map((_data) => ({
      ..._data,
      statusReport: "REPORT",
    }));
    await this.posMasterActRepository.save(data);
    return new HttpSuccess();
  }

  @Post("command21/employee/report/excecute")
  public async command21SalaryEmployeeExcecute(
    @Request() req: RequestWithUser,
    @Body()
    body: {
      refIds: {
        refId: string;
        commandAffectDate: Date | null;
        commandNo: string | null;
        commandId?: string | null;
        commandYear: number;
        templateDoc: string | null;
        amount: Double | null;
        positionSalaryAmount: Double | null;
        mouthSalaryAmount: Double | null;
      }[];
    },
  ) {
    const roleKeycloak = await this.roleKeycloakRepo.findOne({
      where: { name: Like("USER") },
    });
    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 dest_item = await this.salaryRepo.findOne({
          where: { profileEmployeeId: item.refId },
          order: { order: "DESC" },
        });
        const before = null;
        const data = new ProfileSalary();

        const meta = {
          profileEmployeeId: profile.id,
          date: new Date(),
          amount: item.amount,
          commandId: item.commandId,
          positionSalaryAmount: item.positionSalaryAmount,
          mouthSalaryAmount: item.mouthSalaryAmount,
          posNo: profile.posMasterNoTemp,
          position: profile.positionTemp,
          positionType: profile.posTypeNameTemp,
          positionLevel: profile.posLevelNameTemp,
          refCommandNo: `${item.commandNo}/${Extension.ToThaiYear(item.commandYear)}`,
          templateDoc: item.templateDoc,
          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, 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"],
        });
        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;
        // 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.next_holderId = null;
        if (posMasterOld != null) await this.employeePosMasterRepository.save(posMasterOld);
        await this.employeePosMasterRepository.save(posMaster);

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

        if (positionNew != null) {
          // Create Keycloak
          const userKeycloakId = await createUser(profile.citizenId, profile.citizenId, {
            firstName: profile.firstName,
            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;
          profile.roleKeycloaks = roleKeycloak ? [roleKeycloak] : [];
          // End Create Keycloak

          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 = new Date();
          // profile.amount = item.amount == null ? _null : item.amount.toString(); //เผื่อไว้
          // profile.positionSalaryAmount = item.positionSalaryAmount == null ? _null : item.positionSalaryAmount.toString();
          // profile.mouthSalaryAmount = item.mouthSalaryAmount == null ? _null : item.mouthSalaryAmount.toString();

          await this.profileEmployeeRepository.save(profile);
          await this.employeePositionRepository.save(positionNew);
        }
      }),
    );

    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;
        commandAffectDate: Date | null;
        commandNo: string | null;
        commandId?: string | null;
        commandYear: number;
        templateDoc: string | null;
        amount: Double | null;
        positionSalaryAmount: Double | null;
        mouthSalaryAmount: Double | null;
      }[];
    },
  ) {
    const posMasters = await this.posMasterActRepository.find({
      where: { id: In(body.refIds.map((x) => x.refId)) },
    });
    const data = posMasters.map((_data) => ({
      ..._data,
      statusReport: "PENDING",
    }));
    await this.posMasterActRepository.save(data);
    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;
        PositionSalaryAmount?: any | null;
        MouthSalaryAmount?: any | null;
        RemarkHorizontal?: any | null;
        RemarkVertical?: any | null;
        CommandYear?: any | 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: "-",
          dateEnd: "-",
          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;
        commandAffectDate: Date | null;
        commandNo: string | null;
        commandId?: string | null;
        commandYear: number;
        templateDoc: string | null;
        amount: Double | null;
        positionSalaryAmount: Double | null;
        mouthSalaryAmount: Double | null;
      }[];
    },
  ) {
    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 shortName =
            posMaster != null && posMaster.orgChild4 != null
              ? `${posMaster.orgChild4.orgChild4ShortName}${posMaster.posMasterNo}`
              : posMaster != null && posMaster.orgChild3 != null
                ? `${posMaster.orgChild3.orgChild3ShortName}${posMaster.posMasterNo}`
                : posMaster != null && posMaster.orgChild2 != null
                  ? `${posMaster.orgChild2.orgChild2ShortName}${posMaster.posMasterNo}`
                  : posMaster != null && posMaster.orgChild1 != null
                    ? `${posMaster.orgChild1.orgChild1ShortName}${posMaster.posMasterNo}`
                    : posMaster != null && posMaster?.orgRoot != null
                      ? `${posMaster.orgRoot.orgRootShortName}${posMaster.posMasterNo}`
                      : 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();

          const meta = {
            profileId: profile?.id,
            date: new Date(),
            amount: item.amount,
            commandId: item.commandId,
            positionSalaryAmount: item.positionSalaryAmount,
            mouthSalaryAmount: item.mouthSalaryAmount,
            posNo: shortName ?? null,
            position: position?.positionName ?? null,
            positionType: position?.posType.posTypeName ?? null,
            positionLevel: position?.posLevel.posLevelName ?? null,
            refCommandNo: `${item.commandNo}/${Extension.ToThaiYear(item.commandYear)}`,
            templateDoc: item.templateDoc,
            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, 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,
    };
    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)),
      },
    });
  }
}
