diff --git a/src/controllers/KpiCapacityController.ts b/src/controllers/KpiCapacityController.ts index d7853e5..3b37809 100644 --- a/src/controllers/KpiCapacityController.ts +++ b/src/controllers/KpiCapacityController.ts @@ -25,6 +25,8 @@ import { KpiCapacityDetail } from "../entities/kpiCapacityDetail"; import { Like, In } from "typeorm"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/capacity") @Tags("kpiCapacity") @Security("bearerAuth") @@ -75,11 +77,14 @@ export class kpiCapacityController extends Controller { name: requestBody.name, description: requestBody.description, }); + const before = null; + kpiCapacity.createdUserId = request.user.sub; kpiCapacity.createdFullName = request.user.name; kpiCapacity.lastUpdateUserId = request.user.sub; kpiCapacity.lastUpdateFullName = request.user.name; - await this.kpiCapacityRepository.save(kpiCapacity); + await this.kpiCapacityRepository.save(kpiCapacity, { data: request }); + setLogDataDiff(request, { before, after: kpiCapacity }); let idx: number = 0; for (const data of requestBody.capacityDetails) { @@ -95,7 +100,8 @@ export class kpiCapacityController extends Controller { kpiCapacityDetail.createdFullName = request.user.name; kpiCapacityDetail.lastUpdateUserId = request.user.sub; kpiCapacityDetail.lastUpdateFullName = request.user.name; - await this.kpiCapacityDetailRepository.save(kpiCapacityDetail); + await this.kpiCapacityDetailRepository.save(kpiCapacityDetail, { data: request }); + setLogDataDiff(request, { before, after: kpiCapacityDetail }); } return new HttpSuccess(kpiCapacity.id); @@ -146,15 +152,17 @@ export class kpiCapacityController extends Controller { name: requestBody.name, description: requestBody.description, }); + const before = structuredClone(kpiCapacity); kpiCapacity.lastUpdateUserId = request.user.sub; kpiCapacity.lastUpdateFullName = request.user.name; this.kpiCapacityRepository.merge(kpiCapacity, _kpiCapacity); - await this.kpiCapacityRepository.save(kpiCapacity); + await this.kpiCapacityRepository.save(kpiCapacity, { data: request }); + setLogDataDiff(request, { before, after: kpiCapacity }); const _kpiCapacityDetailsOld = await this.kpiCapacityDetailRepository.find({ where: { kpiCapacityId: kpiCapacity.id }, }); - await this.kpiCapacityDetailRepository.remove(_kpiCapacityDetailsOld); + await this.kpiCapacityDetailRepository.remove(_kpiCapacityDetailsOld, { data: request }); let idx: number = 0; for (const data of requestBody.capacityDetails) { @@ -166,11 +174,14 @@ export class kpiCapacityController extends Controller { description: data.description, kpiCapacityId: kpiCapacity.id, }); + const beforeDetail = structuredClone(kpiCapacityDetail); + kpiCapacityDetail.createdUserId = request.user.sub; kpiCapacityDetail.createdFullName = request.user.name; kpiCapacityDetail.lastUpdateUserId = request.user.sub; kpiCapacityDetail.lastUpdateFullName = request.user.name; - await this.kpiCapacityDetailRepository.save(kpiCapacityDetail); + await this.kpiCapacityDetailRepository.save(kpiCapacityDetail, { data: request }); + setLogDataDiff(request, { before: beforeDetail, after: kpiCapacityDetail }); } return new HttpSuccess(kpiCapacity.id); @@ -374,9 +385,9 @@ export class kpiCapacityController extends Controller { where: { kpiCapacityId: id }, }); if (kpiCapacityDetails.length > 0) { - await this.kpiCapacityDetailRepository.remove(kpiCapacityDetails); + await this.kpiCapacityDetailRepository.remove(kpiCapacityDetails, { data: request }); } - await this.kpiCapacityRepository.remove(kpiCapacity); + await this.kpiCapacityRepository.remove(kpiCapacity, { data: request }); return new HttpSuccess(); } } diff --git a/src/controllers/KpiEvaluationController.ts b/src/controllers/KpiEvaluationController.ts index 011ea40..e339601 100644 --- a/src/controllers/KpiEvaluationController.ts +++ b/src/controllers/KpiEvaluationController.ts @@ -19,6 +19,8 @@ import HttpStatusCode from "../interfaces/http-status"; import { KpiEvaluation, updateKpiEvaluation } from "../entities/kpiEvaluation"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/evaluation") @Tags("kpiEvaluation") @Security("bearerAuth") @@ -49,11 +51,13 @@ export class kpiEvaluationController extends Controller { if (!kpiEvaluation) { throw new HttpError(HttpStatusCode.NOT_FOUND, `ไม่พบข้อมูลเกณฑ์การประเมินนี้: ${item.id}`); } + const before = structuredClone(kpiEvaluation); this.kpiEvaluationRepository.merge(kpiEvaluation, item); kpiEvaluation.lastUpdateUserId = request.user.sub; kpiEvaluation.lastUpdateFullName = request.user.name; - await this.kpiEvaluationRepository.save(kpiEvaluation); + await this.kpiEvaluationRepository.save(kpiEvaluation, { data: request }); + setLogDataDiff(request, { before, after: kpiEvaluation }); updatedIds.push(item.id); } diff --git a/src/controllers/KpiGroupController.ts b/src/controllers/KpiGroupController.ts index 7b8824d..67c11f7 100644 --- a/src/controllers/KpiGroupController.ts +++ b/src/controllers/KpiGroupController.ts @@ -23,6 +23,8 @@ import HttpStatusCode from "../interfaces/http-status"; import { KpiGroup, createKpiGroup, updateKpiGroup } from "../entities/kpiGroup"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/group") @Tags("kpiGroup") @Security("bearerAuth") @@ -54,11 +56,15 @@ export class kpiGroupController extends Controller { if (chkkpinameGroup) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อกลุ่มงานนี้มีอยู่ในระบบแล้ว"); } + const before = null; + kpiGroup.createdUserId = request.user.sub; kpiGroup.createdFullName = request.user.name; kpiGroup.lastUpdateUserId = request.user.sub; kpiGroup.lastUpdateFullName = request.user.name; - await this.kpiGroupRepository.save(kpiGroup); + await this.kpiGroupRepository.save(kpiGroup, { data: request }); + setLogDataDiff(request, { before, after: kpiGroup }); + return new HttpSuccess(kpiGroup.id); } @@ -89,10 +95,14 @@ export class kpiGroupController extends Controller { if (chkkpinameGroup) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อกลุ่มงานนี้มีอยู่ในระบบแล้ว"); } + const before = structuredClone(kpiGroup); + this.kpiGroupRepository.merge(kpiGroup, requestBody); kpiGroup.lastUpdateUserId = request.user.sub; kpiGroup.lastUpdateFullName = request.user.name; - await this.kpiGroupRepository.save(kpiGroup); + await this.kpiGroupRepository.save(kpiGroup, { data: request }); + setLogDataDiff(request, { before, after: kpiGroup }); + return new HttpSuccess(id); } @@ -130,7 +140,7 @@ export class kpiGroupController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลกลุ่มงานนี้"); } - await this.kpiGroupRepository.remove(kpiGroup); + await this.kpiGroupRepository.remove(kpiGroup, { data: request }); return new HttpSuccess(); } diff --git a/src/controllers/KpiLinkController.ts b/src/controllers/KpiLinkController.ts index 44b338f..401d26f 100644 --- a/src/controllers/KpiLinkController.ts +++ b/src/controllers/KpiLinkController.ts @@ -25,6 +25,8 @@ import { KpiCapacity } from "../entities/kpiCapacity"; import { Position } from "../entities/position"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/link") @Tags("kpiLink") @Security("bearerAuth") @@ -56,6 +58,7 @@ export class kpiLinkController extends Controller { if (!chkkpiGroup) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการเชื่อมโยง"); } + const before = null; const kpiLink = Object.assign(new KpiLink(), requestBody, { createdUserId: request.user.sub, @@ -64,7 +67,8 @@ export class kpiLinkController extends Controller { lastUpdateFullName: request.user.name, kpiGroup: chkkpiGroup, }); - await this.kpiLinkRepository.save(kpiLink); + await this.kpiLinkRepository.save(kpiLink, { data: request }); + setLogDataDiff(request, { before, after: kpiLink }); if (requestBody.positions != null) { await Promise.all( @@ -76,7 +80,8 @@ export class kpiLinkController extends Controller { position.createdFullName = request.user.name; position.lastUpdateUserId = request.user.sub; position.lastUpdateFullName = request.user.name; - await this.positionRepository.save(position); + await this.positionRepository.save(position, { data: request }); + setLogDataDiff(request, { before, after: position }); }), ); } @@ -91,7 +96,8 @@ export class kpiLinkController extends Controller { } kpiLink.kpiCapacitys = chkCapacity; - await this.kpiLinkRepository.save(kpiLink); + await this.kpiLinkRepository.save(kpiLink, { data: request }); + setLogDataDiff(request, { before, after: kpiLink }); return new HttpSuccess(kpiLink.id); } @@ -119,8 +125,9 @@ export class kpiLinkController extends Controller { if (!chkKpiLink) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการเชื่อมโยง"); } + const before = structuredClone(chkKpiLink); - await this.positionRepository.remove(chkKpiLink.positions); + await this.positionRepository.remove(chkKpiLink.positions, { data: request }); Object.assign(chkKpiLink, { ...requestBody, kpiCapacitys: [], @@ -139,7 +146,8 @@ export class kpiLinkController extends Controller { position.createdFullName = request.user.name; position.lastUpdateUserId = request.user.sub; position.lastUpdateFullName = request.user.name; - await this.positionRepository.save(position); + await this.positionRepository.save(position, { data: request }); + setLogDataDiff(request, { before: null, after: position }); }), ); } @@ -154,7 +162,8 @@ export class kpiLinkController extends Controller { } chkKpiLink.kpiCapacitys = chkCapacity; - await this.kpiLinkRepository.save(chkKpiLink); + await this.kpiLinkRepository.save(chkKpiLink, { data: request }); + setLogDataDiff(request, { before, after: chkKpiLink }); return new HttpSuccess(chkKpiLink.id); } @@ -208,8 +217,9 @@ export class kpiLinkController extends Controller { if (!kpiLink) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลการเชื่อมโยง"); } + kpiLink.kpiCapacitys = []; - await this.kpiLinkRepository.save(kpiLink); + await this.kpiLinkRepository.save(kpiLink, { data: request }); await this.positionRepository.delete({ kpiLinkId: id }); await this.kpiLinkRepository.delete({ id: id }); diff --git a/src/controllers/KpiPeriodController.ts b/src/controllers/KpiPeriodController.ts index 39423ed..95d420e 100644 --- a/src/controllers/KpiPeriodController.ts +++ b/src/controllers/KpiPeriodController.ts @@ -30,6 +30,7 @@ import { KpiUserCapacity } from "../entities/kpiUserCapacity"; import { KpiUserSpecial } from "../entities/kpiUserSpecial"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/period") @Tags("kpiPeriod") @@ -70,13 +71,16 @@ export class kpiPeriodController extends Controller { if (chkkpiPeriod) { throw new HttpError(HttpStatusCode.NOT_FOUND, "รอบการประเมินผลนี้มีอยู่ในระบบแล้ว"); } + const before = null; const kpiPeriod = Object.assign(new KpiPeriod(), requestBody); kpiPeriod.durationKPI = requestBody.durationKPI.trim().toUpperCase(); kpiPeriod.createdUserId = request.user.sub; kpiPeriod.createdFullName = request.user.name; kpiPeriod.lastUpdateUserId = request.user.sub; kpiPeriod.lastUpdateFullName = request.user.name; - await this.kpiPeriodRepository.save(kpiPeriod); + await this.kpiPeriodRepository.save(kpiPeriod, { data: request }); + setLogDataDiff(request, { before, after: kpiPeriod }); + return new HttpSuccess(kpiPeriod.id); } @@ -112,6 +116,7 @@ export class kpiPeriodController extends Controller { if (chkkpiPeriod) { throw new HttpError(HttpStatusCode.NOT_FOUND, "รอบการประเมินผลนี้มีอยู่ในระบบแล้ว"); } + const before = structuredClone(kpiPeriod); requestBody.durationKPI = requestBody.durationKPI.trim().toUpperCase(); this.kpiPeriodRepository.merge(kpiPeriod, requestBody); @@ -119,7 +124,9 @@ export class kpiPeriodController extends Controller { kpiPeriod.createdFullName = request.user.name; kpiPeriod.lastUpdateUserId = request.user.sub; kpiPeriod.lastUpdateFullName = request.user.name; - await this.kpiPeriodRepository.save(kpiPeriod); + await this.kpiPeriodRepository.save(kpiPeriod, { data: request }); + setLogDataDiff(request, { before, after: kpiPeriod }); + return new HttpSuccess(id); } @@ -133,7 +140,7 @@ export class kpiPeriodController extends Controller { startDate: "datetime", //วันเริ่มต้น endDate: "datetime", //วันสิ้นสุด }) - async CloseKpiPeriodById(@Path() id: string) { + async CloseKpiPeriodById(@Path() id: string, @Request() request: RequestWithUser) { const kpiPeriod = await this.kpiPeriodRepository.findOne({ where: { id: id }, }); @@ -143,8 +150,12 @@ export class kpiPeriodController extends Controller { "ไม่พบข้อมูลรอบการประเมินผลการปฏิบัติหน้าที่ราชการนี้", ); } + const before = structuredClone(kpiPeriod); + kpiPeriod.isActive = false; - await this.kpiPeriodRepository.save(kpiPeriod); + await this.kpiPeriodRepository.save(kpiPeriod, { data: request }); + setLogDataDiff(request, { before, after: kpiPeriod }); + return new HttpSuccess(kpiPeriod); } @@ -158,7 +169,7 @@ export class kpiPeriodController extends Controller { startDate: "datetime", //วันเริ่มต้น endDate: "datetime", //วันสิ้นสุด }) - async OpenKpiPeriodById(@Path() id: string) { + async OpenKpiPeriodById(@Path() id: string, @Request() request: RequestWithUser) { const kpiPeriod = await this.kpiPeriodRepository.findOne({ where: { id: id }, }); @@ -168,8 +179,12 @@ export class kpiPeriodController extends Controller { "ไม่พบข้อมูลรอบการประเมินผลการปฏิบัติหน้าที่ราชการนี้", ); } + const before = structuredClone(kpiPeriod); + kpiPeriod.isActive = true; - await this.kpiPeriodRepository.save(kpiPeriod); + await this.kpiPeriodRepository.save(kpiPeriod, { data: request }); + setLogDataDiff(request, { before, after: kpiPeriod }); + return new HttpSuccess(kpiPeriod); } @@ -303,18 +318,18 @@ export class kpiPeriodController extends Controller { where: { kpiUserEvaluationId: In(kpiPlan.map((x) => x.id)) }, }); - await this.kpiUserRoleRepository.remove(kpiUserRole); - await this.kpiUserPlannedRepository.remove(kpiUserPlanned); + await this.kpiUserRoleRepository.remove(kpiUserRole, { data: request }); + await this.kpiUserPlannedRepository.remove(kpiUserPlanned, { data: request }); - await this.kpiUserRoleRepository.remove(_kpiUserRole); - await this.kpiUserPlannedRepository.remove(_kpiUserPlanned); - await this.kpiUserCapacityRepository.remove(_kpiUserCapacity); - await this.kpiUserSpecialRepository.remove(_kpiUserSpecial); + await this.kpiUserRoleRepository.remove(_kpiUserRole, { data: request }); + await this.kpiUserPlannedRepository.remove(_kpiUserPlanned, { data: request }); + await this.kpiUserCapacityRepository.remove(_kpiUserCapacity, { data: request }); + await this.kpiUserSpecialRepository.remove(_kpiUserSpecial, { data: request }); - await this.kpiRoleRepository.remove(kpiRole); - await this.kpiPlanRepository.remove(kpiPlan); - await this.kpiUserEvaluationRepository.remove(kpiUserEvaluation); - await this.kpiPeriodRepository.remove(kpiPeriod); + await this.kpiRoleRepository.remove(kpiRole, { data: request }); + await this.kpiPlanRepository.remove(kpiPlan, { data: request }); + await this.kpiUserEvaluationRepository.remove(kpiUserEvaluation, { data: request }); + await this.kpiPeriodRepository.remove(kpiPeriod, { data: request }); return new HttpSuccess(); } } diff --git a/src/controllers/KpiPlanController.ts b/src/controllers/KpiPlanController.ts index e710c33..45f4a2b 100644 --- a/src/controllers/KpiPlanController.ts +++ b/src/controllers/KpiPlanController.ts @@ -26,6 +26,8 @@ import { KpiSpecial } from "../entities/kpiSpecial"; import { KpiRole } from "../entities/kpiRole"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/plan") @Tags("kpiPlan") @Security("bearerAuth") @@ -177,12 +179,15 @@ export class kpiPlanController extends Controller { }) .getRawOne(); } + const before = null; + kpiPlan.including = maxIncludingPlan.maxIncluding + 1; kpiPlan.createdUserId = request.user.sub; kpiPlan.createdFullName = request.user.name; kpiPlan.lastUpdateUserId = request.user.sub; kpiPlan.lastUpdateFullName = request.user.name; - await this.kpiPlanRepository.save(kpiPlan); + await this.kpiPlanRepository.save(kpiPlan, { data: request }); + setLogDataDiff(request, { before, after: kpiPlan }); const history = new KpiPlanHistory(); history.kpiPlanId = kpiPlan.id; @@ -190,7 +195,8 @@ export class kpiPlanController extends Controller { history.createdFullName = request.user.name; history.lastUpdateUserId = request.user.sub; history.lastUpdateFullName = request.user.name; - await this.kpiPlanHistoryRepository.save(history); + await this.kpiPlanHistoryRepository.save(history, { data: request }); + setLogDataDiff(request, { before: null, after: history }); return new HttpSuccess(kpiPlan.id); } @@ -267,19 +273,25 @@ export class kpiPlanController extends Controller { kpiPlan.strategyChild5Id = requestBody.strategy <= 4 ? null : x.strategyChild5Id; }) .catch((x) => {}); + + const before = structuredClone(kpiPlan); + kpiPlan.createdUserId = request.user.sub; kpiPlan.createdFullName = request.user.name; kpiPlan.lastUpdateUserId = request.user.sub; kpiPlan.lastUpdateFullName = request.user.name; - await this.kpiPlanRepository.save(kpiPlan); + await this.kpiPlanRepository.save(kpiPlan, { data: request }); + setLogDataDiff(request, { before, after: kpiPlan }); const history = new KpiPlanHistory(); + history.kpiPlanId = kpiPlan.id; history.createdUserId = request.user.sub; history.createdFullName = request.user.name; history.lastUpdateUserId = request.user.sub; history.lastUpdateFullName = request.user.name; - await this.kpiPlanHistoryRepository.save(history); + await this.kpiPlanHistoryRepository.save(history, { data: request }); + setLogDataDiff(request, { before: null, after: history }); return new HttpSuccess(id); } @@ -522,7 +534,7 @@ export class kpiPlanController extends Controller { type = 4; } await this.kpiPlanHistoryRepository.delete({ kpiPlanId: id }); - await this.kpiPlanRepository.remove(kpiPlan); + await this.kpiPlanRepository.remove(kpiPlan, { data: request }); if (kpiPlan) { let remainingKpiPlans: any; @@ -579,7 +591,7 @@ export class kpiPlanController extends Controller { remainingKpiPlans.forEach((kpiPlan: any, index: any) => { kpiPlan.including = index + 1; }); - await this.kpiPlanRepository.save(remainingKpiPlans); + await this.kpiPlanRepository.save(remainingKpiPlans, { data: request }); } return new HttpSuccess(); diff --git a/src/controllers/KpiReasonController.ts b/src/controllers/KpiReasonController.ts index ad72e43..d9caade 100644 --- a/src/controllers/KpiReasonController.ts +++ b/src/controllers/KpiReasonController.ts @@ -29,6 +29,8 @@ import { KpiUserSpecial } from "../entities/kpiUserSpecial"; import { KpiUserCapacity } from "../entities/kpiUserCapacity"; import { KpiUserDevelopment } from "../entities/kpiUserDevelopment"; import { KpiUserPlanned } from "../entities/kpiUserPlanned"; +import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/reason") @Tags("kpiReason") @@ -69,7 +71,7 @@ export class kpiReasonController extends Controller { @Path() user: string, @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { if (user.trim().toUpperCase() == "USER") { const kpiUserEvaluation = await this.kpiUserPlan.findOne({ @@ -112,12 +114,16 @@ export class kpiReasonController extends Controller { ? "DONE" : "EVALUATOR"; } + const before = structuredClone(kpiUserEvaluationReason); + kpiUserEvaluationReason.kpiUserPlannedId = id; kpiUserEvaluationReason.createdUserId = request.user.sub; kpiUserEvaluationReason.createdFullName = request.user.name; kpiUserEvaluationReason.lastUpdateUserId = request.user.sub; kpiUserEvaluationReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonPlan.save(kpiUserEvaluationReason); + await this.kpiUserEvaluationReasonPlan.save(kpiUserEvaluationReason, { data: request }); + setLogDataDiff(request, { before, after: kpiUserEvaluationReason }); + return new HttpSuccess(kpiUserEvaluationReason.id); } else { const kpiReason = await this.kpiUserEvaluationReasonPlan.findOne({ @@ -149,9 +155,13 @@ export class kpiReasonController extends Controller { kpiReason.reasonCommanderHigh = requestBody.reason == null ? "" : requestBody.reason; kpiReason.status = "DONE"; } + const before = structuredClone(kpiReason); + kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonPlan.save(kpiReason); + await this.kpiUserEvaluationReasonPlan.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } } @@ -167,7 +177,7 @@ export class kpiReasonController extends Controller { async sendKpiPlanReason( @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const kpiReason = await this.kpiUserEvaluationReasonPlan.findOne({ where: { id: id }, @@ -179,6 +189,7 @@ export class kpiReasonController extends Controller { "ไม่พบข้อมูลรายการประเมินผลการปฏิบัติราชการระดับบุคคลนี้", ); } + const before = structuredClone(kpiReason); kpiReason.status = kpiReason.kpiUserPlanned.kpiUserEvaluation.evaluatorId == null || @@ -188,7 +199,9 @@ export class kpiReasonController extends Controller { kpiReason.reason = requestBody.reason == null ? "" : requestBody.reason; kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonPlan.save(kpiReason); + await this.kpiUserEvaluationReasonPlan.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } @@ -285,7 +298,7 @@ export class kpiReasonController extends Controller { @Path() user: string, @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { if (user.trim().toUpperCase() == "USER") { const kpiUserEvaluation = await this.kpiUserRole.findOne({ @@ -328,13 +341,16 @@ export class kpiReasonController extends Controller { ? "DONE" : "EVALUATOR"; } + const before = structuredClone(kpiUserEvaluationReason); kpiUserEvaluationReason.kpiUserRoleId = id; kpiUserEvaluationReason.createdUserId = request.user.sub; kpiUserEvaluationReason.createdFullName = request.user.name; kpiUserEvaluationReason.lastUpdateUserId = request.user.sub; kpiUserEvaluationReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonRole.save(kpiUserEvaluationReason); + await this.kpiUserEvaluationReasonRole.save(kpiUserEvaluationReason, { data: request }); + setLogDataDiff(request, { before, after: kpiUserEvaluationReason }); + return new HttpSuccess(kpiUserEvaluationReason.id); } else { const kpiReason = await this.kpiUserEvaluationReasonRole.findOne({ @@ -366,9 +382,13 @@ export class kpiReasonController extends Controller { kpiReason.reasonCommanderHigh = requestBody.reason == null ? "" : requestBody.reason; kpiReason.status = "DONE"; } + const before = structuredClone(kpiReason); + kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonRole.save(kpiReason); + await this.kpiUserEvaluationReasonRole.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } } @@ -384,7 +404,7 @@ export class kpiReasonController extends Controller { async sendKpiRoleReason( @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const kpiReason = await this.kpiUserEvaluationReasonRole.findOne({ where: { id: id }, @@ -396,6 +416,7 @@ export class kpiReasonController extends Controller { "ไม่พบข้อมูลรายการประเมินผลการปฏิบัติราชการระดับบุคคลนี้", ); } + const before = structuredClone(kpiReason); kpiReason.status = kpiReason.kpiUserRole.kpiUserEvaluation.evaluatorId == null || @@ -405,7 +426,9 @@ export class kpiReasonController extends Controller { kpiReason.reason = requestBody.reason == null ? "" : requestBody.reason; kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonRole.save(kpiReason); + await this.kpiUserEvaluationReasonRole.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } @@ -502,7 +525,7 @@ export class kpiReasonController extends Controller { @Path() user: string, @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { if (user.trim().toUpperCase() == "USER") { const kpiUserEvaluation = await this.kpiUserSpecial.findOne({ @@ -548,12 +571,16 @@ export class kpiReasonController extends Controller { ? "DONE" : "EVALUATOR"; } + const before = structuredClone(kpiUserEvaluationReason); + kpiUserEvaluationReason.kpiUserSpecialId = id; kpiUserEvaluationReason.createdUserId = request.user.sub; kpiUserEvaluationReason.createdFullName = request.user.name; kpiUserEvaluationReason.lastUpdateUserId = request.user.sub; kpiUserEvaluationReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonSpecial.save(kpiUserEvaluationReason); + await this.kpiUserEvaluationReasonSpecial.save(kpiUserEvaluationReason, { data: request }); + setLogDataDiff(request, { before, after: kpiUserEvaluationReason }); + return new HttpSuccess(kpiUserEvaluationReason.id); } else { const kpiReason = await this.kpiUserEvaluationReasonSpecial.findOne({ @@ -585,9 +612,13 @@ export class kpiReasonController extends Controller { kpiReason.reasonCommanderHigh = requestBody.reason == null ? "" : requestBody.reason; kpiReason.status = "DONE"; } + const before = structuredClone(kpiReason); + kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonSpecial.save(kpiReason); + await this.kpiUserEvaluationReasonSpecial.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } } @@ -603,7 +634,7 @@ export class kpiReasonController extends Controller { async sendKpiSpecialReason( @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const kpiReason = await this.kpiUserEvaluationReasonSpecial.findOne({ where: { id: id }, @@ -615,6 +646,7 @@ export class kpiReasonController extends Controller { "ไม่พบข้อมูลรายการประเมินผลการปฏิบัติราชการระดับบุคคลนี้", ); } + const before = structuredClone(kpiReason); kpiReason.status = kpiReason.kpiUserSpecial.kpiUserEvaluation.evaluatorId == null || @@ -624,7 +656,9 @@ export class kpiReasonController extends Controller { kpiReason.reason = requestBody.reason == null ? "" : requestBody.reason; kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonSpecial.save(kpiReason); + await this.kpiUserEvaluationReasonSpecial.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } @@ -721,7 +755,7 @@ export class kpiReasonController extends Controller { @Path() user: string, @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { if (user.trim().toUpperCase() == "USER") { const kpiUserEvaluation = await this.kpiUserDevelopment.findOne({ @@ -763,12 +797,18 @@ export class kpiReasonController extends Controller { } kpiUserEvaluationReason.status = "DONE"; } + const before = structuredClone(kpiUserEvaluationReason); + kpiUserEvaluationReason.kpiUserDevelopmentId = id; kpiUserEvaluationReason.createdUserId = request.user.sub; kpiUserEvaluationReason.createdFullName = request.user.name; kpiUserEvaluationReason.lastUpdateUserId = request.user.sub; kpiUserEvaluationReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonDevelopment.save(kpiUserEvaluationReason); + await this.kpiUserEvaluationReasonDevelopment.save(kpiUserEvaluationReason, { + data: request, + }); + setLogDataDiff(request, { before, after: kpiUserEvaluationReason }); + return new HttpSuccess(kpiUserEvaluationReason.id); } else { const kpiReason = await this.kpiUserEvaluationReasonDevelopment.findOne({ @@ -800,9 +840,13 @@ export class kpiReasonController extends Controller { kpiReason.reasonCommanderHigh = requestBody.reason == null ? "" : requestBody.reason; kpiReason.status = "DONE"; } + const before = structuredClone(kpiReason); + kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonDevelopment.save(kpiReason); + await this.kpiUserEvaluationReasonDevelopment.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } } @@ -818,7 +862,7 @@ export class kpiReasonController extends Controller { async sendKpiDevelopmentReason( @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const kpiReason = await this.kpiUserEvaluationReasonDevelopment.findOne({ where: { id: id }, @@ -830,6 +874,7 @@ export class kpiReasonController extends Controller { "ไม่พบข้อมูลรายการประเมินผลการปฏิบัติราชการระดับบุคคลนี้", ); } + const before = structuredClone(kpiReason); kpiReason.status = kpiReason.kpiUserDevelopment.kpiUserEvaluation.evaluatorId == null || @@ -839,7 +884,9 @@ export class kpiReasonController extends Controller { kpiReason.reason = requestBody.reason == null ? "" : requestBody.reason; kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonDevelopment.save(kpiReason); + await this.kpiUserEvaluationReasonDevelopment.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } @@ -940,7 +987,7 @@ export class kpiReasonController extends Controller { @Path() user: string, @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { if (user.trim().toUpperCase() == "USER") { const kpiUserEvaluation = await this.kpiUserCapacity.findOne({ @@ -982,12 +1029,16 @@ export class kpiReasonController extends Controller { } kpiUserEvaluationReason.status = "DONE"; } + const before = structuredClone(kpiUserEvaluationReason); + kpiUserEvaluationReason.kpiUserCapacityId = id; kpiUserEvaluationReason.createdUserId = request.user.sub; kpiUserEvaluationReason.createdFullName = request.user.name; kpiUserEvaluationReason.lastUpdateUserId = request.user.sub; kpiUserEvaluationReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonCapacity.save(kpiUserEvaluationReason); + await this.kpiUserEvaluationReasonCapacity.save(kpiUserEvaluationReason, { data: request }); + setLogDataDiff(request, { before, after: kpiUserEvaluationReason }); + return new HttpSuccess(kpiUserEvaluationReason.id); } else { const kpiReason = await this.kpiUserEvaluationReasonCapacity.findOne({ @@ -1019,9 +1070,13 @@ export class kpiReasonController extends Controller { kpiReason.reasonCommanderHigh = requestBody.reason == null ? "" : requestBody.reason; kpiReason.status = "DONE"; } + const before = structuredClone(kpiReason); + kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonCapacity.save(kpiReason); + await this.kpiUserEvaluationReasonCapacity.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } } @@ -1037,7 +1092,7 @@ export class kpiReasonController extends Controller { async sendKpiCapacityReason( @Path() id: string, @Body() requestBody: updateKpiUserReasonEvaluation, - @Request() request: { user: Record }, + @Request() request: RequestWithUser, ) { const kpiReason = await this.kpiUserEvaluationReasonCapacity.findOne({ where: { id: id }, @@ -1049,6 +1104,7 @@ export class kpiReasonController extends Controller { "ไม่พบข้อมูลรายการประเมินผลการปฏิบัติราชการระดับบุคคลนี้", ); } + const before = structuredClone(kpiReason); kpiReason.status = kpiReason.kpiUserCapacity.kpiUserEvaluation.evaluatorId == null || @@ -1058,7 +1114,9 @@ export class kpiReasonController extends Controller { kpiReason.reason = requestBody.reason == null ? "" : requestBody.reason; kpiReason.lastUpdateUserId = request.user.sub; kpiReason.lastUpdateFullName = request.user.name; - await this.kpiUserEvaluationReasonCapacity.save(kpiReason); + await this.kpiUserEvaluationReasonCapacity.save(kpiReason, { data: request }); + setLogDataDiff(request, { before, after: kpiReason }); + return new HttpSuccess(kpiReason.id); } diff --git a/src/controllers/KpiRoleController.ts b/src/controllers/KpiRoleController.ts index cb7e3d8..6864400 100644 --- a/src/controllers/KpiRoleController.ts +++ b/src/controllers/KpiRoleController.ts @@ -24,6 +24,9 @@ import { Brackets, IsNull, Like } from "typeorm"; import { KpiRoleHistory } from "../entities/kpiRoleHistory"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; + +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/role") @Tags("kpiRole") @Security("bearerAuth") @@ -170,12 +173,16 @@ export class kpiRoleController extends Controller { }) .getRawOne(); } + + const before = null; + kpiRole.including = maxIncludingRole.maxIncluding + 1; kpiRole.createdUserId = request.user.sub; kpiRole.createdFullName = request.user.name; kpiRole.lastUpdateUserId = request.user.sub; kpiRole.lastUpdateFullName = request.user.name; - await this.kpiRoleRepository.save(kpiRole); + await this.kpiRoleRepository.save(kpiRole, { data: request }); + setLogDataDiff(request, { before, after: kpiRole }); const history = new KpiRoleHistory(); history.kpiRoleId = kpiRole.id; @@ -183,7 +190,8 @@ export class kpiRoleController extends Controller { history.createdFullName = request.user.name; history.lastUpdateUserId = request.user.sub; history.lastUpdateFullName = request.user.name; - await this.kpiRoleHistoryRepository.save(history); + await this.kpiRoleHistoryRepository.save(history, { data: request }); + setLogDataDiff(request, { before, after: kpiRole }); return new HttpSuccess(kpiRole.id); } @@ -242,19 +250,25 @@ export class kpiRoleController extends Controller { kpiRole.child4ShortName = requestBody.node <= 3 ? null : x.child4ShortName; }) .catch((x) => {}); + let before = null; + before = structuredClone(kpiRole); + kpiRole.createdUserId = request.user.sub; kpiRole.createdFullName = request.user.name; kpiRole.lastUpdateUserId = request.user.sub; kpiRole.lastUpdateFullName = request.user.name; - await this.kpiRoleRepository.save(kpiRole); + await this.kpiRoleRepository.save(kpiRole, { data: request }); + setLogDataDiff(request, { before, after: kpiRole }); + before = null; const history = new KpiRoleHistory(); history.kpiRoleId = kpiRole.id; history.createdUserId = request.user.sub; history.createdFullName = request.user.name; history.lastUpdateUserId = request.user.sub; history.lastUpdateFullName = request.user.name; - await this.kpiRoleHistoryRepository.save(history); + await this.kpiRoleHistoryRepository.save(history, { data: request }); + setLogDataDiff(request, { before, after: kpiRole }); return new HttpSuccess(id); } @@ -485,7 +499,7 @@ export class kpiRoleController extends Controller { type = 4; } await this.kpiRoleHistoryRepository.delete({ kpiRoleId: id }); - await this.kpiRoleRepository.remove(kpiRole); + await this.kpiRoleRepository.remove(kpiRole, { data: request }); if (kpiRole) { let remainingKpiRoles: any; @@ -547,7 +561,7 @@ export class kpiRoleController extends Controller { remainingKpiRoles.forEach((kpiRole: any, index: any) => { kpiRole.including = index + 1; }); - await this.kpiRoleRepository.save(remainingKpiRoles); + await this.kpiRoleRepository.save(remainingKpiRoles, { data: request }); } return new HttpSuccess(); } diff --git a/src/controllers/KpiSpecialController.ts b/src/controllers/KpiSpecialController.ts index 58fe976..4089499 100644 --- a/src/controllers/KpiSpecialController.ts +++ b/src/controllers/KpiSpecialController.ts @@ -21,6 +21,8 @@ import { KpiSpecial, CreateKpiSpecial, UpdateKpiSpecial } from "../entities/kpiS import { Brackets, Not } from "typeorm"; import permission from "../interfaces/permission"; import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; + @Route("api/v1/kpi/special") @Tags("kpiSpecial") @Security("bearerAuth") @@ -59,11 +61,15 @@ export class kpiSpecialController extends Controller { if (!kpiSpecial) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); } + const before = null; + kpiSpecial.createdUserId = request.user.sub; kpiSpecial.createdFullName = request.user.name; kpiSpecial.lastUpdateUserId = request.user.sub; kpiSpecial.lastUpdateFullName = request.user.name; - await this.kpiSpecialRepository.save(kpiSpecial); + await this.kpiSpecialRepository.save(kpiSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiSpecial }); + return new HttpSuccess(kpiSpecial.id); } @@ -100,10 +106,14 @@ export class kpiSpecialController extends Controller { "ไม่สามารถเพิ่มข้อมูลได้เนื่องจากข้อมูลตัวชี้วัดซ้ำ", ); } + const before = structuredClone(kpiSpecial); + kpiSpecial.lastUpdateUserId = request.user.sub; kpiSpecial.lastUpdateFullName = request.user.name; Object.assign(kpiSpecial, requestBody); - await this.kpiSpecialRepository.save(kpiSpecial); + await this.kpiSpecialRepository.save(kpiSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiSpecial }); + return new HttpSuccess(id); } @@ -224,7 +234,7 @@ export class kpiSpecialController extends Controller { if (!kpiSpecial) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตัวชี้วัด Specialนี้"); } - await this.kpiSpecialRepository.remove(kpiSpecial); + await this.kpiSpecialRepository.remove(kpiSpecial, { data: request }); return new HttpSuccess(); } } diff --git a/src/controllers/KpiUserCapacityController.ts b/src/controllers/KpiUserCapacityController.ts index 0e2764f..b635c56 100644 --- a/src/controllers/KpiUserCapacityController.ts +++ b/src/controllers/KpiUserCapacityController.ts @@ -24,6 +24,8 @@ import { KpiUserCapacity, KpiUserCapacityDataPoint } from "../entities/kpiUserCa import { Not } from "typeorm"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { request } from "axios"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/user/capacity") @Tags("kpiUserCapacity") @@ -84,12 +86,16 @@ export class KpiUserCapacityController extends Controller { "ไม่สามารถเพิ่มข้อมูลได้เนื่องจากรายการสมรรถนะซ้ำ", ); } + const before = null; + const kpiUserCapacity = Object.assign(new KpiUserCapacity(), requestBody); kpiUserCapacity.createdUserId = request.user.sub; kpiUserCapacity.createdFullName = request.user.name; kpiUserCapacity.lastUpdateUserId = request.user.sub; kpiUserCapacity.lastUpdateFullName = request.user.name; - await this.kpiUserCapacityRepository.save(kpiUserCapacity); + await this.kpiUserCapacityRepository.save(kpiUserCapacity, { data: request }); + setLogDataDiff(request, { before, after: kpiUserCapacity }); + return new HttpSuccess(kpiUserCapacity.id); } @@ -150,11 +156,14 @@ export class KpiUserCapacityController extends Controller { "ไม่สามารถแก้ไขข้อมูลได้เนื่องจากรายการสมรรถนะซ้ำ", ); } + const before = structuredClone(kpiUserCapacity); const _kpiUserCapacity = Object.assign(new KpiUserCapacity(), requestBody); kpiUserCapacity.lastUpdateUserId = request.user.sub; kpiUserCapacity.lastUpdateFullName = request.user.name; this.kpiUserCapacityRepository.merge(kpiUserCapacity, _kpiUserCapacity); - await this.kpiUserCapacityRepository.save(kpiUserCapacity); + await this.kpiUserCapacityRepository.save(kpiUserCapacity, { data: request }); + setLogDataDiff(request, { before, after: kpiUserCapacity }); + return new HttpSuccess(kpiUserCapacity.id); } @@ -271,10 +280,13 @@ export class KpiUserCapacityController extends Controller { `ไม่พบข้อมูลพฤติกรรมการปฎิบัติราชการ (สมรรถนะ): ${item.id}`, ); } + const before = structuredClone(kpiUserCapacity); + this.kpiUserCapacityRepository.merge(kpiUserCapacity, item); kpiUserCapacity.lastUpdateUserId = request.user.sub; kpiUserCapacity.lastUpdateFullName = request.user.name; - await this.kpiUserCapacityRepository.save(kpiUserCapacity); + await this.kpiUserCapacityRepository.save(kpiUserCapacity, { data: request }); + setLogDataDiff(request, { before, after: kpiUserCapacity }); } return new HttpSuccess(); } diff --git a/src/controllers/KpiUserDevelopmentController.ts b/src/controllers/KpiUserDevelopmentController.ts index a43a604..a94441b 100644 --- a/src/controllers/KpiUserDevelopmentController.ts +++ b/src/controllers/KpiUserDevelopmentController.ts @@ -29,6 +29,7 @@ import { Not, Brackets } from "typeorm"; import { DevelopmentProject } from "../entities/developmentProject"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/user/achievement/development") @Tags("KpiUserDevelopment") @@ -89,12 +90,13 @@ export class KpiUserDevelopmentController extends Controller { // "ไม่สามารถเพิ่มข้อมูลได้เนื่องจากข้อมูลตัวชี้วัดซ้ำ", // ); // } - + let before = null; kpiUserDevelopment.createdUserId = request.user.sub; kpiUserDevelopment.createdFullName = request.user.name; kpiUserDevelopment.lastUpdateUserId = request.user.sub; kpiUserDevelopment.lastUpdateFullName = request.user.name; - await this.kpiUserDevelopmentRepository.save(kpiUserDevelopment); + await this.kpiUserDevelopmentRepository.save(kpiUserDevelopment, { data: request }); + setLogDataDiff(request, { before, after: kpiUserDevelopment }); if (requestBody.developmentProjects != null) { await Promise.all( @@ -106,7 +108,8 @@ export class KpiUserDevelopmentController extends Controller { data.lastUpdateUserId = request.user.sub; data.lastUpdateFullName = request.user.name; data.kpiUserDevelopmentId = kpiUserDevelopment.id; - await this.developmentProjectRepository.save(data); + await this.developmentProjectRepository.save(data, { data: request }); + setLogDataDiff(request, { before, after: data }); }), ); } @@ -169,12 +172,17 @@ export class KpiUserDevelopmentController extends Controller { // "ไม่สามารถเพิ่มข้อมูลได้เนื่องจากข้อมูลตัวชี้วัดซ้ำ", // ); // } - await this.developmentProjectRepository.remove(kpiUserDevelopment.developmentProjects); + await this.developmentProjectRepository.remove(kpiUserDevelopment.developmentProjects, { + data: request, + }); + const before = structuredClone(kpiUserDevelopment); kpiUserDevelopment.lastUpdateUserId = request.user.sub; kpiUserDevelopment.lastUpdateFullName = request.user.name; Object.assign(kpiUserDevelopment, requestBody); - await this.kpiUserDevelopmentRepository.save(kpiUserDevelopment); + await this.kpiUserDevelopmentRepository.save(kpiUserDevelopment, { data: request }); + setLogDataDiff(request, { before, after: kpiUserDevelopment }); + if (requestBody.developmentProjects != null) { await Promise.all( requestBody.developmentProjects.map(async (x) => { @@ -185,7 +193,8 @@ export class KpiUserDevelopmentController extends Controller { data.lastUpdateUserId = request.user.sub; data.lastUpdateFullName = request.user.name; data.kpiUserDevelopmentId = kpiUserDevelopment.id; - await this.developmentProjectRepository.save(data); + await this.developmentProjectRepository.save(data, { data: request }); + setLogDataDiff(request, { before: null, after: data }); }), ); } @@ -208,8 +217,10 @@ export class KpiUserDevelopmentController extends Controller { if (!delKpiUserDevelopment) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลพัฒนาตนเองนี้"); } - await this.developmentProjectRepository.remove(delKpiUserDevelopment.developmentProjects); - await this.kpiUserDevelopmentRepository.remove(delKpiUserDevelopment); + await this.developmentProjectRepository.remove(delKpiUserDevelopment.developmentProjects, { + data: request, + }); + await this.kpiUserDevelopmentRepository.remove(delKpiUserDevelopment, { data: request }); return new HttpSuccess(); } @@ -310,10 +321,12 @@ export class KpiUserDevelopmentController extends Controller { if (!kpiUserDevelopment) { throw new HttpError(HttpStatusCode.NOT_FOUND, `ไม่พบข้อมูลพัฒนาตนเองนี้: ${item.id}`); } + const before = null; this.kpiUserDevelopmentRepository.merge(kpiUserDevelopment, item); kpiUserDevelopment.lastUpdateUserId = request.user.sub; kpiUserDevelopment.lastUpdateFullName = request.user.name; - await this.kpiUserDevelopmentRepository.save(kpiUserDevelopment); + await this.kpiUserDevelopmentRepository.save(kpiUserDevelopment, { data: request }); + setLogDataDiff(request, { before, after: kpiUserDevelopment }); } return new HttpSuccess(); } diff --git a/src/controllers/KpiUserEvaluationController.ts b/src/controllers/KpiUserEvaluationController.ts index 5ed37ce..0b130c4 100644 --- a/src/controllers/KpiUserEvaluationController.ts +++ b/src/controllers/KpiUserEvaluationController.ts @@ -10,9 +10,11 @@ import { Body, Path, Request, + Example, SuccessResponse, Response, Query, + ArrayValidator, } from "tsoa"; import { AppDataSource } from "../database/data-source"; import HttpSuccess from "../interfaces/http-success"; @@ -29,7 +31,7 @@ import { updateKpiUserReqEditEvaluation, updateKpiUserResultEvaluation, } from "../entities/kpiUserEvaluation"; -import { In, Brackets, IsNull, Not } from "typeorm"; +import { Like, In, Brackets, IsNull, Not } from "typeorm"; import CallAPI from "../interfaces/call-api"; import { KpiCapacity } from "../entities/kpiCapacity"; import { Position } from "../entities/position"; @@ -192,123 +194,6 @@ export class KpiUserEvaluationController extends Controller { return new HttpSuccess({ data: mapData, total }); } - /** - * API - * - * @summary รายการประเมินผลการปฏิบัติราชการระดับบุคคลทั้งหมด - * - */ - @Post("list-announce") - async listKpiListEvaluationAnnounce( - @Request() request: RequestWithUser, - @Body() - requestBody: { - page: number; - pageSize: number; - kpiPeriodId?: string; - keyword?: string; - status?: string | null; - results?: string | null; - reqedit?: string | null; - evaluating?: boolean | null; - }, - ) { - await new permission().PermissionDelete(request, "SYS_RESULT"); - let conditionFullName = - "CONCAT(kpiUserEvaluation.prefix, kpiUserEvaluation.firstName, ' ', kpiUserEvaluation.lastName) LIKE :keyword"; - const [kpiUserEvaluation, total] = await AppDataSource.getRepository(KpiUserEvaluation) - .createQueryBuilder("kpiUserEvaluation") - .andWhere(requestBody.kpiPeriodId ? "kpiPeriodId LIKE :kpiPeriodId" : "1=1", { - kpiPeriodId: requestBody.kpiPeriodId, - }) - .andWhere( - requestBody.status != null && requestBody.status != undefined - ? "evaluationstatus LIKE :status" - : "1=1", - { - status: - requestBody.status == null || requestBody.status == undefined - ? null - : requestBody.status.trim().toUpperCase(), - }, - ) - .andWhere( - requestBody.results != null && requestBody.results != undefined - ? "evaluationResults LIKE :results" - : "1=1", - { - results: - requestBody.results == null || requestBody.results == undefined - ? null - : requestBody.results.trim().toUpperCase(), - }, - ) - .andWhere( - new Brackets((qb) => { - qb.orWhere("kpiUserEvaluation.prefix LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere("kpiUserEvaluation.firstName LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere("kpiUserEvaluation.lastName LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere("kpiUserEvaluation.org LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere("kpiUserEvaluation.position LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere("kpiUserEvaluation.posTypeName LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere("kpiUserEvaluation.posLevelName LIKE :keyword", { - keyword: `%${requestBody.keyword}%`, - }) - .orWhere(conditionFullName, { - keyword: `%${requestBody.keyword}%`, - }); - }), - ) - .orderBy("kpiUserEvaluation.createdAt", "ASC") - .skip((requestBody.page - 1) * requestBody.pageSize) - .take(requestBody.pageSize) - .getManyAndCount(); - - const mapData = kpiUserEvaluation.map((item) => { - const fullNameParts = [item.child4, item.child3, item.child2, item.child1, item.org]; - - const organization = fullNameParts - .filter((part) => part !== undefined && part !== null) - .join("/"); - - return { - id: item.id, - profileId: item.profileId, - prefix: item.prefix, - firstname: item.firstName, - lastname: item.lastName, - kpiPeriodId: item.kpiPeriodId, - evaluationStatus: item.evaluationStatus, - evaluationResults: item.evaluationResults, - createdAt: item.createdAt, - evaluatorId: item.evaluatorId, - commanderId: item.commanderId, - commanderHighId: item.commanderHighId, - root: item.org ? item.org : null, - rootId: item.orgId ? item.orgId : null, - position: item.position ? item.position : null, - // posTypeId: item.posTypeId, - posTypeName: item.posTypeName ? item.posTypeName : null, - // posLevelId: item.posLevelId, - posLevelName: item.posLevelName ? item.posLevelName : null, - organization: organization ? organization : null, - }; - }); - return new HttpSuccess({ data: mapData, total }); - } - /** * API * @@ -317,7 +202,7 @@ export class KpiUserEvaluationController extends Controller { */ @Post("list") async listKpiListEvaluation( - @Request() request: RequestWithUser, + @Request() request: { user: Record }, @Body() requestBody: { page: number; @@ -330,7 +215,6 @@ export class KpiUserEvaluationController extends Controller { evaluating?: boolean | null; }, ) { - await new permission().PermissionDelete(request, "SYS_KPI_LIST"); let conditionFullName = "CONCAT(kpiUserEvaluation.prefix, kpiUserEvaluation.firstName, ' ', kpiUserEvaluation.lastName) LIKE :keyword"; const [kpiUserEvaluation, total] = await AppDataSource.getRepository(KpiUserEvaluation) @@ -1558,8 +1442,10 @@ export class KpiUserEvaluationController extends Controller { * @param {string} id Guid, *Id คนประเมิน (USER) */ @Get("reason/{id}") - async getReasonKpiEvaluation(@Path() id: string, @Request() request: RequestWithUser) { - await new permission().PermissionGet(request, "SYS_KPI_LIST"); + async getReasonKpiEvaluation( + @Path() id: string, + @Request() request: { user: Record }, + ) { const kpiUserEvaluation = await this.kpiUserEvalutionRepository.findOne({ where: { id: id }, select: [ @@ -1625,7 +1511,7 @@ export class KpiUserEvaluationController extends Controller { kpiUserEvaluation.evaluationStatus = "SUMMARY"; kpiUserEvaluation.lastUpdateUserId = request.user.sub; kpiUserEvaluation.lastUpdateFullName = request.user.name; - await this.kpiUserEvalutionRepository.save(kpiUserEvaluation); + await this.kpiUserEvalutionRepository.save(kpiUserEvaluation, { data: request }); return new HttpSuccess(kpiUserEvaluation); } } diff --git a/src/controllers/KpiUserPlannedController.ts b/src/controllers/KpiUserPlannedController.ts index 8249dc0..28fc8ce 100644 --- a/src/controllers/KpiUserPlannedController.ts +++ b/src/controllers/KpiUserPlannedController.ts @@ -29,6 +29,7 @@ import { KpiUserEvaluation } from "../entities/kpiUserEvaluation"; import { KpiPlan } from "../entities/kpiPlan"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/user/achievement/planned") @Tags("KpiUserPlanned") @@ -88,6 +89,7 @@ export class KpiUserPlannedController extends Controller { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); } + const before = null; kpiUserPlanned.startDate = requestBody.startDate == undefined ? null : requestBody.startDate; kpiUserPlanned.endDate = requestBody.endDate == undefined ? null : requestBody.endDate; kpiUserPlanned.createdUserId = request.user.sub; @@ -102,7 +104,8 @@ export class KpiUserPlannedController extends Controller { // kpiUserPlanned.achievement3 = request.user.achievement3; // kpiUserPlanned.achievement4 = request.user.achievement4; // kpiUserPlanned.achievement5 = request.user.achievement5; - await this.kpiUserPlannedRepository.save(kpiUserPlanned); + await this.kpiUserPlannedRepository.save(kpiUserPlanned, { data: request }); + setLogDataDiff(request, { before, after: kpiUserPlanned }); return new HttpSuccess(kpiUserPlanned.id); } @@ -138,7 +141,7 @@ export class KpiUserPlannedController extends Controller { "ไม่สามารถเพิ่มข้อมูลได้เนื่องจากข้อมูลตัวชี้วัดซ้ำ", ); } - + const before = structuredClone(kpiUserPlanned); kpiUserPlanned.lastUpdateUserId = request.user.sub; kpiUserPlanned.lastUpdateFullName = request.user.name; // kpiUserPlanned.documentInfoEvidence = request.user.documentInfoEvidence; @@ -153,7 +156,8 @@ export class KpiUserPlannedController extends Controller { Object.assign(kpiUserPlanned, requestBody); kpiUserPlanned.startDate = requestBody.startDate == undefined ? null : requestBody.startDate; kpiUserPlanned.endDate = requestBody.endDate == undefined ? null : requestBody.endDate; - await this.kpiUserPlannedRepository.save(kpiUserPlanned); + await this.kpiUserPlannedRepository.save(kpiUserPlanned, { data: request }); + setLogDataDiff(request, { before, after: kpiUserPlanned }); return new HttpSuccess(kpiUserPlanned.id); } @@ -171,7 +175,7 @@ export class KpiUserPlannedController extends Controller { if (!delKpiUserPlanned) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลงานตามแผนปฏิบัติราชการประจำปีนี้"); } - await this.kpiUserPlannedRepository.remove(delKpiUserPlanned); + await this.kpiUserPlannedRepository.remove(delKpiUserPlanned, { data: request }); return new HttpSuccess(); } @@ -292,10 +296,12 @@ export class KpiUserPlannedController extends Controller { `ไม่พบข้อมูลงานตามแผนปฏิบัติราชการประจำปีนี้: ${item.id}`, ); } + const before = structuredClone(kpiUserPlanned); this.kpiUserPlannedRepository.merge(kpiUserPlanned, item); kpiUserPlanned.lastUpdateUserId = request.user.sub; kpiUserPlanned.lastUpdateFullName = request.user.name; - await this.kpiUserPlannedRepository.save(kpiUserPlanned); + await this.kpiUserPlannedRepository.save(kpiUserPlanned, { data: request }); + setLogDataDiff(request, { before, after: kpiUserPlanned }); } return new HttpSuccess(); } diff --git a/src/controllers/KpiUserRoleController.ts b/src/controllers/KpiUserRoleController.ts index f0f7ebe..22eccd8 100644 --- a/src/controllers/KpiUserRoleController.ts +++ b/src/controllers/KpiUserRoleController.ts @@ -29,6 +29,7 @@ import { KpiUserEvaluation } from "../entities/kpiUserEvaluation"; import { KpiRole } from "../entities/kpiRole"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/user/achievement/role") @Tags("KpiUserRole") @@ -91,13 +92,16 @@ export class KpiUserRoleController extends Controller { ); } + const before = null; kpiUserRole.startDate = requestBody.startDate == undefined ? null : requestBody.startDate; kpiUserRole.endDate = requestBody.endDate == undefined ? null : requestBody.endDate; kpiUserRole.createdUserId = request.user.sub; kpiUserRole.createdFullName = request.user.name; kpiUserRole.lastUpdateUserId = request.user.sub; kpiUserRole.lastUpdateFullName = request.user.name; - await this.kpiUserRoleRepository.save(kpiUserRole); + await this.kpiUserRoleRepository.save(kpiUserRole, { data: request }); + setLogDataDiff(request, { before, after: kpiUserRole }); + return new HttpSuccess(kpiUserRole.id); } @@ -149,13 +153,15 @@ export class KpiUserRoleController extends Controller { "ไม่สามารถเพิ่มข้อมูลได้เนื่องจากข้อมูลตัวชี้วัดซ้ำ", ); } - + const before = structuredClone(kpiUserRole); kpiUserRole.lastUpdateUserId = request.user.sub; kpiUserRole.lastUpdateFullName = request.user.name; Object.assign(kpiUserRole, requestBody); kpiUserRole.startDate = requestBody.startDate == undefined ? null : requestBody.startDate; kpiUserRole.endDate = requestBody.endDate == undefined ? null : requestBody.endDate; - await this.kpiUserRoleRepository.save(kpiUserRole); + await this.kpiUserRoleRepository.save(kpiUserRole, { data: request }); + setLogDataDiff(request, { before, after: kpiUserRole }); + return new HttpSuccess(kpiUserRole.id); } @@ -173,7 +179,7 @@ export class KpiUserRoleController extends Controller { if (!delKpiUserRole) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลงานตามหน้าที่ความรับผิดชอบหลักนี้"); } - await this.kpiUserRoleRepository.remove(delKpiUserRole); + await this.kpiUserRoleRepository.remove(delKpiUserRole, { data: request }); return new HttpSuccess(); } @@ -295,10 +301,12 @@ export class KpiUserRoleController extends Controller { `ไม่พบข้อมูลงานตามหน้าที่ความรับผิดชอบหลักนี้: ${item.id}`, ); } + const before = null; this.kpiUserRoleRepository.merge(kpiUserRole, item); kpiUserRole.lastUpdateUserId = request.user.sub; kpiUserRole.lastUpdateFullName = request.user.name; - await this.kpiUserRoleRepository.save(kpiUserRole); + await this.kpiUserRoleRepository.save(kpiUserRole, { data: request }); + setLogDataDiff(request, { before, after: kpiUserRole }); } return new HttpSuccess(); } diff --git a/src/controllers/KpiUserSpecialController.ts b/src/controllers/KpiUserSpecialController.ts index 1345029..4e5647a 100644 --- a/src/controllers/KpiUserSpecialController.ts +++ b/src/controllers/KpiUserSpecialController.ts @@ -29,6 +29,7 @@ import { KpiSpecial } from "../entities/kpiSpecial"; import { Not } from "typeorm"; import { RequestWithUser } from "../middlewares/user"; import permission from "../interfaces/permission"; +import { addLogSequence, setLogDataDiff } from "../interfaces/utils"; @Route("api/v1/kpi/user/achievement/special") @Tags("KpiUserSpecial") @@ -93,6 +94,7 @@ export class KpiUserSpecialController extends Controller { includingName: String(requestBody.includingName), }, }); + let before = null; if (!chk_kpiSpecial) { const kpiSpecial = Object.assign(new KpiSpecial(), requestBody); if (!kpiSpecial) { @@ -102,7 +104,8 @@ export class KpiUserSpecialController extends Controller { kpiSpecial.createdFullName = request.user.name; kpiSpecial.lastUpdateUserId = request.user.sub; kpiSpecial.lastUpdateFullName = request.user.name; - await this.kpiSpecialRepository.save(kpiSpecial); + await this.kpiSpecialRepository.save(kpiSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiSpecial }); } kpiUserSpecial.startDate = requestBody.startDate == undefined ? null : requestBody.startDate; kpiUserSpecial.endDate = requestBody.endDate == undefined ? null : requestBody.endDate; @@ -110,7 +113,9 @@ export class KpiUserSpecialController extends Controller { kpiUserSpecial.createdFullName = request.user.name; kpiUserSpecial.lastUpdateUserId = request.user.sub; kpiUserSpecial.lastUpdateFullName = request.user.name; - await this.kpiUserSpecialRepository.save(kpiUserSpecial); + await this.kpiUserSpecialRepository.save(kpiUserSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiUserSpecial }); + return new HttpSuccess(kpiUserSpecial.id); } @@ -165,23 +170,29 @@ export class KpiUserSpecialController extends Controller { includingName: String(requestBody.includingName), }, }); + let before = null; if (!chk_kpiSpecial) { const kpiSpecial = Object.assign(new KpiSpecial(), requestBody); if (!kpiSpecial) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล"); } + before = structuredClone(kpiSpecial); kpiSpecial.createdUserId = request.user.sub; kpiSpecial.createdFullName = request.user.name; kpiSpecial.lastUpdateUserId = request.user.sub; kpiSpecial.lastUpdateFullName = request.user.name; - await this.kpiSpecialRepository.save(kpiSpecial); + await this.kpiSpecialRepository.save(kpiSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiSpecial }); } + before = structuredClone(kpiUserSpecial); kpiUserSpecial.lastUpdateUserId = request.user.sub; kpiUserSpecial.lastUpdateFullName = request.user.name; Object.assign(kpiUserSpecial, requestBody); kpiUserSpecial.startDate = requestBody.startDate == undefined ? null : requestBody.startDate; kpiUserSpecial.endDate = requestBody.endDate == undefined ? null : requestBody.endDate; - await this.kpiUserSpecialRepository.save(kpiUserSpecial); + await this.kpiUserSpecialRepository.save(kpiUserSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiUserSpecial }); + return new HttpSuccess(kpiUserSpecial.id); } @@ -198,7 +209,7 @@ export class KpiUserSpecialController extends Controller { if (!delKpiUserSpecial) { throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลงานที่ได้รับมอบหมายพิเศษนี้"); } - await this.kpiUserSpecialRepository.remove(delKpiUserSpecial); + await this.kpiUserSpecialRepository.remove(delKpiUserSpecial, { data: request }); return new HttpSuccess(); } @@ -330,10 +341,12 @@ export class KpiUserSpecialController extends Controller { `ไม่พบข้อมูลงานที่ได้รับมอบหมายพิเศษนี้: ${item.id}`, ); } + const before = null; this.kpiUserSpecialRepository.merge(kpiUserSpecial, item); kpiUserSpecial.lastUpdateUserId = request.user.sub; kpiUserSpecial.lastUpdateFullName = request.user.name; - await this.kpiUserSpecialRepository.save(kpiUserSpecial); + await this.kpiUserSpecialRepository.save(kpiUserSpecial, { data: request }); + setLogDataDiff(request, { before, after: kpiUserSpecial }); } return new HttpSuccess(); } diff --git a/src/database/data-source.ts b/src/database/data-source.ts index 7c70f52..d713314 100644 --- a/src/database/data-source.ts +++ b/src/database/data-source.ts @@ -1,6 +1,46 @@ import "dotenv/config"; import "reflect-metadata"; -import { DataSource } from "typeorm"; +import { DataSource, LogLevel, LogMessage } from "typeorm"; +import { Logger } from "typeorm"; +import { QueryRunner } from "typeorm/browser"; +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 +51,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 +61,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..cd4cdfa --- /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: "KPI", + 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;