import { Controller, Get, Post, Put, Delete, Route, Security, Tags, Body, Path, Request, Example, Query, } from "tsoa"; import { SalaryEmployee, CreateSalaryEmployee, UpdateSalaryEmployee, } from "../entities/SalaryEmployee"; import { AppDataSource } from "../database/data-source"; import { Not, Brackets } from "typeorm"; import HttpSuccess from "../interfaces/http-success"; import HttpError from "../interfaces/http-error"; import HttpStatusCode from "../interfaces/http-status"; import { SalaryRankEmployee } from "../entities/SalaryRankEmployee"; import { randomUUID } from "crypto"; import { SalaryFormulaEmployee } from "../entities/SalaryFormulaEmployee"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; import { setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/employee") @Tags("SalaryEmployee") @Security("bearerAuth") export class SalaryEmployeeController extends Controller { private salaryEmployeeRepository = AppDataSource.getRepository(SalaryEmployee); private salaryRankEmployeeRepository = AppDataSource.getRepository(SalaryRankEmployee); private salaryFormulaEmployeeRepository = AppDataSource.getRepository(SalaryFormulaEmployee); /** * API รายการผังเงินเดือนลูกจ้าง(Active) * * */ @Get("active") async listSalaryActive() { const salary = await this.salaryEmployeeRepository.find({ where: { isActive: true, }, }); return new HttpSuccess(salary); } /** * API สร้างผังเงินเดือนลูกจ้าง * * */ @Post() @Example({ name: "string", //*ชื่อผัง group: "string", //*กลุ่มผัง isActive: "boolean", //*สถานะการใช้งาน date: "datetime", //ให้ไว้ ณ วันที่ startDate: "datetime", //วันที่มีผลบังคับใช้ endDate: "datetime", //วันที่สิ้นสุดบังคับใช้ detail: "string", //คำอธิบาย }) async create_salary( @Body() requestBody: CreateSalaryEmployee, @Request() request: RequestWithUser, ) { await new permission().PermissionCreate(request, "SYS_WAGE_CHART_EMP"); const salarys = Object.assign(new SalaryEmployee(), requestBody); if (!salarys) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); } const chk_3fields = await this.salaryEmployeeRepository.findOne({ where: { group: salarys.group, }, }); if (chk_3fields && salarys.isActive) { salarys.isActive = false; } const before = null; salarys.createdUserId = request.user.sub; salarys.createdFullName = request.user.name; salarys.lastUpdateUserId = request.user.sub; salarys.lastUpdateFullName = request.user.name; salarys.createdAt = new Date(); salarys.lastUpdatedAt = new Date(); await this.salaryEmployeeRepository.save(salarys, { data: request }); setLogDataDiff(request, { before, after: salarys }); return new HttpSuccess(salarys.id); } /** * API แก้ไขผังเงินเดือนลูกจ้าง * * * @param {string} id Guid, *Id ผังเงินเดือน */ @Put("{id}") @Example({ name: "string", //*ชื่อผัง group: "string", //*กลุ่มผัง isActive: "boolean", //*สถานะการใช้งาน date: "datetime", //ให้ไว้ ณ วันที่ startDate: "datetime", //วันที่มีผลบังคับใช้ endDate: "datetime", //วันที่สิ้นสุดบังคับใช้ detail: "string", //คำอธิบาย }) async update_salary( @Path() id: string, @Body() requestBody: UpdateSalaryEmployee, @Request() request: RequestWithUser, ) { await new permission().PermissionUpdate(request, "SYS_WAGE_CHART_EMP"); const chk_Salary = await this.salaryEmployeeRepository.findOne({ where: { id: id }, }); if (!chk_Salary) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } if (chk_Salary.isActive && !requestBody.isActive) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่สามารถแก้ไขสถานะการใช้งานที่เป็น Default ได้", ); } const chk_3fields = await this.salaryEmployeeRepository.find({ where: { group: requestBody.group, isActive: true, id: Not(id), }, }); if (chk_3fields.length > 0 && requestBody.isActive) { const beforeChk_3fields = structuredClone(chk_3fields); chk_3fields.forEach(async (item) => { item.isActive = false; item.lastUpdateUserId = request.user.sub; item.lastUpdateFullName = request.user.name; item.lastUpdatedAt = new Date(); await this.salaryEmployeeRepository.save(chk_3fields, { data: request }); setLogDataDiff(request, { before: beforeChk_3fields, after: chk_3fields }); }); } const mergeData = Object.assign(new SalaryEmployee(), requestBody); const before = structuredClone(chk_Salary); chk_Salary.lastUpdateUserId = request.user.sub; chk_Salary.lastUpdateFullName = request.user.name; chk_Salary.lastUpdatedAt = new Date(); this.salaryEmployeeRepository.merge(chk_Salary, mergeData); await this.salaryEmployeeRepository.save(chk_Salary, { data: request }); setLogDataDiff(request, { before, after: chk_Salary }); return new HttpSuccess(id); } /** * API ลบผังเงินเดือนลูกจ้าง * * * @param {string} id Guid, *Id ผังเงินเดือน */ @Delete("{id}") async delete_salary(@Path() id: string, @Request() request: RequestWithUser) { await new permission().PermissionDelete(request, "SYS_WAGE_CHART_EMP"); const chk_Salary = await this.salaryEmployeeRepository.findOne({ where: { id: id }, }); if (!chk_Salary) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } if (chk_Salary.isActive) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่สามารถลบข้อมูลนี้ได้ เนื่องจากเปิดใช้งานอยู่", ); } const chk_SalaryFormulaEmp = await this.salaryFormulaEmployeeRepository.find({ where: { salaryEmployeeId: id }, }); if (chk_SalaryFormulaEmp.length > 0) { throw new HttpError( HttpStatusCode.NOT_FOUND, "ไม่สามารถลบรายการนี้ได้เนื่องจากมีการใช้งานอยู่", ); } const del_SalaryRank = await this.salaryRankEmployeeRepository.find({ where: { salaryEmployeeId: chk_Salary.id }, }); await this.salaryRankEmployeeRepository.remove(del_SalaryRank, { data: request }); await this.salaryEmployeeRepository.remove(chk_Salary, { data: request }); return new HttpSuccess(); } /** * API รายละเอียดผังเงินเดือนลูกจ้าง * * * @param {string} id Guid, *Id ผังเงินเดือน */ @Get("{id}") @Example({ name: "string", //*ชื่อผัง group: "string", //*กลุ่มผัง isActive: "boolean", //*สถานะการใช้งาน date: "datetime", //ให้ไว้ ณ วันที่ startDate: "datetime", //วันที่มีผลบังคับใช้ endDate: "datetime", //วันที่สิ้นสุดบังคับใช้ detail: "string", //คำอธิบาย }) async GetSalaryById(@Request() request: RequestWithUser, @Path() id: string) { let _workflow = await new permission().Workflow(request, id, "SYS_WAGE_CHART_EMP"); if (_workflow == false) await new permission().PermissionGet(request, "SYS_WAGE_CHART_EMP"); const salary = await this.salaryEmployeeRepository.findOne({ where: { id: id }, select: ["name", "group", "isActive", "date", "startDate", "endDate", "details"], }); if (!salary) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } return new HttpSuccess(salary); } /** * API รายการผังเงินเดือนลูกจ้าง * * */ @Get() async listSalary( @Request() request: RequestWithUser, @Query("page") page: number = 1, @Query("pageSize") pageSize: number = 10, @Query("keyword") keyword?: string, ) { await new permission().PermissionList(request, "SYS_WAGE_CHART_EMP"); const [salaryEmployee, total] = await AppDataSource.getRepository(SalaryEmployee) .createQueryBuilder("salaryEmployee") .andWhere( new Brackets((qb) => { qb.orWhere("salaryEmployee.name LIKE :keyword", { keyword: `%${keyword}%` }).orWhere( "salaryEmployee.group LIKE :keyword", { keyword: `%${keyword}%` }, ); }), ) .orderBy("salaryEmployee.isActive", "DESC") .addOrderBy("salaryEmployee.group", "ASC") .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); const _salaryEmployee = salaryEmployee.map((item) => ({ id: item.id, name: item.name, group: item.group, isActive: item.isActive, date: item.date, startDate: item.startDate, endDate: item.endDate, details: item.details, })); return new HttpSuccess({ data: _salaryEmployee, total }); } /** * API copy ผังเงินเดือนลูกจ้าง * * */ @Post("copy") async copySalary(@Body() body: { id: string }, @Request() request: RequestWithUser) { await new permission().PermissionCreate(request, "SYS_WAGE_CHART_EMP"); const salary = await this.salaryEmployeeRepository.findOne({ relations: ["salaryRankEmployees_"], where: { id: body.id }, }); if (!salary) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } const salaryRank = await this.salaryRankEmployeeRepository.find({ where: { salaryEmployeeId: salary?.id }, }); const newSalary = { ...salary, id: randomUUID(), isActive: false }; const before = null; newSalary.createdUserId = request.user.sub; newSalary.createdFullName = request.user.name; newSalary.lastUpdateUserId = request.user.sub; newSalary.lastUpdateFullName = request.user.name; newSalary.createdAt = new Date(); newSalary.lastUpdatedAt = new Date(); await this.salaryEmployeeRepository.save(newSalary, { data: request }); setLogDataDiff(request, { before, after: newSalary }); await Promise.all( salaryRank.map(async (v) => { const newSalaryRank = { ...v, id: randomUUID() }; newSalaryRank.createdUserId = request.user.sub; newSalaryRank.createdFullName = request.user.name; newSalaryRank.lastUpdateUserId = request.user.sub; newSalaryRank.lastUpdateFullName = request.user.name; newSalaryRank.createdAt = new Date(); newSalaryRank.lastUpdatedAt = new Date(); await this.salaryRankEmployeeRepository.save(newSalaryRank, { data: request }); setLogDataDiff(request, { before, after: newSalaryRank }); }), ); return new HttpSuccess({ id: newSalary.id }); } }