import { Controller, Get, Post, Put, Delete, Route, Security, Tags, Body, Path, Request, Example, SuccessResponse, Response, Query, } from "tsoa"; import { AppDataSource } from "../database/data-source"; import HttpSuccess from "../interfaces/http-success"; import HttpError from "../interfaces/http-error"; import HttpStatusCode from "../interfaces/http-status"; import { KpiCapacity } from "../entities/kpiCapacity"; import { Position } from "../entities/position"; import { KpiCapacityDetail } from "../entities/kpiCapacityDetail"; import { Like, In, Not, IsNull } from "typeorm"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; import { setLogDataDiff } from "../interfaces/utils"; import { KpiUserCapacity } from "../entities/kpiUserCapacity"; @Route("api/v1/kpi/capacity") @Tags("kpiCapacity") @Security("bearerAuth") @Response( HttpStatusCode.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", ) @SuccessResponse(HttpStatusCode.OK, "สำเร็จ") export class kpiCapacityController extends Controller { private kpiCapacityRepository = AppDataSource.getRepository(KpiCapacity); private kpiCapacityDetailRepository = AppDataSource.getRepository(KpiCapacityDetail); private kpiUserCapacityRepository = AppDataSource.getRepository(KpiUserCapacity); private positionRepository = AppDataSource.getRepository(Position); /** * API สร้างรายการสมรรถนะ * * @summary สร้างรายการสมรรถนะ * */ @Post() @Example({ type: "HEAD", name: "ชื่อสมรรถนะ", description: "คำจำกัดความ", kpiCapacityDetails: [ { level: "ระดับ", description: "คำอธิบายระดับ", }, ], }) async createKpiCapacity( @Body() requestBody: { type: string; name: string; description: string; capacityDetails: { level: string; description: string; }[]; }, @Request() request: RequestWithUser, ) { await new permission().PermissionCreate(request, "SYS_EVA_COMPETENCY"); const kpiCapacity = Object.assign(new KpiCapacity(), { type: requestBody.type, name: requestBody.name, description: requestBody.description, }); const before = null; kpiCapacity.createdUserId = request.user.sub; kpiCapacity.createdFullName = request.user.name; kpiCapacity.lastUpdateUserId = request.user.sub; kpiCapacity.lastUpdateFullName = request.user.name; kpiCapacity.createdAt = new Date(); kpiCapacity.lastUpdatedAt = new Date(); await this.kpiCapacityRepository.save(kpiCapacity, { data: request }); setLogDataDiff(request, { before, after: kpiCapacity }); let idx: number = 0; for (const data of requestBody.capacityDetails) { idx += 1; let _level = kpiCapacity.type === "HEAD" || kpiCapacity.type === "GROUP" ? idx.toString() : data.level; const kpiCapacityDetail = Object.assign(new KpiCapacityDetail(), { level: _level, description: data.description, kpiCapacityId: kpiCapacity.id, }); kpiCapacityDetail.createdUserId = request.user.sub; kpiCapacityDetail.createdFullName = request.user.name; kpiCapacityDetail.lastUpdateUserId = request.user.sub; kpiCapacityDetail.lastUpdateFullName = request.user.name; kpiCapacityDetail.createdAt = new Date(); kpiCapacityDetail.lastUpdatedAt = new Date(); await this.kpiCapacityDetailRepository.save(kpiCapacityDetail, { data: request }); setLogDataDiff(request, { before, after: kpiCapacityDetail }); } return new HttpSuccess(kpiCapacity.id); } /** * API แก้ไขรายการสมรรถนะ * * @summary แก้ไขรายการสมรรถนะ * * @param {string} id Guid, *Id รายการสมรรถนะ */ @Put("{id}") @Example({ type: "HEAD", name: "ชื่อสมรรถนะ", description: "คำจำกัดความ", kpiCapacityDetails: [ { level: "ระดับ", description: "คำอธิบายระดับ", }, ], }) async updateKpiCapacity( @Path() id: string, @Body() requestBody: { type: string; name: string; description: string; capacityDetails: { level: string; description: string; }[]; }, @Request() request: RequestWithUser, ) { await new permission().PermissionUpdate(request, "SYS_EVA_COMPETENCY"); const kpiCapacity = await this.kpiCapacityRepository.findOne({ where: { id: id }, }); if (!kpiCapacity) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรายการสมรรถนะนี้"); } const _kpiCapacity = Object.assign(new KpiCapacity(), { type: requestBody.type, name: requestBody.name, description: requestBody.description, }); const before = structuredClone(kpiCapacity); kpiCapacity.lastUpdateUserId = request.user.sub; kpiCapacity.lastUpdateFullName = request.user.name; kpiCapacity.lastUpdatedAt = new Date(); this.kpiCapacityRepository.merge(kpiCapacity, _kpiCapacity); await this.kpiCapacityRepository.save(kpiCapacity, { data: request }); setLogDataDiff(request, { before, after: kpiCapacity }); const _kpiCapacityDetailsOld = await this.kpiCapacityDetailRepository.find({ where: { kpiCapacityId: kpiCapacity.id }, }); await this.kpiCapacityDetailRepository.remove(_kpiCapacityDetailsOld, { data: request }); let idx: number = 0; for (const data of requestBody.capacityDetails) { idx += 1; let _level = kpiCapacity.type === "HEAD" || kpiCapacity.type === "GROUP" ? idx.toString() : data.level; const kpiCapacityDetail = Object.assign(new KpiCapacityDetail(), { level: _level, description: data.description, kpiCapacityId: kpiCapacity.id, }); const beforeDetail = structuredClone(kpiCapacityDetail); kpiCapacityDetail.createdUserId = request.user.sub; kpiCapacityDetail.createdFullName = request.user.name; kpiCapacityDetail.lastUpdateUserId = request.user.sub; kpiCapacityDetail.lastUpdateFullName = request.user.name; kpiCapacityDetail.createdAt = new Date(); kpiCapacityDetail.lastUpdatedAt = new Date(); await this.kpiCapacityDetailRepository.save(kpiCapacityDetail, { data: request }); setLogDataDiff(request, { before: beforeDetail, after: kpiCapacityDetail }); } return new HttpSuccess(kpiCapacity.id); } /** * API รายละเอียดรายการสมรรถนะ "สมรรถนะหลัก" * * @summary รายละเอียดดรายการสมรรถนะ "สมรรถนะหลัก" * */ @Get("head") async GetKpiCapacityTypeHEAD() { const kpiCapacity = await this.kpiCapacityRepository.find({ where: { type: In(["HEAD"]), kpiCapacityDetails: { level: "1" }, }, select: ["id", "name"], relations: ["kpiCapacityDetails"], order: { createdAt: "ASC" }, }); const mapData = kpiCapacity.map((x) => ({ id: x.id, name: x.name, level: x.kpiCapacityDetails.length > 0 ? x.kpiCapacityDetails[0].level : null, description: x.kpiCapacityDetails.length > 0 ? x.kpiCapacityDetails[0].description : null, })); return new HttpSuccess(mapData); } /** * API รายละเอียดรายการสมรรถนะ "สมรรถนะประจำกลุ่มงาน" * * @summary รายละเอียดดรายการสมรรถนะ "สมรรถนะประจำกลุ่มงาน" * */ @Get("group") async GetKpiCapacityTypeGROUP(@Query("positionName") positionName: string) { let position = await this.positionRepository.findOne({ where: { name: Like(`${positionName}`), kpiLink: Not(IsNull()) || Not(""), }, relations: ["kpiLink", "kpiLink.kpiCapacitys"], }); if (position == null) { position = await this.positionRepository.findOne({ where: { name: "นักจัดการงานทั่วไป", kpiLink: Not(IsNull()) || Not(""), }, relations: ["kpiLink", "kpiLink.kpiCapacitys"], }); } let positionLinkId: any; positionLinkId = position != null ? position : null; if (positionLinkId == null || positionLinkId.kpiLink == null) return new HttpSuccess([]); const kpiCapacityIds = positionLinkId.kpiLink.kpiCapacitys.map( (kpiCapacity: any) => kpiCapacity.id, ); const kpiCapacity = await this.kpiCapacityRepository.find({ where: { id: In(kpiCapacityIds), type: In(["GROUP"]), kpiCapacityDetails: { level: "2" }, }, select: ["id", "name"], relations: ["kpiCapacityDetails"], }); const mapData = kpiCapacity.map((x) => ({ id: x.id, name: x.name, level: x.kpiCapacityDetails.length > 0 ? x.kpiCapacityDetails[0].level : null, description: x.kpiCapacityDetails.length > 0 ? x.kpiCapacityDetails[0].description : null, })); return new HttpSuccess(mapData); } /** * API Summaryรายการสมรรถนะ * * @summary Summaryรายการสมรรถนะ * */ @Get("summary") async listSummaryKpiCapacity() { const kpiCapacity = await AppDataSource.getRepository(KpiCapacity) .createQueryBuilder("kpiCapacity") .groupBy("kpiCapacity.type") .select(["kpiCapacity.type AS type", "COUNT(kpiCapacity.type) AS total"]) .getRawMany(); return new HttpSuccess(kpiCapacity); } /** * API รายละเอียดรายการสมรรถนะ * * @summary รายละเอียดดรายการสมรรถนะ * * @param {string} id Guid, *Id รายการสมรรถนะ */ @Get("edit/{id}") @Example({ type: "HEAD", name: "ชื่อสมรรถนะ", description: "คำจำกัดความ", kpiCapacityDetails: [ { level: 1, description: "คำอธิบายระดับ", }, ], }) async GetKpiCapacityByIdEdit(@Request() request: RequestWithUser, @Path() id: string) { let _workflow = await new permission().Workflow(request, id, "SYS_EVA_COMPETENCY"); if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_COMPETENCY"); const kpiCapacity = await this.kpiCapacityRepository.findOne({ where: { id: id }, select: ["type", "name", "description"], }); if (!kpiCapacity) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรายการสมรรถนะนี้"); } const kpiCapacityDetails = await this.kpiCapacityDetailRepository.find({ where: { kpiCapacityId: id }, select: ["level", "description"], order: { level: "ASC" }, }); const mapData = { type: kpiCapacity.type, name: kpiCapacity.name, description: kpiCapacity.description, capacityDetails: kpiCapacityDetails, }; return new HttpSuccess(mapData); } /** * API รายการสมรรถนะ * * @summary รายการสมรรถนะ * */ @Get("edit") async listKpiCapacityEdit( @Request() request: RequestWithUser, @Query("page") page: number = 1, @Query("pageSize") pageSize: number = 10, @Query("type") type?: string, @Query("keyword") keyword?: string, @Query("sortBy") sortBy?: string, @Query("descending") descending?: boolean, ) { let _data = await new permission().PermissionList(request, "SYS_EVA_COMPETENCY"); let query = await AppDataSource.getRepository(KpiCapacity) .createQueryBuilder("kpiCapacity") .leftJoinAndSelect("kpiCapacity.kpiCapacityDetails", "kpiCapacityDetail") .andWhere(keyword == undefined ? "1=1" : [{ name: Like(`%${keyword}%`) }]) .andWhere(type == undefined ? "1=1" : { type: type }) .orderBy("kpiCapacity.createdAt", "ASC") if (sortBy) { query = query.orderBy( `kpiCapacity.${sortBy}`, descending ? "DESC" : "ASC" ); } const [kpiCapacity, total] = await query .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); const mapFormula = kpiCapacity.map((item) => ({ id: item.id, type: item.type, name: item.name, description: item.description, capacityDetails: item.kpiCapacityDetails.map((detail) => { return { id: detail.id, description: detail.description, level: detail.level, capacityId: detail.kpiCapacityId, }; }), })); return new HttpSuccess({ data: mapFormula, total }); } /** * API รายละเอียดรายการสมรรถนะ * * @summary รายละเอียดดรายการสมรรถนะ * * @param {string} id Guid, *Id รายการสมรรถนะ */ @Get("{id}") @Example({ type: "HEAD", name: "ชื่อสมรรถนะ", description: "คำจำกัดความ", kpiCapacityDetails: [ { level: 1, description: "คำอธิบายระดับ", }, ], }) async GetKpiCapacityById(@Request() request: RequestWithUser, @Path() id: string) { const kpiCapacity = await this.kpiCapacityRepository.findOne({ where: { id: id }, select: ["type", "name", "description"], }); if (!kpiCapacity) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรายการสมรรถนะนี้"); } const kpiCapacityDetails = await this.kpiCapacityDetailRepository.find({ where: { kpiCapacityId: id }, select: ["level", "description"], order: { level: "ASC" }, }); const mapData = { type: kpiCapacity.type, name: kpiCapacity.name, description: kpiCapacity.description, capacityDetails: kpiCapacityDetails, }; return new HttpSuccess(mapData); } /** * API รายการสมรรถนะ * * @summary รายการสมรรถนะ * */ @Get() async listKpiCapacity( @Request() request: RequestWithUser, @Query("page") page: number = 1, @Query("pageSize") pageSize?: number, @Query("type") type?: string, @Query("keyword") keyword?: string, ) { let query = await AppDataSource.getRepository(KpiCapacity) .createQueryBuilder("kpiCapacity") .leftJoinAndSelect("kpiCapacity.kpiCapacityDetails", "kpiCapacityDetail") .andWhere( keyword == undefined ? "1=1" : [{ name: Like(`%${keyword}%`) }, { description: Like(`%${keyword}%`) }], ) .andWhere(type == undefined ? "1=1" : { type: type }) .orderBy("kpiCapacity.createdAt", "ASC") if (pageSize) { query = query.skip((page - 1) * pageSize) .take(pageSize) } const [kpiCapacity, total] = await query .getManyAndCount(); const mapFormula = kpiCapacity.map((item) => ({ id: item.id, type: item.type, name: item.name, description: item.description, capacityDetails: item.kpiCapacityDetails.map((detail) => { return { id: detail.id, description: detail.description, level: detail.level, capacityId: detail.kpiCapacityId, }; }), })); return new HttpSuccess({ data: mapFormula, total }); } /** * API ลบรายการสมรรถนะ * * @summary ลบรายการสมรรถนะ * * @param {string} id Guid, *Id รายการสมรรถนะ */ @Delete("{id}") async deleteKpiCapacity(@Path() id: string, @Request() request: RequestWithUser) { await new permission().PermissionDelete(request, "SYS_EVA_COMPETENCY"); const kpiCapacity = await this.kpiCapacityRepository.findOne({ where: { id: id }, }); if (!kpiCapacity) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรายการสมรรถนะนี้"); } const kpiCapacityDetails = await this.kpiCapacityDetailRepository.find({ where: { kpiCapacityId: id }, }); const kpiUserCapacity = await this.kpiUserCapacityRepository.find({ where: { kpiCapacityId: id }, }); if (kpiCapacityDetails.length > 0) { await this.kpiCapacityDetailRepository.remove(kpiCapacityDetails, { data: request }); } if (kpiUserCapacity.length > 0) { await this.kpiUserCapacityRepository.remove(kpiUserCapacity, { data: request }); } await this.kpiCapacityRepository.remove(kpiCapacity, { data: request }); return new HttpSuccess(); } }