import { Controller, Post, Put, Delete, Route, Security, Tags, Body, Path, Request, SuccessResponse, Response, Get, } 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 { Profile, CreateProfile, UpdateProfile } from "../entities/Profile"; import { Brackets, In, IsNull, Like, Not } from "typeorm"; import { OrgRevision } from "../entities/OrgRevision"; import { PosMaster } from "../entities/PosMaster"; import { PosLevel } from "../entities/PosLevel"; import { PosType } from "../entities/PosType"; @Route("api/v1/org/profile") @Tags("Profile") @Security("bearerAuth") @Response( HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", ) @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") export class ProfileController extends Controller { private orgRevisionRepository = AppDataSource.getRepository(OrgRevision); private posMasterRepository = AppDataSource.getRepository(PosMaster); private profileRepository = AppDataSource.getRepository(Profile); private posLevelRepository = AppDataSource.getRepository(PosLevel); private posTypeRepository = AppDataSource.getRepository(PosType); /** * API สร้างทะเบียนประวัติ * * @summary ORG_065 - สร้างทะเบียนประวัติ (ADMIN) #70 * */ @Post() async createProfile( @Body() requestBody: CreateProfile, @Request() request: { user: Record }, ) { if (requestBody.posLevelId == "") { requestBody.posLevelId = null; } if (requestBody.posLevelId) { const checkPosLevel = await this.posLevelRepository.findOne({ where: { id: requestBody.posLevelId }, }); if (!checkPosLevel) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลใน PosLevel จากไอดีนี้ : " + requestBody.posLevelId, ); } } if (requestBody.posTypeId == "") { requestBody.posTypeId = null; } if (requestBody.posTypeId) { const checkPosType = await this.posTypeRepository.findOne({ where: { id: requestBody.posTypeId }, }); if (!checkPosType) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลใน PosType จากไอดีนี้ : " + requestBody.posTypeId, ); } } const checkCitizenId = await this.profileRepository.findOne({ where: { citizenId: requestBody.citizenId }, }); if (checkCitizenId) { throw new HttpError( HttpStatusCode.NOT_FOUND, "มีรหัสประจำตัวประชาชนนี้แล้วในระบบ (citizenId)", ); } try { const profile = Object.assign(new Profile(), requestBody); profile.createdUserId = request.user.sub; profile.createdFullName = request.user.name; profile.lastUpdateUserId = request.user.sub; profile.lastUpdateFullName = request.user.name; await this.profileRepository.save(profile); return new HttpSuccess(); } catch (error) { return error; } } /** * API แก้ไขทะเบียนประวัติ * * @summary ORG_065 - แก้ไขทะเบียนประวัติ (ADMIN) #70 * * @param {string} id Id ทะเบียนประวัติ */ @Put("{id}") async updateProfile( @Path() id: string, @Body() requestBody: CreateProfile, @Request() request: { user: Record }, ) { const profile = await this.profileRepository.findOne({ where: { id: id } }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้ : " + id); } if (requestBody.posLevelId == "") { requestBody.posLevelId = null; } if (requestBody.posLevelId) { const checkPosLevel = await this.posLevelRepository.findOne({ where: { id: requestBody.posLevelId }, }); if (!checkPosLevel) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลใน PosLevel จากไอดีนี้ : " + requestBody.posLevelId, ); } } if (requestBody.posTypeId == "") { requestBody.posTypeId = null; } if (requestBody.posTypeId) { const checkPosType = await this.posTypeRepository.findOne({ where: { id: requestBody.posTypeId }, }); if (!checkPosType) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลใน PosType จากไอดีนี้ : " + requestBody.posTypeId, ); } } const checkCitizenId = await this.profileRepository.findOne({ where: { citizenId: requestBody.citizenId }, }); if (checkCitizenId) { throw new HttpError( HttpStatusCode.NOT_FOUND, "มีรหัสประจำตัวประชาชนนี้แล้วในระบบ (citizenId)", ); } try { profile.lastUpdateUserId = request.user.sub; profile.lastUpdateFullName = request.user.name; this.profileRepository.merge(profile, requestBody); await this.profileRepository.save(profile); return new HttpSuccess(); } catch (error) { return error; } } /** * API ลบทะเบียนประวัติ * * @summary ORG_065 - ลบทะเบียนประวัติ (ADMIN) #70 * * @param {string} id Id ทะเบียนประวัติ */ @Delete("{id}") async deleteProfile(@Path() id: string) { const delProfile = await this.profileRepository.findOne({ where: { id }, }); if (!delProfile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งตามไอดีนี้ : " + id); } try { await this.profileRepository.delete({ id: id }); return new HttpSuccess(); } catch (error) { return error; } } /** * API รายละเอียดรายการทะเบียนประวัติ * * @summary ORG_065 - รายละเอียดรายการทะเบียนประวัติ (ADMIN) #70 * * @param {string} id Id ทะเบียนประวัติ */ @Get("{id}") async detailProfile(@Path() id: string) { const profile = await this.profileRepository.findOne({ where: { id }, select: [ "id", "prefix", "firstName", "lastName", "citizenId", "position", "posLevelId", "posTypeId", ], }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); } try { return new HttpSuccess(profile); } catch (error) { return error; } } /** * API รายการทะเบียนประวัติ * * @summary ORG_065 - รายการทะเบียนประวัติ (ADMIN) #70 * */ @Get() async listProfile() { const profile = await this.profileRepository.find({ select: [ "id", "prefix", "firstName", "lastName", "citizenId", "position", "posLevelId", "posTypeId", ], order: { createdAt: "ASC" }, }); if (!profile) { return new HttpSuccess([]); } try { return new HttpSuccess(profile); } catch (error) { return error; } } /** * API ค้นหารายชื่อไปครองตำแหน่ง * * @summary ORG_063 - ค้นหารายชื่อไปครองตำแหน่ง (ADMIN) #68 * */ @Post("search") async searchProfileOrg( @Body() requestBody: { position?: string; posLevelId?: string; posTypeId?: string; page: number; pageSize: number; keyword?: string; }, ) { try { const orgRevision = await this.orgRevisionRepository.findOne({ where: { orgRevisionIsDraft: true, orgRevisionIsCurrent: false, }, relations: ["posMasters"], }); if (!orgRevision) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง"); } const [profiles, total] = await this.profileRepository .createQueryBuilder("profile") .leftJoinAndSelect("profile.next_holders", "next_holders") .leftJoinAndSelect("profile.posLevel", "posLevel") .leftJoinAndSelect("profile.posType", "posType") .where( requestBody.position != null && requestBody.position != "" ? "profile.position LIKE :position" : "1=1", { position: `%${requestBody.position}%`, }, ) .andWhere( new Brackets((qb) => { qb.where( requestBody.keyword != null && requestBody.keyword != "" ? "profile.prefix LIKE :keyword" : "1=1", { keyword: `%${requestBody.keyword}%`, }, ) .orWhere( requestBody.keyword != null && requestBody.keyword != "" ? "profile.firstName LIKE :keyword" : "1=1", { keyword: `%${requestBody.keyword}%`, }, ) .orWhere( requestBody.keyword != null && requestBody.keyword != "" ? "profile.lastName LIKE :keyword" : "1=1", { keyword: `%${requestBody.keyword}%`, }, ) .orWhere( requestBody.keyword != null && requestBody.keyword != "" ? "profile.citizenId LIKE :keyword" : "1=1", { keyword: `%${requestBody.keyword}%`, }, ); }), ) .andWhere( requestBody.posTypeId != null && requestBody.posTypeId != "" ? "profile.posTypeId LIKE :posTypeId" : "1=1", { posTypeId: `%${requestBody.posTypeId}%`, }, ) .andWhere( requestBody.posLevelId != null && requestBody.posLevelId != "" ? "profile.posLevelId LIKE :posLevelId" : "1=1", { posLevelId: `%${requestBody.posLevelId}%`, }, ) .andWhere( new Brackets((qb) => { qb.where("next_holders.id IS NULL").orWhere("next_holders.id NOT IN (:...ids)", { ids: orgRevision.posMasters.map((x) => x.id), }); }), ) .skip((requestBody.page - 1) * requestBody.pageSize) .take(requestBody.pageSize) .getManyAndCount(); const data = profiles.map((_data) => ({ id: _data.id, prefix: _data.prefix, firstName: _data.firstName, lastName: _data.lastName, citizenId: _data.citizenId, posLevel: _data.posLevel == null ? null : _data.posLevel.posLevelName, posType: _data.posType == null ? null : _data.posType.posTypeName, position: _data.position, })); return new HttpSuccess({ data: data, total }); } catch (error) { return error; } } /** * API ข้อมูลทะเบียนประวัติตาม keycloak * * @summary ORG_065 - ข้อมูลทะเบียนประวัติตาม keycloak (ADMIN) #70 * */ @Get("keycloak/position") async getProfileByKeycloak(@Request() request: { user: Record }) { const profile = await this.profileRepository.findOne({ where: { keycloak: request.user.sub }, relations: ["posLevel", "posType"], }); if (!profile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง"); } const _profile = { profileId: profile.id, prefix: profile.prefix, firstName: profile.firstName, lastName: profile.lastName, citizenId: profile.citizenId, position: profile.position, posLevelName: profile.posLevel == null ? null : profile.posLevel.posLevelName, posLevelRank: profile.posLevel == null ? null : profile.posLevel.posLevelRank, posLevelId: profile.posLevel == null ? null : profile.posLevel.id, posTypeName: profile.posType == null ? null : profile.posType.posTypeName, posTypeRank: profile.posType == null ? null : profile.posType.posTypeRank, posTypeId: profile.posType == null ? null : profile.posType.id, }; try { return new HttpSuccess(_profile); } catch (error: any) { throw new Error(error); } } /** * API ค้นหาข้อมูลทะเบียนประวัติ * * @summary ORG_065 - ค้นหาข้อมูลทะเบียนประวัติ (ADMIN) #70 * */ @Post("search-personal") async getProfileBySearchKeyword( @Body() body: { fieldName: string; keyword?: string; }, ) { try { let findProfile: any; switch (body.fieldName) { case "idcard": findProfile = await this.profileRepository.find({ where: { citizenId: Like(`%${body.keyword}%`) }, relations: ["posType", "posLevel"], }); break; case "firstname": findProfile = await this.profileRepository.find({ where: { firstName: Like(`%${body.keyword}%`) }, relations: ["posType", "posLevel"], }); break; case "lastname": findProfile = await this.profileRepository.find({ where: { lastName: Like(`%${body.keyword}%`) }, relations: ["posType", "posLevel"], }); break; default: findProfile = await this.profileRepository.find({ relations: ["posType", "posLevel"], }); break; } const mapDataProfile = await Promise.all( findProfile.map(async (item: Profile) => { return { id: item.id, prefix: item.prefix, firstName: item.firstName, lastName: item.lastName, position: item.position, idcard: item.citizenId, email: item.email, phone: item.phone, }; }), ); return new HttpSuccess(mapDataProfile); } catch (error: any) { throw new Error(error); } } /** * API ค้นหาผู้บังคับบัญชา * * @summary ORG_069 - ค้นหาผู้บังคับบัญชา (ADMIN) #75 * */ @Get("search/commander") async searchCommander(@Request() request: { user: Record }) { let fullName_: any = {}; let position_: any = {}; let commanderAboveFullname_: any = {}; let commanderAbovePosition_: any = {}; let commanderFullname_: any = {}; let commanderPosition_: any = {}; const findProfile = await this.profileRepository.findOne({ where: { keycloak: request.user.sub }, }); const findRevision = await this.orgRevisionRepository.findOne({ where: { orgRevisionIsCurrent: true, }, }); const findPosMaster = await this.posMasterRepository.findOne({ where: { current_holderId: findProfile?.id, orgRevisionId: findRevision?.id, }, }); let node = 4; let childId = findPosMaster?.orgChild4Id; let condition: any = { orgChild4Id: childId }; if (findPosMaster?.orgChild4Id == null && findPosMaster?.orgChild3Id != null) { node = 3; childId = findPosMaster?.orgChild3Id; condition = { orgChild3Id: childId, orgChild4Id: IsNull() }; } else if (findPosMaster?.orgChild3Id == null && findPosMaster?.orgChild2Id != null) { node = 2; childId = findPosMaster?.orgChild2Id; condition = { orgChild2Id: childId, orgChild3Id: IsNull() }; } else if (findPosMaster?.orgChild2Id == null && findPosMaster?.orgChild1Id != null) { node = 1; childId = findPosMaster?.orgChild1Id; condition = { orgChild1Id: childId, orgChild2Id: IsNull() }; } else if (findPosMaster?.orgChild1Id == null) { node = 0; childId = findPosMaster?.orgRootId; condition = { orgRootId: childId, orgChild1Id: IsNull() }; } const findCmd = await this.posMasterRepository.findOne({ where: { current_holderId: Not(IsNull()) || Not(""), orgRevisionId: findRevision?.id, ...condition, }, relations: ["current_holder"], order: { posMasterOrder: "ASC" }, }); let findOSAB: PosMaster | null = null; let findTSAB: PosMaster | null = null; //หาผู้บังคับบัญชาที่เหนือขึ้นไปอีก 1 ขั้น if (node !== 0) { findOSAB = await AppDataSource.getRepository(PosMaster) .createQueryBuilder("posMaster") .leftJoinAndSelect("posMaster.current_holder", "current_holder") .where("posMaster.current_holderId IS NOT NULL") .andWhere("posMaster.orgRevisionId = :revisionId", { revisionId: findRevision?.id }) .andWhere( new Brackets((qb) => { if (node === 4) { qb.andWhere("posMaster.orgChild4Id IS NULL"); qb.andWhere("posMaster.orgChild3Id = :childId", { childId: findPosMaster?.orgChild3Id, }); } else if (node === 3) { qb.andWhere("posMaster.orgChild3Id IS NULL"); qb.andWhere("posMaster.orgChild2Id = :childId", { childId: findPosMaster?.orgChild2Id, }); } else if (node === 2) { qb.andWhere("posMaster.orgChild2Id IS NULL"); qb.andWhere("posMaster.orgChild1Id = :childId", { childId: findPosMaster?.orgChild1Id, }); } else if (node === 1) { qb.andWhere("posMaster.orgChild1Id IS NULL"); qb.andWhere("posMaster.orgRootId = :childId", { childId: findPosMaster?.orgRootId }); } }), ) .orderBy("posMaster.posMasterOrder", "ASC") .getOne(); } //หาผู้บังคับบัญชาที่เหนือขึ้นไปอีก 2 ขั้น if (node !== 0 && node !== 1) { findTSAB = await AppDataSource.getRepository(PosMaster) .createQueryBuilder("posMaster") .leftJoinAndSelect("posMaster.current_holder", "current_holder") .where("posMaster.current_holderId IS NOT NULL") .andWhere("posMaster.orgRevisionId = :revisionId", { revisionId: findRevision?.id }) .andWhere( new Brackets((qb) => { if (node === 4) { qb.andWhere("posMaster.orgChild3Id IS NULL"); qb.andWhere("posMaster.orgChild2Id = :childId", { childId: findPosMaster?.orgChild2Id, }); } else if (node === 3) { qb.andWhere("posMaster.orgChild2Id IS NULL"); qb.andWhere("posMaster.orgChild1Id = :childId", { childId: findPosMaster?.orgChild1Id, }); } else if (node === 2) { qb.andWhere("posMaster.orgChild1Id IS NULL"); qb.andWhere("posMaster.orgRootId = :childId", { childId: findPosMaster?.orgRootId, }); } }), ) .orderBy("posMaster.posMasterOrder", "ASC") .getOne(); } fullName_ = (findProfile?.prefix ?? "") + (findProfile?.firstName ?? "") + " " + (findProfile?.lastName ?? ""); position_ = findProfile?.position ?? ""; commanderFullname_ = (findCmd?.current_holder?.prefix ?? "") + (findCmd?.current_holder?.firstName ?? "") + " " + (findCmd?.current_holder?.lastName ?? ""); commanderPosition_ = findCmd?.current_holder?.position ?? ""; commanderAboveFullname_ = (findOSAB?.current_holder?.prefix ?? "") + (findOSAB?.current_holder?.firstName ?? "") + " " + (findOSAB?.current_holder?.lastName ?? ""); commanderAbovePosition_ = findOSAB?.current_holder?.position ?? ""; if (findCmd?.current_holderId == findProfile?.id) { commanderFullname_ = (findOSAB?.current_holder?.prefix ?? "") + (findOSAB?.current_holder?.firstName ?? "") + " " + (findOSAB?.current_holder?.lastName ?? ""); commanderPosition_ = findOSAB?.current_holder?.position ?? ""; commanderAboveFullname_ = (findTSAB?.current_holder?.prefix ?? "") + (findTSAB?.current_holder?.firstName ?? "") + " " + (findTSAB?.current_holder?.lastName ?? ""); commanderAbovePosition_ = findTSAB?.current_holder?.position ?? ""; const formattedDataTSAB = { fullname: fullName_, position: position_, commanderAboveFullname: commanderAboveFullname_, commanderAbovePosition: commanderAbovePosition_, commanderFullname: commanderFullname_, commanderPosition: commanderPosition_, }; return new HttpSuccess(formattedDataTSAB); } const formattedData = { fullname: fullName_, position: position_, commanderAboveFullname: commanderAboveFullname_, commanderAbovePosition: commanderAbovePosition_, commanderFullname: commanderFullname_, commanderPosition: commanderPosition_, }; return new HttpSuccess(formattedData); } }