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) { // 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 = profile?.dateAppoint ? profile?.dateAppoint : 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 }; } // return true; const _commandRecive = await commandReciveRepository.findOne({ where: { commandId: commandId }, }); let _leaveType: string = ""; switch (String(_type?.commandType.code)) { case "C-PM-12": { _leaveType = "PROBATION_REPORT"; break; } case "C-PM-13": { _leaveType = "PLACEMENT_TRANSFER"; break; } case "C-PM-17": { _leaveType = "RETIRE_RESIGN"; break; } case "C-PM-18": { _leaveType = "RETIRE_OUT"; break; } case "C-PM-19": { _leaveType = "DISCIPLINE_RESULT_REMOVE"; break; } case "C-PM-20": { _leaveType = "DISCIPLINE_RESULT_DISMISS"; break; } case "C-PM-23": { _leaveType = "RETIRE_RESIGN_EMP"; break; } case "C-PM-43": { _leaveType = "RETIRE_OUT_EMP"; break; } default: { _leaveType = ""; } } return { status: true, LeaveType: _leaveType, leaveRemark: _commandRecive ? _commandRecive.remarkVertical : 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; } }