hrms-api-org/src/interfaces/utils.ts
Adisak 8a649086f7
All checks were successful
Build & Deploy on Dev / build (push) Successful in 48s
fix: #2239
2026-02-06 14:55:59 +07:00

755 lines
No EOL
24 KiB
TypeScript

import { OrgRevision } from "../entities/OrgRevision";
import { AppDataSource } from "../database/data-source";
import { PosMaster } from "../entities/PosMaster";
import { Position } from "../entities/Position";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { EmployeePosition } from "../entities/EmployeePosition";
import { In, IsNull, MoreThan, Not } from "typeorm";
import { RequestWithUser } from "../middlewares/user";
import { Command } from "../entities/Command";
import { ProfileSalary } from "../entities/ProfileSalary";
import { Profile } from "../entities/Profile";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import { CommandRecive } from "../entities/CommandRecive";
import { PosMasterAct } from "../entities/PosMasterAct";
export function calculateAge(start: Date, end = new Date()) {
if (start.getTime() > end.getTime()) return null;
let year = end.getFullYear() - start.getFullYear();
let month = end.getMonth() - start.getMonth();
let day = end.getDate() - start.getDate();
// if (month < 0) {
// month += 12;
// year -= 1;
// }
// if (day < 0) {
// month -= 1;
// day =
// new Date(start.getFullYear(), start.getMonth(), 0).getDate() -
// start.getDate() +
// end.getDate();
// }
if (day < 0) {
month -= 1;
day += new Date(end.getFullYear(), end.getMonth(), 0).getDate();
}
if (month < 0) {
month += 12;
year -= 1;
}
return { year, month, day };
}
export async function calculateGovAge(profileId: string, type: string, bkk?: boolean) {
// type = OFFICER , EMPLOYEE
const isEmployee = type === "EMPLOYEE";
// const records = await AppDataSource.getRepository(ProfileSalary).find({
// where: {
// [isEmployee ? "profileEmployeeId" : "profileId"]: profileId,
// },
// select: ["commandDateAffect", "dateGovernment", "isGovernment"],
// order: { order: "ASC" },
// });
// if (!records || records.length === 0) {
// return null;
// }
let endDateFristRec: any = null;
endDateFristRec = await AppDataSource.getRepository(ProfileSalary).findOne({
where: {
[isEmployee ? "profileEmployeeId" : "profileId"]: profileId,
dateGovernment: Not(IsNull()),
isGovernment: false,
},
select: ["dateGovernment", "order"],
order: { order: "ASC" },
});
// console.log("endDateFristRec", endDateFristRec.dateGovernment);
const calculateDuration = (startDate: any, endDate: any, inclusive = false) => {
if (inclusive) {
endDate = new Date(endDate.getTime() + 86400000); // +1 วัน
}
let years = endDate.getFullYear() - startDate.getFullYear();
let months = endDate.getMonth() - startDate.getMonth();
let days = endDate.getDate() - startDate.getDate();
if (days < 0) {
months--;
const lastMonthDays = new Date(endDate.getFullYear(), endDate.getMonth(), 0).getDate();
days += lastMonthDays;
}
if (months < 0) {
months += 12;
years--;
}
return { years, months, days };
};
let profile: any;
profile = await AppDataSource.getRepository(Profile).findOne({
where: {
id: profileId,
},
});
if (isEmployee) {
profile = await AppDataSource.getRepository(ProfileEmployee).findOne({
where: {
id: profileId,
},
});
}
// const firstStartDate = new Date(records[0].date);
const firstStartDate = !bkk
? profile?.dateAppoint ? profile?.dateAppoint : new Date()
: profile?.dateStart ? profile?.dateStart : new Date();
const firstEndDate = endDateFristRec ? new Date(endDateFristRec.dateGovernment) : new Date();
// console.log("firstStartDate1", firstStartDate);
// console.log("firstEndDate1", firstEndDate);
const {
years: totalYears1,
months: totalMonths1,
days: totalDays1,
} = calculateDuration(firstStartDate, firstEndDate);
const records_middle = await AppDataSource.getRepository(ProfileSalary).find({
where: {
[isEmployee ? "profileEmployeeId" : "profileId"]: profileId,
order: MoreThan(endDateFristRec?.order),
dateGovernment: Not(IsNull()),
},
select: ["dateGovernment", "isGovernment"],
order: { order: "ASC" },
});
//ถ้าไม่มีเข้าออกราชการหลายครั้ง
if (!records_middle || records_middle.length === 0) {
return { year: totalYears1, month: totalMonths1, day: totalDays1 };
}
let totalYears2 = 0,
totalMonths2 = 0,
totalDays2 = 0;
// case ที่เข้าออกราชการหลายครั้ง
for (let i = 0; i < records_middle.length; i++) {
const current = records_middle[i];
const next = records_middle[i + 1];
// นับเฉพาะช่วงที่เป็นราชการ
if (current.isGovernment === true) {
const startDate = new Date(current.dateGovernment);
const endDate = next ? new Date(next.dateGovernment) : new Date();
const { years, months, days } = calculateDuration(startDate, endDate);
totalYears2 += years;
totalMonths2 += months;
totalDays2 += days;
// console.log(`✔ นับช่วง ${startDate.toISOString()} → ${endDate.toISOString()} ได้ ${years} ปี ${months} เดือน ${days} วัน`);
}
// else {
// console.log(`❌ ไม่รวมช่วง ${current.dateGovernment} เพราะ isGovernment = false`);
// }
}
//ตั้งแต่วันที่กลับมารับราขการไปจนถึงรวมถึงวันที่ปัจจุบัน
const adjustTotal = (years: number, months: number, days: number) => {
const daysInThisMonth = new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0).getDate();
if (days >= daysInThisMonth) {
months += Math.floor(days / daysInThisMonth);
days %= daysInThisMonth;
}
if (months >= 12) {
years += Math.floor(months / 12);
months %= 12;
}
return { years, months, days };
};
let sumYears = totalYears1 + totalYears2;
let sumMonths = totalMonths1 + totalMonths2;
let sumDays = totalDays1 + totalDays2;
// console.log("totalYears1", totalYears1);
// console.log("totalMonths1", totalMonths1);
// console.log("totalDays1", totalDays1);
// console.log("totalYears2", totalYears2);
// console.log("totalMonths2", totalMonths2);
// console.log("totalDays2", totalDays2);
// console.log("sumYears", sumYears);
// console.log("sumMonths", sumMonths);
// console.log("sumDays", sumDays);
const finalAdjusted = adjustTotal(sumYears, sumMonths, sumDays);
return {
year: finalAdjusted.years,
month: finalAdjusted.months,
day: finalAdjusted.days,
};
}
export function calculateRetireDate(birthDate: Date) {
// let _birthDate = birthDate;
// _birthDate.setFullYear(_birthDate.getFullYear() + 60); var year = d.getFullYear();
var d = birthDate;
var year = d.getFullYear();
var month = d.getMonth();
var day = d.getDate();
var c = new Date(year + 60, month, day - 1);
return c;
}
export function calculateRetireLaw(birthDate: Date) {
let dd = birthDate.getDate();
let mm = birthDate.getMonth();
let yy = birthDate.getFullYear();
let flag = true;
switch (mm) {
case 9:
if (dd >= 2) flag = false;
break;
case 10:
flag = false;
break;
case 11:
flag = false;
break;
}
if (flag == true) return new Date(`${yy + 60}-09-30T00:00:00.000+07:00`);
return new Date(`${yy + 61}-09-30T00:00:00.000+07:00`);
}
export function calculateRetireYear(birthDate: Date) {
let dd = birthDate.getDate();
let mm = birthDate.getMonth();
let yy = birthDate.getFullYear();
let flag = true;
switch (mm) {
case 10:
if (dd >= 2) flag = false;
break;
case 11:
break;
case 12:
break;
}
if (flag) return yy + 60;
return yy + 61;
}
export async function removeProfileInOrganize(profileId: string, type: string) {
const currentRevision = await AppDataSource.getRepository(OrgRevision)
.createQueryBuilder("orgRevision")
.where("orgRevision.orgRevisionIsDraft = false")
.andWhere("orgRevision.orgRevisionIsCurrent = true")
.getOne();
const draftRevision = await AppDataSource.getRepository(OrgRevision)
.createQueryBuilder("orgRevision")
.where("orgRevision.orgRevisionIsDraft = true")
.andWhere("orgRevision.orgRevisionIsCurrent = false")
.getOne();
if (!currentRevision && !draftRevision) {
return;
}
if (type === "OFFICER") {
const findProfileInposMaster = await AppDataSource.getRepository(PosMaster)
.createQueryBuilder("posMaster")
.where("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: currentRevision?.id })
.andWhere("posMaster.current_holderId = :profileId", { profileId })
.getOne();
await AppDataSource.getRepository(PosMaster)
.createQueryBuilder()
.update(PosMaster)
.set({ current_holderId: null })
.where("id = :id", { id: findProfileInposMaster?.id })
.execute();
const findProfileInposMasterDraft = await AppDataSource.getRepository(PosMaster)
.createQueryBuilder("posMaster")
.where("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: draftRevision?.id })
.andWhere("posMaster.next_holderId = :profileId", { profileId })
.getOne();
await AppDataSource.getRepository(PosMaster)
.createQueryBuilder()
.update(PosMaster)
.set({ next_holderId: null })
.where("id = :id", { id: findProfileInposMasterDraft?.id })
.execute();
if (!findProfileInposMaster && !findProfileInposMasterDraft) {
return;
}
const findPosition = await AppDataSource.getRepository(Position)
.createQueryBuilder("position")
.where("position.posMasterId = :posMasterId", { posMasterId: findProfileInposMaster?.id })
.getMany();
if (!findPosition) {
return;
}
await AppDataSource.getRepository(Position)
.createQueryBuilder()
.update(Position)
.set({ positionIsSelected: false })
.where("id IN (:...ids)", { ids: findPosition.map((item) => item.id) })
.execute();
}
if (type === "EMPLOYEE") {
const findProfileInEmpPosMaster = await AppDataSource.getRepository(EmployeePosMaster)
.createQueryBuilder("employeePosMaster")
.where("employeePosMaster.orgRevisionId = :orgRevisionId", {
orgRevisionId: currentRevision?.id,
})
.andWhere("employeePosMaster.current_holderId = :profileId", { profileId })
.getOne();
await AppDataSource.getRepository(EmployeePosMaster)
.createQueryBuilder()
.update(EmployeePosMaster)
.set({ current_holderId: null })
.where("id = :id", { id: findProfileInEmpPosMaster?.id })
.execute();
if (!findProfileInEmpPosMaster) {
return;
}
const findEmpPosition = await AppDataSource.getRepository(EmployeePosition)
.createQueryBuilder("employeePosition")
.where("employeePosition.posMasterId = :posMasterId", {
posMasterId: findProfileInEmpPosMaster?.id,
})
.getMany();
if (!findEmpPosition) {
return;
}
await AppDataSource.getRepository(EmployeePosition)
.createQueryBuilder()
.update(EmployeePosition)
.set({ positionIsSelected: false })
.where("id IN (:...ids)", { ids: findEmpPosition.map((item) => item.id) })
.execute();
}
}
export async function removePostMasterAct(profileId: string) {
const currentRevision = await AppDataSource.getRepository(OrgRevision)
.createQueryBuilder("orgRevision")
.where("orgRevision.orgRevisionIsDraft = false")
.andWhere("orgRevision.orgRevisionIsCurrent = true")
.getOne();
if (!currentRevision) {
return;
}
const findProfileInposMaster = await AppDataSource.getRepository(PosMaster)
.createQueryBuilder("posMaster")
.where("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: currentRevision?.id })
.andWhere("posMaster.current_holderId = :profileId", { profileId })
.getOne();
if (!findProfileInposMaster) {
return;
}
const posMasterAct = await AppDataSource.getRepository(PosMasterAct)
.createQueryBuilder("posMasterAct")
.where("posMasterAct.posMasterChildId = :posMasterChildId", { posMasterChildId: findProfileInposMaster.id })
.getMany();
await AppDataSource.getRepository(PosMasterAct).remove(posMasterAct);
}
export async function checkReturnCommandType(commandId: string) {
const commandRepository = AppDataSource.getRepository(Command);
const _type = await commandRepository.findOne({
where: {
id: commandId,
},
relations: ["commandType"],
});
if (!["C-PM-08", "C-PM-09"].includes(String(_type?.commandType.code))) {
return false;
}
return true;
}
export async function checkExceptCommandType(commandId: string) {
const commandRepository = AppDataSource.getRepository(Command);
const commandReciveRepository = AppDataSource.getRepository(CommandRecive);
const _type = await commandRepository.findOne({
where: {
id: commandId,
},
relations: ["commandType"],
});
if (!["C-PM-25", "C-PM-26"].includes(String(_type?.commandType.code))) {
return { status: false, LeaveType: null, leaveRemark: null };
}
const _commandRecive = await commandReciveRepository.findOne({
where: { commandId: commandId },
});
let _leaveType: string = "";
switch (String(_type?.commandType.code)) {
case "C-PM-25": {
_leaveType = "DISCIPLINE_SUSPEND"; //คำสั่งพักจากราชการ
break;
}
case "C-PM-26": {
_leaveType = "DISCIPLINE_TEMP_SUSPEND"; //คำสั่งให้ออกจากราชการไว้ก่อน
break;
}
default: {
_leaveType = "";
}
}
return {
status: true,
LeaveType: _leaveType,
leaveRemark: _commandRecive ? _commandRecive.remarkVertical : null,
};
}
export async function checkCommandType(commandId: string) {
const commandRepository = AppDataSource.getRepository(Command);
const commandReciveRepository = AppDataSource.getRepository(CommandRecive);
const _type = await commandRepository.findOne({
where: {
id: commandId,
},
relations: ["commandType", "commandRecives"],
});
if (
![
"C-PM-12",
"C-PM-13",
"C-PM-17",
"C-PM-18",
"C-PM-23",
"C-PM-19",
"C-PM-20",
"C-PM-43",
].includes(String(_type?.commandType.code))
) {
// return false;
return { status: false, LeaveType: null, leaveRemark: null, retireTypeName: null };
}
// return true;
const _commandRecive = await commandReciveRepository.findOne({
where: { commandId: commandId },
});
let _leaveType: string = "";
let _retireTypeName: string = ""; //อิงตามเหตุผลการพ้นจากราชการ ข้อมูลทะเบียนประวัติผู้พ้นจากราชการ
switch (String(_type?.commandType.code)) {
case "C-PM-12": {
_leaveType = "PROBATION_REPORT";
_retireTypeName = "ผลการทดลองฯ ต่ำกว่ามาตรฐานที่กำหนด"
break;
}
case "C-PM-13": {
_leaveType = "PLACEMENT_TRANSFER";
_retireTypeName = "โอนออก";
break;
}
case "C-PM-17": {
_leaveType = "RETIRE_RESIGN";
_retireTypeName = "ลาออกจากราชการ";
break;
}
case "C-PM-18": {
_leaveType = "RETIRE_OUT";
_retireTypeName = "ให้ออกจากราชการ";
break;
}
case "C-PM-19": {
_leaveType = "DISCIPLINE_RESULT_REMOVE";
_retireTypeName = "ปลดออกจากราชการ";
break;
}
case "C-PM-20": {
_leaveType = "DISCIPLINE_RESULT_DISMISS";
_retireTypeName = "ไล่ออกจากราชการ";
break;
}
case "C-PM-23": {
_leaveType = "RETIRE_RESIGN_EMP";
_retireTypeName = "ลาออกจากราชการ";
break;
}
case "C-PM-43": {
_leaveType = "RETIRE_OUT_EMP";
_retireTypeName = "ให้ออกจากราชการ";
break;
}
default: {
_leaveType = "";
_retireTypeName = "";
}
}
return {
status: true,
LeaveType: _leaveType,
leaveRemark: _commandRecive ? _commandRecive.remarkVertical : null,
retireTypeName: _retireTypeName ? _retireTypeName : null
};
}
//logs
export type DataDiff = {
before: any;
after: any;
};
export type LogSequence = {
action: string;
status: "success" | "error";
description: string;
query?: any;
request?: {
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
url?: string;
payload?: string;
response?: string;
};
};
export function setLogDataDiff(req: RequestWithUser, data: DataDiff) {
// Check if data.before and data.after are valid objects
if (
data.before &&
typeof data.before === "object" &&
data.after &&
typeof data.after === "object"
) {
req.app.locals.logData.dataDiff = {
before: JSON.stringify(data.before),
after: JSON.stringify(data.after),
};
} else {
console.error("Invalid data provided: both before and after must be valid objects.");
}
}
export function addLogSequence(req: RequestWithUser, data: LogSequence) {
if (!req?.app?.locals?.logData?.sequence) {
req.app.locals.logData.sequence = [];
}
req.app.locals.logData.sequence = req.app.locals.logData.sequence.concat(data);
}
export function editLogSequence(req: RequestWithUser, index: number, data: LogSequence) {
req.app.locals.logData.sequence[index] = data;
}
export async function checkQueueInProgress(queueName: string) {
const axios = require('axios');
// console.log("Checking queue in progress");
const res = await axios.get(`${process.env.RABBIT_API_URL}/api/queues/%2F/${queueName}`, {
auth: { username: process.env.RABBIT_USER, password: process.env.RABBIT_PASS },
});
const q = res.data;
// console.log(`Queue "${queueName}" has:`);
// console.log(` - ${q.messages_ready} messages ready`);
// console.log(` - ${q.messages_unacknowledged} messages in progress (unacked)`);
if (q.messages_unacknowledged > 0) {
return true;
}
return false;
}
export function chunkArray(array: any, size: number) {
const result = [];
for (let i = 0; i < array.length; i += size) {
result.push(array.slice(i, i + size));
}
return result;
}
export async function PayloadSendNoti(commandId: string) {
if (!commandId)
return "";
const commandRepository = AppDataSource.getRepository(Command);
const _command = await commandRepository.findOne({
where: {
id: commandId,
},
relations: ["commandType"],
});
if (!_command || !_command.commandType)
return "";
const _payload = {
name: _command && _command.commandType
? `คำสั่ง${_command.commandType.name}`
: "",
url: `${process.env.API_URL}/salary/file/ระบบออกคำสั่ง/คำสั่ง/${commandId}/คำสั่ง`,
isReport: true,
isTemplate: false,
}
let attachments = {}
if (_command.commandType.isUploadAttachment === true) {
const _payloadAtt = {
name: _command && _command.commandType
? `เอกสารแนบท้ายคำสั่ง${_command.commandType.name}`
: "",
url: `${process.env.API_URL}/salary/file/ระบบออกคำสั่ง/แนบท้าย/${commandId}/แนบท้าย`,
isReport: true,
isTemplate: false,
}
attachments = {
attachments: [_payload, _payloadAtt]
};
}
else {
attachments = {
attachments: [_payload]
};
}
return JSON.stringify(attachments);
}
export function commandTypePath(commandCode: string): string | null {
switch (commandCode) {
case "C-PM-01":
return "/placement/recruit/report"; //
case "C-PM-02":
return "/placement/candidate/report"; //
case "C-PM-03":
return "/placement/appoint/report";
case "C-PM-04":
return "/placement/move/report";
case "C-PM-05":
return "/placement/appointment/appoint/report";
case "C-PM-06":
return "/placement/slip/report";
case "C-PM-07":
return "/placement/appointment/move/report";
case "C-PM-08":
return "/retirement/other/appoint/report";
case "C-PM-09":
return "/retirement/other/out/report";
case "C-PM-10":
return "/probation/report/command10/officer/report";
case "C-PM-11":
return "/probation/report/command11/officer/report"; //PROBATION
case "C-PM-12":
return "/probation/report/command12/officer/report"; //PROBATION
case "C-PM-13":
return "/placement/transfer/command/report";
case "C-PM-14":
return "/placement/receive/command/report";
case "C-PM-15":
return "/placement/officer/command/report";
case "C-PM-16":
return "/placement/repatriation/command/report";
case "C-PM-17":
return "/retirement/resign/command/report";
case "C-PM-18":
return "/retirement/out/command/report";
case "C-PM-19":
return "/discipline/result/command19/report";
case "C-PM-20":
return "/discipline/result/command20/report";
case "C-PM-21":
return "/org/command/command21/employee/report"; //ORG
case "C-PM-22":
return "/placement/appointment/employee-appoint/report";
case "C-PM-23":
return "/retirement/resign-employee/command/report";
case "C-PM-24":
return "/placement/appointment/employee-move/report";
case "C-PM-25":
return "/discipline/result/command25/report";
case "C-PM-26":
return "/discipline/result/command26/report";
case "C-PM-27":
return "/discipline/result/command27/report";
case "C-PM-28":
return "/discipline/result/command28/report";
case "C-PM-29":
return "/discipline/result/command29/report";
case "C-PM-30":
return "/discipline/result/command30/report";
case "C-PM-31":
return "/discipline/result/command31/report";
case "C-PM-32":
return "/discipline/result/command32/report";
case "C-PM-33":
return "/salary/report/command33/officer/report"; //SALARY
case "C-PM-34":
return "/salary/report/command34/officer/report"; //SALARY
case "C-PM-35":
return "/salary/report/command35/officer/report"; //SALARY
case "C-PM-36":
return "/salary/report/command36/employee/report"; //SALARY
case "C-PM-37":
return "/salary/report/command37/employee/report"; //SALARY
case "C-PM-38":
return "/org/command/command38/officer/report"; //ORG
case "C-PM-39":
return "/placement/appointment/slip/report";
case "C-PM-40":
return "/org/command/command40/officer/report"; //ORG
case "C-PM-41":
return "/retirement/resign/leave-cancel/report";
case "C-PM-42":
return "/retirement/resign-employee/leave-cancel/report";
case "C-PM-43":
return "/retirement/out/command/report";
case "C-PM-45":
return "/salary/report/command35/officer/report"; //SALARY
case "C-PM-46":
return "/salary/report/command36/employee/report"; //SALARY
case "C-PM-47":
return "/placement/appointment/gazette/report";
default:
return null;
}
}
export function resolveNodeLevel(data: any) {
if (data.child4DnaId) return 4;
if (data.child3DnaId) return 3;
if (data.child2DnaId) return 2;
if (data.child1DnaId) return 1;
if (data.rootDnaId) return 0;
return null;
}
export function resolveNodeId(data: any) {
return (
data.child4DnaId ??
data.child3DnaId ??
data.child2DnaId ??
data.child1DnaId ??
data.rootDnaId ??
null
);
}