diff --git a/src/app.ts b/src/app.ts index b0180b1..840d5de 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,6 +9,7 @@ import error from "./middlewares/error"; import { AppDataSource } from "./database/data-source"; import { RegisterRoutes } from "./routes"; import { SalaryPeriodController } from "./controllers/SalaryPeriodController"; +import logMiddleware from "./middlewares/logs"; async function main() { await AppDataSource.initialize(); @@ -23,10 +24,11 @@ async function main() { app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use("/", express.static("static")); + app.use(logMiddleware); app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); RegisterRoutes(app); - + app.use(error); const APP_HOST = process.env.APP_HOST || "0.0.0.0"; const APP_PORT = +(process.env.APP_PORT || 3000); @@ -35,7 +37,6 @@ async function main() { try { const salaryPeriod = new SalaryPeriodController(); await salaryPeriod.CronjobSalaryPeriod(); - } catch (error) { console.error("Error executing function from controller:", error); } diff --git a/src/controllers/PosLevelController.ts b/src/controllers/PosLevelController.ts index 51cd00a..dfd576d 100644 --- a/src/controllers/PosLevelController.ts +++ b/src/controllers/PosLevelController.ts @@ -23,6 +23,8 @@ import { PosType } from "../entities/PosType"; import { PosLevel, CreatePosLevel, UpdatePosLevel } from "../entities/PosLevel"; import HttpError from "../interfaces/http-error"; import { Not } from "typeorm"; +import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/pos/level") @Tags("PosLevel") @@ -52,7 +54,7 @@ export class PosLevelController extends Controller { async createLevel( @Body() requestBody: CreatePosLevel, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const posLevel = Object.assign(new PosLevel(), requestBody); if (!posLevel) { @@ -64,10 +66,7 @@ export class PosLevelController extends Controller { }, }); if (!chkPosTypeId) { - throw new HttpError( - HttpStatusCode.NOT_FOUND, - "ไม่พบข้อมูลประเภทตำแหน่งนี้" - ); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } const chkPosLevelName = await this.posLevelRepository.findOne({ @@ -92,11 +91,13 @@ export class PosLevelController extends Controller { } // try { + const before = null; posLevel.createdUserId = request.user.sub; posLevel.createdFullName = request.user.name; posLevel.lastUpdateUserId = request.user.sub; posLevel.lastUpdateFullName = request.user.name; - await this.posLevelRepository.save(posLevel); + await this.posLevelRepository.save(posLevel, { data: request }); + setLogDataDiff(request, { before, after: posLevel }); return new HttpSuccess(posLevel); // } catch (error) { // return error; @@ -118,7 +119,7 @@ export class PosLevelController extends Controller { async editLevel( @Path() id: string, @Body() requestBody: UpdatePosLevel, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const posLevel = await this.posLevelRepository.findOne({ where: { id } }); if (!posLevel) { @@ -131,10 +132,7 @@ export class PosLevelController extends Controller { }, }); if (!chkPosTypeId) { - throw new HttpError( - HttpStatusCode.NOT_FOUND, - "ไม่พบข้อมูลระดับตำแหน่งนี้" - ); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } const chkPosLevelName = await this.posLevelRepository.findOne({ @@ -159,10 +157,12 @@ export class PosLevelController extends Controller { } // try { + const before = structuredClone(posLevel); posLevel.lastUpdateUserId = request.user.sub; posLevel.lastUpdateFullName = request.user.name; this.posLevelRepository.merge(posLevel, requestBody); - await this.posLevelRepository.save(posLevel); + await this.posLevelRepository.save(posLevel, { data: Request }); + setLogDataDiff(request, { before, after: posLevel }); return new HttpSuccess(posLevel.id); // } catch (error) { // return error; @@ -177,13 +177,13 @@ export class PosLevelController extends Controller { * @param {string} id Id ระดับตำแหน่ง */ @Delete("{id}") - async deleteLevel(@Path() id: string) { + async deleteLevel(@Path() id: string, @Request() request: RequestWithUser) { const delPosLevel = await this.posLevelRepository.findOne({ where: { id } }); if (!delPosLevel) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } // try { - await this.posLevelRepository.remove(delPosLevel); + await this.posLevelRepository.remove(delPosLevel, { data: request }); return new HttpSuccess(); // } catch (error) { // return error; diff --git a/src/controllers/PosTypeController.ts b/src/controllers/PosTypeController.ts index 4004641..0c3be9a 100644 --- a/src/controllers/PosTypeController.ts +++ b/src/controllers/PosTypeController.ts @@ -23,6 +23,8 @@ import { PosType, CreatePosType, UpdatePosType } from "../entities/PosType"; import { PosLevel } from "../entities/PosLevel"; import HttpError from "../interfaces/http-error"; import { Not } from "typeorm"; +import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/pos/type") @Tags("PosType") @@ -50,7 +52,7 @@ export class PosTypeController extends Controller { async createType( @Body() requestBody: CreatePosType, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const posType = Object.assign(new PosType(), requestBody); if (!posType) { @@ -68,11 +70,13 @@ export class PosTypeController extends Controller { ); } // try { + const before = null; posType.createdUserId = request.user.sub; posType.createdFullName = request.user.name; posType.lastUpdateUserId = request.user.sub; posType.lastUpdateFullName = request.user.name; - await this.posTypeRepository.save(posType); + await this.posTypeRepository.save(posType, { data: request }); + setLogDataDiff(request, { before, after: posType }); return new HttpSuccess(posType); // } catch (error) { // return error; @@ -94,7 +98,7 @@ export class PosTypeController extends Controller { async editType( @Path() id: string, @Body() requestBody: UpdatePosType, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const posType = await this.posTypeRepository.findOne({ where: { id } }); if (!posType) { @@ -113,10 +117,12 @@ export class PosTypeController extends Controller { ); } // try { + const before = structuredClone(posType); posType.lastUpdateUserId = request.user.sub; posType.lastUpdateFullName = request.user.name; this.posTypeRepository.merge(posType, requestBody); - await this.posTypeRepository.save(posType); + await this.posTypeRepository.save(posType, { data: request }); + setLogDataDiff(request, { before, after: posType }); return new HttpSuccess(posType.id); // } catch (error) { // return error; @@ -131,7 +137,7 @@ export class PosTypeController extends Controller { * @param {string} id Id ตำแหน่ง */ @Delete("{id}") - async deleteType(@Path() id: string) { + async deleteType(@Path() id: string, @Request() request: RequestWithUser) { const delPosType = await this.posTypeRepository.findOne({ where: { id } }); if (!delPosType) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); @@ -144,7 +150,7 @@ export class PosTypeController extends Controller { } // try { - await this.posTypeRepository.remove(delPosType); + await this.posTypeRepository.remove(delPosType, { data: request }); return new HttpSuccess(); // } catch (error) { // return error; diff --git a/src/controllers/ReportController.ts b/src/controllers/ReportController.ts index 3ca0009..c1725b8 100644 --- a/src/controllers/ReportController.ts +++ b/src/controllers/ReportController.ts @@ -35,6 +35,9 @@ import { EmployeePosType } from "../entities/EmployeePosType"; import { EmployeePosLevel } from "../entities/EmployeePosLevel"; import { SalaryOrgEmployee } from "../entities/SalaryOrgEmployee"; import { SalaryProfileEmployee } from "../entities/SalaryProfileEmployee"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; +import { RequestWithUser } from "../middlewares/user"; + import CallAPI from "../interfaces/call-api"; @Route("api/v1/salary/report") @Tags("Report") @@ -2101,7 +2104,7 @@ export class ReportController extends Controller { }); const root = _root?.root == null ? "" : _root.root; // const agency = salaryProfile[0] == null ? "" : salaryProfile[0].root; - + const formattedData = salaryProfile.map((item, index) => ({ no: Extension.ToThaiNumber(String(index + 1)), fullname: item.prefix + item.firstName + " " + item.lastName, @@ -2114,8 +2117,10 @@ export class ReportController extends Controller { (item.root == undefined && item.root == null ? "" : item.root), posType: item.posType, posLevel: item.posLevel, - posExecutive: item.posExecutive ? item.posExecutive:null, - fullPositionName: item.posExecutive ? item.position + " (" + item.posExecutive + ")" : item.position || null, + posExecutive: item.posExecutive ? item.posExecutive : null, + fullPositionName: item.posExecutive + ? item.position + " (" + item.posExecutive + ")" + : item.position || null, posMasterNo: Extension.ToThaiNumber(item.orgShortName) + Extension.ToThaiNumber(String(item.posMasterNo.toLocaleString())), @@ -4186,8 +4191,8 @@ export class ReportController extends Controller { reportName: "emp2-02", data: { year: Extension.ToThaiNumber(String(Extension.ToThaiYear(salaryPeriod.year))), - yearOld: Extension.ToThaiNumber(String(Extension.ToThaiYear(salaryPeriod.year-1))), - yearOld2: Extension.ToThaiNumber(String(Extension.ToThaiYear(salaryPeriod.year-2))), + yearOld: Extension.ToThaiNumber(String(Extension.ToThaiYear(salaryPeriod.year - 1))), + yearOld2: Extension.ToThaiNumber(String(Extension.ToThaiYear(salaryPeriod.year - 2))), agency: _root?.root == null ? "" : _root?.root, data: formattedData, }, @@ -4694,7 +4699,7 @@ export class ReportController extends Controller { : null, score: profile.result, reason: profile.remark, - remark:null, + remark: null, }; }); @@ -4766,7 +4771,6 @@ export class ReportController extends Controller { .join("/"); const fullName = `${profile.prefix}${profile.firstName} ${profile.lastName}`; - return { no: Extension.ToThaiNumber((index + 1).toLocaleString()), fullName: fullName, @@ -5210,7 +5214,7 @@ export class ReportController extends Controller { const agency = _salaryPeriod[0] == null ? "" : _salaryPeriod[0].root; const formattedData = _salaryPeriod.map((profile, index) => { - const fullNameParts = [ + const fullNameParts = [ profile.child4, profile.child3, profile.child2, @@ -5321,7 +5325,7 @@ export class ReportController extends Controller { const agency = salaryProfile[0] == null ? "" : salaryProfile[0].root; const formattedData = salaryProfile.map((profile, index) => { - const fullNameParts = [ + const fullNameParts = [ profile.child4, profile.child3, profile.child2, @@ -5404,7 +5408,7 @@ export class ReportController extends Controller { const agency = _salaryProfileEmp[0] == null ? "" : _salaryProfileEmp[0].root; const formattedData = _salaryProfileEmp.map((profile, index) => { - const fullNameParts = [ + const fullNameParts = [ profile.child4, profile.child3, profile.child2, @@ -5504,7 +5508,7 @@ export class ReportController extends Controller { .filter((part) => part !== undefined && part !== null) .join("/"); const fullName = `${profile.prefix}${profile.firstName} ${profile.lastName}`; - + return { no: Extension.ToThaiNumber((index + 1).toLocaleString()), fullName: fullName, @@ -5895,7 +5899,6 @@ export class ReportController extends Controller { .join("/"); const fullName = `${profile.prefix}${profile.firstName} ${profile.lastName}`; - return { no: Extension.ToThaiNumber((index + 1).toLocaleString()), fullName: fullName, @@ -6273,7 +6276,7 @@ export class ReportController extends Controller { async SalaryReport33Resume( @Body() body: { result: { id: string; refCommandNo: string; templateDoc: string; personId: string }[] }, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { await Promise.all( body.result.map(async (v) => { @@ -6282,6 +6285,7 @@ export class ReportController extends Controller { id: v.id, }, }); + if (salary != null) { await new CallAPI() .PostData(request, "/org/profile/salary", { @@ -6301,8 +6305,10 @@ export class ReportController extends Controller { templateDoc: v.templateDoc, }) .then(async (x) => { + const before = null; salary.status = "DONE"; - await this.salaryProfileRepository.save(salary); + await this.salaryProfileRepository.save(salary, { data: request }); + setLogDataDiff(request, { before, after: salary }); }); } }), @@ -6321,7 +6327,7 @@ export class ReportController extends Controller { async SalaryReport34Resume( @Body() body: { result: { id: string; refCommandNo: string; templateDoc: string; personId: string }[] }, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { await Promise.all( body.result.map(async (v) => { @@ -6349,8 +6355,10 @@ export class ReportController extends Controller { templateDoc: v.templateDoc, }) .then(async (x) => { + const before = null; salary.status = "DONE"; - await this.salaryProfileRepository.save(salary); + await this.salaryProfileRepository.save(salary, { data: request }); + setLogDataDiff(request, { before, after: salary }); }); } }), @@ -6369,7 +6377,7 @@ export class ReportController extends Controller { async SalaryReport35Resume( @Body() body: { result: { id: string; refCommandNo: string; templateDoc: string; personId: string }[] }, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { await Promise.all( body.result.map(async (v) => { @@ -6397,8 +6405,10 @@ export class ReportController extends Controller { templateDoc: v.templateDoc, }) .then(async (x) => { + const before = null; salary.status = "DONE"; - await this.salaryProfileRepository.save(salary); + await this.salaryProfileRepository.save(salary, { data: request }); + setLogDataDiff(request, { before, after: salary }); }); } }), @@ -6417,7 +6427,7 @@ export class ReportController extends Controller { async SalaryReport36Resume( @Body() body: { result: { id: string; refCommandNo: string; templateDoc: string; personId: string }[] }, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { await Promise.all( body.result.map(async (v) => { @@ -6445,8 +6455,10 @@ export class ReportController extends Controller { templateDoc: v.templateDoc, }) .then(async (x) => { + const before = null; salary.status = "DONE"; - await this.salaryProfileEmployeeRepository.save(salary); + await this.salaryProfileEmployeeRepository.save(salary, { data: request }); + setLogDataDiff(request, { before, after: salary }); }); } }), @@ -6465,7 +6477,7 @@ export class ReportController extends Controller { async SalaryReport37Resume( @Body() body: { result: { id: string; refCommandNo: string; templateDoc: string; personId: string }[] }, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { await Promise.all( body.result.map(async (v) => { @@ -6493,8 +6505,10 @@ export class ReportController extends Controller { templateDoc: v.templateDoc, }) .then(async (x) => { + const before = null; salary.status = "DONE"; - await this.salaryProfileEmployeeRepository.save(salary); + await this.salaryProfileEmployeeRepository.save(salary, { data: request }); + setLogDataDiff(request, { before, after: salary }); }); } }), diff --git a/src/controllers/SalaryController.ts b/src/controllers/SalaryController.ts index f94234a..9f89ee0 100644 --- a/src/controllers/SalaryController.ts +++ b/src/controllers/SalaryController.ts @@ -25,6 +25,7 @@ import { SalaryRanks } from "../entities/SalaryRanks"; import { randomUUID } from "crypto"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary") @Tags("Salary") @@ -95,13 +96,15 @@ export class SalaryController extends Controller { if (chk_fields && salarys.isActive) { salarys.isActive = false; } + const before = null; salarys.name = salarys.name; salarys.isSpecial = salarys.isSpecial; salarys.createdUserId = request.user.sub; salarys.createdFullName = request.user.name; salarys.lastUpdateUserId = request.user.sub; salarys.lastUpdateFullName = request.user.name; - await this.salaryRepository.save(salarys); + await this.salaryRepository.save(salarys, { data: request }); + setLogDataDiff(request, { before, after: salarys }); return new HttpSuccess(salarys.id); } @@ -167,12 +170,14 @@ export class SalaryController extends Controller { } if (chk_fields.length > 0 && requestBody.isActive) { + const before = structuredClone(chk_fields); chk_fields.forEach(async (item: any) => { item.isActive = false; item.lastUpdateUserId = request.user.sub; item.lastUpdateFullName = request.user.name; item.lastUpdatedAt = new Date(); - await this.salaryRepository.save(chk_fields); + await this.salaryRepository.save(chk_fields, { data: request }); + setLogDataDiff(request, { before, after: request }); }); } @@ -191,11 +196,13 @@ export class SalaryController extends Controller { } const mergeData = Object.assign(new Salarys(), requestBody); + const before = structuredClone(chk_Salary); chk_Salary.lastUpdateUserId = request.user.sub; chk_Salary.lastUpdateFullName = request.user.name; chk_Salary.lastUpdatedAt = new Date(); this.salaryRepository.merge(chk_Salary, mergeData); - await this.salaryRepository.save(chk_Salary); + await this.salaryRepository.save(chk_Salary, { data: request }); + setLogDataDiff(request, { before, after: chk_Salary }); return new HttpSuccess(id); } @@ -224,8 +231,8 @@ export class SalaryController extends Controller { const del_SalaryRank = await this.salaryRankRepository.find({ where: { salaryId: chk_Salary.id }, }); - await this.salaryRankRepository.remove(del_SalaryRank); - await this.salaryRepository.remove(chk_Salary); + await this.salaryRankRepository.remove(del_SalaryRank, { data: request }); + await this.salaryRepository.remove(chk_Salary, { data: request }); return new HttpSuccess(); } @@ -345,14 +352,17 @@ export class SalaryController extends Controller { where: { salaryId: salary?.id }, }); + const before = null; const newSalary = { ...salary, id: randomUUID(), isActive: false }; - await this.salaryRepository.save(newSalary); + await this.salaryRepository.save(newSalary, { data: request }); + setLogDataDiff(request, { before, after: newSalary }); await Promise.all( salaryRank.map(async (v) => { const newSalaryRank = { ...v, id: randomUUID() }; - await this.salaryRankRepository.save(newSalaryRank); + await this.salaryRankRepository.save(newSalaryRank, { data: request }); + setLogDataDiff(request, { before, after: newSalaryRank }); }), ); diff --git a/src/controllers/SalaryEmployeeController.ts b/src/controllers/SalaryEmployeeController.ts index 43a9fdb..6cc38ad 100644 --- a/src/controllers/SalaryEmployeeController.ts +++ b/src/controllers/SalaryEmployeeController.ts @@ -29,6 +29,7 @@ import { Salarys } from "../entities/Salarys"; import { SalaryFormulaEmployee } from "../entities/SalaryFormulaEmployee"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/employee") @Tags("SalaryEmployee") @@ -86,11 +87,13 @@ export class SalaryEmployeeController extends Controller { 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; - await this.salaryEmployeeRepository.save(salarys); + await this.salaryEmployeeRepository.save(salarys, { data: request }); + setLogDataDiff(request, { before, after: salarys }); return new HttpSuccess(salarys.id); } @@ -139,22 +142,25 @@ export class SalaryEmployeeController extends Controller { }); 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); + 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); + await this.salaryEmployeeRepository.save(chk_Salary, { data: request }); + setLogDataDiff(request, { before, after: chk_Salary }); return new HttpSuccess(id); } @@ -192,8 +198,8 @@ export class SalaryEmployeeController extends Controller { const del_SalaryRank = await this.salaryRankEmployeeRepository.find({ where: { salaryEmployeeId: chk_Salary.id }, }); - await this.salaryRankEmployeeRepository.remove(del_SalaryRank); - await this.salaryEmployeeRepository.remove(chk_Salary); + await this.salaryRankEmployeeRepository.remove(del_SalaryRank, { data: request }); + await this.salaryEmployeeRepository.remove(chk_Salary, { data: request }); return new HttpSuccess(); } @@ -213,8 +219,7 @@ export class SalaryEmployeeController extends Controller { endDate: "datetime", //วันที่สิ้นสุดบังคับใช้ detail: "string", //คำอธิบาย }) - async GetSalaryById( - @Request() request: RequestWithUser,@Path() id: string) { + async GetSalaryById(@Request() request: RequestWithUser, @Path() id: string) { await new permission().PermissionGet(request, "SYS_WAGE_CHART_EMP"); const salary = await this.salaryEmployeeRepository.findOne({ where: { id: id }, @@ -290,13 +295,15 @@ export class SalaryEmployeeController extends Controller { }); const newSalary = { ...salary, id: randomUUID(), isActive: false }; - - await this.salaryEmployeeRepository.save(newSalary); + const before = null; + await this.salaryEmployeeRepository.save(newSalary, { data: request }); + setLogDataDiff(request, { before, after: newSalary }); await Promise.all( salaryRank.map(async (v) => { const newSalaryRank = { ...v, id: randomUUID() }; - await this.salaryRankEmployeeRepository.save(newSalaryRank); + await this.salaryRankEmployeeRepository.save(newSalaryRank, { data: request }); + setLogDataDiff(request, { before, after: newSalaryRank }); }), ); diff --git a/src/controllers/SalaryFormulaEmployeeController.ts b/src/controllers/SalaryFormulaEmployeeController.ts index 6ef1ce5..f85db72 100644 --- a/src/controllers/SalaryFormulaEmployeeController.ts +++ b/src/controllers/SalaryFormulaEmployeeController.ts @@ -32,6 +32,7 @@ import { EmployeePosType } from "../entities/EmployeePosType"; import { SalaryEmployee } from "../entities/SalaryEmployee"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/formula") @Tags("SalaryFormula") @@ -98,12 +99,14 @@ export class SalaryFormulaEmployeeController extends Controller { }, }); + const before = null; formula.salaryEmployeeMins = chkSalaryEmployeeMin; formula.createdUserId = request.user.sub; formula.createdFullName = request.user.name; formula.lastUpdateUserId = request.user.sub; formula.lastUpdateFullName = request.user.name; - await this.salaryFormulaEmployeeRepository.save(formula); + await this.salaryFormulaEmployeeRepository.save(formula, { data: request }); + setLogDataDiff(request, { before, after: formula }); return new HttpSuccess(formula); } @@ -160,6 +163,7 @@ export class SalaryFormulaEmployeeController extends Controller { id: In(requestBody.salaryEmployeeMinIds), }, }); + const before = structuredClone(formula); formula.position = requestBody.position; formula.salaryMin = requestBody.salaryMin; formula.salary = requestBody.salary; @@ -171,7 +175,8 @@ export class SalaryFormulaEmployeeController extends Controller { formula.salaryEmployeeMins = chkSalaryEmployeeMin; formula.lastUpdateUserId = request.user.sub; formula.lastUpdateFullName = request.user.name; - await this.salaryFormulaEmployeeRepository.save(formula); + await this.salaryFormulaEmployeeRepository.save(formula, { data: request }); + setLogDataDiff(request, { before, after: formula }); return new HttpSuccess(formula.id); } @@ -187,7 +192,7 @@ export class SalaryFormulaEmployeeController extends Controller { const delFormula = await this.salaryFormulaEmployeeRepository.findOne({ where: { id } }); if (!delFormula) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังค่าจ้างนี้"); - await this.salaryFormulaEmployeeRepository.remove(delFormula); + await this.salaryFormulaEmployeeRepository.remove(delFormula, { data: request }); return new HttpSuccess(); } diff --git a/src/controllers/SalaryPeriodController.ts b/src/controllers/SalaryPeriodController.ts index 0aa4061..d58b847 100644 --- a/src/controllers/SalaryPeriodController.ts +++ b/src/controllers/SalaryPeriodController.ts @@ -31,6 +31,7 @@ import { SalaryProfileEmployee } from "../entities/SalaryProfileEmployee"; import { isNullOrUndefined } from "util"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/period") @Tags("Salary") @@ -297,7 +298,7 @@ export class SalaryPeriodController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการขอเงินเดือนผู้ใช้งานนี้ในระบบ"); } - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryProfileRepository.remove(salaryProfile, { data: req }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -328,7 +329,7 @@ export class SalaryPeriodController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg,{data:req}); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -382,7 +383,7 @@ export class SalaryPeriodController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg,{data:req}); } } } @@ -578,8 +579,9 @@ export class SalaryPeriodController extends Controller { } else { throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); } - - await this.salaryProfileRepository.save(salaryProfile); + const before = null; + await this.salaryProfileRepository.save(salaryProfile, { data: request }); + setLogDataDiff(request, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -610,7 +612,8 @@ export class SalaryPeriodController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -664,7 +667,8 @@ export class SalaryPeriodController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: salaryOrg }); } } } @@ -701,9 +705,12 @@ export class SalaryPeriodController extends Controller { if (!salaryOrg) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลกลุ่มการขอเลื่อนเงินเดือน"); } + const before = null; salaryProfile.salaryOrgId = salaryOrg.id; - await this.salaryProfileRepository.save(salaryProfile); + await this.salaryProfileRepository.save(salaryProfile, { data: req }); + setLogDataDiff(req, { before, after: salaryProfile }); + const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], where: { id: salaryProfile.id }, @@ -733,7 +740,8 @@ export class SalaryPeriodController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -787,7 +795,8 @@ export class SalaryPeriodController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } @@ -1017,7 +1026,9 @@ export class SalaryPeriodController extends Controller { } else { throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); } - await this.salaryProfileRepository.save(salaryProfile); + const before = null; + await this.salaryProfileRepository.save(salaryProfile, { data: req }); + setLogDataDiff(req, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -1048,7 +1059,8 @@ export class SalaryPeriodController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -1102,7 +1114,8 @@ export class SalaryPeriodController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } @@ -1221,6 +1234,7 @@ export class SalaryPeriodController extends Controller { if (!salaryProfile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการเพิ่มเงินเดือนของบุคคลนี้"); } + const before = structuredClone(salaryProfile); salaryProfile.isPunish = body.isPunish; salaryProfile.isSuspension = body.isSuspension; salaryProfile.isAbsent = body.isAbsent; @@ -1228,7 +1242,9 @@ export class SalaryPeriodController extends Controller { salaryProfile.lastUpdateUserId = request.user.sub; salaryProfile.lastUpdateFullName = request.user.name; salaryProfile.lastUpdatedAt = new Date(); - await this.salaryProfileRepository.save(salaryProfile); + await this.salaryProfileRepository.save(salaryProfile, { data: request }); + setLogDataDiff(request, { before, after: salaryProfile }); + return new HttpSuccess(); } @@ -1446,12 +1462,14 @@ export class SalaryPeriodController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); } + const before = null; salaryProfile.salaryOrgId = salaryOrg.id; salaryProfile.createdUserId = request.user.sub; salaryProfile.createdFullName = request.user.name; salaryProfile.lastUpdateUserId = request.user.sub; salaryProfile.lastUpdateFullName = request.user.name; - await this.salaryProfileRepository.save(salaryProfile); + await this.salaryProfileRepository.save(salaryProfile, { data: request }); + setLogDataDiff(request, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -1482,7 +1500,8 @@ export class SalaryPeriodController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -1536,7 +1555,8 @@ export class SalaryPeriodController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: salaryOrg }); } } } @@ -1554,15 +1574,18 @@ export class SalaryPeriodController extends Controller { * @param {string} id Guid, *Id รอบเงินเดือน */ @Get("close/{id}") - async closeSalaryPeriod_ById(@Path() id: string) { + async closeSalaryPeriod_ById(@Path() id: string, @Request() request: RequestWithUser) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: id }, }); if (!salaryPeriod) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรอบผังเงินเดือนนี้"); } + const before = structuredClone(salaryPeriod); salaryPeriod.isClose = !salaryPeriod.isClose; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); + return new HttpSuccess(); } @@ -1598,13 +1621,14 @@ export class SalaryPeriodController extends Controller { "ประเภทผังปี " + Extension.ToThaiYear(salaryPeriod.year) + " ซ้ำ", ); } - + const before = null; salaryPeriod.period = salaryPeriod.period.toUpperCase(); salaryPeriod.createdUserId = request.user.sub; salaryPeriod.createdFullName = request.user.name; salaryPeriod.lastUpdateUserId = request.user.sub; salaryPeriod.lastUpdateFullName = request.user.name; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); if (salaryPeriod.period == "SPECIAL") { const snapshot = "SNAP1"; @@ -1614,8 +1638,8 @@ export class SalaryPeriodController extends Controller { const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryOrgRepository.remove(salaryOrg); - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryOrgRepository.remove(salaryOrg, { data: request }); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); const salaryOrgEmployee = await this.salaryOrgEmployeeRepository.find({ where: { salaryPeriodId: salaryPeriod.id, snapshot: snapshot }, @@ -1623,14 +1647,15 @@ export class SalaryPeriodController extends Controller { const salaryProfileEmployee = await this.salaryProfileEmployeeRepository.find({ where: { salaryOrgId: In(salaryOrgEmployee.map((x) => x.id)) }, }); - await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee); - await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee); + await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee, { data: request }); + await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee, { data: request }); let orgs = await new CallAPI().GetData(request, "/org/unauthorize/active/root/id"); let revisionId = await new CallAPI().GetData(request, "/org/unauthorize/revision/latest"); salaryPeriod.revisionId = revisionId; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); await Promise.all( orgs.map(async (root: any) => { @@ -1646,7 +1671,8 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); }), ); await Promise.all( @@ -1663,7 +1689,8 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgEmployeeRepository.save(salaryOrgNew); + await this.salaryOrgEmployeeRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); }), ); } @@ -1709,13 +1736,15 @@ export class SalaryPeriodController extends Controller { "ประเภทผังปี " + (requestBody.effectiveDate.getFullYear() + 543) + " ซ้ำ", ); } - + const beforeChk_SalaryPeriod = structuredClone(chk_SalaryPeriod); chk_SalaryPeriod.period = requestBody.period.toUpperCase(); chk_SalaryPeriod.lastUpdateUserId = request.user.sub; chk_SalaryPeriod.lastUpdateFullName = request.user.name; chk_SalaryPeriod.lastUpdatedAt = new Date(); this.salaryPeriodRepository.merge(chk_SalaryPeriod, requestBody); - await this.salaryPeriodRepository.save(chk_SalaryPeriod); + await this.salaryPeriodRepository.save(chk_SalaryPeriod, { data: request }); + setLogDataDiff(request, { before: beforeChk_SalaryPeriod, after: chk_SalaryPeriod }); + if (chk_SalaryPeriod.period == "SPECIAL") { const snapshot = "SNAP1"; const salaryOrg = await this.salaryOrgRepository.find({ @@ -1724,8 +1753,8 @@ export class SalaryPeriodController extends Controller { const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryOrgRepository.remove(salaryOrg); - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryOrgRepository.remove(salaryOrg, { data: request }); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); const salaryOrgEmployee = await this.salaryOrgEmployeeRepository.find({ where: { salaryPeriodId: chk_SalaryPeriod.id, snapshot: snapshot }, @@ -1733,18 +1762,21 @@ export class SalaryPeriodController extends Controller { const salaryProfileEmployee = await this.salaryProfileEmployeeRepository.find({ where: { salaryOrgId: In(salaryOrgEmployee.map((x) => x.id)) }, }); - await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee); - await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee); + await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee, { data: request }); + await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee, { data: request }); let orgs = await new CallAPI().GetData(request, "/org/unauthorize/active/root/id"); let revisionId = await new CallAPI().GetData(request, "/org/unauthorize/revision/latest"); chk_SalaryPeriod.revisionId = revisionId; - await this.salaryPeriodRepository.save(chk_SalaryPeriod); + await this.salaryPeriodRepository.save(chk_SalaryPeriod, { data: request }); + setLogDataDiff(request, { before: beforeChk_SalaryPeriod, after: chk_SalaryPeriod }); await Promise.all( orgs.map(async (root: any) => { let salaryOrgNew = Object.assign(new SalaryOrg()); + const beforeSalaryOrgNew = structuredClone(salaryOrgNew); + salaryOrgNew.salaryPeriodId = chk_SalaryPeriod.id; salaryOrgNew.status = "PENDING"; salaryOrgNew.rootId = root.rootId; @@ -1756,13 +1788,16 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryOrgNew, after: salaryOrgNew }); }), ); await Promise.all( orgs.map(async (root: any) => { let salaryOrgNew = Object.assign(new SalaryOrgEmployee()); + const beforeSalaryOrgNew = structuredClone(salaryOrgNew); + salaryOrgNew.salaryPeriodId = chk_SalaryPeriod.id; salaryOrgNew.status = "PENDING"; salaryOrgNew.rootId = root.rootId; @@ -1774,7 +1809,8 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgEmployeeRepository.save(salaryOrgNew); + await this.salaryOrgEmployeeRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryOrgNew, after: salaryOrgNew }); }), ); } @@ -1805,8 +1841,8 @@ export class SalaryPeriodController extends Controller { const salaryProfile = SalaryOrg.find((x) => x.salaryProfiles.length > 0); if (salaryProfile) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบได้"); - await this.salaryOrgRepository.remove(SalaryOrg); - await this.salaryPeriodRepository.remove(SalaryPeriod); + await this.salaryOrgRepository.remove(SalaryOrg, { data: request }); + await this.salaryPeriodRepository.remove(SalaryPeriod, { data: request }); return new HttpSuccess(); } else { const SalaryOrg = await this.salaryOrgRepository.findOne({ @@ -1814,7 +1850,7 @@ export class SalaryPeriodController extends Controller { }); if (SalaryOrg) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบได้"); - await this.salaryPeriodRepository.remove(SalaryPeriod); + await this.salaryPeriodRepository.remove(SalaryPeriod, { data: request }); return new HttpSuccess(); } } @@ -1963,7 +1999,7 @@ export class SalaryPeriodController extends Controller { async SnapshotSalary( @Path() snapshot: string, salaryPeriodId: string, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { snapshot = snapshot.toLocaleUpperCase(); const salaryPeriod = await this.salaryPeriodRepository.findOne({ @@ -1979,8 +2015,8 @@ export class SalaryPeriodController extends Controller { const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryProfileRepository.remove(salaryProfile); - await this.salaryOrgRepository.remove(salaryOrg); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); + await this.salaryOrgRepository.remove(salaryOrg, { data: request }); const salaryOrgEmployee = await this.salaryOrgEmployeeRepository.find({ where: { salaryPeriodId: salaryPeriod.id, snapshot: snapshot }, @@ -1988,8 +2024,8 @@ export class SalaryPeriodController extends Controller { const salaryProfileEmployee = await this.salaryProfileEmployeeRepository.find({ where: { salaryOrgId: In(salaryOrgEmployee.map((x) => x.id)) }, }); - await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee); - await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee); + await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee, { data: request }); + await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee, { data: request }); let orgs = await new CallAPI().GetData(request, "/org/unauthorize/active/root/id"); let total = 1000; let _orgProfiles = await new CallAPI().PostData(request, "/org/unauthorize/salary/gen", { @@ -2050,13 +2086,17 @@ export class SalaryPeriodController extends Controller { } let revisionId = await new CallAPI().GetData(request, "/org/unauthorize/revision/latest"); + const beforeSalaryPeriod = structuredClone(salaryPeriod); salaryPeriod.revisionId = revisionId; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before: beforeSalaryPeriod, after: salaryPeriod }); await Promise.all( orgs.map(async (root: any) => { let salaryOrgNew = Object.assign(new SalaryOrg()); delete salaryOrgNew.id; + const beforeSalaryOrgNew = structuredClone(salaryOrgNew); + salaryOrgNew.salaryPeriodId = salaryPeriod.id; salaryOrgNew.status = "PENDING"; salaryOrgNew.rootId = root.rootId; @@ -2068,11 +2108,14 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryOrgNew, after: salaryOrgNew }); + if (salaryPeriod.period != "SPECIAL") { delete salaryOrgNew.id; salaryOrgNew.group = "GROUP2"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryOrgNew, after: salaryOrgNew }); } }), ); @@ -2080,6 +2123,8 @@ export class SalaryPeriodController extends Controller { await Promise.all( orgs.map(async (root: any) => { let salaryOrgNew = Object.assign(new SalaryOrgEmployee()); + const beforeSalaryOrgNew = structuredClone(salaryOrgNew); + salaryOrgNew.salaryPeriodId = salaryPeriod.id; salaryOrgNew.status = "PENDING"; salaryOrgNew.rootId = root.rootId; @@ -2091,11 +2136,14 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgEmployeeRepository.save(salaryOrgNew); + await this.salaryOrgEmployeeRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryOrgNew, after: salaryOrgNew }); + if (salaryPeriod.period != "SPECIAL") { delete salaryOrgNew.id; salaryOrgNew.group = "GROUP2"; - await this.salaryOrgEmployeeRepository.save(salaryOrgNew); + await this.salaryOrgEmployeeRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryOrgNew, after: salaryOrgNew }); } }), ); @@ -2125,6 +2173,9 @@ export class SalaryPeriodController extends Controller { if (salaryOrgNew != null) { let salaryProfileNew = Object.assign(new SalaryProfile(), profile); delete salaryProfileNew.id; + + const beforeSalaryProfileNew = structuredClone(salaryProfileNew); + salaryProfileNew.salaryOrgId = salaryOrgNew.id; salaryProfileNew.revisionId = salaryPeriod.revisionId; salaryProfileNew.createdUserId = request.user.sub; @@ -2153,7 +2204,8 @@ export class SalaryPeriodController extends Controller { salaryProfileNew.isReserve = salaryOld == null ? false : salaryOld.isReserve; salaryProfileNew.isRetired = salaryOld == null ? false : salaryOld.isRetired; } - await this.salaryProfileRepository.save(salaryProfileNew); + await this.salaryProfileRepository.save(salaryProfileNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryProfileNew, after: salaryProfileNew }); } }), ); @@ -2171,6 +2223,8 @@ export class SalaryPeriodController extends Controller { if (salaryOrgNew != null) { let salaryProfileNew = Object.assign(new SalaryProfileEmployee(), profile); delete salaryProfileNew.id; + const beforeSalaryProfileNew = structuredClone(salaryProfileNew); + salaryProfileNew.salaryOrgId = salaryOrgNew.id; salaryProfileNew.revisionId = salaryPeriod.revisionId; salaryProfileNew.createdUserId = request.user.sub; @@ -2199,7 +2253,8 @@ export class SalaryPeriodController extends Controller { salaryProfileNew.isReserve = salaryOld == null ? false : salaryOld.isReserve; salaryProfileNew.isRetired = salaryOld == null ? false : salaryOld.isRetired; } - await this.salaryProfileEmployeeRepository.save(salaryProfileNew); + await this.salaryProfileEmployeeRepository.save(salaryProfileNew, { data: request }); + setLogDataDiff(request, { before: beforeSalaryProfileNew, after: salaryProfileNew }); } }), ); @@ -2239,6 +2294,7 @@ export class SalaryPeriodController extends Controller { : Extension.sumObjectValues(salaryOrgSnap2Old.salaryProfiles, "amountUse"); } + const before_salaryOrg = structuredClone(_salaryOrg); if (snapshot == "SNAP2") { const salaryOrgSnap1 = await this.salaryOrgRepository.findOne({ where: { @@ -2265,6 +2321,7 @@ export class SalaryPeriodController extends Controller { } } else { const totalProfile = Extension.sumObjectValues(_salaryOrg.salaryProfiles, "amount"); + _salaryOrg.currentAmount = totalProfile; _salaryOrg.total = _salaryOrg.salaryProfiles.length; _salaryOrg.sixPercentAmount = totalProfile * 0.06; @@ -2272,12 +2329,15 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainingAmount = totalProfile * 0.06 - totalAmount; } - await this.salaryOrgRepository.save(_salaryOrg); + await this.salaryOrgRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before: before_salaryOrg, after: _salaryOrg }); }), ); await Promise.all( salaryOrgEmployeeNew.map(async (_salaryOrg: SalaryOrgEmployee) => { let totalAmount = 0; + const before_salaryOrg = structuredClone(_salaryOrg); + if (salaryPeriodAPROld != null) { const salaryOrgSnap2Old: any = await this.salaryOrgEmployeeRepository.findOne({ where: { @@ -2327,12 +2387,15 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainingAmount = totalProfile * 0.06 - totalAmount; } - await this.salaryOrgEmployeeRepository.save(_salaryOrg); + await this.salaryOrgEmployeeRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before: before_salaryOrg, after: _salaryOrg }); }), ); } else if (salaryPeriod.period == "APR") { await Promise.all( salaryOrgNew.map(async (_salaryOrg: SalaryOrg) => { + const before_salaryOrg = structuredClone(_salaryOrg); + if (snapshot == "SNAP2") { const salaryOrgSnap1 = await this.salaryOrgRepository.findOne({ where: { @@ -2361,11 +2424,14 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainQuota = Math.floor((_salaryOrg.salaryProfiles.length * 15) / 100); } - await this.salaryOrgRepository.save(_salaryOrg); + await this.salaryOrgRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before: before_salaryOrg, after: _salaryOrg }); }), ); await Promise.all( salaryOrgEmployeeNew.map(async (_salaryOrg: SalaryOrgEmployee) => { + const before_salaryOrg = structuredClone(_salaryOrg); + if (snapshot == "SNAP2") { const salaryOrgSnap1 = await this.salaryOrgEmployeeRepository.findOne({ where: { @@ -2394,7 +2460,8 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainQuota = Math.floor((_salaryOrg.salaryProfiles.length * 15) / 100); } - await this.salaryOrgEmployeeRepository.save(_salaryOrg); + await this.salaryOrgEmployeeRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before: before_salaryOrg, after: _salaryOrg }); }), ); } @@ -2471,8 +2538,8 @@ export class SalaryPeriodController extends Controller { const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryOrgRepository.remove(salaryOrg); - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryOrgRepository.remove(salaryOrg, { data: request }); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); const salaryOrgEmployee = await this.salaryOrgEmployeeRepository.find({ where: { salaryPeriodId: salaryPeriod.id, snapshot: snapshot }, @@ -2480,8 +2547,8 @@ export class SalaryPeriodController extends Controller { const salaryProfileEmployee = await this.salaryProfileEmployeeRepository.find({ where: { salaryOrgId: In(salaryOrgEmployee.map((x) => x.id)) }, }); - await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee); - await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee); + await this.salaryProfileEmployeeRepository.remove(salaryProfileEmployee, { data: request }); + await this.salaryOrgEmployeeRepository.remove(salaryOrgEmployee, { data: request }); let orgs = await new CallAPI().GetData(request, "/org/unauthorize/active/root/id"); let total = 1000; @@ -2541,9 +2608,10 @@ export class SalaryPeriodController extends Controller { } } let revisionId = await new CallAPI().GetData(request, "/org/unauthorize/revision/latest"); - + const before = null; salaryPeriod.revisionId = revisionId; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); await Promise.all( orgs.map(async (root: any) => { @@ -2559,11 +2627,14 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); + if (salaryPeriod.period != "SPECIAL") { delete salaryOrgNew.id; salaryOrgNew.group = "GROUP2"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); } }), ); @@ -2582,11 +2653,14 @@ export class SalaryPeriodController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); + if (salaryPeriod.period != "SPECIAL") { delete salaryOrgNew.id; salaryOrgNew.group = "GROUP2"; - await this.salaryOrgEmployeeRepository.save(salaryOrgNew); + await this.salaryOrgEmployeeRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); } }), ); @@ -2645,7 +2719,8 @@ export class SalaryPeriodController extends Controller { salaryProfileNew.isReserve = salaryOld == null ? false : salaryOld.isReserve; salaryProfileNew.isRetired = salaryOld == null ? false : salaryOld.isRetired; } - await this.salaryProfileRepository.save(salaryProfileNew); + await this.salaryProfileRepository.save(salaryProfileNew, { data: request }); + setLogDataDiff(request, { before, after: salaryProfileNew }); } }), ); @@ -2691,7 +2766,8 @@ export class SalaryPeriodController extends Controller { salaryProfileNew.isReserve = salaryOld == null ? false : salaryOld.isReserve; salaryProfileNew.isRetired = salaryOld == null ? false : salaryOld.isRetired; } - await this.salaryProfileEmployeeRepository.save(salaryProfileNew); + await this.salaryProfileEmployeeRepository.save(salaryProfileNew, { data: request }); + setLogDataDiff(request, { before, after: salaryProfileNew }); } }), ); @@ -2764,7 +2840,8 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainingAmount = totalProfile * 0.06 - totalAmount; } - await this.salaryOrgRepository.save(_salaryOrg); + await this.salaryOrgRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: _salaryOrg }); }), ); await Promise.all( @@ -2819,7 +2896,8 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainingAmount = totalProfile * 0.06 - totalAmount; } - await this.salaryOrgEmployeeRepository.save(_salaryOrg); + await this.salaryOrgEmployeeRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: _salaryOrg }); }), ); } else if (salaryPeriod.period == "APR") { @@ -2853,7 +2931,8 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainQuota = Math.floor((_salaryOrg.salaryProfiles.length * 15) / 100); } - await this.salaryOrgRepository.save(_salaryOrg); + await this.salaryOrgRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: _salaryOrg }); }), ); await Promise.all( @@ -2886,7 +2965,8 @@ export class SalaryPeriodController extends Controller { _salaryOrg.remainQuota = Math.floor((_salaryOrg.salaryProfiles.length * 15) / 100); } - await this.salaryOrgEmployeeRepository.save(_salaryOrg); + await this.salaryOrgEmployeeRepository.save(_salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: _salaryOrg }); }), ); } @@ -2900,7 +2980,11 @@ export class SalaryPeriodController extends Controller { * @param {string} rootId Guid, *Id สำนัก */ @Get("officer/approve/{periodId}/{rootId}") - async OfficerApprove(@Path() periodId: string, rootId: string) { + async OfficerApprove( + @Path() periodId: string, + rootId: string, + @Request() request: RequestWithUser, + ) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: periodId }, relations: ["salaryOrgs"], @@ -2911,8 +2995,10 @@ export class SalaryPeriodController extends Controller { salaryPeriod.salaryOrgs .filter((x) => x.rootId == rootId) .map(async (x) => { + const before = structuredClone(x); x.status = "WAITHEAD1"; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -2926,7 +3012,7 @@ export class SalaryPeriodController extends Controller { * @param {string} rootId Guid, *Id สำนัก */ @Get("head/approve/{periodId}/{rootId}") - async HeadApprove(@Path() periodId: string, rootId: string) { + async HeadApprove(@Path() periodId: string, rootId: string, @Request() request: RequestWithUser) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: periodId }, relations: ["salaryOrgs"], @@ -2938,8 +3024,10 @@ export class SalaryPeriodController extends Controller { salaryPeriod.salaryOrgs .filter((x) => x.rootId == rootId) .map(async (x) => { + const before = structuredClone(x); x.status = "WAITOWNER1"; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -2953,7 +3041,11 @@ export class SalaryPeriodController extends Controller { * @param {string} rootId Guid, *Id สำนัก */ @Get("owner/approve/{periodId}/{rootId}") - async OwnerApprove(@Path() periodId: string, rootId: string) { + async OwnerApprove( + @Path() periodId: string, + rootId: string, + @Request() request: RequestWithUser, + ) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: periodId }, relations: ["salaryOrgs"], @@ -2965,8 +3057,10 @@ export class SalaryPeriodController extends Controller { salaryPeriod.salaryOrgs .filter((x) => x.rootId == rootId) .map(async (x) => { + const before = structuredClone(x); x.status = "REPORT"; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -3001,9 +3095,12 @@ export class SalaryPeriodController extends Controller { salaryPeriod.salaryOrgs .filter((x) => x.rootId == rootId) .map(async (x) => { + const before = structuredClone(x); x.status = "WAITHEAD2"; x.ownerRecommend = body.titleRecommend; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x,{data:request}); + setLogDataDiff(request, { before, after: x }); + }), ); return new HttpSuccess(); @@ -3038,9 +3135,12 @@ export class SalaryPeriodController extends Controller { salaryPeriod.salaryOrgs .filter((x) => x.rootId == rootId) .map(async (x) => { + const before = structuredClone(x); x.status = "REPORT"; x.ownerRecommend = body.titleRecommend; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x,{data:request}); + setLogDataDiff(request, { before, after: x }); + }), ); return new HttpSuccess(); diff --git a/src/controllers/SalaryPeriodEmployeeController.ts b/src/controllers/SalaryPeriodEmployeeController.ts index 8837444..ca76961 100644 --- a/src/controllers/SalaryPeriodEmployeeController.ts +++ b/src/controllers/SalaryPeriodEmployeeController.ts @@ -32,6 +32,7 @@ import { SalaryRankEmployee } from "../entities/SalaryRankEmployee"; import { SalaryFormulaEmployee } from "../entities/SalaryFormulaEmployee"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/salary/period-employee") @Tags("SalaryEmployee") @@ -258,7 +259,7 @@ export class SalaryPeriodEmployeeController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการขอเงินเดือนผู้ใช้งานนี้ในระบบ"); } - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -289,7 +290,7 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -343,7 +344,7 @@ export class SalaryPeriodEmployeeController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); } } } @@ -712,7 +713,9 @@ export class SalaryPeriodEmployeeController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); } - await this.salaryProfileRepository.save(salaryProfile); + const before = null; + await this.salaryProfileRepository.save(salaryProfile, { data: req }); + setLogDataDiff(req, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -743,7 +746,8 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -797,7 +801,8 @@ export class SalaryPeriodEmployeeController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } @@ -835,9 +840,10 @@ export class SalaryPeriodEmployeeController extends Controller { if (!salaryOrg) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลกลุ่มการขอเลื่อนเงินเดือน"); } - + const before = null; salaryProfile.salaryOrgId = salaryOrg.id; - await this.salaryProfileRepository.save(salaryProfile); + await this.salaryProfileRepository.save(salaryProfile, { data: req }); + setLogDataDiff(req, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], where: { id: salaryProfile.id }, @@ -867,7 +873,8 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -921,7 +928,8 @@ export class SalaryPeriodEmployeeController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } @@ -1326,7 +1334,9 @@ export class SalaryPeriodEmployeeController extends Controller { } else { throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); } - await this.salaryProfileRepository.save(salaryProfile); + const before = null; + await this.salaryProfileRepository.save(salaryProfile, { data: req }); + setLogDataDiff(req, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -1357,7 +1367,8 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -1411,7 +1422,8 @@ export class SalaryPeriodEmployeeController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: req }); + setLogDataDiff(req, { before, after: salaryOrg }); } } } @@ -1583,6 +1595,7 @@ export class SalaryPeriodEmployeeController extends Controller { if (!salaryProfile) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการเพิ่มเงินเดือนของบุคคลนี้"); } + const before = structuredClone(salaryProfile); salaryProfile.isPunish = body.isPunish; salaryProfile.isSuspension = body.isSuspension; salaryProfile.isAbsent = body.isAbsent; @@ -1590,7 +1603,9 @@ export class SalaryPeriodEmployeeController extends Controller { salaryProfile.lastUpdateUserId = request.user.sub; salaryProfile.lastUpdateFullName = request.user.name; salaryProfile.lastUpdatedAt = new Date(); - await this.salaryProfileRepository.save(salaryProfile); + await this.salaryProfileRepository.save(salaryProfile, { data: request }); + setLogDataDiff(request, { before, after: salaryProfile }); + return new HttpSuccess(); } @@ -1982,12 +1997,14 @@ export class SalaryPeriodEmployeeController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); } + const before = null; salaryProfile.salaryOrgId = salaryOrg.id; salaryProfile.createdUserId = request.user.sub; salaryProfile.createdFullName = request.user.name; salaryProfile.lastUpdateUserId = request.user.sub; salaryProfile.lastUpdateFullName = request.user.name; - await this.salaryProfileRepository.save(salaryProfile); + await this.salaryProfileRepository.save(salaryProfile, { data: request }); + setLogDataDiff(request, { before, after: salaryProfile }); const _salaryProfile = await this.salaryProfileRepository.findOne({ relations: ["salaryOrg", "salaryOrg.salaryPeriod"], @@ -2018,7 +2035,8 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrg.quantityUsed = amountFullType; const calRemainQuota = salaryOrg.fifteenPercent - amountFullType; salaryOrg.remainQuota = calRemainQuota; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: salaryOrg }); } } } else if (_salaryProfile.salaryOrg.salaryPeriod.period == "OCT") { @@ -2072,7 +2090,8 @@ export class SalaryPeriodEmployeeController extends Controller { ? 0 : sumAmountUse.totalAmount; salaryOrg.remainingAmount = calRemainAmount; - await this.salaryOrgRepository.save(salaryOrg); + await this.salaryOrgRepository.save(salaryOrg, { data: request }); + setLogDataDiff(request, { before, after: salaryOrg }); } } } @@ -2091,15 +2110,17 @@ export class SalaryPeriodEmployeeController extends Controller { * @param {string} id Guid, *Id รอบเงินเดือน */ @Get("close/{id}") - async closeSalaryPeriod_ById(@Path() id: string) { + async closeSalaryPeriod_ById(@Path() id: string, @Request() request: RequestWithUser) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: id }, }); if (!salaryPeriod) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรอบผังเงินเดือนนี้"); } + const before = structuredClone(salaryPeriod); salaryPeriod.isClose = !salaryPeriod.isClose; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); return new HttpSuccess(); } @@ -2135,13 +2156,14 @@ export class SalaryPeriodEmployeeController extends Controller { "ประเภทผังปี " + Extension.ToThaiYear(salaryPeriod.year) + " ซ้ำ", ); } - + const before = null; salaryPeriod.period = salaryPeriod.period.toUpperCase(); salaryPeriod.createdUserId = request.user.sub; salaryPeriod.createdFullName = request.user.name; salaryPeriod.lastUpdateUserId = request.user.sub; salaryPeriod.lastUpdateFullName = request.user.name; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); if (salaryPeriod.period == "SPECIAL") { const snapshot = "SNAP1"; @@ -2151,14 +2173,15 @@ export class SalaryPeriodEmployeeController extends Controller { const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryOrgRepository.remove(salaryOrg); - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryOrgRepository.remove(salaryOrg, { data: request }); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); let orgs = await new CallAPI().GetData(request, "/org/unauthorize/active/root/id"); let revisionId = await new CallAPI().GetData(request, "/org/unauthorize/revision/latest"); salaryPeriod.revisionId = revisionId; - await this.salaryPeriodRepository.save(salaryPeriod); + await this.salaryPeriodRepository.save(salaryPeriod, { data: request }); + setLogDataDiff(request, { before, after: salaryPeriod }); await Promise.all( orgs.map(async (rootId: string) => { @@ -2173,7 +2196,8 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); }), ); } @@ -2219,13 +2243,15 @@ export class SalaryPeriodEmployeeController extends Controller { "ประเภทผังปี " + (requestBody.effectiveDate.getFullYear() + 543) + " ซ้ำ", ); } - + const beforechk_SalaryPeriod = structuredClone(chk_SalaryPeriod); chk_SalaryPeriod.period = requestBody.period.toUpperCase(); chk_SalaryPeriod.lastUpdateUserId = request.user.sub; chk_SalaryPeriod.lastUpdateFullName = request.user.name; chk_SalaryPeriod.lastUpdatedAt = new Date(); this.salaryPeriodRepository.merge(chk_SalaryPeriod, requestBody); - await this.salaryPeriodRepository.save(chk_SalaryPeriod); + await this.salaryPeriodRepository.save(chk_SalaryPeriod, { data: request }); + setLogDataDiff(request, { before: beforechk_SalaryPeriod, after: chk_SalaryPeriod }); + if (chk_SalaryPeriod.period == "SPECIAL") { const snapshot = "SNAP1"; const salaryOrg = await this.salaryOrgRepository.find({ @@ -2234,18 +2260,20 @@ export class SalaryPeriodEmployeeController extends Controller { const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryOrgRepository.remove(salaryOrg); - await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryOrgRepository.remove(salaryOrg, { data: request }); + await this.salaryProfileRepository.remove(salaryProfile, { data: request }); let orgs = await new CallAPI().GetData(request, "/org/unauthorize/active/root/id"); let revisionId = await new CallAPI().GetData(request, "/org/unauthorize/revision/latest"); chk_SalaryPeriod.revisionId = revisionId; - await this.salaryPeriodRepository.save(chk_SalaryPeriod); + await this.salaryPeriodRepository.save(chk_SalaryPeriod, { data: request }); + setLogDataDiff(request, { before: beforechk_SalaryPeriod, after: chk_SalaryPeriod }); await Promise.all( orgs.map(async (rootId: string) => { let salaryOrgNew = Object.assign(new SalaryOrgEmployee()); + const before = structuredClone(salaryOrgNew); salaryOrgNew.salaryPeriodId = chk_SalaryPeriod.id; salaryOrgNew.status = "PENDING"; salaryOrgNew.rootId = rootId; @@ -2256,7 +2284,8 @@ export class SalaryPeriodEmployeeController extends Controller { salaryOrgNew.lastUpdateUserId = request.user.sub; salaryOrgNew.lastUpdateFullName = request.user.name; salaryOrgNew.group = "GROUP1"; - await this.salaryOrgRepository.save(salaryOrgNew); + await this.salaryOrgRepository.save(salaryOrgNew, { data: request }); + setLogDataDiff(request, { before, after: salaryOrgNew }); }), ); } @@ -2287,8 +2316,8 @@ export class SalaryPeriodEmployeeController extends Controller { const salaryProfile = SalaryOrg.find((x) => x.salaryProfiles.length > 0); if (salaryProfile) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบได้"); - await this.salaryOrgRepository.remove(SalaryOrg); - await this.salaryPeriodRepository.remove(SalaryPeriod); + await this.salaryOrgRepository.remove(SalaryOrg, { data: request }); + await this.salaryPeriodRepository.remove(SalaryPeriod, { data: request }); return new HttpSuccess(); } else { const SalaryOrg = await this.salaryOrgRepository.findOne({ @@ -2296,7 +2325,7 @@ export class SalaryPeriodEmployeeController extends Controller { }); if (SalaryOrg) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบได้"); - await this.salaryPeriodRepository.remove(SalaryPeriod); + await this.salaryPeriodRepository.remove(SalaryPeriod, { data: request }); return new HttpSuccess(); } } @@ -2405,7 +2434,11 @@ export class SalaryPeriodEmployeeController extends Controller { * @param {string} rootId Guid, *Id สำนัก */ @Get("officer/approve/{periodId}/{rootId}") - async OfficerApprove(@Path() periodId: string, rootId: string) { + async OfficerApprove( + @Path() periodId: string, + rootId: string, + @Request() request: RequestWithUser, + ) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: periodId }, relations: ["salaryOrgEmployees"], @@ -2416,8 +2449,10 @@ export class SalaryPeriodEmployeeController extends Controller { salaryPeriod.salaryOrgEmployees .filter((x) => x.rootId == rootId) .map(async (x: any) => { + const before = structuredClone(x); x.status = "WAITHEAD1"; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -2431,7 +2466,7 @@ export class SalaryPeriodEmployeeController extends Controller { * @param {string} rootId Guid, *Id สำนัก */ @Get("head/approve/{periodId}/{rootId}") - async HeadApprove(@Path() periodId: string, rootId: string) { + async HeadApprove(@Path() periodId: string, rootId: string, @Request() request: RequestWithUser) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: periodId }, relations: ["salaryOrgEmployees"], @@ -2443,8 +2478,10 @@ export class SalaryPeriodEmployeeController extends Controller { salaryPeriod.salaryOrgEmployees .filter((x) => x.rootId == rootId) .map(async (x: any) => { + const before = structuredClone(x); x.status = "WAITOWNER1"; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -2458,7 +2495,11 @@ export class SalaryPeriodEmployeeController extends Controller { * @param {string} rootId Guid, *Id สำนัก */ @Get("owner/approve/{periodId}/{rootId}") - async OwnerApprove(@Path() periodId: string, rootId: string) { + async OwnerApprove( + @Path() periodId: string, + rootId: string, + @Request() request: RequestWithUser, + ) { const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: periodId }, relations: ["salaryOrgEmployees"], @@ -2470,8 +2511,10 @@ export class SalaryPeriodEmployeeController extends Controller { salaryPeriod.salaryOrgEmployees .filter((x) => x.rootId == rootId) .map(async (x: any) => { + const before = structuredClone(x); x.status = "REPORT"; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -2506,9 +2549,11 @@ export class SalaryPeriodEmployeeController extends Controller { salaryPeriod.salaryOrgEmployees .filter((x) => x.rootId == rootId) .map(async (x: any) => { + const before = structuredClone(x); x.status = "WAITHEAD2"; x.ownerRecommend = body.titleRecommend; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); @@ -2543,9 +2588,11 @@ export class SalaryPeriodEmployeeController extends Controller { salaryPeriod.salaryOrgEmployees .filter((x) => x.rootId == rootId) .map(async (x: any) => { + const before = structuredClone(x); x.status = "REPORT"; x.ownerRecommend = body.titleRecommend; - await this.salaryOrgRepository.save(x); + await this.salaryOrgRepository.save(x, { data: request }); + setLogDataDiff(request, { before, after: x }); }), ); return new HttpSuccess(); diff --git a/src/controllers/SalaryRankController.ts b/src/controllers/SalaryRankController.ts index be303c3..0dfa984 100644 --- a/src/controllers/SalaryRankController.ts +++ b/src/controllers/SalaryRankController.ts @@ -23,6 +23,8 @@ import { CreateSalaryRank, SalaryRanks, UpdateSalaryRank } from "../entities/Sal import { Salarys } from "../entities/Salarys"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/salary/rate") @Tags("SalaryRank") @Security("bearerAuth") @@ -55,12 +57,14 @@ export class SalaryRanksController extends Controller { if (!checkSalary) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } + const before = null; const salaryRank = Object.assign(new SalaryRanks(), requestBody); salaryRank.createdUserId = request.user.sub; salaryRank.createdFullName = request.user.name; salaryRank.lastUpdateUserId = request.user.sub; salaryRank.lastUpdateFullName = request.user.name; - await this.salaryRankRepository.save(salaryRank); + await this.salaryRankRepository.save(salaryRank, { data: request }); + setLogDataDiff(request, { before, after: salaryRank }); return new HttpSuccess(); } catch (error: any) { throw new Error(error); @@ -86,10 +90,12 @@ export class SalaryRanksController extends Controller { if (!salaryRank) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับผังเงินเดือนนี้"); } + const before = structuredClone(salaryRank); salaryRank.lastUpdateUserId = request.user.sub; salaryRank.lastUpdateFullName = request.user.name; this.salaryRankRepository.merge(salaryRank, requestBody); - await this.salaryRankRepository.save(salaryRank); + await this.salaryRankRepository.save(salaryRank, { data: request }); + setLogDataDiff(request, { before, after: salaryRank }); return new HttpSuccess(); } diff --git a/src/controllers/SalaryRankEmployeeController.ts b/src/controllers/SalaryRankEmployeeController.ts index 2889444..7cfa4af 100644 --- a/src/controllers/SalaryRankEmployeeController.ts +++ b/src/controllers/SalaryRankEmployeeController.ts @@ -27,6 +27,8 @@ import { import { SalaryEmployee } from "../entities/SalaryEmployee"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/salary/rate/employee") @Tags("SalaryRankEmployee") @Security("bearerAuth") @@ -68,11 +70,13 @@ export class SalaryRankEmployeeController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถเพิ่มได้ เนื่องจากลำดับขั้นนี้ซ้ำ"); } const salaryRankEmployee = Object.assign(new SalaryRankEmployee(), requestBody); + const before = null; salaryRankEmployee.createdUserId = request.user.sub; salaryRankEmployee.createdFullName = request.user.name; salaryRankEmployee.lastUpdateUserId = request.user.sub; salaryRankEmployee.lastUpdateFullName = request.user.name; - await this.salaryRankEmployeeRepository.save(salaryRankEmployee); + await this.salaryRankEmployeeRepository.save(salaryRankEmployee, { data: request }); + setLogDataDiff(request, { before, after: salaryRankEmployee }); return new HttpSuccess(); } catch (error: any) { throw new Error(error); @@ -109,10 +113,12 @@ export class SalaryRankEmployeeController extends Controller { if (checkStep.length > 0) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถแก้ไขได้ เนื่องจากลำดับขั้นนี้ซ้ำ"); } + const before = structuredClone(salaryRankEmployee); salaryRankEmployee.lastUpdateUserId = request.user.sub; salaryRankEmployee.lastUpdateFullName = request.user.name; this.salaryRankEmployeeRepository.merge(salaryRankEmployee, requestBody); - await this.salaryRankEmployeeRepository.save(salaryRankEmployee); + await this.salaryRankEmployeeRepository.save(salaryRankEmployee, { data: request }); + setLogDataDiff(request, { before, after: salaryRankEmployee }); return new HttpSuccess(); } diff --git a/src/database/data-source.ts b/src/database/data-source.ts index 7c70f52..5f6b6b0 100644 --- a/src/database/data-source.ts +++ b/src/database/data-source.ts @@ -1,6 +1,45 @@ import "dotenv/config"; import "reflect-metadata"; -import { DataSource } from "typeorm"; +import { DataSource, LogLevel, LogMessage, QueryRunner } from "typeorm"; +import { Logger } from "typeorm"; +import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence } from "../interfaces/utils"; + +export class MyCustomLogger implements Logger { + log(level: "log" | "info" | "warn", message: any, queryRunner?: QueryRunner) {} + + logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner): void { + const req = queryRunner?.data as RequestWithUser; + if (req?.app?.locals.logData?.sequence) { + addLogSequence(req, { + action: "database", + status: "success", + description: "Query Data.", + query: [ + "Query: " + query + (parameters ? " - Parameters:" + JSON.stringify(parameters) : ""), + ], + }); + } + + // const req = queryRunner?.data as RequestWithUser | undefined; + // const logData = req?.app?.locals.logData?.sequence?.at(-1); + + // if (logData && !logData.query) logData.query = []; + // if (logData) logData.query.push( + // "Query: " + query + (parameters ? (" - Parameters:" + JSON.stringify(parameters)) : '') + // ); + } + + logMigration(message: string, queryRunner?: QueryRunner) {} + logQueryError( + error: string | Error, + query: string, + parameters?: any[], + queryRunner?: QueryRunner, + ) {} + logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner) {} + logSchemaBuild(message: string, queryRunner?: QueryRunner) {} +} export const AppDataSource = new DataSource({ type: "mysql", @@ -11,7 +50,7 @@ export const AppDataSource = new DataSource({ password: process.env.DB_PASSWORD, connectorPackage: "mysql2", synchronize: false, - logging: true, + logging: ["query", "error"], entities: process.env.NODE_ENV !== "production" ? ["src/entities/**/*.ts"] @@ -21,7 +60,5 @@ export const AppDataSource = new DataSource({ ? ["src/migration/**/*.ts"] : ["dist/migration/**/*{.ts,.js}"], subscribers: [], + logger: new MyCustomLogger(), }); -// console.log(AppDataSource); - -// export default database; diff --git a/src/interfaces/call-api.ts b/src/interfaces/call-api.ts index 69364e4..78f0f14 100644 --- a/src/interfaces/call-api.ts +++ b/src/interfaces/call-api.ts @@ -12,6 +12,7 @@ import { Path, } from "tsoa"; import axios from "axios"; +import { addLogSequence } from "./utils"; class CallAPI { //Get @@ -26,8 +27,28 @@ class CallAPI { api_key: process.env.API_KEY, }, }); + addLogSequence(request, { + action: "request", + status: "success", + description: "connected", + request: { + method: "GET", + url: url, + response: JSON.stringify(response.data.result), + }, + }); return response.data.result; } catch (error) { + addLogSequence(request, { + action: "request", + status: "error", + description: "unconnected", + request: { + method: "GET", + url: url, + response: JSON.stringify(error), + }, + }); throw error; } } @@ -43,8 +64,30 @@ class CallAPI { api_key: process.env.API_KEY, }, }); + addLogSequence(request, { + action: "request", + status: "success", + description: "connected", + request: { + method: "POST", + url: url, + payload: JSON.stringify(sendData), + response: JSON.stringify(response.data.result), + }, + }); return response.data.result; } catch (error) { + addLogSequence(request, { + action: "request", + status: "error", + description: "unconnected", + request: { + method: "POST", + url: url, + payload: JSON.stringify(sendData), + response: JSON.stringify(error), + }, + }); throw error; } } diff --git a/src/interfaces/utils.ts b/src/interfaces/utils.ts new file mode 100644 index 0000000..30035f0 --- /dev/null +++ b/src/interfaces/utils.ts @@ -0,0 +1,37 @@ +import { RequestWithUser } from "../middlewares/user"; + +export type DataDiff = { + before: any; + after: any; +}; + +export type LogSequence = { + action: string; + status: "success" | "error"; + description: string; + query?: any; + request?: { + method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; + url?: string; + payload?: string; + response?: string; + }; +}; + +export function setLogDataDiff(req: RequestWithUser, data: DataDiff) { + req.app.locals.logData.dataDiff = { + before: JSON.stringify(data.before), + after: JSON.stringify(data.after), + }; +} + +export function addLogSequence(req: RequestWithUser, data: LogSequence) { + if (!req?.app?.locals?.logData?.sequence) { + req.app.locals.logData.sequence = []; + } + req.app.locals.logData.sequence = req.app.locals.logData.sequence.concat(data); +} + +export function editLogSequence(req: RequestWithUser, index: number, data: LogSequence) { + req.app.locals.logData.sequence[index] = data; +} diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts index e81aa15..de43a0c 100644 --- a/src/middlewares/auth.ts +++ b/src/middlewares/auth.ts @@ -3,15 +3,13 @@ import { createDecoder, createVerifier } from "fast-jwt"; import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; +import { addLogSequence } from "../interfaces/utils"; +import { RequestWithUser } from "./user"; if (!process.env.AUTH_PUBLIC_KEY && !process.env.AUTH_REALM_URL) { throw new Error("Require keycloak AUTH_PUBLIC_KEY or AUTH_REALM_URL."); } -if ( - process.env.AUTH_PUBLIC_KEY && - process.env.AUTH_REALM_URL && - !process.env.AUTH_PREFERRED_MODE -) { +if (process.env.AUTH_PUBLIC_KEY && process.env.AUTH_REALM_URL && !process.env.AUTH_PREFERRED_MODE) { throw new Error( "AUTH_PREFFERRED must be specified if AUTH_PUBLIC_KEY and AUTH_REALM_URL is provided.", ); @@ -26,7 +24,7 @@ const jwtVerify = createVerifier({ const jwtDecode = createDecoder(); export async function expressAuthentication( - request: express.Request, + request: RequestWithUser, securityName: string, _scopes?: string[], ) { @@ -56,6 +54,18 @@ export async function expressAuthentication( if (process.env.AUTH_PUBLIC_KEY) payload = await verifyOffline(token); break; } + if (!request.app.locals.logData) { + request.app.locals.logData = {}; + } + + // addLogSequence(request, { + // action: "database", + // status: "success", + // description: "Query Data.", + // }); + request.app.locals.logData.userId = payload.sub; + request.app.locals.logData.userName = payload.name; + request.app.locals.logData.user = payload.preferred_username; return payload; } diff --git a/src/middlewares/error.ts b/src/middlewares/error.ts index b010f0a..f8d0b56 100644 --- a/src/middlewares/error.ts +++ b/src/middlewares/error.ts @@ -4,6 +4,12 @@ import HttpStatus from "../interfaces/http-status"; import { ValidateError } from "tsoa"; function error(error: Error, _req: Request, res: Response, _next: NextFunction) { + const logData = _req.app.locals.logData.sequence?.at(-1); + if (logData) { + logData.status = "error"; + logData.description = error.message; + } + if (error instanceof HttpError) { return res.status(error.status).json({ status: error.status, diff --git a/src/middlewares/logs.ts b/src/middlewares/logs.ts new file mode 100644 index 0000000..f4b0b80 --- /dev/null +++ b/src/middlewares/logs.ts @@ -0,0 +1,74 @@ +import { NextFunction, Request, Response } from "express"; +import { Client } from "@elastic/elasticsearch"; + +if (!process.env.ELASTICSEARCH_INDEX) { + throw new Error("Require ELASTICSEARCH_INDEX to store log."); +} + +const ELASTICSEARCH_INDEX = process.env.ELASTICSEARCH_INDEX; + +const LOG_LEVEL_MAP: Record = { + debug: 4, + info: 3, + warning: 2, + error: 1, + none: 0, +}; + +const elasticsearch = new Client({ + node: `${process.env.ELASTICSEARCH_PROTOCOL}://${process.env.ELASTICSEARCH_HOST}:${process.env.ELASTICSEARCH_PORT}`, +}); + +async function logMiddleware(req: Request, res: Response, next: NextFunction) { + if (!req.url.startsWith("/api/")) return next(); + + let data: any; + + const originalJson = res.json; + + res.json = function (v: any) { + data = v; + return originalJson.call(this, v); + }; + + const timestamp = new Date().toISOString(); + const start = performance.now(); + + req.app.locals.logData = {}; + + res.on("finish", () => { + if (!req.url.startsWith("/api/")) return; + + const level = LOG_LEVEL_MAP[process.env.LOG_LEVEL ?? "debug"] || 4; + + if (level === 1 && res.statusCode < 500) return; + if (level === 2 && res.statusCode < 400) return; + if (level === 3 && res.statusCode < 200) return; + + const obj = { + logType: res.statusCode >= 500 ? "error" : res.statusCode >= 400 ? "warning" : "info", + ip: req.ip, + systemName: "salary", + startTimeStamp: timestamp, + endTimeStamp: new Date().toISOString(), + processTime: performance.now() - start, + host: req.hostname, + method: req.method, + endpoint: req.url, + responseCode: String(res.statusCode === 304 ? 200 : res.statusCode), + responseDescription: data?.message, + input: (level === 4 && JSON.stringify(req.body, null, 2)) || undefined, + output: (level === 4 && JSON.stringify(data, null, 2)) || undefined, + ...req.app.locals.logData, + }; + + elasticsearch.index({ + index: ELASTICSEARCH_INDEX, + document: obj, + }); + }); + + return next(); +} + +export default logMiddleware;