import { Body, Controller, Delete, Get, Patch, Path, Post, Query, Request, Route, Security, Tags, } from "tsoa"; import { AppDataSource } from "../database/data-source"; import HttpSuccess from "../interfaces/http-success"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; import { RequestWithUser } from "../middlewares/user"; import { Profile } from "../entities/Profile"; import { CreateDevelopmentRequest, DevelopmentRequest } from "../entities/DevelopmentRequest"; import permission from "../interfaces/permission"; import { Brackets } from "typeorm"; import { DevelopmentProject } from "../entities/DevelopmentProject"; import { ProfileDevelopment } from "../entities/ProfileDevelopment"; import { ProfileDevelopmentHistory } from "../entities/ProfileDevelopmentHistory"; import { setLogDataDiff } from "../interfaces/utils"; import CallAPI from "../interfaces/call-api"; @Route("api/v1/org/profile/development-request") @Tags("DevelopmentRequest") @Security("bearerAuth") export class DevelopmentRequestController extends Controller { private profileRepository = AppDataSource.getRepository(Profile); private profileDevelopmentRepository = AppDataSource.getRepository(ProfileDevelopment); private developmentRequestRepository = AppDataSource.getRepository(DevelopmentRequest); private developmentProjectRepository = AppDataSource.getRepository(DevelopmentProject); private developmentHistoryRepository = AppDataSource.getRepository(ProfileDevelopmentHistory); @Get("user") public async getDevelopmentRequestUser( @Request() req: RequestWithUser, @Query("keyword") keyword: string = "", @Query("page") page: number = 1, @Query("pageSize") pageSize: number = 10, @Query("status") status?: string, ) { const profile = await this.profileRepository.findOneBy({ keycloak: req.user.sub }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } const [lists, total] = await AppDataSource.getRepository(DevelopmentRequest) .createQueryBuilder("developmentRequest") .andWhere( status == undefined || status.trim().toUpperCase() == "ALL" || status == "" ? "1=1" : "developmentRequest.status = :status", { status: status == undefined || status == null ? "" : status.trim().toUpperCase(), }, ) .andWhere("developmentRequest.profileId = :profileId", { profileId: profile.id }) .andWhere( new Brackets((qb) => { qb.where( keyword != null && keyword != "" ? "developmentRequest.reason LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.name LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.developmentTarget LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.developmentResults LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.developmentReport LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ); }), ) .orderBy("developmentRequest.createdAt", "ASC") .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); return new HttpSuccess({ data: lists, total }); } @Get("admin") public async getDevelopmentRequestAdmin( @Request() req: RequestWithUser, @Query("status") status: string, @Query("keyword") keyword: string = "", @Query("page") page: number = 1, @Query("pageSize") pageSize: number = 10, ) { // await new permission().PermissionList(req, "SYS_REGISTRY_OFFICER"); const [lists, total] = await AppDataSource.getRepository(DevelopmentRequest) .createQueryBuilder("developmentRequest") .andWhere( status == undefined || status.trim().toUpperCase() == "ALL" || status == "" ? "1=1" : "developmentRequest.status = :status", { status: status == undefined || status == null ? "" : status.trim().toUpperCase(), }, ) .andWhere( new Brackets((qb) => { qb.where( keyword != null && keyword != "" ? "developmentRequest.reason LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.name LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.developmentTarget LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.developmentResults LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ) .orWhere( keyword != null && keyword != "" ? "developmentRequest.developmentReport LIKE :keyword" : "1=1", { keyword: `%${keyword}%`, }, ); }), ) .orderBy("developmentRequest.createdAt", "ASC") .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); return new HttpSuccess({ data: lists, total }); } @Get("admin/{id}") public async getDevelopmentRequestByUser(@Path() id: string, @Request() req: RequestWithUser) { let _workflow = await new permission().Workflow(req, id, "SYS_REGISTRY_OFFICER"); if (_workflow == false) await new permission().PermissionGet(req, "SYS_REGISTRY_OFFICER"); const data = await this.developmentRequestRepository.findOne({ where: { id: id }, relations: ["developmentProjects"], }); if (!data) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); const _data = { ...data, developmentProjects: data.developmentProjects.map((x) => x.name), }; return new HttpSuccess(_data); } @Get("user/{id}") public async getDevelopmentRequestByAdmin(@Path() id: string, @Request() req: RequestWithUser) { const data = await this.developmentRequestRepository.findOne({ where: { id: id }, relations: ["developmentProjects"], }); if (!data) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); const _data = { ...data, developmentProjects: data.developmentProjects.map((x) => x.name), }; return new HttpSuccess(_data); } @Post() public async newDevelopmentRequest( @Request() req: RequestWithUser, @Body() body: CreateDevelopmentRequest, ) { const profile = await this.profileRepository.findOne({ where: { keycloak: req.user.sub }, relations: ["posLevel", "posType"], }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } const before = null; const data = new DevelopmentRequest(); const meta = { createdUserId: req.user.sub, createdFullName: req.user.name, lastUpdateUserId: req.user.sub, lastUpdateFullName: req.user.name, createdAt: new Date(), lastUpdatedAt: new Date(), }; Object.assign(data, { ...body, ...meta }); data.profileId = profile.id; data.status = "PENDING"; await this.developmentRequestRepository.save(data, { data: req }); setLogDataDiff(req, { before, after: data }); if (body.developmentProjects != null) { await Promise.all( body.developmentProjects.map(async (x) => { let developmentProject = new DevelopmentProject(); developmentProject.name = x; developmentProject.createdUserId = req.user.sub; developmentProject.createdFullName = req.user.name; developmentProject.lastUpdateUserId = req.user.sub; developmentProject.lastUpdateFullName = req.user.name; developmentProject.createdAt = new Date(); developmentProject.lastUpdatedAt = new Date(); developmentProject.developmentRequestId = data.id; await this.developmentProjectRepository.save(developmentProject, { data: req }); setLogDataDiff(req, { before, after: developmentProject }); }), ); } await new CallAPI() .PostData(req, "/org/workflow/add-workflow", { refId: data.id, sysName: "REGISTRY_IDP", posLevelName: profile.posLevel.posLevelName, posTypeName: profile.posType.posTypeName, }) .catch((error) => { console.error("Error calling API:", error); }); return new HttpSuccess(data.id); } @Patch("user/{developmentId}") public async editUserDevelopmentRequest( @Request() req: RequestWithUser, @Body() body: CreateDevelopmentRequest, @Path() developmentId: string, ) { const record = await this.developmentRequestRepository.findOne({ where: { id: developmentId }, relations: ["developmentProjects"], }); const before = structuredClone(record); if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); Object.assign(record, body); record.lastUpdateUserId = req.user.sub; record.lastUpdateFullName = req.user.name; record.lastUpdatedAt = new Date(); await this.developmentRequestRepository.save(record, { data: req }); setLogDataDiff(req, { before, after: record }); await this.developmentProjectRepository.delete({ developmentRequestId: record.id }); if (body.developmentProjects != null) { await Promise.all( body.developmentProjects.map(async (x) => { let developmentProject = new DevelopmentProject(); developmentProject.name = x; developmentProject.createdUserId = req.user.sub; developmentProject.createdFullName = req.user.name; developmentProject.lastUpdateUserId = req.user.sub; developmentProject.lastUpdateFullName = req.user.name; developmentProject.createdAt = new Date(); developmentProject.lastUpdatedAt = new Date(); developmentProject.developmentRequestId = record.id; await this.developmentProjectRepository.save(developmentProject, { data: req }); setLogDataDiff(req, { before: null, after: record }); }), ); } return new HttpSuccess(record.id); } @Patch("admin/{developmentId}") public async editAdminDevelopmentRequest( @Request() req: RequestWithUser, @Body() requestBody: { reason?: string | null; status: string }, @Path() developmentId: string, ) { const record = await this.developmentRequestRepository.findOne({ where: { id: developmentId }, relations: ["developmentProjects"], }); if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); await new permission().PermissionUpdate(req, "SYS_REGISTRY_OFFICER"); if (requestBody.status == "APPROVE" && record.status == "PENDING") { let profileDevelopment = new ProfileDevelopment(); const meta = { createdUserId: req.user.sub, createdFullName: req.user.name, lastUpdateUserId: req.user.sub, lastUpdateFullName: req.user.name, createdAt: new Date(), lastUpdatedAt: new Date(), }; Object.assign(profileDevelopment, { ...record, ...meta, id: undefined, type: "REQUEST", kpiDevelopmentId: record.id, developmentProjects: [], }); await this.profileDevelopmentRepository.save(profileDevelopment, { data: req }); const history = new ProfileDevelopmentHistory(); Object.assign(history, { ...profileDevelopment, id: undefined, type: "REQUEST", kpiDevelopmentId: record.id, developmentProjects: [], }); history.profileDevelopmentId = profileDevelopment.id; await this.developmentHistoryRepository.save(history, { data: req }); if (record.developmentProjects != null) { await Promise.all( record.developmentProjects.map(async (x) => { let developmentProject = new DevelopmentProject(); let developmentProjectHistory = new DevelopmentProject(); Object.assign(developmentProject, { ...meta, id: undefined, name: record.name, profileDevelopmentId: profileDevelopment.id, }); Object.assign(developmentProject, { ...meta, id: undefined, name: record.name, profileDevelopmentHistoryId: history.id, }); await Promise.all([ this.developmentProjectRepository.save(developmentProject, { data: req }), setLogDataDiff(req, { before: null, after: developmentProject }), this.developmentProjectRepository.save(developmentProjectHistory, { data: req }), ]); }), ); } } const before = structuredClone(record); requestBody.status = requestBody.status.trim().toUpperCase(); Object.assign(record, requestBody); record.lastUpdateUserId = req.user.sub; record.lastUpdateFullName = req.user.name; record.lastUpdatedAt = new Date(); await this.developmentRequestRepository.save(record, { data: req }); setLogDataDiff(req, { before, after: record }); return new HttpSuccess(record.id); } @Delete("{id}") public async deleteDevelopmentRequest(@Path() id: string, @Request() req: RequestWithUser) { const developmentRequest = await this.developmentRequestRepository.findOne({ where: { id }, }); if (!developmentRequest) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลคำขอนี้"); } await this.developmentProjectRepository.delete({ developmentRequestId: id }); await this.developmentRequestRepository.delete({ id }); return new HttpSuccess(); } }