diff --git a/src/controllers/FileController.ts b/src/controllers/FileController.ts index 0a1dd32..3359dcc 100644 --- a/src/controllers/FileController.ts +++ b/src/controllers/FileController.ts @@ -22,7 +22,7 @@ import { listFile, updateFile, } from "../services/edm"; -import { s3DeleteFile, s3DownloadFile, s3ListFile, s3UploadFile } from "../services/minio"; +import { s3DeleteFile, s3DownloadFile, s3ListFile, s3UploadFile, truncateFileName } from "../services/minio"; @Route("api/v1/salary/file/{name}/{group}") @Security("bearerAuth") @@ -257,7 +257,7 @@ export class FileController extends Controller { const map = fileList.map(async ({ fileName, ...props }) => [ fileName, - await createFile(path, fileName, props), + await createFile(path, truncateFileName(fileName), props), ]); const result = await Promise.all(map).catch((e) => @@ -607,7 +607,7 @@ export class SubFileController extends Controller { const map = fileList.map(async ({ fileName, ...props }) => [ fileName, - await createFile(path, fileName, props), + await createFile(path, truncateFileName(fileName), props), ]); const result = await Promise.all(map).catch((e) => diff --git a/src/controllers/ReportController.ts b/src/controllers/ReportController.ts index 2e53835..8c0e3d4 100644 --- a/src/controllers/ReportController.ts +++ b/src/controllers/ReportController.ts @@ -9074,78 +9074,132 @@ export class ReportController extends Controller { */ @Post("command33/officer/report/excecute") async SalaryReportExcecute33( - @Body() - body: { - refIds: { - refId: string; - // commandAffectDate: Date | null;//เก่า - commandDateAffect: Date | null; //ใหม่ (ปรับตาม rabbitMQ ORG) - commandNo: string | null; - commandYear: number | null; - commandId: string | null; - remark: string | null; - amount: Double | null; - amountSpecial?: Double | null; - positionSalaryAmount: Double | null; - mouthSalaryAmount: Double | null; - commandCode?: string | null; - commandName?: string | null; - commandDateSign: Date | null; - }[]; - }, - @Request() request: RequestWithUser, + @Body() + body: { + refIds: { + refId: string; + commandDateAffect: Date | null; + commandNo: string | null; + commandYear: number | null; + commandId: string | null; + remark: string | null; + amount: Double | null; + amountSpecial?: Double | null; + positionSalaryAmount: Double | null; + mouthSalaryAmount: Double | null; + commandCode?: string | null; + commandName?: string | null; + commandDateSign: Date | null; + }[]; + }, + @Request() request: RequestWithUser, ) { - await Promise.all( - body.refIds.map(async (v) => { - const salary = await this.salaryProfileRepository.findOne({ - where: { - id: v.refId, - }, - }); - if (salary != null) { - await new CallAPI() - .PostData(request, "/org/profile/salary/update", { - profileId: salary.profileId, - commandDateAffect: v.commandDateAffect, - commandDateSign: v.commandDateSign, - amount: v.amount, - amountSpecial: v.amountSpecial, - positionSalaryAmount: v.positionSalaryAmount, - mouthSalaryAmount: v.mouthSalaryAmount, - posNo: salary.posMasterNo.toString(), - posNoAbb: salary.orgShortName, - positionName: salary.position, - positionExecutive: salary.posExecutive, - positionExecutiveField: salary.positionExecutiveField, - positionArea: salary.positionArea, - positionType: salary.posType, - positionLevel: salary.posLevel, - commandId: v.commandId, - remark: v.remark, - orgRoot: salary.root, - orgChild1: salary.child1, - orgChild2: salary.child2, - orgChild3: salary.child3, - orgChild4: salary.child4, - commandCode: v.commandCode, - commandName: v.commandName, - commandNo: v.commandNo, - commandYear: v.commandYear, - }) - .then(async () => { - const before = null; - salary.status33 = "DONE"; - salary.lastUpdateUserId = request.user.sub; - salary.lastUpdateFullName = request.user.name; - salary.lastUpdatedAt = new Date(); - await this.salaryProfileRepository.save(salary, { data: request }); - setLogDataDiff(request, { before, after: salary }); - }); - } - }), - ); - return new HttpSuccess(); - } + // ═══════════════════════════════════════════════════════════════ + // old circle flow (เก็บไว้อ้างอิง — ลบการใช้งานจริงออกแล้ว) + // ═══════════════════════════════════════════════════════════════ + // await Promise.all( + // body.refIds.map(async (v) => { + // const salary = await this.salaryProfileRepository.findOne({ + // where: { id: v.refId }, + // }); + // if (salary != null) { + // // เดิม: ยิง callback เข้า org เพื่อให้ org สร้าง salary record + // await new CallAPI() + // .PostData(request, "/org/profile/salary/update", { + // profileId: salary.profileId, + // commandDateAffect: v.commandDateAffect, + // commandDateSign: v.commandDateSign, + // amount: v.amount, + // amountSpecial: v.amountSpecial, + // positionSalaryAmount: v.positionSalaryAmount, + // mouthSalaryAmount: v.mouthSalaryAmount, + // posNo: salary.posMasterNo.toString(), + // posNoAbb: salary.orgShortName, + // positionName: salary.position, + // positionExecutive: salary.posExecutive, + // positionExecutiveField: salary.positionExecutiveField, + // positionArea: salary.positionArea, + // positionType: salary.posType, + // positionLevel: salary.posLevel, + // commandId: v.commandId, + // remark: v.remark, + // orgRoot: salary.root, + // orgChild1: salary.child1, + // orgChild2: salary.child2, + // orgChild3: salary.child3, + // orgChild4: salary.child4, + // commandCode: v.commandCode, + // commandName: v.commandName, + // commandNo: v.commandNo, + // commandYear: v.commandYear, + // }) + // // เดิม: set status33 ใน .then() หลัง org ตอบกลับสำเร็จเท่านั้น + // .then(async () => { + // const before = null; + // salary.status33 = "DONE"; + // salary.lastUpdateUserId = request.user.sub; + // salary.lastUpdateFullName = request.user.name; + // salary.lastUpdatedAt = new Date(); + // await this.salaryProfileRepository.save(salary, { data: request }); + // setLogDataDiff(request, { before, after: salary }); + // }); + // } + // }), + // ); + // return new HttpSuccess(); + + // ═══════════════════════════════════════════════════════════════ + // new linear flow + // ═══════════════════════════════════════════════════════════════ + // เปลี่ยน: ไม่ยิง callback เข้า org แล้ว → ทำงานของตัวเอง (set status) แล้ว return data + // ให้ org ทำงานต่อ (org AMQ จะเรียก ExecuteSalaryReportService เองหลังได้รับ response) + const result = await Promise.all( + body.refIds.map(async (v) => { + const salary = await this.salaryProfileRepository.findOne({ where: { id: v.refId } }); + if (salary != null) { + // 1) set status33 = DONE (ย้ายขึ้นมาทำก่อนเลย ไม่ต้องรอ org ตอบกลับ) + salary.status33 = "DONE"; + salary.lastUpdateUserId = request.user.sub; + salary.lastUpdateFullName = request.user.name; + salary.lastUpdatedAt = new Date(); + await this.salaryProfileRepository.save(salary, { data: request }); + setLogDataDiff(request, { before: null, after: salary }); + + // 2) return ข้อมูลที่ org ต้องการสร้าง ProfileSalary (shape เดียวกับที่เคย PostData) + return { + profileId: salary.profileId, + commandDateAffect: v.commandDateAffect, + commandDateSign: v.commandDateSign, + amount: v.amount, + amountSpecial: v.amountSpecial, + positionSalaryAmount: v.positionSalaryAmount, + mouthSalaryAmount: v.mouthSalaryAmount, + posNo: salary.posMasterNo.toString(), + posNoAbb: salary.orgShortName, + positionName: salary.position, + positionExecutive: salary.posExecutive, + positionExecutiveField: salary.positionExecutiveField, + positionArea: salary.positionArea, + positionType: salary.posType, + positionLevel: salary.posLevel, + commandId: v.commandId, + remark: v.remark, + orgRoot: salary.root, + orgChild1: salary.child1, + orgChild2: salary.child2, + orgChild3: salary.child3, + orgChild4: salary.child4, + commandCode: v.commandCode, + commandName: v.commandName, + commandNo: v.commandNo, + commandYear: v.commandYear, + }; + } + return null; // refId ที่ไม่พบ salary → กรองออก (เหมือนเดิมที่ข้ามไป) + }), + ); + return { result: result.filter(Boolean) }; // return array ของ salary data ให้ org ทำงานต่อ + } /** * API ออกคำสั่ง C-PM-34 @@ -9155,80 +9209,129 @@ export class ReportController extends Controller { * @param {string} id Guid, *Id ผังเงินเดือน */ @Post("command34/officer/report/excecute") - async SalaryReportExcecute34( - @Body() - body: { - refIds: { - refId: string; - // commandAffectDate: Date | null;//เก่า - commandDateAffect: Date | null; //ใหม่ (ปรับตาม rabbitMQ ORG) - commandNo: string | null; - commandYear: number | null; - commandId: string | null; - remark: string | null; - amount: Double | null; - amountSpecial?: Double | null; - positionSalaryAmount: Double | null; - mouthSalaryAmount: Double | null; - commandCode?: string | null; - commandName?: string | null; - commandDateSign: Date | null; - }[]; - }, - @Request() request: RequestWithUser, - ) { - await Promise.all( - body.refIds.map(async (v) => { - const salary = await this.salaryProfileRepository.findOne({ - where: { - id: v.refId, - }, - }); +async SalaryReportExcecute34( + @Body() + body: { + refIds: { + refId: string; + commandDateAffect: Date | null; + commandNo: string | null; + commandYear: number | null; + commandId: string | null; + remark: string | null; + amount: Double | null; + amountSpecial?: Double | null; + positionSalaryAmount: Double | null; + mouthSalaryAmount: Double | null; + commandCode?: string | null; + commandName?: string | null; + commandDateSign: Date | null; + }[]; + }, + @Request() request: RequestWithUser, +) { + // ═══════════════════════════════════════════════════════════════ + // old circle flow (เก็บไว้อ้างอิง — ลบการใช้งานจริงออกแล้ว) + // ═══════════════════════════════════════════════════════════════ + // await Promise.all( + // body.refIds.map(async (v) => { + // const salary = await this.salaryProfileRepository.findOne({ + // where: { id: v.refId }, + // }); + // if (salary != null) { + // await new CallAPI() + // .PostData(request, "/org/profile/salary/update", { + // profileId: salary.profileId, + // commandDateAffect: v.commandDateAffect, + // commandDateSign: v.commandDateSign, + // amount: v.amount, + // amountSpecial: v.amountSpecial, + // positionSalaryAmount: v.positionSalaryAmount, + // mouthSalaryAmount: v.mouthSalaryAmount, + // posNo: salary.posMasterNo.toString(), + // posNoAbb: salary.orgShortName, + // positionName: salary.position, + // positionExecutive: salary.posExecutive, + // positionExecutiveField: salary.positionExecutiveField, + // positionArea: salary.positionArea, + // positionType: salary.posType, + // positionLevel: salary.posLevel, + // commandId: v.commandId, + // remark: v.remark, + // orgRoot: salary.root, + // orgChild1: salary.child1, + // orgChild2: salary.child2, + // orgChild3: salary.child3, + // orgChild4: salary.child4, + // commandCode: v.commandCode, + // commandName: v.commandName, + // commandNo: v.commandNo, + // commandYear: v.commandYear, + // }) + // .then(async () => { + // const before = null; + // salary.status34 = "DONE"; + // salary.lastUpdateUserId = request.user.sub; + // salary.lastUpdateFullName = request.user.name; + // salary.lastUpdatedAt = new Date(); + // await this.salaryProfileRepository.save(salary, { data: request }); + // setLogDataDiff(request, { before, after: salary }); + // }); + // } + // }), + // ); + // return new HttpSuccess(); - if (salary != null) { - await new CallAPI() - .PostData(request, "/org/profile/salary/update", { - profileId: salary.profileId, - commandDateAffect: v.commandDateAffect, - commandDateSign: v.commandDateSign, - amount: v.amount, - amountSpecial: v.amountSpecial, - positionSalaryAmount: v.positionSalaryAmount, - mouthSalaryAmount: v.mouthSalaryAmount, - posNo: salary.posMasterNo.toString(), - posNoAbb: salary.orgShortName, - positionName: salary.position, - positionExecutive: salary.posExecutive, - positionExecutiveField: salary.positionExecutiveField, - positionArea: salary.positionArea, - positionType: salary.posType, - positionLevel: salary.posLevel, - commandId: v.commandId, - remark: v.remark, - orgRoot: salary.root, - orgChild1: salary.child1, - orgChild2: salary.child2, - orgChild3: salary.child3, - orgChild4: salary.child4, - commandCode: v.commandCode, - commandName: v.commandName, - commandNo: v.commandNo, - commandYear: v.commandYear, - }) - .then(async () => { - const before = null; - salary.status34 = "DONE"; - salary.lastUpdateUserId = request.user.sub; - salary.lastUpdateFullName = request.user.name; - salary.lastUpdatedAt = new Date(); - await this.salaryProfileRepository.save(salary, { data: request }); - setLogDataDiff(request, { before, after: salary }); - }); - } - }), - ); - return new HttpSuccess(); - } + // ═══════════════════════════════════════════════════════════════ + // new linear flow + // ═══════════════════════════════════════════════════════════════ + const result = await Promise.all( + body.refIds.map(async (v) => { + const salary = await this.salaryProfileRepository.findOne({ where: { id: v.refId } }); + if (salary != null) { + // 1) set status34 = DONE (ย้ายขึ้นมาทำก่อนเลย ไม่ต้องรอ org ตอบกลับ) + salary.status34 = "DONE"; + salary.lastUpdateUserId = request.user.sub; + salary.lastUpdateFullName = request.user.name; + salary.lastUpdatedAt = new Date(); + await this.salaryProfileRepository.save(salary, { data: request }); + setLogDataDiff(request, { before: null, after: salary }); + + // 2) return ข้อมูลที่ org ต้องการสร้าง ProfileSalary (shape เดียวกับที่เคย PostData) + return { + profileId: salary.profileId, + commandDateAffect: v.commandDateAffect, + commandDateSign: v.commandDateSign, + amount: v.amount, + amountSpecial: v.amountSpecial, + positionSalaryAmount: v.positionSalaryAmount, + mouthSalaryAmount: v.mouthSalaryAmount, + posNo: salary.posMasterNo.toString(), + posNoAbb: salary.orgShortName, + positionName: salary.position, + positionExecutive: salary.posExecutive, + positionExecutiveField: salary.positionExecutiveField, + positionArea: salary.positionArea, + positionType: salary.posType, + positionLevel: salary.posLevel, + commandId: v.commandId, + remark: v.remark, + orgRoot: salary.root, + orgChild1: salary.child1, + orgChild2: salary.child2, + orgChild3: salary.child3, + orgChild4: salary.child4, + commandCode: v.commandCode, + commandName: v.commandName, + commandNo: v.commandNo, + commandYear: v.commandYear, + }; + } + return null; + }), + ); + return { result: result.filter(Boolean) }; +} /** * API ออกคำสั่ง C-PM-35 @@ -9239,78 +9342,128 @@ export class ReportController extends Controller { */ @Post("command35/officer/report/excecute") async SalaryReportExcecute35( - @Body() - body: { - refIds: { - refId: string; - // commandAffectDate: Date | null;//เก่า - commandDateAffect: Date | null; //ใหม่ (ปรับตาม rabbitMQ ORG) - commandNo: string | null; - commandYear: number | null; - commandId: string | null; - remark: string | null; - amount: Double | null; - amountSpecial?: Double | null; - positionSalaryAmount: Double | null; - mouthSalaryAmount: Double | null; - commandCode?: string | null; - commandName?: string | null; - commandDateSign: Date | null; - }[]; - }, - @Request() request: RequestWithUser, + @Body() + body: { + refIds: { + refId: string; + commandDateAffect: Date | null; + commandNo: string | null; + commandYear: number | null; + commandId: string | null; + remark: string | null; + amount: Double | null; + amountSpecial?: Double | null; + positionSalaryAmount: Double | null; + mouthSalaryAmount: Double | null; + commandCode?: string | null; + commandName?: string | null; + commandDateSign: Date | null; + }[]; + }, + @Request() request: RequestWithUser, ) { - await Promise.all( - body.refIds.map(async (v) => { - const salary = await this.salaryProfileRepository.findOne({ - where: { - id: v.refId, - }, - }); + // ═══════════════════════════════════════════════════════════════ + // old circle flow (เก็บไว้อ้างอิง — ลบการใช้งานจริงออกแล้ว) + // ═══════════════════════════════════════════════════════════════ + // await Promise.all( + // body.refIds.map(async (v) => { + // const salary = await this.salaryProfileRepository.findOne({ + // where: { id: v.refId }, + // }); + // if (salary != null) { + // await new CallAPI() + // .PostData(request, "/org/profile/salary/update", { + // profileId: salary.profileId, + // commandDateAffect: v.commandDateAffect, + // commandDateSign: v.commandDateSign, + // amount: v.amount, + // amountSpecial: v.amountSpecial, + // positionSalaryAmount: v.positionSalaryAmount, + // mouthSalaryAmount: v.mouthSalaryAmount, + // posNo: salary.posMasterNo.toString(), + // posNoAbb: salary.orgShortName, + // positionName: salary.position, + // positionExecutive: salary.posExecutive, + // positionExecutiveField: salary.positionExecutiveField, + // positionArea: salary.positionArea, + // positionType: salary.posType, + // positionLevel: salary.posLevel, + // commandId: v.commandId, + // remark: v.remark, + // orgRoot: salary.root, + // orgChild1: salary.child1, + // orgChild2: salary.child2, + // orgChild3: salary.child3, + // orgChild4: salary.child4, + // commandCode: v.commandCode, + // commandName: v.commandName, + // commandNo: v.commandNo, + // commandYear: v.commandYear, + // }) + // .then(async () => { + // const before = null; + // salary.status35 = "DONE"; + // salary.lastUpdateUserId = request.user.sub; + // salary.lastUpdateFullName = request.user.name; + // salary.lastUpdatedAt = new Date(); + // await this.salaryProfileRepository.save(salary, { data: request }); + // setLogDataDiff(request, { before, after: salary }); + // }); + // } + // }), + // ); + // return new HttpSuccess(); - if (salary != null) { - await new CallAPI() - .PostData(request, "/org/profile/salary/update", { - profileId: salary.profileId, - commandDateAffect: v.commandDateAffect, - commandDateSign: v.commandDateSign, - amount: v.amount, - amountSpecial: v.amountSpecial, - positionSalaryAmount: v.positionSalaryAmount, - mouthSalaryAmount: v.mouthSalaryAmount, - posNo: salary.posMasterNo.toString(), - posNoAbb: salary.orgShortName, - positionName: salary.position, - positionExecutive: salary.posExecutive, - positionExecutiveField: salary.positionExecutiveField, - positionArea: salary.positionArea, - positionType: salary.posType, - positionLevel: salary.posLevel, - commandId: v.commandId, - remark: v.remark, - orgRoot: salary.root, - orgChild1: salary.child1, - orgChild2: salary.child2, - orgChild3: salary.child3, - orgChild4: salary.child4, - commandCode: v.commandCode, - commandName: v.commandName, - commandNo: v.commandNo, - commandYear: v.commandYear, - }) - .then(async () => { - const before = null; - salary.status35 = "DONE"; - salary.lastUpdateUserId = request.user.sub; - salary.lastUpdateFullName = request.user.name; - salary.lastUpdatedAt = new Date(); - await this.salaryProfileRepository.save(salary, { data: request }); - setLogDataDiff(request, { before, after: salary }); - }); - } - }), - ); - return new HttpSuccess(); + // ═══════════════════════════════════════════════════════════════ + // new linear flow + // ═══════════════════════════════════════════════════════════════ + // ใช้ร่วมกับ C-PM-45 (path reuse) — ทั้ง C-PM-35/45 ยิงเข้าที่นี่ ตั้ง status35 เหมือนกัน + const result = await Promise.all( + body.refIds.map(async (v) => { + const salary = await this.salaryProfileRepository.findOne({ where: { id: v.refId } }); + if (salary != null) { + // 1) set status35 = DONE (ย้ายขึ้นมาทำก่อนเลย ไม่ต้องรอ org ตอบกลับ) + salary.status35 = "DONE"; + salary.lastUpdateUserId = request.user.sub; + salary.lastUpdateFullName = request.user.name; + salary.lastUpdatedAt = new Date(); + await this.salaryProfileRepository.save(salary, { data: request }); + setLogDataDiff(request, { before: null, after: salary }); + + // 2) return ข้อมูลที่ org ต้องการสร้าง ProfileSalary (shape เดียวกับที่เคย PostData) + return { + profileId: salary.profileId, + commandDateAffect: v.commandDateAffect, + commandDateSign: v.commandDateSign, + amount: v.amount, + amountSpecial: v.amountSpecial, + positionSalaryAmount: v.positionSalaryAmount, + mouthSalaryAmount: v.mouthSalaryAmount, + posNo: salary.posMasterNo.toString(), + posNoAbb: salary.orgShortName, + positionName: salary.position, + positionExecutive: salary.posExecutive, + positionExecutiveField: salary.positionExecutiveField, + positionArea: salary.positionArea, + positionType: salary.posType, + positionLevel: salary.posLevel, + commandId: v.commandId, + remark: v.remark, + orgRoot: salary.root, + orgChild1: salary.child1, + orgChild2: salary.child2, + orgChild3: salary.child3, + orgChild4: salary.child4, + commandCode: v.commandCode, + commandName: v.commandName, + commandNo: v.commandNo, + commandYear: v.commandYear, + }; + } + return null; + }), + ); + return { result: result.filter(Boolean) }; } /** @@ -9322,86 +9475,139 @@ export class ReportController extends Controller { */ @Post("command36/employee/report/excecute") async SalaryEmployeeReportExcecute36( - @Body() - body: { - refIds: { - refId: string; - // commandAffectDate: Date | null;//เก่า - commandDateAffect: Date | null; //ใหม่ (ปรับตาม rabbitMQ ORG) - commandDateSign?: Date | null; - commandNo: string | null; - commandYear: number | null; - commandId: string | null; - commandCode?: string | null; - commandName?: string | null; - templateDoc?: string | null; - amount: Double | null; - amountSpecial?: Double | null; - positionSalaryAmount: Double | null; - mouthSalaryAmount: Double | null; - mpCee?: string | null; - refCommandCode?: string | null; - refCommandName?: string | null; - remark?: string | null; - }[]; - }, - @Request() request: RequestWithUser, + @Body() + body: { + refIds: { + refId: string; + commandDateAffect: Date | null; + commandDateSign?: Date | null; + commandNo: string | null; + commandYear: number | null; + commandId: string | null; + commandCode?: string | null; + commandName?: string | null; + templateDoc?: string | null; + amount: Double | null; + amountSpecial?: Double | null; + positionSalaryAmount: Double | null; + mouthSalaryAmount: Double | null; + mpCee?: string | null; + refCommandCode?: string | null; + refCommandName?: string | null; + remark?: string | null; + }[]; + }, + @Request() request: RequestWithUser, ) { - await Promise.all( - body.refIds.map(async (v) => { - const salary = await this.salaryProfileEmployeeRepository.findOne({ - where: { - id: v.refId, - }, - }); + // ═══════════════════════════════════════════════════════════════ + // old circle flow (เก็บไว้อ้างอิง — ลบการใช้งานจริงออกแล้ว) + // ═══════════════════════════════════════════════════════════════ + // await Promise.all( + // body.refIds.map(async (v) => { + // const salary = await this.salaryProfileEmployeeRepository.findOne({ + // where: { id: v.refId }, + // }); + // if (salary != null) { + // await new CallAPI() + // .PostData(request, "/org/profile-employee/salary/update", { + // profileEmployeeId: salary.profileId, + // commandDateAffect: v.commandDateAffect, + // commandDateSign: v.commandDateSign, + // amount: v.amount, + // amountSpecial: v.amountSpecial, + // positionSalaryAmount: v.positionSalaryAmount, + // mouthSalaryAmount: v.mouthSalaryAmount, + // posNo: salary.posMasterNo != null ? salary.posMasterNo.toString() : null, + // posNoAbb: salary.orgShortName, + // positionName: salary.position, + // positionType: salary.posType, + // positionLevel: + // (salary.posTypeShort != null ? salary.posTypeShort + " " : "") + + // (salary.posLevel != null ? salary.posLevel.toString() : ""), + // remark: v.remark, + // orgRoot: salary.root, + // orgChild1: salary.child1, + // orgChild2: salary.child2, + // orgChild3: salary.child3, + // orgChild4: salary.child4, + // commandCode: v.commandCode, + // commandName: v.commandName, + // commandNo: v.commandNo, + // commandYear: v.commandYear, + // commandId: v.commandId, + // salaryLevel: + // salary.salaryLevel && salary.salaryLevelNew + // ? salary.salaryLevelNew + // : salary.salaryLevel, + // group: salary.groupNew ?? salary.group, + // }) + // .then(async () => { + // const before = null; + // salary.status36 = "DONE"; + // salary.lastUpdateUserId = request.user.sub; + // salary.lastUpdateFullName = request.user.name; + // salary.lastUpdatedAt = new Date(); + // await this.salaryProfileEmployeeRepository.save(salary, { data: request }); + // setLogDataDiff(request, { before, after: salary }); + // }); + // } + // }), + // ); + // return new HttpSuccess(); - if (salary != null) { - await new CallAPI() - .PostData(request, "/org/profile-employee/salary/update", { - profileEmployeeId: salary.profileId, - commandDateAffect: v.commandDateAffect, - commandDateSign: v.commandDateSign, - amount: v.amount, - amountSpecial: v.amountSpecial, - positionSalaryAmount: v.positionSalaryAmount, - mouthSalaryAmount: v.mouthSalaryAmount, - posNo: salary.posMasterNo != null ? salary.posMasterNo.toString() : null, - posNoAbb: salary.orgShortName, - positionName: salary.position, - positionType: salary.posType, - positionLevel: - (salary.posTypeShort != null ? salary.posTypeShort + " " : "") + - (salary.posLevel != null ? salary.posLevel.toString() : ""), - remark: v.remark, - orgRoot: salary.root, - orgChild1: salary.child1, - orgChild2: salary.child2, - orgChild3: salary.child3, - orgChild4: salary.child4, - commandCode: v.commandCode, - commandName: v.commandName, - commandNo: v.commandNo, - commandYear: v.commandYear, - commandId: v.commandId, - salaryLevel: - salary.salaryLevel && salary.salaryLevelNew - ? salary.salaryLevelNew - : salary.salaryLevel, - group: salary.groupNew ?? salary.group, - }) - .then(async () => { - const before = null; - salary.status36 = "DONE"; - salary.lastUpdateUserId = request.user.sub; - salary.lastUpdateFullName = request.user.name; - salary.lastUpdatedAt = new Date(); - await this.salaryProfileEmployeeRepository.save(salary, { data: request }); - setLogDataDiff(request, { before, after: salary }); - }); - } - }), - ); - return new HttpSuccess(); + // ═══════════════════════════════════════════════════════════════ + // new linear flow + // ═══════════════════════════════════════════════════════════════ + // ใช้ร่วมกับ C-PM-46 (path reuse) — ทั้ง C-PM-36/46 ยิงเข้าที่นี่ ตั้ง status36 เหมือนกัน + const result = await Promise.all( + body.refIds.map(async (v) => { + const salary = await this.salaryProfileEmployeeRepository.findOne({ where: { id: v.refId } }); + if (salary != null) { + // 1) set status36 = DONE (ย้ายขึ้นมาทำก่อนเลย ไม่ต้องรอ org ตอบกลับ) + salary.status36 = "DONE"; + salary.lastUpdateUserId = request.user.sub; + salary.lastUpdateFullName = request.user.name; + salary.lastUpdatedAt = new Date(); + await this.salaryProfileEmployeeRepository.save(salary, { data: request }); + setLogDataDiff(request, { before: null, after: salary }); + + // 2) return ข้อมูลที่ org ต้องการสร้าง ProfileSalary (shape เดียวกับที่เคย PostData) + // สังเกต: profileEmployeeId (ไม่ใช่ profileId) + salaryLevel/group เพิ่ม + return { + profileEmployeeId: salary.profileId, + commandDateAffect: v.commandDateAffect, + commandDateSign: v.commandDateSign, + amount: v.amount, + amountSpecial: v.amountSpecial, + positionSalaryAmount: v.positionSalaryAmount, + mouthSalaryAmount: v.mouthSalaryAmount, + posNo: salary.posMasterNo != null ? salary.posMasterNo.toString() : null, + posNoAbb: salary.orgShortName, + positionName: salary.position, + positionType: salary.posType, + positionLevel: + (salary.posTypeShort != null ? salary.posTypeShort + " " : "") + + (salary.posLevel != null ? salary.posLevel.toString() : ""), + remark: v.remark, + orgRoot: salary.root, + orgChild1: salary.child1, + orgChild2: salary.child2, + orgChild3: salary.child3, + orgChild4: salary.child4, + commandCode: v.commandCode, + commandName: v.commandName, + commandNo: v.commandNo, + commandYear: v.commandYear, + commandId: v.commandId, + salaryLevel: + salary.salaryLevel && salary.salaryLevelNew ? salary.salaryLevelNew : salary.salaryLevel, + group: salary.groupNew ?? salary.group, + }; + } + return null; + }), + ); + return { result: result.filter(Boolean) }; } /** @@ -9413,86 +9619,137 @@ export class ReportController extends Controller { */ @Post("command37/employee/report/excecute") async SalaryEmployeeReportExcecute37( - @Body() - body: { - refIds: { - refId: string; - // commandAffectDate: Date | null;//เก่า - commandDateAffect: Date | null; //ใหม่ (ปรับตาม rabbitMQ ORG) - commandDateSign?: Date | null; - commandNo: string | null; - commandYear: number | null; - commandId: string | null; - commandCode?: string | null; - commandName?: string | null; - templateDoc?: string | null; - amount: Double | null; - amountSpecial?: Double | null; - positionSalaryAmount: Double | null; - mouthSalaryAmount: Double | null; - mpCee?: string | null; - refCommandCode?: string | null; - refCommandName?: string | null; - remark?: string | null; - }[]; - }, - @Request() request: RequestWithUser, + @Body() + body: { + refIds: { + refId: string; + commandDateAffect: Date | null; + commandDateSign?: Date | null; + commandNo: string | null; + commandYear: number | null; + commandId: string | null; + commandCode?: string | null; + commandName?: string | null; + templateDoc?: string | null; + amount: Double | null; + amountSpecial?: Double | null; + positionSalaryAmount: Double | null; + mouthSalaryAmount: Double | null; + mpCee?: string | null; + refCommandCode?: string | null; + refCommandName?: string | null; + remark?: string | null; + }[]; + }, + @Request() request: RequestWithUser, ) { - await Promise.all( - body.refIds.map(async (v) => { - const salary = await this.salaryProfileEmployeeRepository.findOne({ - where: { - id: v.refId, - }, - }); + // ═══════════════════════════════════════════════════════════════ + // old circle flow (เก็บไว้อ้างอิง — ลบการใช้งานจริงออกแล้ว) + // ═══════════════════════════════════════════════════════════════ + // await Promise.all( + // body.refIds.map(async (v) => { + // const salary = await this.salaryProfileEmployeeRepository.findOne({ + // where: { id: v.refId }, + // }); + // if (salary != null) { + // await new CallAPI() + // .PostData(request, "/org/profile-employee/salary/update", { + // profileEmployeeId: salary.profileId, + // commandDateAffect: v.commandDateAffect, + // commandDateSign: v.commandDateSign, + // amount: v.amount, + // amountSpecial: v.amountSpecial, + // positionSalaryAmount: v.positionSalaryAmount, + // mouthSalaryAmount: v.mouthSalaryAmount, + // posNo: salary.posMasterNo != null ? salary.posMasterNo.toString() : null, + // posNoAbb: salary.orgShortName, + // positionName: salary.position, + // positionType: salary.posType, + // positionLevel: + // (salary.posTypeShort != null ? salary.posTypeShort + " " : "") + + // (salary.posLevel != null ? salary.posLevel.toString() : ""), + // remark: v.remark, + // orgRoot: salary.root, + // orgChild1: salary.child1, + // orgChild2: salary.child2, + // orgChild3: salary.child3, + // orgChild4: salary.child4, + // commandCode: v.commandCode, + // commandName: v.commandName, + // commandNo: v.commandNo, + // commandYear: v.commandYear, + // commandId: v.commandId, + // salaryLevel: + // salary.salaryLevel && salary.salaryLevelNew + // ? salary.salaryLevelNew + // : salary.salaryLevel, + // group: salary.groupNew ?? salary.group, + // }) + // .then(async () => { + // const before = null; + // salary.status37 = "DONE"; + // salary.lastUpdateUserId = request.user.sub; + // salary.lastUpdateFullName = request.user.name; + // salary.lastUpdatedAt = new Date(); + // await this.salaryProfileEmployeeRepository.save(salary, { data: request }); + // setLogDataDiff(request, { before, after: salary }); + // }); + // } + // }), + // ); + // return new HttpSuccess(); - if (salary != null) { - await new CallAPI() - .PostData(request, "/org/profile-employee/salary/update", { - profileEmployeeId: salary.profileId, - commandDateAffect: v.commandDateAffect, - commandDateSign: v.commandDateSign, - amount: v.amount, - amountSpecial: v.amountSpecial, - positionSalaryAmount: v.positionSalaryAmount, - mouthSalaryAmount: v.mouthSalaryAmount, - posNo: salary.posMasterNo != null ? salary.posMasterNo.toString() : null, - posNoAbb: salary.orgShortName, - positionName: salary.position, - positionType: salary.posType, - positionLevel: - (salary.posTypeShort != null ? salary.posTypeShort + " " : "") + - (salary.posLevel != null ? salary.posLevel.toString() : ""), - remark: v.remark, - orgRoot: salary.root, - orgChild1: salary.child1, - orgChild2: salary.child2, - orgChild3: salary.child3, - orgChild4: salary.child4, - commandCode: v.commandCode, - commandName: v.commandName, - commandNo: v.commandNo, - commandYear: v.commandYear, - commandId: v.commandId, - salaryLevel: - salary.salaryLevel && salary.salaryLevelNew - ? salary.salaryLevelNew - : salary.salaryLevel, - group: salary.groupNew ?? salary.group, - }) - .then(async () => { - const before = null; - salary.status37 = "DONE"; - salary.lastUpdateUserId = request.user.sub; - salary.lastUpdateFullName = request.user.name; - salary.lastUpdatedAt = new Date(); - await this.salaryProfileEmployeeRepository.save(salary, { data: request }); - setLogDataDiff(request, { before, after: salary }); - }); - } - }), - ); - return new HttpSuccess(); + // ═══════════════════════════════════════════════════════════════ + // new linear flow + // ═══════════════════════════════════════════════════════════════ + const result = await Promise.all( + body.refIds.map(async (v) => { + const salary = await this.salaryProfileEmployeeRepository.findOne({ where: { id: v.refId } }); + if (salary != null) { + // 1) set status37 = DONE (ย้ายขึ้นมาทำก่อนเลย ไม่ต้องรอ org ตอบกลับ) + salary.status37 = "DONE"; + salary.lastUpdateUserId = request.user.sub; + salary.lastUpdateFullName = request.user.name; + salary.lastUpdatedAt = new Date(); + await this.salaryProfileEmployeeRepository.save(salary, { data: request }); + setLogDataDiff(request, { before: null, after: salary }); + + // 2) return ข้อมูลที่ org ต้องการสร้าง ProfileSalary (shape เดียวกับที่เคย PostData) + return { + profileEmployeeId: salary.profileId, + commandDateAffect: v.commandDateAffect, + commandDateSign: v.commandDateSign, + amount: v.amount, + amountSpecial: v.amountSpecial, + positionSalaryAmount: v.positionSalaryAmount, + mouthSalaryAmount: v.mouthSalaryAmount, + posNo: salary.posMasterNo != null ? salary.posMasterNo.toString() : null, + posNoAbb: salary.orgShortName, + positionName: salary.position, + positionType: salary.posType, + positionLevel: + (salary.posTypeShort != null ? salary.posTypeShort + " " : "") + + (salary.posLevel != null ? salary.posLevel.toString() : ""), + remark: v.remark, + orgRoot: salary.root, + orgChild1: salary.child1, + orgChild2: salary.child2, + orgChild3: salary.child3, + orgChild4: salary.child4, + commandCode: v.commandCode, + commandName: v.commandName, + commandNo: v.commandNo, + commandYear: v.commandYear, + commandId: v.commandId, + salaryLevel: + salary.salaryLevel && salary.salaryLevelNew ? salary.salaryLevelNew : salary.salaryLevel, + group: salary.groupNew ?? salary.group, + }; + } + return null; + }), + ); + return { result: result.filter(Boolean) }; } /** diff --git a/src/controllers/SalaryPeriodController.ts b/src/controllers/SalaryPeriodController.ts index 14d74e3..12276e7 100644 --- a/src/controllers/SalaryPeriodController.ts +++ b/src/controllers/SalaryPeriodController.ts @@ -470,7 +470,7 @@ export class SalaryPeriodController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -935,7 +935,7 @@ export class SalaryPeriodController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -1272,7 +1272,7 @@ export class SalaryPeriodController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -1981,7 +1981,7 @@ export class SalaryPeriodController extends Controller { Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -2474,7 +2474,7 @@ export class SalaryPeriodController extends Controller { const posLevel = await this.posLevelRepository.findOne({ where: { posTypeId: posType.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!posLevel) { diff --git a/src/controllers/SalaryPeriodEmployeeController.ts b/src/controllers/SalaryPeriodEmployeeController.ts index 88120ab..1f96f04 100644 --- a/src/controllers/SalaryPeriodEmployeeController.ts +++ b/src/controllers/SalaryPeriodEmployeeController.ts @@ -430,7 +430,7 @@ export class SalaryPeriodEmployeeController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -750,7 +750,7 @@ export class SalaryPeriodEmployeeController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -941,7 +941,7 @@ export class SalaryPeriodEmployeeController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -1132,7 +1132,7 @@ export class SalaryPeriodEmployeeController extends Controller { const Level = await this.posLevelRepository.findOne({ where: { posTypeId: Type.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!Level) { @@ -1597,7 +1597,7 @@ export class SalaryPeriodEmployeeController extends Controller { const posLevel = await this.posLevelRepository.findOne({ where: { posTypeId: posType.id, - posLevelName: salaryProfile.posLevel, + posLevelName: salaryProfile.posLevel?.split("/")[0], }, }); if (!posLevel) { diff --git a/src/entities/EmployeePosLevel.ts b/src/entities/EmployeePosLevel.ts index fd2c681..d618164 100644 --- a/src/entities/EmployeePosLevel.ts +++ b/src/entities/EmployeePosLevel.ts @@ -12,9 +12,9 @@ enum EmployeePosLevelAuthoritys { export class EmployeePosLevel extends EntityBase { @Column({ comment: "ชื่อระดับชั้นงาน", - type: "int", + length: 255, }) - posLevelName: number; + posLevelName: string; @Column({ comment: "ระดับของระดับชั้นงาน", diff --git a/src/entities/SalaryProfileEmployee.ts b/src/entities/SalaryProfileEmployee.ts index 0f98cec..b8f8091 100644 --- a/src/entities/SalaryProfileEmployee.ts +++ b/src/entities/SalaryProfileEmployee.ts @@ -134,7 +134,7 @@ export class SalaryProfileEmployee extends EntityBase { comment: "ระดับตำแหน่ง", default: null, }) - posLevel: number; + posLevel: string; @Column({ type: "double", @@ -482,7 +482,7 @@ export class CreateSalaryProfileEmployee { posType: string | null; @Column() - posLevel: number | null; + posLevel: string | null; @Column() group: number | null; diff --git a/src/migration/20260407112136-update_table_posLevel_to_string.ts b/src/migration/20260407112136-update_table_posLevel_to_string.ts new file mode 100644 index 0000000..d5ffc28 --- /dev/null +++ b/src/migration/20260407112136-update_table_posLevel_to_string.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTablePosLevelToString20260407112136 implements MigrationInterface { + name = 'UpdateTablePosLevelToString20260407112136' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`salaryProfileEmployee\` CHANGE \`posLevel\` \`posLevel\` varchar(255) NULL COMMENT 'ระดับตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`employeePosLevel\` CHANGE \`posLevelName\` \`posLevelName\` varchar(255) NOT NULL COMMENT 'ชื่อระดับชั้นงาน'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`salaryProfileEmployee\` CHANGE \`posLevel\` \`posLevel\` double NULL COMMENT 'ระดับตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`employeePosLevel\` CHANGE \`posLevelName\` \`posLevelName\` int NOT NULL COMMENT 'ชื่อระดับชั้นงาน'`); + } + +} diff --git a/src/services/minio.ts b/src/services/minio.ts index 48bd91f..940d5ca 100644 --- a/src/services/minio.ts +++ b/src/services/minio.ts @@ -16,6 +16,26 @@ const minio = new Client({ export default minio; +/** + * ตัดชื่อไฟล์ถ้ายาวเกิน limit + * @param fileName - ชื่อไฟล์เดิม + * @param maxLength - ความยาวสูงสุดของชื่อไฟล์ (default: 50 ตัวอักษร ไม่รวมนามสกุล) + * @returns ชื่อไฟล์ที่ตัดแล้ว + */ +export function truncateFileName(fileName: string, maxLength: number = 50): string { + const dot = fileName.lastIndexOf("."); + const name = dot !== -1 && !fileName.startsWith(".") ? fileName.slice(0, dot) : fileName; + const ext = dot !== -1 && !fileName.startsWith(".") ? fileName.slice(dot) : ""; + + if (name.length <= maxLength) { + return fileName; + } + + // ตัดชื่อและเติม "..." ตามด้วย 5 ตัวสุดท้ายของชื่อเดิม + const truncated = name.slice(0, maxLength - 8) + "..." + name.slice(-5); + return truncated + ext; +} + function exception(e: any): never { console.error(e); throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์"); @@ -74,6 +94,11 @@ export async function s3DeleteFolder(path: string) { export async function s3UploadFile(replace: boolean, ...pathname: string[]) { if (!pathname.length) return; + // ตัดชื่อไฟล์ถ้ายาวเกิน + const originalFileName = pathname.at(-1) as string; + const truncatedFileName = truncateFileName(originalFileName); + pathname = [...pathname.slice(0, -1), truncatedFileName]; + if (!replace) { const list = await s3ListFile(...pathname.slice(0, -1)).catch(exception); @@ -146,7 +171,7 @@ export async function s3DownloadFile(...pathname: string[]) { } export async function duplicateAvatarFile(refId: string, prefix: string, fileName: string) { - try { + try { await minio.statObject(MINIO_BUCKET, refId); const avatar = `${prefix}/${fileName}`; await minio.copyObject( @@ -159,4 +184,4 @@ export async function duplicateAvatarFile(refId: string, prefix: string, fileNam } } -export const fileLocation = (...path: string[]) => path.join("/"); +export const fileLocation = (...path: string[]) => path.join("/"); \ No newline at end of file