Compare commits
No commits in common. "dev" and "develop" have entirely different histories.
20 changed files with 511 additions and 1626 deletions
|
|
@ -1,154 +0,0 @@
|
|||
-- =====================================================
|
||||
-- Update position fields in profile table
|
||||
-- อัพเดทฟิลด์ตำแหน่งในตาราง profile
|
||||
--
|
||||
-- Fields:
|
||||
-- - positionField (สายงาน)
|
||||
-- - posExecutive (ตำแหน่งทางการบริหาร)
|
||||
-- - positionArea (ด้าน/สาขา)
|
||||
-- - positionExecutiveField (ด้านทางการบริหาร)
|
||||
-- - posMasterNo (เลขที่ตำแหน่ง) - format: orgShortName + space + number
|
||||
-- - org (สังกัด)
|
||||
--
|
||||
-- Run each query separately to verify results
|
||||
-- =====================================================
|
||||
USE hrms_organization;
|
||||
-- 1. Update positionField (สายงาน)
|
||||
UPDATE profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
INNER JOIN position pos ON pos.posMasterId = pm.id AND pos.positionIsSelected = 1
|
||||
SET p.positionField = pos.positionField
|
||||
WHERE p.positionField IS NULL;
|
||||
|
||||
-- 2. Update posExecutive (ตำแหน่งทางการบริหาร)
|
||||
UPDATE profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
INNER JOIN position pos ON pos.posMasterId = pm.id AND pos.positionIsSelected = 1
|
||||
INNER JOIN posExecutive pe ON pos.posExecutiveId = pe.id
|
||||
SET p.posExecutive = pe.posExecutiveName
|
||||
WHERE p.posExecutive IS NULL;
|
||||
|
||||
-- 3. Update positionArea (ด้าน/สาขา)
|
||||
UPDATE profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
INNER JOIN position pos ON pos.posMasterId = pm.id AND pos.positionIsSelected = 1
|
||||
SET p.positionArea = pos.positionArea
|
||||
WHERE p.positionArea IS NULL;
|
||||
|
||||
-- 4. Update positionExecutiveField (ด้านทางการบริหาร)
|
||||
UPDATE profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
INNER JOIN position pos ON pos.posMasterId = pm.id AND pos.positionIsSelected = 1
|
||||
SET p.positionExecutiveField = pos.positionExecutiveField
|
||||
WHERE p.positionExecutiveField IS NULL;
|
||||
|
||||
-- 5. Update posMasterNo (เลขที่ตำแหน่ง) - format: orgShortName + space + number
|
||||
UPDATE profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
LEFT JOIN orgRoot r ON pm.orgRootId = r.id
|
||||
LEFT JOIN orgChild1 c1 ON pm.orgChild1Id = c1.id
|
||||
LEFT JOIN orgChild2 c2 ON pm.orgChild2Id = c2.id
|
||||
LEFT JOIN orgChild3 c3 ON pm.orgChild3Id = c3.id
|
||||
LEFT JOIN orgChild4 c4 ON pm.orgChild4Id = c4.id
|
||||
SET p.posMasterNo = TRIM(CONCAT(
|
||||
CASE
|
||||
WHEN pm.orgChild1Id IS NULL THEN r.orgRootShortName
|
||||
WHEN pm.orgChild2Id IS NULL THEN c1.orgChild1ShortName
|
||||
WHEN pm.orgChild3Id IS NULL THEN c2.orgChild2ShortName
|
||||
WHEN pm.orgChild4Id IS NULL THEN c3.orgChild3ShortName
|
||||
ELSE c4.orgChild4ShortName
|
||||
END,
|
||||
' ',
|
||||
CONCAT_WS('', pm.posMasterNoPrefix, pm.posMasterNo, pm.posMasterNoSuffix)
|
||||
))
|
||||
WHERE p.posMasterNo IS NULL;
|
||||
|
||||
-- 6. Update org (สังกัด) - combine all org levels
|
||||
UPDATE profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
LEFT JOIN orgRoot r ON pm.orgRootId = r.id
|
||||
LEFT JOIN orgChild1 c1 ON pm.orgChild1Id = c1.id
|
||||
LEFT JOIN orgChild2 c2 ON pm.orgChild2Id = c2.id
|
||||
LEFT JOIN orgChild3 c3 ON pm.orgChild3Id = c3.id
|
||||
LEFT JOIN orgChild4 c4 ON pm.orgChild4Id = c4.id
|
||||
SET p.org = TRIM(CONCAT_WS(
|
||||
CHAR(10),
|
||||
c4.orgChild4Name,
|
||||
c3.orgChild3Name,
|
||||
c2.orgChild2Name,
|
||||
c1.orgChild1Name,
|
||||
r.orgRootName
|
||||
))
|
||||
WHERE p.org IS NULL;
|
||||
|
||||
-- =====================================================
|
||||
-- เช็คผลลัพธ์ (Check results)
|
||||
-- =====================================================
|
||||
|
||||
-- เช็คจำนวนที่ update ได้
|
||||
SELECT
|
||||
COUNT(CASE WHEN positionField IS NOT NULL THEN 1 END) AS has_positionField,
|
||||
COUNT(CASE WHEN posExecutive IS NOT NULL THEN 1 END) AS has_posExecutive,
|
||||
COUNT(CASE WHEN positionArea IS NOT NULL THEN 1 END) AS has_positionArea,
|
||||
COUNT(CASE WHEN positionExecutiveField IS NOT NULL THEN 1 END) AS has_positionExecutiveField,
|
||||
COUNT(CASE WHEN posMasterNo IS NOT NULL THEN 1 END) AS has_posMasterNo,
|
||||
COUNT(CASE WHEN org IS NOT NULL THEN 1 END) AS has_org
|
||||
FROM profile;
|
||||
|
||||
-- =====================================================
|
||||
-- SELECT query สำหรับทดสอบก่อนรัน (Test before run)
|
||||
-- =====================================================
|
||||
|
||||
SELECT
|
||||
p.id,
|
||||
p.firstName,
|
||||
p.lastName,
|
||||
p.citizenId,
|
||||
|
||||
p.positionField as old_positionField,
|
||||
p.posExecutive as old_posExecutive,
|
||||
p.positionArea as old_positionArea,
|
||||
p.positionExecutiveField as old_positionExecutiveField,
|
||||
p.posMasterNo as old_posMasterNo,
|
||||
p.org as old_org,
|
||||
|
||||
pos.positionField as new_positionField,
|
||||
pe.posExecutiveName as new_posExecutive,
|
||||
pos.positionArea as new_positionArea,
|
||||
pos.positionExecutiveField as new_positionExecutiveField,
|
||||
|
||||
TRIM(CONCAT(
|
||||
CASE
|
||||
WHEN pm.orgChild1Id IS NULL THEN r.orgRootShortName
|
||||
WHEN pm.orgChild2Id IS NULL THEN c1.orgChild1ShortName
|
||||
WHEN pm.orgChild3Id IS NULL THEN c2.orgChild2ShortName
|
||||
WHEN pm.orgChild4Id IS NULL THEN c3.orgChild3ShortName
|
||||
ELSE c4.orgChild4ShortName
|
||||
END,
|
||||
' ',
|
||||
pm.posMasterNo
|
||||
)) as new_posMasterNo,
|
||||
|
||||
TRIM(CONCAT_WS(CHAR(10), c4.orgChild4Name, c3.orgChild3Name, c2.orgChild2Name, c1.orgChild1Name, r.orgRootName)) as new_org
|
||||
|
||||
FROM profile p
|
||||
INNER JOIN posMaster pm ON pm.current_holderId = p.id
|
||||
INNER JOIN orgRevision oRev ON pm.orgRevisionId = oRev.id AND oRev.orgRevisionIsCurrent = 1 AND oRev.orgRevisionIsDraft = 0
|
||||
INNER JOIN position pos ON pos.posMasterId = pm.id AND pos.positionIsSelected = 1
|
||||
LEFT JOIN posExecutive pe ON pos.posExecutiveId = pe.id
|
||||
LEFT JOIN orgRoot r ON pm.orgRootId = r.id
|
||||
LEFT JOIN orgChild1 c1 ON pm.orgChild1Id = c1.id
|
||||
LEFT JOIN orgChild2 c2 ON pm.orgChild2Id = c2.id
|
||||
LEFT JOIN orgChild3 c3 ON pm.orgChild3Id = c3.id
|
||||
LEFT JOIN orgChild4 c4 ON pm.orgChild4Id = c4.id
|
||||
|
||||
-- ใส่ WHERE ทดสอบ 1 คน (Test 1 person)
|
||||
WHERE p.id = 'ใส่ profile_id ที่ต้องการทดสอบ'
|
||||
-- หรือทดสอบ 10 คน (Test 10 persons)
|
||||
-- LIMIT 10;
|
||||
|
|
@ -48,7 +48,6 @@ import {
|
|||
import { Position } from "../entities/Position";
|
||||
import { PosMaster } from "../entities/PosMaster";
|
||||
import { EmployeePosition } from "../entities/EmployeePosition";
|
||||
import { getPosMasterNo, getOrgFullName } from "../utils/org-formatting";
|
||||
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
|
||||
import { ProfileDiscipline } from "../entities/ProfileDiscipline";
|
||||
import { ProfileDisciplineHistory } from "../entities/ProfileDisciplineHistory";
|
||||
|
|
@ -3661,7 +3660,6 @@ export class CommandController extends Controller {
|
|||
|
||||
const posMaster = await this.posMasterRepository.findOne({
|
||||
where: { id: item.posmasterId },
|
||||
relations: ["orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
|
||||
});
|
||||
if (posMaster == null)
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
|
||||
|
|
@ -3717,22 +3715,14 @@ export class CommandController extends Controller {
|
|||
id: item.positionId,
|
||||
posMasterId: item.posmasterId,
|
||||
},
|
||||
relations: ["posExecutive"],
|
||||
});
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (positionNew != null) {
|
||||
positionNew.positionIsSelected = true;
|
||||
// อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
|
||||
profile.posMasterNo = getPosMasterNo(posMaster);
|
||||
profile.org = getOrgFullName(posMaster);
|
||||
if(!posMaster.isSit){
|
||||
profile.posLevelId = positionNew.posLevelId;
|
||||
profile.posTypeId = positionNew.posTypeId;
|
||||
profile.position = positionNew.positionName;
|
||||
profile.positionField = positionNew.positionField ?? null;
|
||||
profile.posExecutive = positionNew.posExecutive?.posExecutiveName ?? null;
|
||||
profile.positionArea = positionNew.positionArea ?? null;
|
||||
profile.positionExecutiveField = positionNew.positionExecutiveField ?? null;
|
||||
}
|
||||
profile.amount = item.amount ?? null;
|
||||
profile.amountSpecial = item.amountSpecial ?? null;
|
||||
|
|
@ -6886,7 +6876,7 @@ export class CommandController extends Controller {
|
|||
where: {
|
||||
id: item.bodyPosition.posmasterId,
|
||||
},
|
||||
relations: { orgRevision: true, orgRoot: true, orgChild1: true, orgChild2: true, orgChild3: true, orgChild4: true }
|
||||
relations: { orgRevision: true }
|
||||
});
|
||||
|
||||
// เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่
|
||||
|
|
@ -6903,8 +6893,9 @@ export class CommandController extends Controller {
|
|||
orgRevisionIsDraft: false
|
||||
}
|
||||
},
|
||||
relations: { orgRevision: true, orgRoot: true, orgChild1: true, orgChild2: true, orgChild3: true, orgChild4: true }
|
||||
}); }
|
||||
relations: { orgRevision: true }
|
||||
});
|
||||
}
|
||||
|
||||
if (posMaster == null)
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
|
||||
|
|
@ -6992,28 +6983,20 @@ export class CommandController extends Controller {
|
|||
id: item.bodyPosition.positionId,
|
||||
posMasterId: posMaster.id,
|
||||
},
|
||||
relations: ["posExecutive"],
|
||||
});
|
||||
}
|
||||
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (positionNew != null) {
|
||||
positionNew.positionIsSelected = true;
|
||||
// อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
|
||||
profile.posMasterNo = getPosMasterNo(posMaster);
|
||||
profile.org = getOrgFullName(posMaster);
|
||||
if(!posMaster.isSit){
|
||||
profile.posLevelId = positionNew.posLevelId;
|
||||
profile.posTypeId = positionNew.posTypeId;
|
||||
profile.position = positionNew.positionName;
|
||||
profile.positionField = positionNew.positionField ?? null;
|
||||
profile.posExecutive = positionNew.posExecutive?.posExecutiveName ?? null;
|
||||
profile.positionArea = positionNew.positionArea ?? null;
|
||||
profile.positionExecutiveField = positionNew.positionExecutiveField ?? null;
|
||||
// profile.dateStart = new Date();
|
||||
await this.profileRepository.save(profile, { data: req });
|
||||
setLogDataDiff(req, { before, after: profile });
|
||||
}
|
||||
await this.profileRepository.save(profile, { data: req });
|
||||
setLogDataDiff(req, { before, after: profile });
|
||||
await this.positionRepository.save(positionNew, { data: req });
|
||||
}
|
||||
// await CreatePosMasterHistoryOfficer(posMaster.id, req);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import {
|
|||
import HttpError from "../interfaces/http-error";
|
||||
import HttpStatusCode from "../interfaces/http-status";
|
||||
import { addLogSequence } from "../interfaces/utils";
|
||||
import HttpSuccess from "../interfaces/http-success";
|
||||
|
||||
interface CachedToken {
|
||||
token: string;
|
||||
|
|
@ -89,8 +88,7 @@ export class ExRetirementController extends Controller {
|
|||
},
|
||||
});
|
||||
|
||||
// return res.data;
|
||||
return new HttpSuccess(res.data.data);
|
||||
return res.data;
|
||||
} catch (error: any) {
|
||||
if (error.response?.status === 500 && retryCount < maxRetries - 1) {
|
||||
TokenCache.delete(`${clientId}:${clientSecret}`);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Controller, Post, Route, Security, Tags, Request, UploadedFile, Path } from "tsoa";
|
||||
import { Controller, Post, Route, Security, Tags, Request, UploadedFile } from "tsoa";
|
||||
import { AppDataSource } from "../database/data-source";
|
||||
import { In, IsNull, LessThanOrEqual, Not, Between } from "typeorm";
|
||||
import HttpSuccess from "../interfaces/http-success";
|
||||
|
|
@ -105,7 +105,6 @@ 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")
|
||||
|
|
@ -6816,502 +6815,4 @@ 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 });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ import {
|
|||
import { orgStructureCache } from "../utils/OrgStructureCache";
|
||||
import { OrgIdMapping, AllOrgMappings, SavePosMasterHistory } from "../interfaces/OrgMapping";
|
||||
import { OrgPermissionData, NodeLevel } from "../interfaces/OrgTypes";
|
||||
import { formatPosMaster, generateLabelName, filterPosMasters, getPosMasterNo, getOrgFullName } from "../utils/org-formatting";
|
||||
import { formatPosMaster, generateLabelName, filterPosMasters } from "../utils/org-formatting";
|
||||
|
||||
@Route("api/v1/org")
|
||||
@Tags("Organization")
|
||||
|
|
@ -8933,25 +8933,13 @@ export class OrganizationController extends Controller {
|
|||
const draftPosMaster = draftPosMasterMap.get(draftPosMasterId) as any;
|
||||
|
||||
// Collect profile update for the selected position
|
||||
// อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
|
||||
if (nextHolderId != null && draftPos.positionIsSelected) {
|
||||
const _null: any = null;
|
||||
profileUpdates.set(nextHolderId, {
|
||||
posMasterNo: draftPosMaster ? (getPosMasterNo(draftPosMaster as PosMaster) ?? _null) : _null,
|
||||
org: draftPosMaster ? (getOrgFullName(draftPosMaster as PosMaster) ?? _null) : _null,
|
||||
});
|
||||
}
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (nextHolderId != null && draftPos.positionIsSelected && !draftPosMaster?.isSit) {
|
||||
const existing = profileUpdates.get(nextHolderId) || {};
|
||||
existing.position = draftPos.positionName;
|
||||
existing.posTypeId = draftPos.posTypeId;
|
||||
existing.posLevelId = draftPos.posLevelId;
|
||||
existing.positionField = draftPos.positionField ?? null;
|
||||
existing.posExecutive = (draftPos as any).posExecutive?.posExecutiveName ?? null;
|
||||
existing.positionArea = draftPos.positionArea ?? null;
|
||||
existing.positionExecutiveField = draftPos.positionExecutiveField ?? null;
|
||||
profileUpdates.set(nextHolderId, existing);
|
||||
profileUpdates.set(nextHolderId, {
|
||||
position: draftPos.positionName,
|
||||
posTypeId: draftPos.posTypeId,
|
||||
posLevelId: draftPos.posLevelId,
|
||||
});
|
||||
if (draftPosMaster && draftPosMaster.ancestorDNA) {
|
||||
// Find the selected position from draft positions
|
||||
const selectedPos =
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import permission from "../interfaces/permission";
|
|||
import { ProfileEmployee } from "../entities/ProfileEmployee";
|
||||
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
|
||||
import { OrgRevision } from "../entities/OrgRevision";
|
||||
import { actingPositionService } from "../services/ActingPositionService";
|
||||
const REDIS_HOST = process.env.REDIS_HOST;
|
||||
const REDIS_PORT = process.env.REDIS_PORT;
|
||||
|
||||
|
|
@ -255,64 +254,6 @@ export class PermissionController extends Controller {
|
|||
return new HttpSuccess(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* API permission with acting positions
|
||||
* @summary permission with acting positions (dotnet api)
|
||||
* @param {string} action action
|
||||
* @param {string} system authSysId
|
||||
*/
|
||||
@Get("dotnet-acting/{action}/{system}")
|
||||
public async dotnetActing(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() action: string,
|
||||
@Path() system: string,
|
||||
) {
|
||||
if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง");
|
||||
}
|
||||
// ดึง privilege ตามปกติ
|
||||
let privilege = await new permission().Permission(req, system.toLocaleUpperCase(), action);
|
||||
|
||||
// ดึงข้อมูล profile และ orgRevision
|
||||
let profile: any = await this.profileRepo.findOne({
|
||||
select: ["id"],
|
||||
where: { keycloak: req.user.sub },
|
||||
});
|
||||
|
||||
if (!profile) {
|
||||
profile = await this.profileEmployeeRepo.findOne({
|
||||
select: ["id"],
|
||||
where: { keycloak: req.user.sub },
|
||||
});
|
||||
if (!profile) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
|
||||
}
|
||||
}
|
||||
|
||||
const orgRevision = await this.orgRevisionRepository.findOne({
|
||||
select: ["id"],
|
||||
where: {
|
||||
orgRevisionIsDraft: false,
|
||||
orgRevisionIsCurrent: true,
|
||||
},
|
||||
});
|
||||
|
||||
// ดึงข้อมูลตำแหน่งที่รักษาการ
|
||||
const actingData = await actingPositionService.getActingPositionsWithPrivilege(
|
||||
profile.id,
|
||||
orgRevision?.id,
|
||||
action,
|
||||
system.toLocaleUpperCase()
|
||||
);
|
||||
|
||||
// ส่งค่ากลับเหมือน dotnet endpoint แต่เพิ่ม isAct และ posMasterActs
|
||||
return new HttpSuccess({
|
||||
privilege,
|
||||
isAct: actingData.isAct,
|
||||
posMasterActs: actingData.posMasterActs,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* API permission (dotnet api)
|
||||
* @summary permission (dotnet api)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ import { AuthRole } from "../entities/AuthRole";
|
|||
import { RequestWithUser } from "../middlewares/user";
|
||||
import permission from "../interfaces/permission";
|
||||
import { resolveNodeLevel, setLogDataDiff } from "../interfaces/utils";
|
||||
import { getPosMasterNo, getOrgFullName } from "../utils/org-formatting";
|
||||
import { PosMasterAssign } from "../entities/PosMasterAssign";
|
||||
import { Assign } from "../entities/Assign";
|
||||
import { ProfileEmployee } from "../entities/ProfileEmployee";
|
||||
|
|
@ -1257,15 +1256,7 @@ export class PositionController extends Controller {
|
|||
) {
|
||||
await new permission().PermissionUpdate(request, "SYS_ORG");
|
||||
const posMaster = await this.posMasterRepository.findOne({
|
||||
relations: [
|
||||
"positions",
|
||||
"orgRevision",
|
||||
"orgRoot",
|
||||
"orgChild1",
|
||||
"orgChild2",
|
||||
"orgChild3",
|
||||
"orgChild4",
|
||||
],
|
||||
relations: ["positions", "orgRevision"],
|
||||
where: { id: id },
|
||||
});
|
||||
if (!posMaster) {
|
||||
|
|
@ -1460,17 +1451,6 @@ export class PositionController extends Controller {
|
|||
}),
|
||||
);
|
||||
|
||||
// อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
|
||||
if (posMaster.orgRevision?.orgRevisionIsCurrent == true && posMaster.current_holderId) {
|
||||
const _profile = await this.profileRepository.findOne({
|
||||
where: { id: posMaster.current_holderId },
|
||||
});
|
||||
if (_profile) {
|
||||
_profile.posMasterNo = getPosMasterNo(posMaster);
|
||||
_profile.org = getOrgFullName(posMaster);
|
||||
await this.profileRepository.save(_profile);
|
||||
}
|
||||
}
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (posMaster.orgRevision?.orgRevisionIsCurrent == true && !posMaster.isSit) {
|
||||
const _position = requestBody.positions.find((p) => p.positionIsSelected == true);
|
||||
|
|
@ -1483,10 +1463,6 @@ export class PositionController extends Controller {
|
|||
_profile.position = _position.posDictName ?? _null;
|
||||
_profile.posTypeId = _position.posTypeId;
|
||||
_profile.posLevelId = _position.posLevelId;
|
||||
_profile.positionField = _position.posDictField ?? _null;
|
||||
_profile.posExecutive = _position.posExecutiveId ?? _null;
|
||||
_profile.positionArea = _position.posDictArea ?? _null;
|
||||
_profile.positionExecutiveField = _position.posDictExecutiveField ?? _null;
|
||||
await this.profileRepository.save(_profile);
|
||||
}
|
||||
}
|
||||
|
|
@ -2411,16 +2387,16 @@ export class PositionController extends Controller {
|
|||
? "posMaster.orgRootId IN (:...root)"
|
||||
: "posMaster.orgRootId is null"
|
||||
: "1=1",
|
||||
{ root: _data.root },
|
||||
{ root: _data.root }
|
||||
)
|
||||
.andWhere(
|
||||
_data.child1 != undefined && _data.child1 != null
|
||||
? _data.child1[0] != null
|
||||
? "posMaster.orgChild1Id IN (:...child1)"
|
||||
: // : `posMaster.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
|
||||
`posMaster.orgChild1Id is null`
|
||||
// : `posMaster.orgChild1Id is ${_data.privilege == "PARENT" ? "not null" : "null"}`
|
||||
: `posMaster.orgChild1Id is null`
|
||||
: "1=1",
|
||||
{ child1: _data.child1 },
|
||||
{ child1: _data.child1 }
|
||||
)
|
||||
.andWhere(
|
||||
_data.child2 != undefined && _data.child2 != null
|
||||
|
|
@ -2451,27 +2427,26 @@ export class PositionController extends Controller {
|
|||
{
|
||||
child4: _data.child4,
|
||||
},
|
||||
);
|
||||
)
|
||||
// .andWhere(checkChildConditions)
|
||||
// .andWhere(typeCondition)
|
||||
// .andWhere(revisionCondition);
|
||||
|
||||
if (body.keyword != null && body.keyword != "") {
|
||||
query
|
||||
.orWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.andWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? body.isAll == false
|
||||
? searchShortName
|
||||
: `CASE WHEN posMaster.orgChild1 is null THEN ${searchShortName0} WHEN posMaster.orgChild2 is null THEN ${searchShortName1} WHEN posMaster.orgChild3 is null THEN ${searchShortName2} WHEN posMaster.orgChild4 is null THEN ${searchShortName3} ELSE ${searchShortName4} END LIKE '%${body.keyword}%'`
|
||||
: "1=1",
|
||||
)
|
||||
.andWhere(checkChildConditions)
|
||||
.andWhere(typeCondition)
|
||||
.andWhere(revisionCondition);
|
||||
}),
|
||||
)
|
||||
query.orWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.andWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? body.isAll == false
|
||||
? searchShortName
|
||||
: `CASE WHEN posMaster.orgChild1 is null THEN ${searchShortName0} WHEN posMaster.orgChild2 is null THEN ${searchShortName1} WHEN posMaster.orgChild3 is null THEN ${searchShortName2} WHEN posMaster.orgChild4 is null THEN ${searchShortName3} ELSE ${searchShortName4} END LIKE '%${body.keyword}%'`
|
||||
: "1=1",
|
||||
)
|
||||
.andWhere(checkChildConditions)
|
||||
.andWhere(typeCondition)
|
||||
.andWhere(revisionCondition);
|
||||
}),
|
||||
)
|
||||
.orWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.andWhere(
|
||||
|
|
@ -2980,50 +2955,50 @@ export class PositionController extends Controller {
|
|||
const type0LastPosMasterNo =
|
||||
requestBody.type == 0
|
||||
? await this.posMasterRepository.find({
|
||||
where: {
|
||||
orgRootId: requestBody.id,
|
||||
orgChild1Id: IsNull(),
|
||||
},
|
||||
})
|
||||
where: {
|
||||
orgRootId: requestBody.id,
|
||||
orgChild1Id: IsNull(),
|
||||
},
|
||||
})
|
||||
: [];
|
||||
|
||||
const type1LastPosMasterNo =
|
||||
requestBody.type == 1
|
||||
? await this.posMasterRepository.find({
|
||||
where: {
|
||||
orgChild1Id: requestBody.id,
|
||||
orgChild2Id: IsNull(),
|
||||
},
|
||||
})
|
||||
where: {
|
||||
orgChild1Id: requestBody.id,
|
||||
orgChild2Id: IsNull(),
|
||||
},
|
||||
})
|
||||
: [];
|
||||
|
||||
const type2LastPosMasterNo =
|
||||
requestBody.type == 2
|
||||
? await this.posMasterRepository.find({
|
||||
where: {
|
||||
orgChild2Id: requestBody.id,
|
||||
orgChild3Id: IsNull(),
|
||||
},
|
||||
})
|
||||
where: {
|
||||
orgChild2Id: requestBody.id,
|
||||
orgChild3Id: IsNull(),
|
||||
},
|
||||
})
|
||||
: [];
|
||||
|
||||
const type3LastPosMasterNo =
|
||||
requestBody.type == 3
|
||||
? await this.posMasterRepository.find({
|
||||
where: {
|
||||
orgChild3Id: requestBody.id,
|
||||
orgChild4Id: IsNull(),
|
||||
},
|
||||
})
|
||||
where: {
|
||||
orgChild3Id: requestBody.id,
|
||||
orgChild4Id: IsNull(),
|
||||
},
|
||||
})
|
||||
: [];
|
||||
|
||||
const type4LastPosMasterNo =
|
||||
requestBody.type == 4
|
||||
? await this.posMasterRepository.find({
|
||||
where: {
|
||||
orgChild4Id: requestBody.id,
|
||||
},
|
||||
})
|
||||
where: {
|
||||
orgChild4Id: requestBody.id,
|
||||
},
|
||||
})
|
||||
: [];
|
||||
|
||||
const allLastPosMasterNo = [
|
||||
|
|
@ -3818,7 +3793,7 @@ export class PositionController extends Controller {
|
|||
await new permission().PermissionUpdate(request, "SYS_ORG");
|
||||
const dataMaster = await this.posMasterRepository.findOne({
|
||||
where: { id: requestBody.posMaster },
|
||||
relations: ["positions", "orgRoot", "orgChild1", "orgChild2", "orgChild3", "orgChild4"],
|
||||
relations: ["positions"],
|
||||
});
|
||||
if (!dataMaster) {
|
||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
|
||||
|
|
@ -3850,24 +3825,16 @@ export class PositionController extends Controller {
|
|||
if (_profile) {
|
||||
let _position = await this.positionRepository.findOne({
|
||||
where: { id: requestBody.position, posMasterId: requestBody.posMaster },
|
||||
relations: ["posExecutive"],
|
||||
});
|
||||
if (_position) {
|
||||
// อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
|
||||
_profile.posMasterNo = getPosMasterNo(dataMaster);
|
||||
_profile.org = getOrgFullName(dataMaster);
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (!dataMaster.isSit) {
|
||||
if(!dataMaster.isSit){
|
||||
_profile.position = _position.positionName;
|
||||
_profile.posTypeId = _position.posTypeId;
|
||||
_profile.posLevelId = _position.posLevelId;
|
||||
_profile.positionField = _position.positionField ?? _null;
|
||||
_profile.posExecutive = _position.posExecutive?.posExecutiveName ?? _null;
|
||||
_profile.positionArea = _position.positionArea ?? _null;
|
||||
_profile.positionExecutiveField = _position.positionExecutiveField ?? _null;
|
||||
await this.profileRepository.save(_profile);
|
||||
setLogDataDiff(request, { before, after: _profile });
|
||||
}
|
||||
await this.profileRepository.save(_profile);
|
||||
setLogDataDiff(request, { before, after: _profile });
|
||||
}
|
||||
}
|
||||
dataMaster.current_holderId = requestBody.profileId;
|
||||
|
|
@ -5202,9 +5169,9 @@ export class PositionController extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* API รายการตำแหน่งติดเงื่อนไข
|
||||
* API รายการอัตรากำลัง
|
||||
*
|
||||
* @summary รายการตำแหน่งติดเงื่อนไข
|
||||
* @summary ORG_070 - รายการอัตรากำลัง (ADMIN) #56
|
||||
*
|
||||
*/
|
||||
@Post("master/position-condition")
|
||||
|
|
@ -5215,7 +5182,7 @@ export class PositionController extends Controller {
|
|||
id: string;
|
||||
revisionId: string;
|
||||
type: number;
|
||||
isAll: boolean; // true คือเลือกเฉพาะตำแหน่งติดเงื่อนไข / false คือเลือกตำแหน่งทั้งหมด
|
||||
isAll: boolean;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
keyword?: string;
|
||||
|
|
@ -5235,7 +5202,7 @@ export class PositionController extends Controller {
|
|||
let level: any = resolveNodeLevel(orgDna);
|
||||
|
||||
const cannotViewRootPosMaster =
|
||||
_data.privilege === "PARENT" ||
|
||||
(_data.privilege === "PARENT") ||
|
||||
(_data.privilege === "BROTHER" && level > 1) ||
|
||||
(_data.privilege === "CHILD" && level > 0) ||
|
||||
(_data.privilege === "NORMAL" && level != 0);
|
||||
|
|
@ -5267,46 +5234,46 @@ export class PositionController extends Controller {
|
|||
typeCondition = {
|
||||
...(cannotViewRootPosMaster ? { orgRootId: null } : { orgRootId: body.id }),
|
||||
};
|
||||
// if (!body.isAll) {
|
||||
// checkChildConditions = {
|
||||
// orgChild1Id: IsNull(),
|
||||
// };
|
||||
// searchShortName = `CONCAT(orgRoot.orgRootShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
// } else {
|
||||
// }
|
||||
if (!body.isAll) {
|
||||
checkChildConditions = {
|
||||
orgChild1Id: IsNull(),
|
||||
};
|
||||
searchShortName = `CONCAT(orgRoot.orgRootShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
} else {
|
||||
}
|
||||
} else if (body.type === 1) {
|
||||
typeCondition = {
|
||||
...(cannotViewChild1PosMaster ? { orgChild1Id: null } : { orgChild1Id: body.id }),
|
||||
};
|
||||
// if (!body.isAll) {
|
||||
// checkChildConditions = {
|
||||
// orgChild2Id: IsNull(),
|
||||
// };
|
||||
// searchShortName = `CONCAT(orgChild1.orgChild1ShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
// } else {
|
||||
// }
|
||||
if (!body.isAll) {
|
||||
checkChildConditions = {
|
||||
orgChild2Id: IsNull(),
|
||||
};
|
||||
searchShortName = `CONCAT(orgChild1.orgChild1ShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
} else {
|
||||
}
|
||||
} else if (body.type === 2) {
|
||||
typeCondition = {
|
||||
...(cannotViewChild2PosMaster ? { orgChild2Id: null } : { orgChild2Id: body.id }),
|
||||
};
|
||||
// if (!body.isAll) {
|
||||
// checkChildConditions = {
|
||||
// orgChild3Id: IsNull(),
|
||||
// };
|
||||
// searchShortName = `CONCAT(orgChild2.orgChild2ShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
// } else {
|
||||
// }
|
||||
if (!body.isAll) {
|
||||
checkChildConditions = {
|
||||
orgChild3Id: IsNull(),
|
||||
};
|
||||
searchShortName = `CONCAT(orgChild2.orgChild2ShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
} else {
|
||||
}
|
||||
} else if (body.type === 3) {
|
||||
typeCondition = {
|
||||
...(cannotViewChild3PosMaster ? { orgChild3Id: null } : { orgChild3Id: body.id }),
|
||||
};
|
||||
// if (!body.isAll) {
|
||||
// checkChildConditions = {
|
||||
// orgChild4Id: IsNull(),
|
||||
// };
|
||||
// searchShortName = `CONCAT(orgChild3.orgChild3ShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
// } else {
|
||||
// }
|
||||
if (!body.isAll) {
|
||||
checkChildConditions = {
|
||||
orgChild4Id: IsNull(),
|
||||
};
|
||||
searchShortName = `CONCAT(orgChild3.orgChild3ShortName," ",COALESCE(posMaster.posMasterNoPrefix, ""),posMaster.posMasterNo,COALESCE(posMaster.posMasterNoSuffix, "")) like '%${body.keyword}%'`;
|
||||
} else {
|
||||
}
|
||||
} else if (body.type === 4) {
|
||||
typeCondition = {
|
||||
...(cannotViewChild4PosMaster ? { orgChild4Id: null } : { orgChild4Id: body.id }),
|
||||
|
|
@ -5379,7 +5346,7 @@ export class PositionController extends Controller {
|
|||
(masterId.length > 0
|
||||
? { id: In(masterId) }
|
||||
: { posMasterNo: Like(`%${body.keyword}%`) })),
|
||||
...(!body.isAll && { isCondition: true }),
|
||||
current_holderId: IsNull(),
|
||||
},
|
||||
];
|
||||
let [posMaster, total] = await AppDataSource.getRepository(PosMaster)
|
||||
|
|
@ -5448,15 +5415,15 @@ export class PositionController extends Controller {
|
|||
new Brackets((qb) => {
|
||||
qb.andWhere(
|
||||
body.keyword != null && body.keyword != ""
|
||||
? `CASE WHEN posMaster.orgChild1 is null THEN ${searchShortName0} WHEN posMaster.orgChild2 is null THEN ${searchShortName1} WHEN posMaster.orgChild3 is null THEN ${searchShortName2} WHEN posMaster.orgChild4 is null THEN ${searchShortName3} ELSE ${searchShortName4} END LIKE '%${body.keyword}%'`
|
||||
? body.isAll == false
|
||||
? searchShortName
|
||||
: `CASE WHEN posMaster.orgChild1 is null THEN ${searchShortName0} WHEN posMaster.orgChild2 is null THEN ${searchShortName1} WHEN posMaster.orgChild3 is null THEN ${searchShortName2} WHEN posMaster.orgChild4 is null THEN ${searchShortName3} ELSE ${searchShortName4} END LIKE '%${body.keyword}%'`
|
||||
: "1=1",
|
||||
)
|
||||
.andWhere(checkChildConditions)
|
||||
.andWhere(typeCondition)
|
||||
.andWhere(revisionCondition);
|
||||
if (!body.isAll) {
|
||||
qb.andWhere({ isCondition: true });
|
||||
}
|
||||
.andWhere(revisionCondition)
|
||||
.andWhere({ current_holderId: IsNull() });
|
||||
}),
|
||||
)
|
||||
.orWhere(
|
||||
|
|
@ -5466,10 +5433,8 @@ export class PositionController extends Controller {
|
|||
)
|
||||
.andWhere(checkChildConditions)
|
||||
.andWhere(typeCondition)
|
||||
.andWhere(revisionCondition);
|
||||
if (!body.isAll) {
|
||||
qb.andWhere({ isCondition: true });
|
||||
}
|
||||
.andWhere(revisionCondition)
|
||||
.andWhere({ current_holderId: IsNull() });
|
||||
}),
|
||||
)
|
||||
.orderBy("orgRoot.orgRootOrder", "ASC")
|
||||
|
|
|
|||
|
|
@ -1679,84 +1679,35 @@ 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" },
|
||||
// });
|
||||
|
||||
// commandCode ที่ถือว่าออกจากราชการ
|
||||
const retireCommandCodes = ["12", "15", "16"];
|
||||
// if (retire_raw) {
|
||||
// const startDate = retire_raw.commandDateAffect;
|
||||
|
||||
// ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
|
||||
const salaries = await this.salaryRepo.find({
|
||||
where: { profileId: id },
|
||||
order: { order: "ASC" },
|
||||
});
|
||||
// // คำนวณจำนวนวันจากวันพ้นสภาพถึงปัจจุบัน
|
||||
// let daysCount = 0;
|
||||
// if (startDate) {
|
||||
// const start = new Date(startDate);
|
||||
// daysCount = Math.ceil((currentDate.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
// }
|
||||
|
||||
// มีคำสั่งพ้นราชการหรือไม่
|
||||
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(),
|
||||
),
|
||||
);
|
||||
// const startDateStr = startDate
|
||||
// ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
|
||||
// : "-";
|
||||
|
||||
// วนลูปหาคู่ของ "ออกราชการ" และ "กลับเข้าราชการ"
|
||||
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()) : "-",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// retires.push({
|
||||
// date: `${startDateStr}`,
|
||||
// detail: retire_raw.commandName ?? "-",
|
||||
// day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
||||
// });
|
||||
// }
|
||||
|
||||
// กรณีไม่มีข้อมูล
|
||||
if (retires.length === 0) {
|
||||
|
|
@ -12014,90 +11965,4 @@ export class ProfileController extends Controller {
|
|||
|
||||
return new HttpSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* API ข้อมูลทะเบียนประวัติตาม keycloak สำหรับเช็คอินเข้าใช้งานระบบ
|
||||
*
|
||||
* @summary ข้อมูลทะเบียนประวัติตาม keycloak สำหรับเช็คอินเข้าใช้งานระบบ
|
||||
*
|
||||
*/
|
||||
@Get("keycloak/position-checkin")
|
||||
async getProfileByKeycloakForCheckin(@Request() request: { user: Record<string, any> }) {
|
||||
const userSub = request.user.sub;
|
||||
const relations = [
|
||||
"current_holders",
|
||||
"current_holders.orgRoot",
|
||||
"current_holders.orgChild1",
|
||||
"current_holders.orgChild2",
|
||||
"current_holders.orgChild3",
|
||||
"current_holders.orgChild4",
|
||||
];
|
||||
|
||||
const [officerProfile, orgRevisionPublish] = await Promise.all([
|
||||
this.profileRepo.findOne({
|
||||
where: { keycloak: userSub },
|
||||
relations,
|
||||
}),
|
||||
this.orgRevisionRepo.findOne({
|
||||
where: {
|
||||
orgRevisionIsDraft: false,
|
||||
orgRevisionIsCurrent: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!orgRevisionPublish) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแบบร่างโครงสร้าง");
|
||||
}
|
||||
|
||||
let profile: any = officerProfile;
|
||||
let profileType: "OFFICER" | "EMPLOYEE" = "OFFICER";
|
||||
|
||||
if (!profile) {
|
||||
profile = await this.profileEmpRepo.findOne({
|
||||
where: { keycloak: userSub },
|
||||
relations,
|
||||
});
|
||||
profileType = "EMPLOYEE";
|
||||
}
|
||||
|
||||
if (!profile) {
|
||||
if (request.user.role.includes("SUPER_ADMIN")) {
|
||||
return new HttpSuccess(null);
|
||||
}
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
|
||||
}
|
||||
|
||||
const currentHolder =
|
||||
profile.current_holders?.find((x: any) => x.orgRevisionId == orgRevisionPublish.id) ?? null;
|
||||
const root = currentHolder?.orgRoot ?? null;
|
||||
const child1 = currentHolder?.orgChild1 ?? null;
|
||||
const child2 = currentHolder?.orgChild2 ?? null;
|
||||
const child3 = currentHolder?.orgChild3 ?? null;
|
||||
const child4 = currentHolder?.orgChild4 ?? null;
|
||||
|
||||
const _profile: any = {
|
||||
profileId: profile.id,
|
||||
keycloak: profile.keycloak,
|
||||
prefix: profile.prefix,
|
||||
avatar: profile.avatar,
|
||||
profileType,
|
||||
isProbation: profile.isProbation,
|
||||
avatarName: profile.avatarName,
|
||||
firstName: profile.firstName,
|
||||
lastName: profile.lastName,
|
||||
citizenId: profile.citizenId,
|
||||
root: root?.orgRootName ?? null,
|
||||
child1: child1?.orgChild1Name ?? null,
|
||||
child2: child2?.orgChild2Name ?? null,
|
||||
child3: child3?.orgChild3Name ?? null,
|
||||
child4: child4?.orgChild4Name ?? null,
|
||||
privacyCheckin: profile.privacyCheckin,
|
||||
privacyUser: profile.privacyUser,
|
||||
privacyMgt: profile.privacyMgt,
|
||||
...(profileType !== "OFFICER" ? { type: profile.employeeClass } : {}),
|
||||
};
|
||||
|
||||
return new HttpSuccess(_profile);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1950,78 +1950,35 @@ 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" },
|
||||
// });
|
||||
|
||||
// commandCode ที่ถือว่าออกจากราชการ
|
||||
const retireCommandCodes = ["12", "15", "16"];
|
||||
// if (retire_raw) {
|
||||
// const startDate = retire_raw.commandDateAffect;
|
||||
|
||||
// ดึงข้อมูล profileSalary ทั้งหมดเพื่อหาประวัติพ้นจากราชการ
|
||||
const salaries = await this.salaryRepo.find({
|
||||
where: { profileEmployeeId: id },
|
||||
order: { order: "ASC" },
|
||||
});
|
||||
// // คำนวณจำนวนวันจากวันพ้นสภาพถึงปัจจุบัน
|
||||
// let daysCount = 0;
|
||||
// if (startDate) {
|
||||
// const start = new Date(startDate);
|
||||
// daysCount = Math.ceil((currentDate.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
// }
|
||||
|
||||
// มีคำสั่งพ้นราชการหรือไม่
|
||||
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())
|
||||
);
|
||||
// const startDateStr = startDate
|
||||
// ? Extension.ToThaiNumber(Extension.ToThaiFullDate2(startDate))
|
||||
// : "-";
|
||||
|
||||
// วนลูปหาคู่ของ "ออกราชการ" และ "กลับเข้าราชการ"
|
||||
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()) : "-"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// retires.push({
|
||||
// date: `${startDateStr} - ปัจจุบัน`,
|
||||
// detail: retire_raw.commandName ?? "-",
|
||||
// day: daysCount > 0 ? Extension.ToThaiNumber(daysCount.toLocaleString()) : "-"
|
||||
// });
|
||||
// }
|
||||
|
||||
// กรณีไม่มีข้อมูล
|
||||
if (retires.length === 0) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import HttpError from "../interfaces/http-error";
|
|||
import { RequestWithUser } from "../middlewares/user";
|
||||
import { Profile } from "../entities/Profile";
|
||||
import { ProfileGovernment, UpdateProfileGovernment } from "../entities/ProfileGovernment";
|
||||
import { Position } from "../entities/Position";
|
||||
import { PosMaster } from "../entities/PosMaster";
|
||||
import {
|
||||
calculateAge,
|
||||
calculateGovAge,
|
||||
|
|
@ -13,6 +15,7 @@ import {
|
|||
setLogDataDiff,
|
||||
} from "../interfaces/utils";
|
||||
import permission from "../interfaces/permission";
|
||||
import { OrgRevision } from "../entities/OrgRevision";
|
||||
import { In } from "typeorm";
|
||||
@Route("api/v1/org/profile/government")
|
||||
@Tags("ProfileGovernment")
|
||||
|
|
@ -20,6 +23,9 @@ import { In } from "typeorm";
|
|||
export class ProfileGovernmentHistoryController extends Controller {
|
||||
private profileRepo = AppDataSource.getRepository(Profile);
|
||||
private govRepo = AppDataSource.getRepository(ProfileGovernment);
|
||||
private positionRepo = AppDataSource.getRepository(Position);
|
||||
private posMasterRepo = AppDataSource.getRepository(PosMaster);
|
||||
private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
|
||||
/**
|
||||
*
|
||||
* @summary ข้อมูลราชการ
|
||||
|
|
@ -27,6 +33,13 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
*/
|
||||
@Get("user")
|
||||
public async getGovHistoryUser(@Request() request: { user: Record<string, any> }) {
|
||||
const orgRevision = await this.orgRevisionRepository.findOne({
|
||||
select: ["id"],
|
||||
where: {
|
||||
orgRevisionIsDraft: false,
|
||||
orgRevisionIsCurrent: true,
|
||||
},
|
||||
});
|
||||
const profile = await this.profileRepo.findOneBy({ keycloak: request.user.sub });
|
||||
if (!profile) {
|
||||
throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
|
||||
|
|
@ -38,19 +51,79 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
posLevel: true,
|
||||
},
|
||||
});
|
||||
const posMaster = await this.posMasterRepo.findOne({
|
||||
where: {
|
||||
// orgRevision: {
|
||||
// orgRevisionIsCurrent: true,
|
||||
// orgRevisionIsDraft: false,
|
||||
// },
|
||||
orgRevisionId: orgRevision?.id,
|
||||
current_holderId: profile.id,
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
relations: {
|
||||
orgRoot: true,
|
||||
orgChild1: true,
|
||||
orgChild2: true,
|
||||
orgChild3: true,
|
||||
orgChild4: true,
|
||||
},
|
||||
});
|
||||
const position = await this.positionRepo.findOne({
|
||||
where: {
|
||||
positionIsSelected: true,
|
||||
posMaster: {
|
||||
// orgRevision: {
|
||||
// orgRevisionIsCurrent: true,
|
||||
// orgRevisionIsDraft: false,
|
||||
// },
|
||||
orgRevisionId: orgRevision?.id,
|
||||
current_holderId: profile.id,
|
||||
},
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
relations: {
|
||||
posExecutive: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
||||
|
||||
// ดึงข้อมูลจาก profile ที่เก็บไว้แล้ว
|
||||
const fullNameParts = [
|
||||
posMaster == null || posMaster.orgChild4 == null ? null : posMaster.orgChild4.orgChild4Name,
|
||||
posMaster == null || posMaster.orgChild3 == null ? null : posMaster.orgChild3.orgChild3Name,
|
||||
posMaster == null || posMaster.orgChild2 == null ? null : posMaster.orgChild2.orgChild2Name,
|
||||
posMaster == null || posMaster.orgChild1 == null ? null : posMaster.orgChild1.orgChild1Name,
|
||||
posMaster == null || posMaster.orgRoot == null ? null : posMaster.orgRoot.orgRootName,
|
||||
];
|
||||
const org = fullNameParts.filter((part) => part !== undefined && part !== null).join("\n");
|
||||
let orgShortName = "";
|
||||
if (posMaster != null) {
|
||||
if (posMaster.orgChild1Id === null) {
|
||||
orgShortName = posMaster.orgRoot?.orgRootShortName;
|
||||
} else if (posMaster.orgChild2Id === null) {
|
||||
orgShortName = posMaster.orgChild1?.orgChild1ShortName;
|
||||
} else if (posMaster.orgChild3Id === null) {
|
||||
orgShortName = posMaster.orgChild2?.orgChild2ShortName;
|
||||
} else if (posMaster.orgChild4Id === null) {
|
||||
orgShortName = posMaster.orgChild3?.orgChild3ShortName;
|
||||
} else {
|
||||
orgShortName = posMaster.orgChild4?.orgChild4ShortName;
|
||||
}
|
||||
}
|
||||
//posMaster?.isSit แก้ไขชั่วคราว
|
||||
const data = {
|
||||
org: record.org ?? null, //สังกัด
|
||||
positionField: record.positionField ?? null, //สายงาน
|
||||
org: org, //สังกัด
|
||||
positionField: position == null || posMaster?.isSit ? null : position.positionField, //สายงาน
|
||||
position: record.position, //ตำแหน่ง
|
||||
posLevel: record.posLevel == null ? null : record.posLevel.posLevelName, //ระดับ
|
||||
posMasterNo: record.posMasterNo ?? null, //เลขที่ตำแหน่ง
|
||||
posMasterNo: posMaster == null ? null : `${orgShortName} ${posMaster.posMasterNo}`, //เลขที่ตำแหน่ง
|
||||
posType: record.posType == null ? null : record.posType.posTypeName, //ประเภท
|
||||
posExecutive: record.posExecutive ?? null, //ตำแหน่งทางการบริหาร
|
||||
positionArea: record.positionArea ?? null, //ด้าน/สาขา
|
||||
positionExecutiveField: record.positionExecutiveField ?? null, //ด้านทางการบริหาร
|
||||
posExecutive:
|
||||
position == null || position.posExecutive == null || posMaster?.isSit
|
||||
? null
|
||||
: position.posExecutive.posExecutiveName, //ตำแหน่งทางการบริหาร
|
||||
positionArea: position == null || posMaster?.isSit ? null : position.positionArea, //ด้าน/สาขา
|
||||
positionExecutiveField: position == null || posMaster?.isSit ? null : position.positionExecutiveField, //ด้านทางการบริหาร
|
||||
dateLeave: record.birthDate == null ? null : calculateRetireDate(record.birthDate),
|
||||
dateRetireLaw: record.dateRetireLaw ?? null,
|
||||
// govAge: record.dateStart == null ? null : calculateAge(record.dateStart),
|
||||
|
|
@ -62,10 +135,10 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
govAgePlus: record.govAgePlus,
|
||||
reasonSameDate: record.reasonSameDate,
|
||||
};
|
||||
|
||||
|
||||
return new HttpSuccess(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary ข้อมูลราชการ
|
||||
|
|
@ -77,17 +150,25 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
let _workflow = await new permission().Workflow(req, profileId, "SYS_REGISTRY_OFFICER");
|
||||
if (_workflow == false)
|
||||
await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", profileId);
|
||||
|
||||
|
||||
const orgRevision = await this.orgRevisionRepository.findOne({
|
||||
select: ["id"],
|
||||
where: {
|
||||
orgRevisionIsDraft: false,
|
||||
orgRevisionIsCurrent: true,
|
||||
},
|
||||
});
|
||||
|
||||
// ค้นหา profile ก่อน
|
||||
const record = await this.profileRepo.findOne({
|
||||
where: { id: profileId },
|
||||
relations: ["posType", "posLevel"],
|
||||
});
|
||||
|
||||
|
||||
if (!record) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล profile");
|
||||
}
|
||||
|
||||
|
||||
// ค้นหา profileSalary แยกต่างหาก
|
||||
const profileWithSalary = await this.profileRepo.findOne({
|
||||
where: {
|
||||
|
|
@ -120,13 +201,70 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// ใช้ profileSalary จาก query ที่สอง หรือ [] ถ้าไม่เจอ
|
||||
record.profileSalary = profileWithSalary?.profileSalary || [];
|
||||
|
||||
const posMaster = await this.posMasterRepo.findOne({
|
||||
where: {
|
||||
orgRevisionId: orgRevision?.id,
|
||||
current_holderId: profileId,
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
relations: {
|
||||
orgRoot: true,
|
||||
orgChild1: true,
|
||||
orgChild2: true,
|
||||
orgChild3: true,
|
||||
orgChild4: true,
|
||||
},
|
||||
});
|
||||
const position = await this.positionRepo.findOne({
|
||||
where: {
|
||||
positionIsSelected: true,
|
||||
posMaster: {
|
||||
orgRevisionId: orgRevision?.id,
|
||||
current_holderId: profileId,
|
||||
},
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
relations: {
|
||||
posExecutive: true,
|
||||
},
|
||||
});
|
||||
|
||||
// if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
||||
const fullNameParts = [
|
||||
posMaster == null || posMaster.orgChild4 == null ? null : posMaster.orgChild4.orgChild4Name,
|
||||
posMaster == null || posMaster.orgChild3 == null ? null : posMaster.orgChild3.orgChild3Name,
|
||||
posMaster == null || posMaster.orgChild2 == null ? null : posMaster.orgChild2.orgChild2Name,
|
||||
posMaster == null || posMaster.orgChild1 == null ? null : posMaster.orgChild1.orgChild1Name,
|
||||
posMaster == null || posMaster.orgRoot == null ? null : posMaster.orgRoot.orgRootName,
|
||||
];
|
||||
const org = fullNameParts.filter((part) => part !== undefined && part !== null).join("\n");
|
||||
let orgShortName = "";
|
||||
if (posMaster != null) {
|
||||
if (posMaster.orgChild1Id === null) {
|
||||
orgShortName = posMaster.orgRoot?.orgRootShortName ?? "";
|
||||
} else if (posMaster.orgChild2Id === null) {
|
||||
orgShortName = posMaster.orgChild1?.orgChild1ShortName ?? "";
|
||||
} else if (posMaster.orgChild3Id === null) {
|
||||
orgShortName = posMaster.orgChild2?.orgChild2ShortName ?? "";
|
||||
} else if (posMaster.orgChild4Id === null) {
|
||||
orgShortName = posMaster.orgChild3?.orgChild3ShortName ?? "";
|
||||
} else {
|
||||
orgShortName = posMaster.orgChild4?.orgChild4ShortName ?? "";
|
||||
}
|
||||
}
|
||||
let _OrgLeave: any = [];
|
||||
let _profileSalary: any = null;
|
||||
if (record?.isLeave && record?.profileSalary.length > 0) {
|
||||
// _OrgLeave = [
|
||||
// record?.profileSalary[0].orgChild4 ? record?.profileSalary[0].orgChild4 : null,
|
||||
// record?.profileSalary[0].orgChild3 ? record?.profileSalary[0].orgChild3 : null,
|
||||
// record?.profileSalary[0].orgChild2 ? record?.profileSalary[0].orgChild2 : null,
|
||||
// record?.profileSalary[0].orgChild1 ? record?.profileSalary[0].orgChild1 : null,
|
||||
// record?.profileSalary[0].orgRoot ? record?.profileSalary[0].orgRoot : null,
|
||||
// ];
|
||||
if (record.leaveType == "RETIRE") {
|
||||
_profileSalary =
|
||||
record?.profileSalary.length > 1
|
||||
|
|
@ -150,23 +288,27 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
}
|
||||
}
|
||||
const orgLeave = _OrgLeave.filter((x: any) => x !== undefined && x !== null).join("\n");
|
||||
|
||||
// ดึงข้อมูลจาก profile ที่เก็บไว้แล้ว
|
||||
//posMaster?.isSit แก้ไขชั่วคราว
|
||||
const data = {
|
||||
org: record?.isLeave == false ? (record.org ?? null) : orgLeave, //สังกัด
|
||||
positionField: record.positionField ?? null, //สายงาน
|
||||
org: record?.isLeave == false ? org : orgLeave, //สังกัด
|
||||
positionField: position == null || posMaster?.isSit ? null : position.positionField, //สายงาน
|
||||
position: record?.position, //ตำแหน่ง
|
||||
posLevel: record?.posLevel == null ? null : record?.posLevel.posLevelName, //ระดับ
|
||||
posMasterNo:
|
||||
record?.isLeave == false
|
||||
? record.posMasterNo ?? null
|
||||
? posMaster == null
|
||||
? null
|
||||
: `${orgShortName} ${posMaster.posMasterNo}`
|
||||
: _profileSalary != null
|
||||
? `${_profileSalary.posNoAbb} ${_profileSalary.posNo}`
|
||||
: null, //เลขที่ตำแหน่ง
|
||||
posType: record?.posType == null ? null : record?.posType.posTypeName, //ประเภท
|
||||
posExecutive: record.posExecutive ?? null, //ตำแหน่งทางการบริหาร
|
||||
positionArea: record.positionArea ?? null, //ด้าน/สาขา
|
||||
positionExecutiveField: record.positionExecutiveField ?? null, //ด้านทางการบริหาร
|
||||
posExecutive:
|
||||
position == null || position.posExecutive == null || posMaster?.isSit
|
||||
? null
|
||||
: position.posExecutive.posExecutiveName, //ตำแหน่งทางการบริหาร
|
||||
positionArea: position == null || posMaster?.isSit ? null : position.positionArea, //ด้าน/สาขา
|
||||
positionExecutiveField: position == null || posMaster?.isSit ? null : position.positionExecutiveField, //ด้านทางการบริหาร
|
||||
dateLeave: record?.birthDate == null ? null : calculateRetireDate(record?.birthDate),
|
||||
dateRetireLaw: record?.dateRetireLaw ?? null,
|
||||
// govAge: record?.dateStart == null ? null : calculateAge(record?.dateStart),
|
||||
|
|
@ -178,22 +320,30 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
govAgePlus: record?.govAgePlus,
|
||||
reasonSameDate: record?.reasonSameDate,
|
||||
};
|
||||
|
||||
|
||||
return new HttpSuccess(data);
|
||||
}
|
||||
|
||||
|
||||
@Get("admin/{profileId}")
|
||||
public async getGovHistoryAdmin(@Path() profileId: string) {
|
||||
const orgRevision = await this.orgRevisionRepository.findOne({
|
||||
select: ["id"],
|
||||
where: {
|
||||
orgRevisionIsDraft: false,
|
||||
orgRevisionIsCurrent: true,
|
||||
},
|
||||
});
|
||||
|
||||
// ค้นหา profile ก่อน
|
||||
const record = await this.profileRepo.findOne({
|
||||
where: { id: profileId },
|
||||
relations: ["posType", "posLevel"],
|
||||
});
|
||||
|
||||
|
||||
if (!record) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล profile");
|
||||
}
|
||||
|
||||
|
||||
// ค้นหา profileSalary แยกต่างหาก
|
||||
const profileWithSalary = await this.profileRepo.findOne({
|
||||
where: {
|
||||
|
|
@ -226,13 +376,70 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// ใช้ profileSalary จาก query ที่สอง หรือ [] ถ้าไม่เจอ
|
||||
record.profileSalary = profileWithSalary?.profileSalary || [];
|
||||
|
||||
const posMaster = await this.posMasterRepo.findOne({
|
||||
where: {
|
||||
orgRevisionId: orgRevision?.id,
|
||||
current_holderId: profileId,
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
relations: {
|
||||
orgRoot: true,
|
||||
orgChild1: true,
|
||||
orgChild2: true,
|
||||
orgChild3: true,
|
||||
orgChild4: true,
|
||||
},
|
||||
});
|
||||
const position = await this.positionRepo.findOne({
|
||||
where: {
|
||||
positionIsSelected: true,
|
||||
posMaster: {
|
||||
orgRevisionId: orgRevision?.id,
|
||||
current_holderId: profileId,
|
||||
},
|
||||
},
|
||||
order: { createdAt: "DESC" },
|
||||
relations: {
|
||||
posExecutive: true,
|
||||
},
|
||||
});
|
||||
|
||||
// if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
||||
const fullNameParts = [
|
||||
posMaster == null || posMaster.orgChild4 == null ? null : posMaster.orgChild4.orgChild4Name,
|
||||
posMaster == null || posMaster.orgChild3 == null ? null : posMaster.orgChild3.orgChild3Name,
|
||||
posMaster == null || posMaster.orgChild2 == null ? null : posMaster.orgChild2.orgChild2Name,
|
||||
posMaster == null || posMaster.orgChild1 == null ? null : posMaster.orgChild1.orgChild1Name,
|
||||
posMaster == null || posMaster.orgRoot == null ? null : posMaster.orgRoot.orgRootName,
|
||||
];
|
||||
const org = fullNameParts.filter((part) => part !== undefined && part !== null).join("\n");
|
||||
let orgShortName = "";
|
||||
if (posMaster != null) {
|
||||
if (posMaster.orgChild1Id === null) {
|
||||
orgShortName = posMaster.orgRoot?.orgRootShortName;
|
||||
} else if (posMaster.orgChild2Id === null) {
|
||||
orgShortName = posMaster.orgChild1?.orgChild1ShortName;
|
||||
} else if (posMaster.orgChild3Id === null) {
|
||||
orgShortName = posMaster.orgChild2?.orgChild2ShortName;
|
||||
} else if (posMaster.orgChild4Id === null) {
|
||||
orgShortName = posMaster.orgChild3?.orgChild3ShortName;
|
||||
} else {
|
||||
orgShortName = posMaster.orgChild4?.orgChild4ShortName;
|
||||
}
|
||||
}
|
||||
let _OrgLeave: any = [];
|
||||
let _profileSalary: any = null;
|
||||
if (record?.isLeave && record?.profileSalary.length > 0) {
|
||||
// _OrgLeave = [
|
||||
// record?.profileSalary[0].orgChild4 ? record?.profileSalary[0].orgChild4 : null,
|
||||
// record?.profileSalary[0].orgChild3 ? record?.profileSalary[0].orgChild3 : null,
|
||||
// record?.profileSalary[0].orgChild2 ? record?.profileSalary[0].orgChild2 : null,
|
||||
// record?.profileSalary[0].orgChild1 ? record?.profileSalary[0].orgChild1 : null,
|
||||
// record?.profileSalary[0].orgRoot ? record?.profileSalary[0].orgRoot : null,
|
||||
// ];
|
||||
if (record.leaveType == "RETIRE") {
|
||||
_profileSalary =
|
||||
record?.profileSalary.length > 1
|
||||
|
|
@ -256,23 +463,27 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
}
|
||||
}
|
||||
const orgLeave = _OrgLeave.filter((x: any) => x !== undefined && x !== null).join("\n");
|
||||
|
||||
// ดึงข้อมูลจาก profile ที่เก็บไว้แล้ว
|
||||
//posMaster?.isSit แก้ไขชั่วคราว
|
||||
const data = {
|
||||
org: record?.isLeave == false ? (record.org ?? null) : orgLeave, //สังกัด
|
||||
positionField: record.positionField ?? null, //สายงาน
|
||||
org: record?.isLeave == false ? org : orgLeave, //สังกัด
|
||||
positionField: position == null || posMaster?.isSit ? null : position.positionField, //สายงาน
|
||||
position: record?.position, //ตำแหน่ง
|
||||
posLevel: record?.posLevel == null ? null : record?.posLevel.posLevelName, //ระดับ
|
||||
posMasterNo:
|
||||
record?.isLeave == false
|
||||
? record.posMasterNo ?? null
|
||||
? posMaster == null
|
||||
? null
|
||||
: `${orgShortName} ${posMaster.posMasterNo}`
|
||||
: _profileSalary != null
|
||||
? `${_profileSalary.posNoAbb} ${_profileSalary.posNo}`
|
||||
: null, //เลขที่ตำแหน่ง
|
||||
posType: record?.posType == null ? null : record?.posType.posTypeName, //ประเภท
|
||||
posExecutive: record.posExecutive ?? null, //ตำแหน่งทางการบริหาร
|
||||
positionArea: record.positionArea ?? null, //ด้าน/สาขา
|
||||
positionExecutiveField: record.positionExecutiveField ?? null, //ด้านทางการบริหาร
|
||||
posExecutive:
|
||||
position == null || position.posExecutive == null || posMaster?.isSit
|
||||
? null
|
||||
: position.posExecutive.posExecutiveName, //ตำแหน่งทางการบริหาร
|
||||
positionArea: position == null || posMaster?.isSit ? null : position.positionArea, //ด้าน/สาขา
|
||||
positionExecutiveField: position == null || posMaster?.isSit ? null : position.positionExecutiveField, //ด้านทางการบริหาร
|
||||
dateLeave: record?.birthDate == null ? null : calculateRetireDate(record?.birthDate),
|
||||
dateRetireLaw: record?.dateRetireLaw ?? null,
|
||||
// govAge: record?.dateStart == null ? null : calculateAge(record?.dateStart),
|
||||
|
|
@ -285,10 +496,10 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
reasonSameDate: record?.reasonSameDate,
|
||||
isLeave: record?.isLeave,
|
||||
};
|
||||
|
||||
|
||||
return new HttpSuccess(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary ประวัติข้อมูลราชการ by keycloak
|
||||
|
|
@ -306,7 +517,7 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
});
|
||||
return new HttpSuccess(record);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary ประวัติข้อมูลราชการ
|
||||
|
|
@ -322,12 +533,12 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
order: { lastUpdatedAt: "DESC" },
|
||||
where: { profileId: profileId },
|
||||
});
|
||||
|
||||
|
||||
// record.pop();
|
||||
|
||||
|
||||
return new HttpSuccess(record);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary แก้ไขข้อมูลราชการ
|
||||
|
|
@ -343,14 +554,14 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
const record = await this.profileRepo.findOne({
|
||||
where: { id: profileId },
|
||||
});
|
||||
|
||||
|
||||
if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
||||
const before = structuredClone(record);
|
||||
const history = new ProfileGovernment();
|
||||
|
||||
|
||||
Object.assign(record, body);
|
||||
Object.assign(history, { ...record, id: undefined });
|
||||
|
||||
|
||||
history.profileId = profileId;
|
||||
record.lastUpdateUserId = req.user.sub;
|
||||
record.lastUpdateFullName = req.user.name;
|
||||
|
|
@ -361,14 +572,13 @@ export class ProfileGovernmentHistoryController extends Controller {
|
|||
history.createdFullName = req.user.name;
|
||||
history.createdAt = new Date();
|
||||
history.lastUpdatedAt = new Date();
|
||||
|
||||
|
||||
await Promise.all([
|
||||
this.profileRepo.save(record, { data: req }),
|
||||
setLogDataDiff(req, { before, after: record }),
|
||||
this.govRepo.save(history, { data: req }),
|
||||
]);
|
||||
|
||||
|
||||
return new HttpSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +23,6 @@ import { ProfileEmployee } from "../entities/ProfileEmployee";
|
|||
import { In, IsNull, LessThan, MoreThan, Not } from "typeorm";
|
||||
import permission from "../interfaces/permission";
|
||||
import { setLogDataDiff } from "../interfaces/utils";
|
||||
import { calculateTenure } from "../utils/tenure";
|
||||
import { TenurePositionOfficer } from "../entities/TenurePositionOfficer";
|
||||
import { TenureLevelOfficer } from "../entities/TenureLevelOfficer";
|
||||
import { TenurePositionEmployee } from "../entities/TenurePositionEmployee";
|
||||
|
|
@ -66,12 +65,10 @@ export class ProfileSalaryController extends Controller {
|
|||
await this.positionOfficerRepo.clear();
|
||||
const profile = await this.profileRepo.find();
|
||||
const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
|
||||
const baseCurrentDate = CURRENT_DATE[0].today;
|
||||
let _currentDate = CURRENT_DATE[0].today;
|
||||
for await (const x of profile) {
|
||||
// Use leave date if available and valid, otherwise use current date
|
||||
let _currentDate = baseCurrentDate;
|
||||
if (x.isLeave && x.leaveDate) {
|
||||
_currentDate = Extension.toDateOnlyString(x.leaveDate);
|
||||
if (x.isLeave) {
|
||||
_currentDate = x.leaveDate ? Extension.toDateOnlyString(x.leaveDate) : _currentDate;
|
||||
}
|
||||
const position = await AppDataSource.query("CALL GetProfileSalaryPosition(?, ?)", [
|
||||
x.id,
|
||||
|
|
@ -95,18 +92,21 @@ export class ProfileSalaryController extends Controller {
|
|||
},
|
||||
{ days_diff: 0, positionName: null },
|
||||
);
|
||||
const { year, month, day } = calculateTenure(calDayDiff.days_diff);
|
||||
const mapData: any = {
|
||||
profileId: x.id,
|
||||
positionName: calDayDiff.positionName,
|
||||
days_diff: calDayDiff.days_diff,
|
||||
Years: year,
|
||||
Months: month,
|
||||
Days: day,
|
||||
// Years: (calDayDiff.days_diff / 365.2524).toFixed(4),
|
||||
// Months: ((calDayDiff.days_diff / 30.4375) % 12).toFixed(4),
|
||||
// Days: (calDayDiff.days_diff % 30.4375).toFixed(4),
|
||||
Years: Math.floor(calDayDiff.days_diff / 365.2524),
|
||||
Months: Math.floor((calDayDiff.days_diff / 30.4375) % 12),
|
||||
Days: Math.floor(calDayDiff.days_diff % 30.4375),
|
||||
};
|
||||
data.push(mapData);
|
||||
// data.push(_mapData);
|
||||
await this.positionOfficerRepo.save(mapData);
|
||||
}
|
||||
await this.positionOfficerRepo.save(data);
|
||||
// await this.positionOfficerRepo.save(data);
|
||||
|
||||
return new HttpSuccess();
|
||||
}
|
||||
|
|
@ -115,13 +115,11 @@ export class ProfileSalaryController extends Controller {
|
|||
let data: any = [];
|
||||
await this.positionEmployeeRepo.clear();
|
||||
const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
|
||||
const baseCurrentDate = CURRENT_DATE[0].today;
|
||||
let _currentDate = CURRENT_DATE[0].today;
|
||||
const profile = await this.profileEmployeeRepo.find();
|
||||
for await (const x of profile) {
|
||||
// Use leave date if available and valid, otherwise use current date
|
||||
let _currentDate = baseCurrentDate;
|
||||
if (x?.isLeave && x.leaveDate) {
|
||||
_currentDate = Extension.toDateOnlyString(x.leaveDate);
|
||||
if (x?.isLeave) {
|
||||
_currentDate = x.leaveDate ? Extension.toDateOnlyString(x.leaveDate) : _currentDate;
|
||||
}
|
||||
const position = await AppDataSource.query("CALL GetProfileEmployeeSalaryPosition(?, ?)", [
|
||||
x.id,
|
||||
|
|
@ -145,18 +143,21 @@ export class ProfileSalaryController extends Controller {
|
|||
},
|
||||
{ days_diff: 0, positionName: null },
|
||||
);
|
||||
const { year, month, day } = calculateTenure(calDayDiff.days_diff);
|
||||
const mapData: any = {
|
||||
profileEmployeeId: x.id,
|
||||
positionName: calDayDiff.positionName,
|
||||
days_diff: calDayDiff.days_diff,
|
||||
Years: year,
|
||||
Months: month,
|
||||
Days: day,
|
||||
// Years: (calDayDiff.days_diff / 365.2524).toFixed(4),
|
||||
// Months: ((calDayDiff.days_diff / 30.4375) % 12).toFixed(4),
|
||||
// Days: (calDayDiff.days_diff % 30.4375).toFixed(4),
|
||||
Years: Math.floor(calDayDiff.days_diff / 365.2524),
|
||||
Months: Math.floor((calDayDiff.days_diff / 30.4375) % 12),
|
||||
Days: Math.floor(calDayDiff.days_diff % 30.4375),
|
||||
};
|
||||
data.push(mapData);
|
||||
// data.push(_mapData);
|
||||
await this.positionEmployeeRepo.save(mapData);
|
||||
}
|
||||
await this.positionEmployeeRepo.save(data);
|
||||
// await this.positionEmployeeRepo.save(data);
|
||||
|
||||
return new HttpSuccess();
|
||||
}
|
||||
|
|
@ -166,12 +167,10 @@ export class ProfileSalaryController extends Controller {
|
|||
await this.levelOfficerRepo.clear();
|
||||
const profile = await this.profileRepo.find({ relations: ["posLevel", "posType"] });
|
||||
const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
|
||||
const baseCurrentDate = CURRENT_DATE[0].today;
|
||||
let _currentDate = CURRENT_DATE[0].today;
|
||||
for await (const x of profile) {
|
||||
// Use leave date if available and valid, otherwise use current date
|
||||
let _currentDate = baseCurrentDate;
|
||||
if (x?.isLeave && x.leaveDate) {
|
||||
_currentDate = Extension.toDateOnlyString(x.leaveDate);
|
||||
if (x?.isLeave) {
|
||||
_currentDate = x.leaveDate ? Extension.toDateOnlyString(x.leaveDate) : _currentDate;
|
||||
}
|
||||
const positionLevel = await AppDataSource.query("CALL GetProfileSalaryLevel(?, ?)", [
|
||||
x.id,
|
||||
|
|
@ -203,20 +202,20 @@ export class ProfileSalaryController extends Controller {
|
|||
},
|
||||
{ days_diff: 0, positionType: null, positionLevel: null, positionCee: null },
|
||||
);
|
||||
const { year, month, day } = calculateTenure(calDayDiff.days_diff);
|
||||
const mapData: any = {
|
||||
profileId: x.id,
|
||||
positionType: calDayDiff.positionType,
|
||||
positionLevel: calDayDiff.positionLevel,
|
||||
positionCee: calDayDiff.positionCee,
|
||||
days_diff: calDayDiff.days_diff,
|
||||
Years: x.posLevel == null ? 0 : year.toFixed(4),
|
||||
Months: x.posLevel == null ? 0 : month.toFixed(4),
|
||||
Days: x.posLevel == null ? 0 : day.toFixed(4),
|
||||
Years: x.posLevel == null ? 0 : (calDayDiff.days_diff / 365.2524).toFixed(4),
|
||||
Months: x.posLevel == null ? 0 : ((calDayDiff.days_diff / 30.4375) % 12).toFixed(4),
|
||||
Days: x.posLevel == null ? 0 : (calDayDiff.days_diff % 30.4375).toFixed(4),
|
||||
};
|
||||
data.push(mapData);
|
||||
// data.push(_mapData);
|
||||
await this.levelOfficerRepo.save(mapData);
|
||||
}
|
||||
await this.levelOfficerRepo.save(data);
|
||||
// await this.levelOfficerRepo.save(data);
|
||||
|
||||
return new HttpSuccess();
|
||||
}
|
||||
|
|
@ -226,12 +225,10 @@ export class ProfileSalaryController extends Controller {
|
|||
await this.levelEmployeeRepo.clear();
|
||||
const profile = await this.profileEmployeeRepo.find({ relations: ["posLevel", "posType"] });
|
||||
const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
|
||||
const baseCurrentDate = CURRENT_DATE[0].today;
|
||||
let _currentDate = CURRENT_DATE[0].today;
|
||||
for await (const x of profile) {
|
||||
// Use leave date if available and valid, otherwise use current date
|
||||
let _currentDate = baseCurrentDate;
|
||||
if (x?.isLeave && x.leaveDate) {
|
||||
_currentDate = Extension.toDateOnlyString(x.leaveDate);
|
||||
if (x?.isLeave) {
|
||||
_currentDate = x.leaveDate ? Extension.toDateOnlyString(x.leaveDate) : _currentDate;
|
||||
}
|
||||
const positionLevel = await AppDataSource.query("CALL GetProfileEmployeeSalaryLevel(?, ?)", [
|
||||
x.id,
|
||||
|
|
@ -263,27 +260,26 @@ export class ProfileSalaryController extends Controller {
|
|||
},
|
||||
{ days_diff: 0, positionType: null, positionLevel: null, positionCee: null },
|
||||
);
|
||||
const { year, month, day } = calculateTenure(calDayDiff.days_diff);
|
||||
const mapData: any = {
|
||||
profileEmployeeId: x.id,
|
||||
positionType: calDayDiff.positionType,
|
||||
positionLevel: calDayDiff.positionLevel,
|
||||
positionCee: calDayDiff.positionCee,
|
||||
days_diff: calDayDiff.days_diff,
|
||||
Years: x.posLevel == null ? 0 : year.toFixed(4),
|
||||
Months: x.posLevel == null ? 0 : month.toFixed(4),
|
||||
Days: x.posLevel == null ? 0 : day.toFixed(4),
|
||||
Years: x.posLevel == null ? 0 : (calDayDiff.days_diff / 365.2524).toFixed(4),
|
||||
Months: x.posLevel == null ? 0 : ((calDayDiff.days_diff / 30.4375) % 12).toFixed(4),
|
||||
Days: x.posLevel == null ? 0 : (calDayDiff.days_diff % 30.4375).toFixed(4),
|
||||
};
|
||||
data.push(mapData);
|
||||
// data.push(_mapData);
|
||||
await this.levelEmployeeRepo.save(mapData);
|
||||
}
|
||||
await this.levelEmployeeRepo.save(data);
|
||||
// await this.levelEmployeeRepo.save(data);
|
||||
|
||||
return new HttpSuccess();
|
||||
}
|
||||
|
||||
@Get("TenurePositionExecutiveOfficer")
|
||||
public async cronjobTenureExecutivePositionOfficer() {
|
||||
let data: any = [];
|
||||
await this.positionExecutiveOfficerRepo.clear();
|
||||
const profile = await this.profileRepo.find();
|
||||
const orgRevision = await this.orgRevisionRepository.findOne({
|
||||
|
|
@ -294,12 +290,10 @@ export class ProfileSalaryController extends Controller {
|
|||
},
|
||||
});
|
||||
const CURRENT_DATE = await AppDataSource.query("SELECT CURRENT_DATE() as today");
|
||||
const baseCurrentDate = CURRENT_DATE[0].today;
|
||||
let _currentDate = CURRENT_DATE[0].today;
|
||||
for await (const x of profile) {
|
||||
// Use leave date if available and valid, otherwise use current date
|
||||
let _currentDate = baseCurrentDate;
|
||||
if (x?.isLeave && x.leaveDate) {
|
||||
_currentDate = Extension.toDateOnlyString(x.leaveDate);
|
||||
if (x?.isLeave) {
|
||||
_currentDate = x.leaveDate ? Extension.toDateOnlyString(x.leaveDate) : _currentDate;
|
||||
}
|
||||
const position = await this.positionRepo.findOne({
|
||||
where: {
|
||||
|
|
@ -337,18 +331,16 @@ export class ProfileSalaryController extends Controller {
|
|||
},
|
||||
{ days_diff: 0, positionExecutive: null },
|
||||
);
|
||||
const { year, month, day } = calculateTenure(calDayDiff.days_diff);
|
||||
const mapData: any = {
|
||||
profileId: x.id,
|
||||
positionExecutiveName: calDayDiff.positionExecutive,
|
||||
days_diff: calDayDiff.days_diff,
|
||||
Years: year.toFixed(4),
|
||||
Months: month.toFixed(4),
|
||||
Days: day.toFixed(4),
|
||||
Years: (calDayDiff.days_diff / 365.2524).toFixed(4),
|
||||
Months: ((calDayDiff.days_diff / 30.4375) % 12).toFixed(4),
|
||||
Days: (calDayDiff.days_diff % 30.4375).toFixed(4),
|
||||
};
|
||||
data.push(mapData);
|
||||
await this.positionExecutiveOfficerRepo.save(mapData);
|
||||
}
|
||||
await this.positionExecutiveOfficerRepo.save(data);
|
||||
return new HttpSuccess();
|
||||
}
|
||||
|
||||
|
|
@ -610,10 +602,10 @@ export class ProfileSalaryController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
// Recalculate year, month, and day
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -649,10 +641,10 @@ export class ProfileSalaryController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
// Recalculate year, month, and day
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -683,10 +675,10 @@ export class ProfileSalaryController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
// Recalculate year, month, and day
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -747,10 +739,10 @@ export class ProfileSalaryController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
// Recalculate year, month, and day
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -790,10 +782,10 @@ export class ProfileSalaryController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
// Recalculate year, month, and day
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -827,10 +819,10 @@ export class ProfileSalaryController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
// Recalculate year, month, and day
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import { Profile } from "../entities/Profile";
|
|||
import { In, LessThan, IsNull, MoreThan } from "typeorm";
|
||||
import permission from "../interfaces/permission";
|
||||
import { setLogDataDiff } from "../interfaces/utils";
|
||||
import { calculateTenure } from "../utils/tenure";
|
||||
import { Command } from "../entities/Command";
|
||||
import { OrgRoot } from "../entities/OrgRoot";
|
||||
import Extension from "../interfaces/extension";
|
||||
|
|
@ -176,10 +175,9 @@ export class ProfileSalaryEmployeeController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -213,10 +211,9 @@ export class ProfileSalaryEmployeeController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -269,10 +266,9 @@ export class ProfileSalaryEmployeeController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
@ -306,10 +302,9 @@ export class ProfileSalaryEmployeeController extends Controller {
|
|||
acc.push(existing);
|
||||
}
|
||||
|
||||
const { year, month, day } = calculateTenure(existing.days);
|
||||
existing.year = year;
|
||||
existing.month = month;
|
||||
existing.day = day;
|
||||
existing.year = Math.floor(existing.days / 365.2524);
|
||||
existing.month = Math.floor((existing.days / 30.4375) % 12);
|
||||
existing.day = Math.ceil(existing.days % 30.4375);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1433,10 +1433,10 @@ export class ProfileSalaryTempController extends Controller {
|
|||
profileEmployeeId: x.profileEmployeeId,
|
||||
dateStart: x.commandDateAffect,
|
||||
dateEnd: null,
|
||||
posNo: `${x.posNoAbb ?? ""} ${x.posNo ?? ""}`.trim(),
|
||||
posNo: `${x.posNoAbb} ${x.posNo}`,
|
||||
position: x.positionName,
|
||||
commandId: x.commandId,
|
||||
refCommandNo: [x.commandNo, x.commandYear].filter(Boolean).join("/") || undefined,
|
||||
refCommandNo: `${x.commandNo}/${x.commandYear}`,
|
||||
refCommandDate: x.commandDateAffect,
|
||||
status: false,
|
||||
isDeleted: false,
|
||||
|
|
@ -1456,7 +1456,7 @@ export class ProfileSalaryTempController extends Controller {
|
|||
dateStart: x.commandDateAffect,
|
||||
dateEnd: null,
|
||||
commandId: x.commandId,
|
||||
commandNo: [x.commandNo, x.commandYear].filter(Boolean).join("/") || undefined,
|
||||
commandNo: `${x.commandNo}/${x.commandYear}`,
|
||||
commandName: x.commandName ?? "ให้ช่วยราชการ",
|
||||
refCommandDate: x.commandDateSign,
|
||||
refId: x.refId,
|
||||
|
|
|
|||
|
|
@ -237,18 +237,11 @@ export class WorkflowController extends Controller {
|
|||
savedStates.find((state) => state.id === so.stateId && state.order === 1),
|
||||
);
|
||||
|
||||
// add link sysName = REGISTRY_PROFILE or REGISTRY_PROFILE_EMP
|
||||
let notiLink = '';
|
||||
if (body.sysName === 'REGISTRY_PROFILE') {
|
||||
notiLink = `${process.env.VITE_URL_MGT}/registry-officer/request-edit/personal/${body.refId}`;
|
||||
} else if (body.sysName === 'REGISTRY_PROFILE_EMP') {
|
||||
notiLink = `${process.env.VITE_URL_MGT}/registry-employee/request-edit/personal/${body.refId}`;
|
||||
}
|
||||
const notificationReceivers = stateOperatorUsersToCreate
|
||||
.filter((user) => firstStateOperators.some((op) => op.operator === user.operator))
|
||||
.map((user) => ({
|
||||
receiverUserId: user.profileType === "OFFICER" ? user.profileId : user.profileEmployeeId,
|
||||
notiLink: notiLink,
|
||||
notiLink: "",
|
||||
}));
|
||||
|
||||
// ส่ง notification แบบ fire-and-forget
|
||||
|
|
|
|||
|
|
@ -140,54 +140,6 @@ export class Profile extends EntityBase {
|
|||
})
|
||||
posTypeId: string | null;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
comment: "สายงาน",
|
||||
length: 45,
|
||||
default: null,
|
||||
})
|
||||
positionField: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
comment: "ตำแหน่งทางการบริหาร",
|
||||
length: 255,
|
||||
default: null,
|
||||
})
|
||||
posExecutive?: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
comment: "ด้าน/สาขา",
|
||||
length: 255,
|
||||
default: null,
|
||||
})
|
||||
positionArea?: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
comment: "ด้านทางการบริหาร",
|
||||
length: 255,
|
||||
default: null,
|
||||
})
|
||||
positionExecutiveField?: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
comment: "เลขที่ตำแหน่ง",
|
||||
length: 255,
|
||||
default: null,
|
||||
})
|
||||
posMasterNo?: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
comment: "สังกัด",
|
||||
type: "text",
|
||||
default: null,
|
||||
})
|
||||
org?: string;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
length: 255,
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class AddPositionFieldsToProfile1776308026834 implements MigrationInterface {
|
||||
name = 'AddPositionFieldsToProfile1776308026834'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` ADD \`positionField\` varchar(45) NULL COMMENT 'สายงาน'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` ADD \`posExecutive\` varchar(255) NULL COMMENT 'ตำแหน่งทางการบริหาร'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` ADD \`positionArea\` varchar(255) NULL COMMENT 'ด้าน/สาขา'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` ADD \`positionExecutiveField\` varchar(255) NULL COMMENT 'ด้านทางการบริหาร'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` ADD \`posMasterNo\` varchar(255) NULL COMMENT 'เลขที่ตำแหน่ง'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` ADD \`org\` text NULL COMMENT 'สังกัด'`);
|
||||
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` ADD \`positionField\` varchar(45) NULL COMMENT 'สายงาน'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` ADD \`posExecutive\` varchar(255) NULL COMMENT 'ตำแหน่งทางการบริหาร'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` ADD \`positionArea\` varchar(255) NULL COMMENT 'ด้าน/สาขา'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` ADD \`positionExecutiveField\` varchar(255) NULL COMMENT 'ด้านทางการบริหาร'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` ADD \`posMasterNo\` varchar(255) NULL COMMENT 'เลขที่ตำแหน่ง'`);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` ADD \`org\` text NULL COMMENT 'สังกัด'`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` DROP COLUMN \`org\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` DROP COLUMN \`posMasterNo\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` DROP COLUMN \`positionExecutiveField\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` DROP COLUMN \`positionArea\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` DROP COLUMN \`posExecutive\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profileHistory\` DROP COLUMN \`positionField\``);
|
||||
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` DROP COLUMN \`org\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` DROP COLUMN \`posMasterNo\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` DROP COLUMN \`positionExecutiveField\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` DROP COLUMN \`positionArea\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` DROP COLUMN \`posExecutive\``);
|
||||
await queryRunner.query(`ALTER TABLE \`profile\` DROP COLUMN \`positionField\``);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
import { AppDataSource } from "../database/data-source";
|
||||
import { AuthRoleAttr } from "../entities/AuthRoleAttr";
|
||||
import { PosMasterAct } from "../entities/PosMasterAct";
|
||||
|
||||
export interface ActingPositionData {
|
||||
isAct: boolean;
|
||||
posMasterActs: Array<{
|
||||
privilege: string | null;
|
||||
posNo: string | null;
|
||||
rootDnaId: string | null;
|
||||
child1DnaId: string | null;
|
||||
child2DnaId: string | null;
|
||||
child3DnaId: string | null;
|
||||
child4DnaId: string | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface ActingPositionWithPrivilegeData extends ActingPositionData {
|
||||
privilege?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service สำหรับจัดการข้อมูลตำแหน่งที่รักษาการและ privilege
|
||||
*/
|
||||
export class ActingPositionService {
|
||||
private posMasterActRepo = AppDataSource.getRepository(PosMasterAct);
|
||||
private authRoleAttrRepo = AppDataSource.getRepository(AuthRoleAttr);
|
||||
|
||||
/**
|
||||
* ดึงข้อมูลตำแหน่งที่รักษาการและ privilege
|
||||
*
|
||||
* @param profileId - ID ของ profile ที่ต้องการตรวจสอบ
|
||||
* @param orgRevisionId - ID ของ orgRevision ปัจจุบัน
|
||||
* @param action - Action ที่ต้องการตรวจสอบสิทธิ์ (CREATE, DELETE, GET, LIST, UPDATE)
|
||||
* @param system - System ID ที่ต้องการตรวจสอบสิทธิ์ (authSysId)
|
||||
* @returns ข้อมูลตำแหน่งที่รักษาการและ privilege
|
||||
*/
|
||||
async getActingPositionsWithPrivilege(
|
||||
profileId: string,
|
||||
orgRevisionId: string | undefined,
|
||||
action?: string,
|
||||
system?: string
|
||||
): Promise<ActingPositionWithPrivilegeData> {
|
||||
// ดึงข้อมูล posMasterAct โดย join กับ posMaster (ตำแหน่งที่ถูกรักษาการ)
|
||||
const posMasterActs = await this.posMasterActRepo
|
||||
.createQueryBuilder("posMasterAct")
|
||||
.leftJoinAndSelect("posMasterAct.posMaster", "posMaster")
|
||||
.addSelect([
|
||||
"posMaster.authRoleId", // เพิ่มการดึง authRoleId จากตำแหน่งที่ถูกรักษาการ
|
||||
"posMaster.posMasterNo", // เพิ่มการดึงเลขที่ตำแหน่ง
|
||||
"posMaster.posMasterNoPrefix", // เพิ่มการดึง prefix ของเลขที่ตำแหน่ง
|
||||
"posMaster.posMasterNoSuffix" // เพิ่มการดึง suffix ของเลขที่ตำแหน่ง
|
||||
])
|
||||
.leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
|
||||
.leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
|
||||
.leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
|
||||
.leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
|
||||
.leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
|
||||
.leftJoinAndSelect("posMaster.orgRevision", "orgRevision")
|
||||
.leftJoinAndSelect("posMasterAct.posMasterChild", "posMasterChild")
|
||||
.leftJoinAndSelect("posMasterChild.current_holder", "profileChild")
|
||||
.where("profileChild.id = :profileId", { profileId })
|
||||
.andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId })
|
||||
.andWhere("orgRevision.orgRevisionIsCurrent = true")
|
||||
.andWhere("orgRevision.orgRevisionIsDraft = false")
|
||||
.getMany();
|
||||
|
||||
if (posMasterActs.length === 0) {
|
||||
return {
|
||||
isAct: false,
|
||||
posMasterActs: [],
|
||||
};
|
||||
}
|
||||
|
||||
// วนลูปแต่ละ posMasterAct เพื่อดึง privilege ของตำแหน่งที่รักษาการ
|
||||
const posMasterActsResponse = await Promise.all(
|
||||
posMasterActs.map(async (act) => {
|
||||
let privilege: string | null = null;
|
||||
let privileges: Record<string, string> = {};
|
||||
|
||||
if (act.posMaster?.authRoleId) {
|
||||
// ถ้าระบุ action และ system มา ให้ดึงเฉพาะ privilege ของระบบนั้นๆ
|
||||
if (action && system) {
|
||||
const roleAttr = await this.authRoleAttrRepo
|
||||
.createQueryBuilder("authRoleAttr")
|
||||
.select(["authRoleAttr.attrPrivilege", "authRoleAttr.attrIsCreate", "authRoleAttr.attrIsDelete", "authRoleAttr.attrIsGet", "authRoleAttr.attrIsList", "authRoleAttr.attrIsUpdate"])
|
||||
.where("authRoleAttr.authRoleId = :authRoleId", {
|
||||
authRoleId: act.posMaster.authRoleId,
|
||||
})
|
||||
.andWhere("authRoleAttr.authSysId = :system", { system })
|
||||
.getOne();
|
||||
|
||||
if (roleAttr) {
|
||||
// ตรวจสอบสิทธิ์ตาม action
|
||||
let hasPermission = false;
|
||||
const actionUpper = action.trim().toUpperCase();
|
||||
|
||||
switch (actionUpper) {
|
||||
case "CREATE":
|
||||
hasPermission = roleAttr.attrIsCreate;
|
||||
break;
|
||||
case "DELETE":
|
||||
hasPermission = roleAttr.attrIsDelete;
|
||||
break;
|
||||
case "GET":
|
||||
hasPermission = roleAttr.attrIsGet;
|
||||
break;
|
||||
case "LIST":
|
||||
hasPermission = roleAttr.attrIsList;
|
||||
break;
|
||||
case "UPDATE":
|
||||
hasPermission = roleAttr.attrIsUpdate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasPermission) {
|
||||
privilege = roleAttr.attrPrivilege;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ดึงข้อมูล AuthRoleAttr สำหรับทุกระบบ
|
||||
const roleAttrs = await this.authRoleAttrRepo
|
||||
.createQueryBuilder("authRoleAttr")
|
||||
.select(["authRoleAttr.authSysId", "authRoleAttr.attrPrivilege"])
|
||||
.where("authRoleAttr.authRoleId = :authRoleId", {
|
||||
authRoleId: act.posMaster.authRoleId,
|
||||
})
|
||||
.getMany();
|
||||
|
||||
privileges = roleAttrs.reduce((acc, attr) => {
|
||||
acc[attr.authSysId] = attr.attrPrivilege;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
}
|
||||
}
|
||||
|
||||
// จัดรูปแบบเลขที่ตำแหน่งตามรูปแบบ shortName ที่ใช้ในระบบ
|
||||
const holder = act.posMaster;
|
||||
const posNo = !holder
|
||||
? null
|
||||
: holder.orgChild4 != null
|
||||
? `${holder.orgChild4.orgChild4ShortName} ${holder.posMasterNo}`
|
||||
: holder.orgChild3 != null
|
||||
? `${holder.orgChild3.orgChild3ShortName} ${holder.posMasterNo}`
|
||||
: holder.orgChild2 != null
|
||||
? `${holder.orgChild2.orgChild2ShortName} ${holder.posMasterNo}`
|
||||
: holder.orgChild1 != null
|
||||
? `${holder.orgChild1.orgChild1ShortName} ${holder.posMasterNo}`
|
||||
: holder.orgRoot != null
|
||||
? `${holder.orgRoot.orgRootShortName} ${holder.posMasterNo}`
|
||||
: null;
|
||||
|
||||
return {
|
||||
posNo: posNo,
|
||||
privilege: action && system ? privilege : JSON.stringify(privileges),
|
||||
rootDnaId: act.posMaster?.orgRoot?.ancestorDNA ?? null,
|
||||
child1DnaId: act.posMaster?.orgChild1?.ancestorDNA ?? null,
|
||||
child2DnaId: act.posMaster?.orgChild2?.ancestorDNA ?? null,
|
||||
child3DnaId: act.posMaster?.orgChild3?.ancestorDNA ?? null,
|
||||
child4DnaId: act.posMaster?.orgChild4?.ancestorDNA ?? null,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// ถ้าระบุ action และ system มา ให้ดึง privilege ของตำแหน่งแรก
|
||||
let specificPrivilege: string | null = null;
|
||||
if (action && system && posMasterActsResponse.length > 0) {
|
||||
specificPrivilege = posMasterActsResponse[0].privilege;
|
||||
}
|
||||
|
||||
const response: ActingPositionWithPrivilegeData = {
|
||||
isAct: true,
|
||||
posMasterActs: posMasterActsResponse,
|
||||
};
|
||||
|
||||
// ถ้าระบุ action และ system มา ให้เพิ่ม privilege เข้าไปใน response ด้วย
|
||||
if (action && system) {
|
||||
response.privilege = specificPrivilege ?? null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
export const actingPositionService = new ActingPositionService();
|
||||
|
|
@ -3,7 +3,6 @@ import { AppDataSource } from "../database/data-source";
|
|||
import { Command } from "../entities/Command";
|
||||
import { chunkArray, commandTypePath } from "../interfaces/utils";
|
||||
import CallAPI from "../interfaces/call-api";
|
||||
import { getPosMasterNo, getOrgFullName } from "../utils/org-formatting";
|
||||
import HttpError from "../interfaces/http-error";
|
||||
import HttpStatusCode from "../interfaces/http-status";
|
||||
import { PosMaster } from "../entities/PosMaster";
|
||||
|
|
@ -652,33 +651,23 @@ async function handler_org(msg: amqp.ConsumeMessage): Promise<boolean> {
|
|||
await posMasterAssignRepository.save(newAssigns);
|
||||
}
|
||||
|
||||
// อัพเดท org และ posMasterNo ตลอดไม่ต้องดัก isSit
|
||||
if (item.next_holderId != null) {
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (item.next_holderId != null && !item.isSit) {
|
||||
const profile = await repoProfile.findOne({
|
||||
where: { id: item.next_holderId == null ? "" : item.next_holderId },
|
||||
});
|
||||
if (profile != null) {
|
||||
profile.posMasterNo = getPosMasterNo(item) ?? _null;
|
||||
profile.org = getOrgFullName(item) ?? _null;
|
||||
|
||||
// ถ้าไม่ใช่ตำแหน่งนั่งทับ (isSit = false) ถึงจะอัพเดทตำแหน่งในทะเบียนประวัติ
|
||||
if (!item.isSit && item.positions.length > 0) {
|
||||
let position = await item.positions.find((x) => x.positionIsSelected == true);
|
||||
if (profile != null && item.positions.length > 0) {
|
||||
let position = await item.positions.find((x) => x.positionIsSelected == true);
|
||||
if (position == null) {
|
||||
position = await item.positions.find((x) => x.posLevelId == profile?.posLevelId);
|
||||
if (position == null) {
|
||||
position = await item.positions.find((x) => x.posLevelId == profile?.posLevelId);
|
||||
if (position == null) {
|
||||
position = await item.positions.sort((a, b) => a.orderNo - b.orderNo)[0];
|
||||
}
|
||||
position = await item.positions.sort((a, b) => a.orderNo - b.orderNo)[0];
|
||||
}
|
||||
|
||||
profile.posLevelId = position?.posLevelId ?? _null;
|
||||
profile.posTypeId = position?.posTypeId ?? _null;
|
||||
profile.position = position?.positionName ?? _null;
|
||||
profile.positionField = position?.positionField ?? _null;
|
||||
profile.posExecutive = position?.posExecutive?.posExecutiveName ?? _null;
|
||||
profile.positionArea = position?.positionArea ?? _null;
|
||||
profile.positionExecutiveField = position?.positionExecutiveField ?? _null;
|
||||
}
|
||||
|
||||
profile.posLevelId = position?.posLevelId ?? _null;
|
||||
profile.posTypeId = position?.posTypeId ?? _null;
|
||||
profile.position = position?.positionName ?? _null;
|
||||
await repoProfile.save(profile);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,47 +68,3 @@ export function filterPosMasters(
|
|||
): PosMaster[] {
|
||||
return posMasters.filter((x) => x[childLevelIdKey] == null && x.isDirector === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* สร้าง orgShortName จาก posMaster (ต้อง load org relations มาก่อน)
|
||||
*/
|
||||
export function getOrgShortName(posMaster: PosMaster): string {
|
||||
if (posMaster.orgChild1Id === null) {
|
||||
return posMaster.orgRoot?.orgRootShortName ?? "";
|
||||
} else if (posMaster.orgChild2Id === null) {
|
||||
return posMaster.orgChild1?.orgChild1ShortName ?? "";
|
||||
} else if (posMaster.orgChild3Id === null) {
|
||||
return posMaster.orgChild2?.orgChild2ShortName ?? "";
|
||||
} else if (posMaster.orgChild4Id === null) {
|
||||
return posMaster.orgChild3?.orgChild3ShortName ?? "";
|
||||
} else {
|
||||
return posMaster.orgChild4?.orgChild4ShortName ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* สร้างชื่อสังกัดเต็ม จาก posMaster (join ด้วย \n)
|
||||
*/
|
||||
export function getOrgFullName(posMaster: PosMaster): string {
|
||||
const parts = [
|
||||
posMaster.orgChild4?.orgChild4Name,
|
||||
posMaster.orgChild3?.orgChild3Name,
|
||||
posMaster.orgChild2?.orgChild2Name,
|
||||
posMaster.orgChild1?.orgChild1Name,
|
||||
posMaster.orgRoot?.orgRootName,
|
||||
];
|
||||
return parts.filter((part) => part !== undefined && part !== null).join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* สร้างเลขที่ตำแหน่ง เช่น "กทม. กบ.1234ช"
|
||||
*/
|
||||
export function getPosMasterNo(posMaster: PosMaster): string {
|
||||
const orgShortName = getOrgShortName(posMaster);
|
||||
const parts = [
|
||||
posMaster.posMasterNoPrefix,
|
||||
posMaster.posMasterNo,
|
||||
posMaster.posMasterNoSuffix,
|
||||
].filter((part) => part !== null && part !== undefined);
|
||||
return `${orgShortName} ${parts.join('')}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* คำนวณอายุงานจากจำนวนวันรวม
|
||||
* @param totalDays จำนวนวันรวม
|
||||
* @returns { year, month, day } ปี เดือน วัน
|
||||
*/
|
||||
export function calculateTenure(totalDays: number) {
|
||||
// 1. แปลงเป็น year เต็ม
|
||||
const year = Math.floor(totalDays / 365.2524);
|
||||
|
||||
// 2. วันที่เหลือหลังหัก year ออก
|
||||
const remainAfterYear = totalDays - year * 365.2524;
|
||||
|
||||
// 3. แปลงเป็น month เต็ม
|
||||
const month = Math.floor(remainAfterYear / 30.4375);
|
||||
|
||||
// 4. วันที่เหลือหลังหัก month ออก
|
||||
const remainAfterMonth = remainAfterYear - month * 30.4375;
|
||||
|
||||
// 5. ปัดลง เฉพาะวัน
|
||||
const day = Math.floor(remainAfterMonth);
|
||||
|
||||
return { year, month, day };
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue