Merge branch 'develop' into adiDev
This commit is contained in:
commit
d46dd03eaf
3 changed files with 636 additions and 51 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { Controller, Post, Route, Security, Tags, Request, UploadedFile } from "tsoa";
|
||||
import { Controller, Post, Route, Security, Tags, Request, UploadedFile, Path } from "tsoa";
|
||||
import { AppDataSource } from "../database/data-source";
|
||||
import { In, IsNull, LessThanOrEqual, Not, Between } from "typeorm";
|
||||
import HttpSuccess from "../interfaces/http-success";
|
||||
|
|
@ -105,6 +105,7 @@ import { positionOfficer } from "../entities/mis/positionOfficer";
|
|||
import { ProvinceMaster } from "../entities/ProvinceMaster";
|
||||
import { SubDistrictMaster } from "../entities/SubDistrictMaster";
|
||||
import { DistrictMaster } from "../entities/DistrictMaster";
|
||||
import { RequestWithUser } from "../middlewares/user";
|
||||
@Route("api/v1/org/upload")
|
||||
@Tags("UPLOAD")
|
||||
@Security("bearerAuth")
|
||||
|
|
@ -6815,4 +6816,502 @@ export class ImportDataController extends Controller {
|
|||
// await repo.save(entities);
|
||||
// return entities;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @summary Import ข้อมูลประวัติตำแหน่งเงินเดือนของข้าราชการเข้าตาราง ProfileSalaryTemp
|
||||
* @param profileId Id โปรไฟล์ข้าราชการ
|
||||
* @param file Excel file with salary history data
|
||||
*/
|
||||
@Post("office-profileSalaryTemp/{profileId}")
|
||||
@UseInterceptors(FileInterceptor("file"))
|
||||
async UploadProfileSalaryTemp(
|
||||
@Path() profileId: string,
|
||||
@Request() req: RequestWithUser,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
if (!profileId) {
|
||||
throw new Error("profileId is required");
|
||||
}
|
||||
|
||||
// อ่านไฟล์ Excel ก่อน (นอก transaction)
|
||||
const workbook = xlsx.read(file.buffer, { type: "buffer" });
|
||||
const sheetName = workbook.SheetNames[0];
|
||||
const sheet = workbook.Sheets[sheetName];
|
||||
const getExcel = xlsx.utils.sheet_to_json(sheet, { header: 1 }) as any[][];
|
||||
|
||||
let salaryTemps: ProfileSalaryTemp[] = [];
|
||||
let dateTime = new Date();
|
||||
|
||||
// เริ่มจาก index 1 เพื่อข้าม header row
|
||||
for (let i = 1; i < getExcel.length; i++) {
|
||||
const row = getExcel[i];
|
||||
|
||||
// ข้าม empty rows
|
||||
if (!row || row.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ข้ามแถวที่ไม่มีลำดับ (row[0] เป็น null, undefined หรือค่าว่าง)
|
||||
if (!row[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const salaryTemp = new ProfileSalaryTemp();
|
||||
|
||||
// ฟังก์ชันแปลงวันที่จาก Excel รองรับทั้ง string format และ serial number
|
||||
const parseExcelDate = (value: any): Date | null => {
|
||||
if (!value) return null;
|
||||
|
||||
// กรณี 1: Excel serial number (ตัวเลข)
|
||||
if (typeof value === "number") {
|
||||
// Excel serial number = จำนวนวันตั้งแต่ 1 ม.ค. 1900
|
||||
// แปลงเป็น JavaScript Date (epoch 1970)
|
||||
let jsDate = new Date(Math.round((value - 25569) * 86400 * 1000));
|
||||
|
||||
// ตรวจสอบและแปลงปี พ.ศ. เป็น ค.ศ. (ถ้าปี > 2500)
|
||||
if (jsDate.getFullYear() > 2500) {
|
||||
const newYear = jsDate.getFullYear() - 543;
|
||||
jsDate = new Date(
|
||||
newYear,
|
||||
jsDate.getMonth(),
|
||||
jsDate.getDate(),
|
||||
jsDate.getHours(),
|
||||
jsDate.getMinutes(),
|
||||
jsDate.getSeconds(),
|
||||
jsDate.getMilliseconds()
|
||||
);
|
||||
}
|
||||
return jsDate;
|
||||
}
|
||||
|
||||
// กรณี 2: String format (dd/mm/yyyy หรือ d/m/yyyy)
|
||||
const dateStr = value.toString().trim();
|
||||
|
||||
// ตรวจสอบว่าเป็น serial number ที่เป็น string หรือไม่
|
||||
if (/^\d+$/.test(dateStr)) {
|
||||
const serialNum = parseInt(dateStr);
|
||||
let jsDate = new Date(Math.round((serialNum - 25569) * 86400 * 1000));
|
||||
|
||||
// ตรวจสอบและแปลงปี พ.ศ. เป็น ค.ศ. (ถ้าปี > 2500)
|
||||
if (jsDate.getFullYear() > 2500) {
|
||||
const newYear = jsDate.getFullYear() - 543;
|
||||
jsDate = new Date(
|
||||
newYear,
|
||||
jsDate.getMonth(),
|
||||
jsDate.getDate(),
|
||||
jsDate.getHours(),
|
||||
jsDate.getMinutes(),
|
||||
jsDate.getSeconds(),
|
||||
jsDate.getMilliseconds()
|
||||
);
|
||||
}
|
||||
return jsDate;
|
||||
}
|
||||
|
||||
// String format ปกติ (dd/mm/yyyy)
|
||||
const dateParts = dateStr.split("/");
|
||||
if (dateParts.length === 3) {
|
||||
// แปลงเป็นตัวเลขแล้วค่อยจัดรูปแบบใหม่ เพื่อรองรับทั้ง 1 หลักและ 2 หลัก
|
||||
const day = parseInt(dateParts[0].trim()).toString().padStart(2, "0");
|
||||
const month = parseInt(dateParts[1].trim()).toString().padStart(2, "0");
|
||||
let year = parseInt(dateParts[2].trim());
|
||||
if (year > 2500) {
|
||||
year -= 543;
|
||||
}
|
||||
const result = new Date(`${year}-${month}-${day}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Index 1: วันที่คำสั่งมีผล
|
||||
let commandDateAffect: Date | null = null;
|
||||
if (row[1]) {
|
||||
commandDateAffect = parseExcelDate(row[1]);
|
||||
}
|
||||
|
||||
// Index 25: วันที่ลงนาม
|
||||
let commandDateSign: Date | null = null;
|
||||
if (row[25]) {
|
||||
commandDateSign = parseExcelDate(row[25]);
|
||||
}
|
||||
|
||||
// Map ข้อมูลจาก Excel ไปยัง ProfileSalaryTemp ตามลำดับ column
|
||||
// ข้อมูลระบบ
|
||||
salaryTemp.profileId = profileId;
|
||||
salaryTemp.profileEmployeeId = null as any;
|
||||
|
||||
// Index 0: ลำดับ
|
||||
salaryTemp.order = row[0] ? parseInt(row[0].toString()) : (null as any);
|
||||
|
||||
// Index 1: วันที่คำสั่งมีผล
|
||||
salaryTemp.commandDateAffect = commandDateAffect as any;
|
||||
|
||||
// Index 2: ตำแหน่งในสายงาน
|
||||
salaryTemp.positionName = row[2] || null;
|
||||
|
||||
// Index 3: ตำแหน่งประเภท
|
||||
salaryTemp.positionType = row[3] || null;
|
||||
|
||||
// Index 4: ระดับ
|
||||
salaryTemp.positionLevel = row[4] || null;
|
||||
|
||||
// Index 5: ระดับซี
|
||||
salaryTemp.positionCee = row[5] || null;
|
||||
|
||||
// Index 6: สายงาน
|
||||
salaryTemp.positionLine = row[6] || null;
|
||||
|
||||
// Index 7: ด้าน/สาขา
|
||||
salaryTemp.positionPathSide = row[7] || null;
|
||||
|
||||
// Index 8: ตำแหน่งทางการบริหาร
|
||||
salaryTemp.positionExecutive = row[8] || null;
|
||||
|
||||
// Index 9: ด้านทางการบริหาร
|
||||
salaryTemp.positionExecutiveField = row[9] || null;
|
||||
|
||||
// Index 10: เงินเดือน
|
||||
salaryTemp.amount = row[10] || 0;
|
||||
|
||||
// Index 11: เงินค่าตอบแทนรายเดือน
|
||||
salaryTemp.mouthSalaryAmount = row[11] || 0;
|
||||
|
||||
// Index 12: เงินประจำตำแหน่ง
|
||||
salaryTemp.positionSalaryAmount = row[12] || 0;
|
||||
|
||||
// Index 13: เงินค่าตอบแทนพิเศษ
|
||||
salaryTemp.amountSpecial = row[13] || 0;
|
||||
|
||||
// Index 14: หน่วยงาน
|
||||
salaryTemp.orgRoot = row[14] || null;
|
||||
|
||||
// Index 15: ส่วนราชการระดับ 1
|
||||
salaryTemp.orgChild1 = row[15] || null;
|
||||
|
||||
// Index 16: ส่วนราชการระดับ 2
|
||||
salaryTemp.orgChild2 = row[16] || null;
|
||||
|
||||
// Index 17: ส่วนราชการระดับ 3
|
||||
salaryTemp.orgChild3 = row[17] || null;
|
||||
|
||||
// Index 18: ส่วนราชการระดับ 4
|
||||
salaryTemp.orgChild4 = row[18] || null;
|
||||
|
||||
// Index 19: ตัวย่อเลขที่ตำแหน่ง
|
||||
salaryTemp.posNoAbb = row[19] || null;
|
||||
|
||||
// Index 20: เลขที่ตำแหน่ง
|
||||
salaryTemp.posNo = row[20] ? row[20].toString() : null;
|
||||
|
||||
// Index 21: หน่วยงานที่ออกคำสั่ง
|
||||
salaryTemp.posNumCodeSit = row[21] || null;
|
||||
|
||||
// Index 22: ตัวย่อหน่วยงานที่ออกคำสั่ง
|
||||
salaryTemp.posNumCodeSitAbb = row[22] || null;
|
||||
|
||||
// Index 23: เลขที่คำสั่ง
|
||||
salaryTemp.commandNo = row[23] || null;
|
||||
|
||||
// Index 24: ปีเลขที่คำสั่ง (แปลงเป็น ค.ศ.)
|
||||
let commandYearValue: number | null = null;
|
||||
if (row[24]) {
|
||||
commandYearValue = parseInt(row[24].toString());
|
||||
// ถ้าปีเป็น พ.ศ. (มากกว่า 2500) ให้แปลงเป็น ค.ศ.
|
||||
if (commandYearValue > 2500) {
|
||||
commandYearValue -= 543;
|
||||
}
|
||||
}
|
||||
salaryTemp.commandYear = commandYearValue as any;
|
||||
|
||||
// Index 25: วันที่ลงนาม (แปลงแล้ว)
|
||||
salaryTemp.commandDateSign = commandDateSign as any;
|
||||
|
||||
// Index 26: ประเภทคำสั่ง
|
||||
salaryTemp.commandName = row[26] || null;
|
||||
|
||||
// Index 27: หมายเหตุ
|
||||
salaryTemp.remark = row[27] || null;
|
||||
|
||||
// Index 28: commandId
|
||||
salaryTemp.commandId = row[28] || null;
|
||||
|
||||
// Index 29: commandCode
|
||||
salaryTemp.commandCode = row[29] || null;
|
||||
|
||||
// ข้อมูลระบบ
|
||||
salaryTemp.isDelete = false;
|
||||
salaryTemp.isEdit = false;
|
||||
salaryTemp.isGovernment = false;
|
||||
salaryTemp.isEntry = false;
|
||||
salaryTemp.createdAt = dateTime;
|
||||
salaryTemp.createdUserId = req.user?.sub || "";
|
||||
salaryTemp.createdFullName = req.user?.name || "System Administrator";
|
||||
salaryTemp.lastUpdatedAt = dateTime;
|
||||
salaryTemp.lastUpdateUserId = req.user?.sub || "";
|
||||
salaryTemp.lastUpdateFullName = req.user?.name || "System Administrator";
|
||||
|
||||
salaryTemps.push(salaryTemp);
|
||||
}
|
||||
|
||||
// ใช้ Transaction เพื่อความปลอดภัย
|
||||
await AppDataSource.transaction(async (transactionalEntityManager) => {
|
||||
// ล้างข้อมูลทั้งหมดในตาราง profileSalaryTemp ของ profileId นั้น
|
||||
await transactionalEntityManager.delete(ProfileSalaryTemp, { profileId });
|
||||
// Insert ข้อมูลใหม่
|
||||
await transactionalEntityManager.save(ProfileSalaryTemp, salaryTemps);
|
||||
});
|
||||
|
||||
return new HttpSuccess({ message: "Import ข้อมูลเรียบร้อย", count: salaryTemps.length });
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Import ข้อมูลประวัติตำแหน่งเงินเดือนของลูกจ้างประจำเข้าตาราง ProfileSalaryTemp
|
||||
* @param profileEmployeeId Id โปรไฟล์ลูกจ้างประจำ
|
||||
* @param file Excel file with salary history data
|
||||
*/
|
||||
@Post("employee-profileSalaryTemp/{profileEmployeeId}")
|
||||
@UseInterceptors(FileInterceptor("file"))
|
||||
async UploadProfileEmployeeSalaryTemp(
|
||||
@Path() profileEmployeeId: string,
|
||||
@Request() req: RequestWithUser,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
if (!profileEmployeeId) {
|
||||
throw new Error("profileEmployeeId is required");
|
||||
}
|
||||
|
||||
// อ่านไฟล์ Excel ก่อน (นอก transaction)
|
||||
const workbook = xlsx.read(file.buffer, { type: "buffer" });
|
||||
const sheetName = workbook.SheetNames[0];
|
||||
const sheet = workbook.Sheets[sheetName];
|
||||
const getExcel = xlsx.utils.sheet_to_json(sheet, { header: 1 }) as any[][];
|
||||
|
||||
let salaryTemps: ProfileSalaryTemp[] = [];
|
||||
let dateTime = new Date();
|
||||
|
||||
// เริ่มจาก index 1 เพื่อข้าม header row
|
||||
for (let i = 1; i < getExcel.length; i++) {
|
||||
const row = getExcel[i];
|
||||
|
||||
// ข้าม empty rows
|
||||
if (!row || row.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ข้ามแถวที่ไม่มีลำดับ (row[0] เป็น null, undefined หรือค่าว่าง)
|
||||
if (!row[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const salaryTemp = new ProfileSalaryTemp();
|
||||
|
||||
// ฟังก์ชันแปลงวันที่จาก Excel รองรับทั้ง string format และ serial number
|
||||
const parseExcelDate = (value: any): Date | null => {
|
||||
if (!value) return null;
|
||||
|
||||
// กรณี 1: Excel serial number (ตัวเลข)
|
||||
if (typeof value === "number") {
|
||||
// Excel serial number = จำนวนวันตั้งแต่ 1 ม.ค. 1900
|
||||
// แปลงเป็น JavaScript Date (epoch 1970)
|
||||
let jsDate = new Date(Math.round((value - 25569) * 86400 * 1000));
|
||||
|
||||
// ตรวจสอบและแปลงปี พ.ศ. เป็น ค.ศ. (ถ้าปี > 2500)
|
||||
if (jsDate.getFullYear() > 2500) {
|
||||
const newYear = jsDate.getFullYear() - 543;
|
||||
jsDate = new Date(
|
||||
newYear,
|
||||
jsDate.getMonth(),
|
||||
jsDate.getDate(),
|
||||
jsDate.getHours(),
|
||||
jsDate.getMinutes(),
|
||||
jsDate.getSeconds(),
|
||||
jsDate.getMilliseconds()
|
||||
);
|
||||
}
|
||||
return jsDate;
|
||||
}
|
||||
|
||||
// กรณี 2: String format (dd/mm/yyyy หรือ d/m/yyyy)
|
||||
const dateStr = value.toString().trim();
|
||||
|
||||
// ตรวจสอบว่าเป็น serial number ที่เป็น string หรือไม่
|
||||
if (/^\d+$/.test(dateStr)) {
|
||||
const serialNum = parseInt(dateStr);
|
||||
let jsDate = new Date(Math.round((serialNum - 25569) * 86400 * 1000));
|
||||
|
||||
// ตรวจสอบและแปลงปี พ.ศ. เป็น ค.ศ. (ถ้าปี > 2500)
|
||||
if (jsDate.getFullYear() > 2500) {
|
||||
const newYear = jsDate.getFullYear() - 543;
|
||||
jsDate = new Date(
|
||||
newYear,
|
||||
jsDate.getMonth(),
|
||||
jsDate.getDate(),
|
||||
jsDate.getHours(),
|
||||
jsDate.getMinutes(),
|
||||
jsDate.getSeconds(),
|
||||
jsDate.getMilliseconds()
|
||||
);
|
||||
}
|
||||
return jsDate;
|
||||
}
|
||||
|
||||
// String format ปกติ (dd/mm/yyyy)
|
||||
const dateParts = dateStr.split("/");
|
||||
if (dateParts.length === 3) {
|
||||
// แปลงเป็นตัวเลขแล้วค่อยจัดรูปแบบใหม่ เพื่อรองรับทั้ง 1 หลักและ 2 หลัก
|
||||
const day = parseInt(dateParts[0].trim()).toString().padStart(2, "0");
|
||||
const month = parseInt(dateParts[1].trim()).toString().padStart(2, "0");
|
||||
let year = parseInt(dateParts[2].trim());
|
||||
if (year > 2500) {
|
||||
year -= 543;
|
||||
}
|
||||
const result = new Date(`${year}-${month}-${day}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Index 1: วันที่คำสั่งมีผล
|
||||
let commandDateAffect: Date | null = null;
|
||||
if (row[1]) {
|
||||
commandDateAffect = parseExcelDate(row[1]);
|
||||
}
|
||||
|
||||
// Index 25: วันที่ลงนาม
|
||||
let commandDateSign: Date | null = null;
|
||||
if (row[25]) {
|
||||
commandDateSign = parseExcelDate(row[25]);
|
||||
}
|
||||
|
||||
// Map ข้อมูลจาก Excel ไปยัง ProfileSalaryTemp ตามลำดับ column
|
||||
// ข้อมูลระบบ
|
||||
salaryTemp.profileEmployeeId = profileEmployeeId;
|
||||
salaryTemp.profileId = null as any;
|
||||
|
||||
// Index 0: ลำดับ
|
||||
salaryTemp.order = row[0] ? parseInt(row[0].toString()) : (null as any);
|
||||
|
||||
// Index 1: วันที่คำสั่งมีผล
|
||||
salaryTemp.commandDateAffect = commandDateAffect as any;
|
||||
|
||||
// Index 2: ตำแหน่งในสายงาน
|
||||
salaryTemp.positionName = row[2] || null;
|
||||
|
||||
// Index 3: ตำแหน่งประเภท
|
||||
salaryTemp.positionType = row[3] || null;
|
||||
|
||||
// Index 4: ระดับ
|
||||
salaryTemp.positionLevel = row[4] || null;
|
||||
|
||||
// Index 5: ระดับซี
|
||||
salaryTemp.positionCee = row[5] || null;
|
||||
|
||||
// Index 6: สายงาน
|
||||
salaryTemp.positionLine = row[6] || null;
|
||||
|
||||
// Index 7: ด้าน/สาขา
|
||||
salaryTemp.positionPathSide = row[7] || null;
|
||||
|
||||
// Index 8: ตำแหน่งทางการบริหาร
|
||||
salaryTemp.positionExecutive = row[8] || null;
|
||||
|
||||
// Index 9: ด้านทางการบริหาร
|
||||
salaryTemp.positionExecutiveField = row[9] || null;
|
||||
|
||||
// Index 10: เงินเดือน
|
||||
salaryTemp.amount = row[10] || 0;
|
||||
|
||||
// Index 11: เงินค่าตอบแทนรายเดือน
|
||||
salaryTemp.mouthSalaryAmount = row[11] || 0;
|
||||
|
||||
// Index 12: เงินประจำตำแหน่ง
|
||||
salaryTemp.positionSalaryAmount = row[12] || 0;
|
||||
|
||||
// Index 13: เงินค่าตอบแทนพิเศษ
|
||||
salaryTemp.amountSpecial = row[13] || 0;
|
||||
|
||||
// Index 14: หน่วยงาน
|
||||
salaryTemp.orgRoot = row[14] || null;
|
||||
|
||||
// Index 15: ส่วนราชการระดับ 1
|
||||
salaryTemp.orgChild1 = row[15] || null;
|
||||
|
||||
// Index 16: ส่วนราชการระดับ 2
|
||||
salaryTemp.orgChild2 = row[16] || null;
|
||||
|
||||
// Index 17: ส่วนราชการระดับ 3
|
||||
salaryTemp.orgChild3 = row[17] || null;
|
||||
|
||||
// Index 18: ส่วนราชการระดับ 4
|
||||
salaryTemp.orgChild4 = row[18] || null;
|
||||
|
||||
// Index 19: ตัวย่อเลขที่ตำแหน่ง
|
||||
salaryTemp.posNoAbb = row[19] || null;
|
||||
|
||||
// Index 20: เลขที่ตำแหน่ง
|
||||
salaryTemp.posNo = row[20] ? row[20].toString() : null;
|
||||
|
||||
// Index 21: หน่วยงานที่ออกคำสั่ง
|
||||
salaryTemp.posNumCodeSit = row[21] || null;
|
||||
|
||||
// Index 22: ตัวย่อหน่วยงานที่ออกคำสั่ง
|
||||
salaryTemp.posNumCodeSitAbb = row[22] || null;
|
||||
|
||||
// Index 23: เลขที่คำสั่ง
|
||||
salaryTemp.commandNo = row[23] || null;
|
||||
|
||||
// Index 24: ปีเลขที่คำสั่ง (แปลงเป็น ค.ศ.)
|
||||
let commandYearValue: number | null = null;
|
||||
if (row[24]) {
|
||||
commandYearValue = parseInt(row[24].toString());
|
||||
// ถ้าปีเป็น พ.ศ. (มากกว่า 2500) ให้แปลงเป็น ค.ศ.
|
||||
if (commandYearValue > 2500) {
|
||||
commandYearValue -= 543;
|
||||
}
|
||||
}
|
||||
salaryTemp.commandYear = commandYearValue as any;
|
||||
|
||||
// Index 25: วันที่ลงนาม (แปลงแล้ว)
|
||||
salaryTemp.commandDateSign = commandDateSign as any;
|
||||
|
||||
// Index 26: ประเภทคำสั่ง
|
||||
salaryTemp.commandName = row[26] || null;
|
||||
|
||||
// Index 27: หมายเหตุ
|
||||
salaryTemp.remark = row[27] || null;
|
||||
|
||||
// Index 28: commandId
|
||||
salaryTemp.commandId = row[28] || null;
|
||||
|
||||
// Index 29: commandCode
|
||||
salaryTemp.commandCode = row[29] || null;
|
||||
|
||||
// ข้อมูลระบบ
|
||||
salaryTemp.isDelete = false;
|
||||
salaryTemp.isEdit = false;
|
||||
salaryTemp.isGovernment = false;
|
||||
salaryTemp.isEntry = false;
|
||||
salaryTemp.createdAt = dateTime;
|
||||
salaryTemp.createdUserId = req.user?.sub || "";
|
||||
salaryTemp.createdFullName = req.user?.name || "System Administrator";
|
||||
salaryTemp.lastUpdatedAt = dateTime;
|
||||
salaryTemp.lastUpdateUserId = req.user?.sub || "";
|
||||
salaryTemp.lastUpdateFullName = req.user?.name || "System Administrator";
|
||||
|
||||
salaryTemps.push(salaryTemp);
|
||||
}
|
||||
|
||||
// ใช้ Transaction เพื่อความปลอดภัย
|
||||
await AppDataSource.transaction(async (transactionalEntityManager) => {
|
||||
// ล้างข้อมูลทั้งหมดในตาราง profileSalaryTemp ของ profileEmployeeId นั้น
|
||||
await transactionalEntityManager.delete(ProfileSalaryTemp, { profileEmployeeId });
|
||||
// Insert ข้อมูลใหม่
|
||||
await transactionalEntityManager.save(ProfileSalaryTemp, salaryTemps);
|
||||
});
|
||||
|
||||
return new HttpSuccess({ message: "Import ข้อมูลเรียบร้อย", count: salaryTemps.length });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1679,35 +1679,78 @@ export class ProfileController extends Controller {
|
|||
// ประวัติพ้นจากราชการ
|
||||
let retires = [];
|
||||
const currentDate = new Date();
|
||||
// todo: รอข้อสรุป
|
||||
// const retire_raw = await this.salaryRepo.findOne({
|
||||
// where: {
|
||||
// profileId: id,
|
||||
// commandCode: In(["12", "15", "16"]),
|
||||
// },
|
||||
// order: { order: "desc" },
|
||||
// });
|
||||
|
||||
// if (retire_raw) {
|
||||
// const startDate = retire_raw.commandDateAffect;
|
||||
// commandCode ที่ถือว่าออกจากราชการ
|
||||
const retireCommandCodes = ["12", "15", "16"];
|
||||
|
||||
// // คำนวณจำนวนวันจากวันพ้นสภาพถึงปัจจุบัน
|
||||
// let daysCount = 0;
|
||||
// if (startDate) {
|
||||
// const start = new Date(startDate);
|
||||
// daysCount = Math.ceil((currentDate.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
// }
|
||||
// ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
|
||||
const salaries = await this.salaryRepo.find({
|
||||
where: { profileId: id },
|
||||
order: { order: "ASC" },
|
||||
});
|
||||
|
||||
// const startDateStr = startDate
|
||||
// ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
|
||||
// : "-";
|
||||
// มีคำสั่งพ้นราชการหรือไม่
|
||||
if (salaries.length > 0 && salaries.some((s) => s.commandCode &&
|
||||
retireCommandCodes.includes(s.commandCode))) {
|
||||
// กรองข้อมูลซ้ำตาม commandDateAffect
|
||||
const uniqueSalaries = salaries.filter((item, index, self) =>
|
||||
index === self.findIndex((t) => t.commandDateAffect?.getTime() === item.commandDateAffect?.getTime())
|
||||
);
|
||||
|
||||
// retires.push({
|
||||
// date: `${startDateStr}`,
|
||||
// detail: retire_raw.commandName ?? "-",
|
||||
// day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
||||
// });
|
||||
// }
|
||||
// วนลูปหาคู่ของ "ออกราชการ" และ "กลับเข้าราชการ"
|
||||
for (let i = 0; i < uniqueSalaries.length; i++) {
|
||||
const current = uniqueSalaries[i];
|
||||
|
||||
// เป็นคำสั่งออกจากราชการหรือไม่
|
||||
if (current.commandCode && retireCommandCodes.includes(current.commandCode)) {
|
||||
const startDate = current.commandDateAffect;
|
||||
let endDate: Date | null = null;
|
||||
let endRecord = null;
|
||||
|
||||
// หาคำสั่งถัดไปที่ไม่ใช่การออกจากราชการ (ถือว่ากลับเข้าราชการ)
|
||||
for (let j = i + 1; j < uniqueSalaries.length; j++) {
|
||||
const next = uniqueSalaries[j];
|
||||
if (next.commandCode && !retireCommandCodes.includes(next.commandCode)) {
|
||||
endDate = next.commandDateAffect;
|
||||
endRecord = next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ถ้าไม่เจอคำสั่งกลับเข้า ให้ใช้วันปัจจุบัน
|
||||
if (!endDate) {
|
||||
endDate = currentDate;
|
||||
}
|
||||
|
||||
// คำนวณจำนวนวัน
|
||||
let daysCount = 0;
|
||||
if (startDate && endDate) {
|
||||
const start = new Date(startDate);
|
||||
const end = new Date(endDate);
|
||||
daysCount = Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
|
||||
// สร้าง detail จาก commandName + remark
|
||||
const commandName = current.commandName || "";
|
||||
const remark = current.remark || "";
|
||||
const detail = `${commandName} ${remark}`.trim();
|
||||
|
||||
// แปลงวันที่เป็น format ไทย
|
||||
const startDateStr = startDate
|
||||
? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
|
||||
: "-";
|
||||
const endDateStr = endDate
|
||||
? Extension.ToThaiNumber(Extension.ToThaiFullDate2(endDate))
|
||||
: "-";
|
||||
|
||||
retires.push({
|
||||
date: `${startDateStr} - ${endDateStr}`,
|
||||
detail: detail || "-",
|
||||
day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// กรณีไม่มีข้อมูล
|
||||
if (retires.length === 0) {
|
||||
|
|
|
|||
|
|
@ -1950,35 +1950,78 @@ export class ProfileEmployeeController extends Controller {
|
|||
// ประวัติพ้นจากราชการ
|
||||
let retires = [];
|
||||
const currentDate = new Date();
|
||||
// todo: รอข้อสรุป
|
||||
// const retire_raw = await this.salaryRepo.findOne({
|
||||
// where: {
|
||||
// profileEmployeeId: id,
|
||||
// commandCode: In(["12", "15", "16"]),
|
||||
// },
|
||||
// order: { order: "desc" },
|
||||
// });
|
||||
|
||||
// if (retire_raw) {
|
||||
// const startDate = retire_raw.commandDateAffect;
|
||||
// commandCode ที่ถือว่าออกจากราชการ
|
||||
const retireCommandCodes = ["12", "15", "16"];
|
||||
|
||||
// // คำนวณจำนวนวันจากวันพ้นสภาพถึงปัจจุบัน
|
||||
// let daysCount = 0;
|
||||
// if (startDate) {
|
||||
// const start = new Date(startDate);
|
||||
// daysCount = Math.ceil((currentDate.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
// }
|
||||
// ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
|
||||
const salaries = await this.salaryRepo.find({
|
||||
where: { profileEmployeeId: id },
|
||||
order: { order: "ASC" },
|
||||
});
|
||||
|
||||
// const startDateStr = startDate
|
||||
// ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
|
||||
// : "-";
|
||||
// มีคำสั่งพ้นราชการหรือไม่
|
||||
if (salaries.length > 0 && salaries.some((s) => s.commandCode &&
|
||||
retireCommandCodes.includes(s.commandCode))) {
|
||||
// กรองข้อมูลซ้ำตาม commandDateAffect
|
||||
const uniqueSalaries = salaries.filter((item, index, self) =>
|
||||
index === self.findIndex((t) => t.commandDateAffect?.getTime() === item.commandDateAffect?.getTime())
|
||||
);
|
||||
|
||||
// retires.push({
|
||||
// date: `${startDateStr} - ปัจจุบัน`,
|
||||
// detail: retire_raw.commandName ?? "-",
|
||||
// day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
||||
// });
|
||||
// }
|
||||
// วนลูปหาคู่ของ "ออกราชการ" และ "กลับเข้าราชการ"
|
||||
for (let i = 0; i < uniqueSalaries.length; i++) {
|
||||
const current = uniqueSalaries[i];
|
||||
|
||||
// เป็นคำสั่งออกจากราชการหรือไม่
|
||||
if (current.commandCode && retireCommandCodes.includes(current.commandCode)) {
|
||||
const startDate = current.commandDateAffect;
|
||||
let endDate: Date | null = null;
|
||||
let endRecord = null;
|
||||
|
||||
// หาคำสั่งถัดไปที่ไม่ใช่การออกจากราชการ (ถือว่ากลับเข้าราชการ)
|
||||
for (let j = i + 1; j < uniqueSalaries.length; j++) {
|
||||
const next = uniqueSalaries[j];
|
||||
if (next.commandCode && !retireCommandCodes.includes(next.commandCode)) {
|
||||
endDate = next.commandDateAffect;
|
||||
endRecord = next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ถ้าไม่เจอคำสั่งกลับเข้า ให้ใช้วันปัจจุบัน
|
||||
if (!endDate) {
|
||||
endDate = currentDate;
|
||||
}
|
||||
|
||||
// คำนวณจำนวนวัน
|
||||
let daysCount = 0;
|
||||
if (startDate && endDate) {
|
||||
const start = new Date(startDate);
|
||||
const end = new Date(endDate);
|
||||
daysCount = Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
|
||||
// สร้าง detail จาก commandName + remark
|
||||
const commandName = current.commandName || "";
|
||||
const remark = current.remark || "";
|
||||
const detail = `${commandName} ${remark}`.trim();
|
||||
|
||||
// แปลงวันที่เป็น format ไทย
|
||||
const startDateStr = startDate
|
||||
? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
|
||||
: "-";
|
||||
const endDateStr = endDate
|
||||
? Extension.ToThaiNumber(Extension.ToThaiFullDate2(endDate))
|
||||
: "-";
|
||||
|
||||
retires.push({
|
||||
date: `${startDateStr} - ${endDateStr}`,
|
||||
detail: detail || "-",
|
||||
day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// กรณีไม่มีข้อมูล
|
||||
if (retires.length === 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue