api import profileSalaryTemp #1570
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m4s
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m4s
& Fix Report KK1 #2439
This commit is contained in:
parent
7e3982a96d
commit
8912e83227
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 { AppDataSource } from "../database/data-source";
|
||||||
import { In, IsNull, LessThanOrEqual, Not, Between } from "typeorm";
|
import { In, IsNull, LessThanOrEqual, Not, Between } from "typeorm";
|
||||||
import HttpSuccess from "../interfaces/http-success";
|
import HttpSuccess from "../interfaces/http-success";
|
||||||
|
|
@ -105,6 +105,7 @@ import { positionOfficer } from "../entities/mis/positionOfficer";
|
||||||
import { ProvinceMaster } from "../entities/ProvinceMaster";
|
import { ProvinceMaster } from "../entities/ProvinceMaster";
|
||||||
import { SubDistrictMaster } from "../entities/SubDistrictMaster";
|
import { SubDistrictMaster } from "../entities/SubDistrictMaster";
|
||||||
import { DistrictMaster } from "../entities/DistrictMaster";
|
import { DistrictMaster } from "../entities/DistrictMaster";
|
||||||
|
import { RequestWithUser } from "../middlewares/user";
|
||||||
@Route("api/v1/org/upload")
|
@Route("api/v1/org/upload")
|
||||||
@Tags("UPLOAD")
|
@Tags("UPLOAD")
|
||||||
@Security("bearerAuth")
|
@Security("bearerAuth")
|
||||||
|
|
@ -6815,4 +6816,502 @@ export class ImportDataController extends Controller {
|
||||||
// await repo.save(entities);
|
// await repo.save(entities);
|
||||||
// return 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 = [];
|
let retires = [];
|
||||||
const currentDate = new Date();
|
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) {
|
// commandCode ที่ถือว่าออกจากราชการ
|
||||||
// const startDate = retire_raw.commandDateAffect;
|
const retireCommandCodes = ["12", "15", "16"];
|
||||||
|
|
||||||
// // คำนวณจำนวนวันจากวันพ้นสภาพถึงปัจจุบัน
|
// ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
|
||||||
// let daysCount = 0;
|
const salaries = await this.salaryRepo.find({
|
||||||
// if (startDate) {
|
where: { profileId: id },
|
||||||
// const start = new Date(startDate);
|
order: { order: "ASC" },
|
||||||
// daysCount = Math.ceil((currentDate.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
});
|
||||||
// }
|
|
||||||
|
|
||||||
// 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}`,
|
for (let i = 0; i < uniqueSalaries.length; i++) {
|
||||||
// detail: retire_raw.commandName ?? "-",
|
const current = uniqueSalaries[i];
|
||||||
// day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
|
||||||
// });
|
// เป็นคำสั่งออกจากราชการหรือไม่
|
||||||
// }
|
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) {
|
if (retires.length === 0) {
|
||||||
|
|
|
||||||
|
|
@ -1950,35 +1950,78 @@ export class ProfileEmployeeController extends Controller {
|
||||||
// ประวัติพ้นจากราชการ
|
// ประวัติพ้นจากราชการ
|
||||||
let retires = [];
|
let retires = [];
|
||||||
const currentDate = new Date();
|
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) {
|
// commandCode ที่ถือว่าออกจากราชการ
|
||||||
// const startDate = retire_raw.commandDateAffect;
|
const retireCommandCodes = ["12", "15", "16"];
|
||||||
|
|
||||||
// // คำนวณจำนวนวันจากวันพ้นสภาพถึงปัจจุบัน
|
// ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
|
||||||
// let daysCount = 0;
|
const salaries = await this.salaryRepo.find({
|
||||||
// if (startDate) {
|
where: { profileEmployeeId: id },
|
||||||
// const start = new Date(startDate);
|
order: { order: "ASC" },
|
||||||
// daysCount = Math.ceil((currentDate.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
});
|
||||||
// }
|
|
||||||
|
|
||||||
// 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} - ปัจจุบัน`,
|
for (let i = 0; i < uniqueSalaries.length; i++) {
|
||||||
// detail: retire_raw.commandName ?? "-",
|
const current = uniqueSalaries[i];
|
||||||
// day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
|
||||||
// });
|
// เป็นคำสั่งออกจากราชการหรือไม่
|
||||||
// }
|
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) {
|
if (retires.length === 0) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue