Linear Flow (RetirementService) #224
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m9s
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m9s
This commit is contained in:
parent
616ccf9e64
commit
d33e818ce8
4 changed files with 989 additions and 708 deletions
|
|
@ -108,6 +108,8 @@ import { ExecuteOfficerProfileService } from "../services/ExecuteOfficerProfileS
|
||||||
import { ExecuteSalaryService } from "../services/ExecuteSalaryService";
|
import { ExecuteSalaryService } from "../services/ExecuteSalaryService";
|
||||||
import { ExecuteSalaryCurrentService } from "../services/ExecuteSalaryCurrentService";
|
import { ExecuteSalaryCurrentService } from "../services/ExecuteSalaryCurrentService";
|
||||||
import { ExecuteSalaryEmployeeCurrentService } from "../services/ExecuteSalaryEmployeeCurrentService";
|
import { ExecuteSalaryEmployeeCurrentService } from "../services/ExecuteSalaryEmployeeCurrentService";
|
||||||
|
import { ExecuteSalaryLeaveService } from "../services/ExecuteSalaryLeaveService";
|
||||||
|
import { ExecuteSalaryEmployeeLeaveService } from "../services/ExecuteSalaryEmployeeLeaveService";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
const REDIS_HOST = process.env.REDIS_HOST;
|
const REDIS_HOST = process.env.REDIS_HOST;
|
||||||
const REDIS_PORT = process.env.REDIS_PORT;
|
const REDIS_PORT = process.env.REDIS_PORT;
|
||||||
|
|
@ -3748,6 +3750,14 @@ export class CommandController extends Controller {
|
||||||
return new HttpSuccess();
|
return new HttpSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API สร้าง ProfileSalary ข้าราชการ + handle leave/กลับเข้าราชการ
|
||||||
|
*
|
||||||
|
* Thin wrapper — เรียก ExecuteSalaryLeaveService (C-PM-08, 09, 17, 18, 41, 48)
|
||||||
|
* ทั้ง endpoint นี้และ consumer ใน rabbitmq ใช้ service ตัวเดียวกัน (Linear Flow)
|
||||||
|
*
|
||||||
|
* @summary API สร้าง ProfileSalary ข้าราชการ + leave/กลับเข้าราชการ
|
||||||
|
*/
|
||||||
@Post("excexute/salary-leave")
|
@Post("excexute/salary-leave")
|
||||||
public async newSalaryAndUpdateLeave(
|
public async newSalaryAndUpdateLeave(
|
||||||
@Request() req: RequestWithUser,
|
@Request() req: RequestWithUser,
|
||||||
|
|
@ -3804,496 +3814,10 @@ export class CommandController extends Controller {
|
||||||
}[];
|
}[];
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const roleKeycloak = await this.roleKeycloakRepo.findOne({
|
await new ExecuteSalaryLeaveService().executeSalaryLeave(body.data, {
|
||||||
where: { name: Like("USER") },
|
user: { sub: req.user.sub, name: req.user.name },
|
||||||
|
req,
|
||||||
});
|
});
|
||||||
let _posNumCodeSit: string = "";
|
|
||||||
let _posNumCodeSitAbb: string = "";
|
|
||||||
const _command = await this.commandRepository.findOne({
|
|
||||||
relations: ["commandType"],
|
|
||||||
where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
|
|
||||||
});
|
|
||||||
if (_command) {
|
|
||||||
if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
|
|
||||||
const orgRootDeputy = await this.orgRootRepository.findOne({
|
|
||||||
where: {
|
|
||||||
isDeputy: true,
|
|
||||||
orgRevision: {
|
|
||||||
orgRevisionIsCurrent: true,
|
|
||||||
orgRevisionIsDraft: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ["orgRevision"],
|
|
||||||
});
|
|
||||||
_posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
|
|
||||||
_posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
|
|
||||||
} else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
|
|
||||||
_posNumCodeSit = "กรุงเทพมหานคร";
|
|
||||||
_posNumCodeSitAbb = "กทม.";
|
|
||||||
} else {
|
|
||||||
let _profileAdmin = await this.profileRepository.findOne({
|
|
||||||
where: {
|
|
||||||
keycloak: _command?.createdUserId.toString(),
|
|
||||||
current_holders: {
|
|
||||||
orgRevision: {
|
|
||||||
orgRevisionIsCurrent: true,
|
|
||||||
orgRevisionIsDraft: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
|
|
||||||
});
|
|
||||||
_posNumCodeSit =
|
|
||||||
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
|
|
||||||
"";
|
|
||||||
_posNumCodeSitAbb =
|
|
||||||
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
|
|
||||||
.orgRootShortName ?? "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const today = new Date().setHours(0, 0, 0, 0);
|
|
||||||
await Promise.all(
|
|
||||||
body.data.map(async (item) => {
|
|
||||||
const profile = await this.profileRepository.findOne({
|
|
||||||
where: { id: item.profileId },
|
|
||||||
relations: {
|
|
||||||
roleKeycloaks: true
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!profile) {
|
|
||||||
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
|
|
||||||
}
|
|
||||||
//ลบตำแหน่งที่รักษาการแทน
|
|
||||||
const code = _command?.commandType?.code;
|
|
||||||
if (code && ["C-PM-08", "C-PM-17", "C-PM-18", "C-PM-48"].includes(code)) {
|
|
||||||
removePostMasterAct(profile.id);
|
|
||||||
}
|
|
||||||
//ออกคำสั่งยกเลิกลาออก ลบเฉพาะคนที่ขอยกเลิกลาออก
|
|
||||||
else if (item.resignId && code && ["C-PM-41"].includes(code)) {
|
|
||||||
const commandResign = await this.commandReciveRepository.findOne({
|
|
||||||
where: { refId: item.resignId },
|
|
||||||
relations: { command: true },
|
|
||||||
});
|
|
||||||
const executeDate = commandResign
|
|
||||||
? new Date(commandResign.command.commandExcecuteDate).setHours(0, 0, 0, 0)
|
|
||||||
: today;
|
|
||||||
if (
|
|
||||||
commandResign &&
|
|
||||||
_command.status !== "REPORTED" &&
|
|
||||||
(_command.status !== "WAITING" || today < executeDate)
|
|
||||||
) {
|
|
||||||
await reOrderCommandRecivesAndDelete(commandResign!.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _commandYear = item.commandYear;
|
|
||||||
if (item.commandYear) {
|
|
||||||
_commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
|
|
||||||
}
|
|
||||||
const returnWork = await checkReturnCommandType(String(item.commandId));
|
|
||||||
const dest_item = await this.salaryRepo.findOne({
|
|
||||||
where: { profileId: item.profileId },
|
|
||||||
order: { order: "DESC" },
|
|
||||||
});
|
|
||||||
const before = null;
|
|
||||||
const data = new ProfileSalary();
|
|
||||||
data.posNumCodeSit = _posNumCodeSit;
|
|
||||||
data.posNumCodeSitAbb = _posNumCodeSitAbb;
|
|
||||||
data.dateGovernment = item.commandDateAffect ?? new Date();
|
|
||||||
data.order = dest_item == null ? 1 : dest_item.order + 1;
|
|
||||||
const meta = {
|
|
||||||
createdUserId: req.user.sub,
|
|
||||||
createdFullName: req.user.name,
|
|
||||||
lastUpdateUserId: req.user.sub,
|
|
||||||
lastUpdateFullName: req.user.name,
|
|
||||||
createdAt: new Date(),
|
|
||||||
lastUpdatedAt: new Date(),
|
|
||||||
};
|
|
||||||
if (!returnWork) {
|
|
||||||
Object.assign(data, { ...item, ...meta });
|
|
||||||
const history = new ProfileSalaryHistory();
|
|
||||||
Object.assign(history, { ...data, id: undefined });
|
|
||||||
await this.salaryRepo.save(data, { data: req });
|
|
||||||
setLogDataDiff(req, { before, after: data });
|
|
||||||
history.profileSalaryId = data.id;
|
|
||||||
await this.salaryHistoryRepo.save(history, { data: req });
|
|
||||||
}
|
|
||||||
const _null: any = null;
|
|
||||||
profile.isLeave = item.isLeave;
|
|
||||||
profile.leaveReason = item.leaveReason ?? _null;
|
|
||||||
profile.dateLeave = item.dateLeave ?? _null;
|
|
||||||
profile.lastUpdateUserId = req.user.sub;
|
|
||||||
profile.lastUpdateFullName = req.user.name;
|
|
||||||
profile.lastUpdatedAt = new Date();
|
|
||||||
const clearProfile = await checkCommandType(String(item.commandId));
|
|
||||||
|
|
||||||
//ปั๊มประวัติก่อนลบตำแหน่ง
|
|
||||||
const curRevision = await this.orgRevisionRepo.findOne({
|
|
||||||
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
||||||
});
|
|
||||||
let orgRootRef = null;
|
|
||||||
let orgChild1Ref = null;
|
|
||||||
let orgChild2Ref = null;
|
|
||||||
let orgChild3Ref = null;
|
|
||||||
let orgChild4Ref = null;
|
|
||||||
if (curRevision) {
|
|
||||||
const curPosMaster = await this.posMasterRepository.findOne({
|
|
||||||
where: {
|
|
||||||
current_holderId: profile.id,
|
|
||||||
orgRevisionId: curRevision.id,
|
|
||||||
},
|
|
||||||
relations: {
|
|
||||||
orgRoot: true,
|
|
||||||
orgChild1: true,
|
|
||||||
orgChild2: true,
|
|
||||||
orgChild3: true,
|
|
||||||
orgChild4: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
orgRootRef = curPosMaster?.orgRoot ?? null;
|
|
||||||
orgChild1Ref = curPosMaster?.orgChild1 ?? null;
|
|
||||||
orgChild2Ref = curPosMaster?.orgChild2 ?? null;
|
|
||||||
orgChild3Ref = curPosMaster?.orgChild3 ?? null;
|
|
||||||
orgChild4Ref = curPosMaster?.orgChild4 ?? null;
|
|
||||||
if (curPosMaster && clearProfile.LeaveType != "RETIRE_OUT_EMP") {
|
|
||||||
await CreatePosMasterHistoryOfficer(curPosMaster.id, req, "DELETE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//ลบตำแหน่ง
|
|
||||||
if (item.isLeave == true) {
|
|
||||||
await removeProfileInOrganize(profile.id, "OFFICER");
|
|
||||||
}
|
|
||||||
if (clearProfile.status) {
|
|
||||||
if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
|
|
||||||
const delUserKeycloak = await deleteUser(profile.keycloak);
|
|
||||||
if (delUserKeycloak) {
|
|
||||||
// Task #228
|
|
||||||
// profile.keycloak = _null;
|
|
||||||
profile.roleKeycloaks = [];
|
|
||||||
profile.isActive = false;
|
|
||||||
profile.isDelete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
profile.leaveCommandId = item.commandId ?? _null;
|
|
||||||
profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
|
|
||||||
profile.leaveRemark = clearProfile.leaveRemark ?? _null;
|
|
||||||
profile.leaveDate = item.commandDateAffect ?? _null;
|
|
||||||
profile.leaveType = clearProfile.LeaveType ?? _null;
|
|
||||||
//ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
|
|
||||||
// profile.position = _null;
|
|
||||||
// profile.posTypeId = _null;
|
|
||||||
// profile.posLevelId = _null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.isGovernment == true) {
|
|
||||||
if (returnWork) {
|
|
||||||
//ปลดตำแหน่งเดิมที่ไม่ถูกปลดออกจากกิ่งครั้งเมื่อออกคำสั่งพักราชการหรือออกราชการไว้
|
|
||||||
await removeProfileInOrganize(profile.id, "OFFICER");
|
|
||||||
//ปั๊มตำแหน่งใหม่
|
|
||||||
// หา posMaster และเช็ค orgRevisionIsCurrent
|
|
||||||
let posMaster = await this.posMasterRepository.findOne({
|
|
||||||
where: { id: item.posmasterId?.toString() },
|
|
||||||
relations: {
|
|
||||||
orgRevision: true,
|
|
||||||
orgRoot: true,
|
|
||||||
orgChild1: true,
|
|
||||||
orgChild2: true,
|
|
||||||
orgChild3: true,
|
|
||||||
orgChild4: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่
|
|
||||||
const isCurrent =
|
|
||||||
posMaster?.orgRevision?.orgRevisionIsCurrent === true &&
|
|
||||||
posMaster?.orgRevision?.orgRevisionIsDraft === false;
|
|
||||||
|
|
||||||
// ถ้าไม่อยู่ในโครงสร้างปัจจุบัน ให้หาตัวใหม่จาก ancestorDNA
|
|
||||||
if (!isCurrent && posMaster?.ancestorDNA) {
|
|
||||||
posMaster = await this.posMasterRepository.findOne({
|
|
||||||
where: {
|
|
||||||
ancestorDNA: posMaster.ancestorDNA,
|
|
||||||
orgRevision: {
|
|
||||||
orgRevisionIsCurrent: true,
|
|
||||||
orgRevisionIsDraft: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: {
|
|
||||||
orgRevision: true,
|
|
||||||
orgRoot: true,
|
|
||||||
orgChild1: true,
|
|
||||||
orgChild2: true,
|
|
||||||
orgChild3: true,
|
|
||||||
orgChild4: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (posMaster) {
|
|
||||||
const checkPosition = await this.positionRepository.find({
|
|
||||||
where: {
|
|
||||||
posMasterId: posMaster.id,
|
|
||||||
positionIsSelected: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (checkPosition.length > 0) {
|
|
||||||
const clearPosition = checkPosition.map((positions) => ({
|
|
||||||
...positions,
|
|
||||||
positionIsSelected: false,
|
|
||||||
}));
|
|
||||||
await this.positionRepository.save(clearPosition);
|
|
||||||
}
|
|
||||||
posMaster.current_holderId = profile.id;
|
|
||||||
posMaster.lastUpdatedAt = new Date();
|
|
||||||
// posMaster.conditionReason = _null;
|
|
||||||
// posMaster.isCondition = false;
|
|
||||||
await this.posMasterRepository.save(posMaster);
|
|
||||||
|
|
||||||
// Match position ตามลำดับ priority:
|
|
||||||
// Condition 1: match จาก positionId
|
|
||||||
// Condition 2: match 7 ฟิลด์ (positionName, posTypeId, posLevelId, positionField, positionArea, positionExecutiveField, posExecutiveId)
|
|
||||||
// Condition 3: match 3 ฟิลด์ (positionName, posTypeId, posLevelId)
|
|
||||||
// Fallback: เลือก position แรกใน posMaster
|
|
||||||
|
|
||||||
let positionNew: Position | null = null;
|
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════
|
|
||||||
// CONDITION 1: เช็คจาก positionId ตรง
|
|
||||||
// ═══════════════════════════════════════════════════════════
|
|
||||||
if (item.positionId) {
|
|
||||||
const positionById = await this.positionRepository.findOne({
|
|
||||||
where: {
|
|
||||||
id: item.positionId,
|
|
||||||
posMasterId: posMaster.id, // ต้องอยู่ใน posMaster ที่ถูกต้อง
|
|
||||||
},
|
|
||||||
relations: ["posExecutive"],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (positionById) {
|
|
||||||
positionNew = positionById;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════
|
|
||||||
// CONDITION 2: Match 7 ฟิลด์ (ถ้า Condition 1 ไม่ match)
|
|
||||||
// ═══════════════════════════════════════════════════════════
|
|
||||||
if (!positionNew && item.positionNameNew && item.positionTypeNew && item.positionLevelNew) {
|
|
||||||
// สร้าง where clause แบบ dynamic - ใส่เฉพาะฟิลด์ที่มีค่า
|
|
||||||
const whereCondition: any = {
|
|
||||||
posMasterId: posMaster.id,
|
|
||||||
positionName: item.positionNameNew,
|
|
||||||
posTypeId: item.positionTypeNew,
|
|
||||||
posLevelId: item.positionLevelNew,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (item.positionField) {
|
|
||||||
whereCondition.positionField = item.positionField;
|
|
||||||
}
|
|
||||||
if (item.posExecutiveId) {
|
|
||||||
whereCondition.posExecutiveId = item.posExecutiveId;
|
|
||||||
}
|
|
||||||
if (item.positionExecutiveField) {
|
|
||||||
whereCondition.positionExecutiveField = item.positionExecutiveField;
|
|
||||||
}
|
|
||||||
if (item.positionArea) {
|
|
||||||
whereCondition.positionArea = item.positionArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
const positionBy7Fields = await this.positionRepository.findOne({
|
|
||||||
where: whereCondition,
|
|
||||||
relations: ["posExecutive"],
|
|
||||||
order: { orderNo: "ASC" }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (positionBy7Fields) {
|
|
||||||
positionNew = positionBy7Fields;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════
|
|
||||||
// CONDITION 3: Match 3 ฟิลด์ (ถ้า Condition 2 ไม่ match)
|
|
||||||
// ═══════════════════════════════════════════════════════════
|
|
||||||
if (!positionNew && item.positionNameNew && item.positionTypeNew && item.positionLevelNew) {
|
|
||||||
const positionBy3Fields = await this.positionRepository.findOne({
|
|
||||||
where: {
|
|
||||||
posMasterId: posMaster.id,
|
|
||||||
positionName: item.positionNameNew,
|
|
||||||
posTypeId: item.positionTypeNew,
|
|
||||||
posLevelId: item.positionLevelNew,
|
|
||||||
},
|
|
||||||
relations: ["posExecutive"],
|
|
||||||
order: { orderNo: "ASC" }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (positionBy3Fields) {
|
|
||||||
positionNew = positionBy3Fields;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // FALLBACK: เลือก position แรก (ถ้าไม่เจอทั้ง 2 condition)
|
|
||||||
// if (!positionNew) {
|
|
||||||
// const fallbackPositions = await this.positionRepository.find({
|
|
||||||
// where: {
|
|
||||||
// posMasterId: posMaster.id,
|
|
||||||
// },
|
|
||||||
// relations: ["posExecutive"],
|
|
||||||
// order: {
|
|
||||||
// orderNo: "ASC",
|
|
||||||
// },
|
|
||||||
// take: 1,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (fallbackPositions.length > 0) {
|
|
||||||
// positionNew = fallbackPositions[0];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (positionNew) {
|
|
||||||
positionNew.positionIsSelected = true;
|
|
||||||
await this.positionRepository.save(positionNew, { data: req });
|
|
||||||
}
|
|
||||||
await CreatePosMasterHistoryOfficer(posMaster.id, req);
|
|
||||||
profile.posMasterNo = getPosMasterNo(posMaster);
|
|
||||||
profile.org = getOrgFullName(posMaster);
|
|
||||||
}
|
|
||||||
const newMapProfileSalary = {
|
|
||||||
profileId: profile.id,
|
|
||||||
commandId: item.commandId,
|
|
||||||
positionName: item.positionNameNew ?? null,
|
|
||||||
positionType: item.posTypeNameNew ?? null,
|
|
||||||
positionLevel: item.posLevelNameNew ?? null,
|
|
||||||
amount: item.amount ? item.amount : null,
|
|
||||||
positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
|
|
||||||
amountSpecial: item.amountSpecial ? item.amountSpecial : null,
|
|
||||||
mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
|
|
||||||
posNo: item.posNoNew,
|
|
||||||
posNoAbb: item.posNoAbbNew,
|
|
||||||
orgRoot: item.orgRootNew,
|
|
||||||
orgChild1: item.orgChild1New,
|
|
||||||
orgChild2: item.orgChild2New,
|
|
||||||
orgChild3: item.orgChild3New,
|
|
||||||
orgChild4: item.orgChild4New,
|
|
||||||
isGovernment: item.isGovernment,
|
|
||||||
commandNo: item.commandNo,
|
|
||||||
commandYear: item.commandYear,
|
|
||||||
commandDateAffect: item.commandDateAffect,
|
|
||||||
commandDateSign: item.commandDateSign,
|
|
||||||
commandCode: item.commandCode,
|
|
||||||
commandName: item.commandName,
|
|
||||||
remark: item.remark,
|
|
||||||
};
|
|
||||||
Object.assign(data, { ...newMapProfileSalary, ...meta });
|
|
||||||
const history = new ProfileSalaryHistory();
|
|
||||||
Object.assign(history, { ...data, id: undefined });
|
|
||||||
await this.salaryRepo.save(data);
|
|
||||||
history.profileSalaryId = data.id;
|
|
||||||
await this.salaryHistoryRepo.save(history);
|
|
||||||
profile.leaveReason = _null;
|
|
||||||
profile.leaveCommandId = _null;
|
|
||||||
profile.leaveCommandNo = _null;
|
|
||||||
profile.leaveRemark = _null;
|
|
||||||
profile.leaveDate = _null;
|
|
||||||
profile.leaveType = _null;
|
|
||||||
profile.position = item.positionNameNew ?? _null;
|
|
||||||
profile.posTypeId = item.positionTypeNew ?? _null;
|
|
||||||
profile.posLevelId = item.positionLevelNew ?? _null;
|
|
||||||
}
|
|
||||||
let userKeycloakId;
|
|
||||||
const checkUser = await getUserByUsername(profile.citizenId);
|
|
||||||
//ถ้ายังไม่มี user keycloak ให้สร้างใหม่
|
|
||||||
if (checkUser.length == 0) {
|
|
||||||
let password = profile.citizenId;
|
|
||||||
if (profile.birthDate != null) {
|
|
||||||
// const gregorianYear = profile.birthDate.getFullYear() + 543;
|
|
||||||
|
|
||||||
// const formattedDate =
|
|
||||||
// profile.birthDate.toISOString().slice(8, 10) +
|
|
||||||
// profile.birthDate.toISOString().slice(5, 7) +
|
|
||||||
// gregorianYear;
|
|
||||||
// password = formattedDate;
|
|
||||||
const _date = new Date(profile.birthDate.toDateString())
|
|
||||||
.getDate()
|
|
||||||
.toString()
|
|
||||||
.padStart(2, "0");
|
|
||||||
const _month = (new Date(profile.birthDate.toDateString()).getMonth() + 1)
|
|
||||||
.toString()
|
|
||||||
.padStart(2, "0");
|
|
||||||
const _year = new Date(profile.birthDate.toDateString()).getFullYear() + 543;
|
|
||||||
password = `${_date}${_month}${_year}`;
|
|
||||||
}
|
|
||||||
// กรอง "." ออกจาก firstName ก่อนส่งไป keycloak
|
|
||||||
const sanitizedFirstName = profile.firstName?.replace(/\./g, "") ?? "";
|
|
||||||
userKeycloakId = await createUser(profile.citizenId, password, {
|
|
||||||
firstName: sanitizedFirstName,
|
|
||||||
lastName: profile.lastName,
|
|
||||||
});
|
|
||||||
const list = await getRoles();
|
|
||||||
let result = false;
|
|
||||||
if (Array.isArray(list) && userKeycloakId) {
|
|
||||||
result = await addUserRoles(
|
|
||||||
userKeycloakId,
|
|
||||||
list
|
|
||||||
.filter((v) => v.name === "USER")
|
|
||||||
.map((x) => ({
|
|
||||||
id: x.id,
|
|
||||||
name: x.name,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
|
|
||||||
profile.keycloak =
|
|
||||||
userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : "";
|
|
||||||
}
|
|
||||||
//ถ้ามีอยู่แล้วให้ใช้อันเดิม
|
|
||||||
else {
|
|
||||||
const rolesData = await getRoleMappings(checkUser[0].id);
|
|
||||||
if (rolesData) {
|
|
||||||
const _roleKeycloak = await this.roleKeycloakRepo.find({
|
|
||||||
where: { name: In(rolesData.map((x: any) => x.name)) },
|
|
||||||
});
|
|
||||||
profile.roleKeycloaks =
|
|
||||||
_roleKeycloak && _roleKeycloak.length > 0 ? _roleKeycloak : [];
|
|
||||||
}
|
|
||||||
profile.keycloak = checkUser[0].id;
|
|
||||||
}
|
|
||||||
profile.amount = item.amount ?? _null;
|
|
||||||
profile.amountSpecial = item.amountSpecial ?? _null;
|
|
||||||
profile.isActive = true;
|
|
||||||
profile.isDelete = false;
|
|
||||||
}
|
|
||||||
await this.profileRepository.save(profile);
|
|
||||||
|
|
||||||
// if (profile.id) {
|
|
||||||
// await this.keycloakAttributeService.clearOrgDnaAttributes(
|
|
||||||
// [profile.id],
|
|
||||||
// "PROFILE",
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// update user attribute in keycloak
|
|
||||||
await updateUserAttributes(profile.keycloak ?? "", {
|
|
||||||
profileId: [profile.id],
|
|
||||||
prefix: [profile.prefix || ""],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Task #2190
|
|
||||||
if (code && ["C-PM-17", "C-PM-18", "C-PM-48"].includes(code)) {
|
|
||||||
let organizeName = "";
|
|
||||||
if (orgRootRef) {
|
|
||||||
const names = [
|
|
||||||
orgChild4Ref?.orgChild4Name,
|
|
||||||
orgChild3Ref?.orgChild3Name,
|
|
||||||
orgChild2Ref?.orgChild2Name,
|
|
||||||
orgChild1Ref?.orgChild1Name,
|
|
||||||
orgRootRef?.orgRootName,
|
|
||||||
].filter(Boolean);
|
|
||||||
organizeName = names.join(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return new HttpSuccess();
|
return new HttpSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4337,223 +3861,13 @@ export class CommandController extends Controller {
|
||||||
}[];
|
}[];
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
let _posNumCodeSit: string = "";
|
await new ExecuteSalaryEmployeeLeaveService().executeSalaryEmployeeLeave(body.data, {
|
||||||
let _posNumCodeSitAbb: string = "";
|
user: { sub: req.user.sub, name: req.user.name },
|
||||||
const _command = await this.commandRepository.findOne({
|
req,
|
||||||
where: { id: body.data.find((x) => x.commandId)?.commandId ?? "" },
|
|
||||||
relations: { commandType: true },
|
|
||||||
});
|
});
|
||||||
if (_command) {
|
|
||||||
if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
|
|
||||||
const orgRootDeputy = await this.orgRootRepository.findOne({
|
|
||||||
where: {
|
|
||||||
isDeputy: true,
|
|
||||||
orgRevision: {
|
|
||||||
orgRevisionIsCurrent: true,
|
|
||||||
orgRevisionIsDraft: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ["orgRevision"],
|
|
||||||
});
|
|
||||||
_posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
|
|
||||||
_posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
|
|
||||||
} else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
|
|
||||||
_posNumCodeSit = "กรุงเทพมหานคร";
|
|
||||||
_posNumCodeSitAbb = "กทม.";
|
|
||||||
} else {
|
|
||||||
let _profileAdmin = await this.profileRepository.findOne({
|
|
||||||
where: {
|
|
||||||
keycloak: _command?.createdUserId.toString(),
|
|
||||||
current_holders: {
|
|
||||||
orgRevision: {
|
|
||||||
orgRevisionIsCurrent: true,
|
|
||||||
orgRevisionIsDraft: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
|
|
||||||
});
|
|
||||||
_posNumCodeSit =
|
|
||||||
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
|
|
||||||
"";
|
|
||||||
_posNumCodeSitAbb =
|
|
||||||
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
|
|
||||||
.orgRootShortName ?? "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const today = new Date().setHours(0, 0, 0, 0);
|
|
||||||
await Promise.all(
|
|
||||||
body.data.map(async (item) => {
|
|
||||||
const profile = await this.profileEmployeeRepository.findOne({
|
|
||||||
where: { id: item.profileId },
|
|
||||||
// relations: ["roleKeycloaks"],
|
|
||||||
relations: {
|
|
||||||
roleKeycloaks: true,
|
|
||||||
posType: true,
|
|
||||||
posLevel: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!profile) {
|
|
||||||
throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
|
|
||||||
}
|
|
||||||
const code = _command?.commandType?.code;
|
|
||||||
//ออกคำสั่งยกเลิกลาออก ลบเฉพาะคนที่ขอยกเลิกลาออก
|
|
||||||
if (item.resignId && code && ["C-PM-42"].includes(code)) {
|
|
||||||
const commandResign = await this.commandReciveRepository.findOne({
|
|
||||||
where: { refId: item.resignId },
|
|
||||||
relations: { command: true },
|
|
||||||
});
|
|
||||||
const executeDate = commandResign
|
|
||||||
? new Date(commandResign.command.commandExcecuteDate).setHours(0, 0, 0, 0)
|
|
||||||
: today;
|
|
||||||
if (
|
|
||||||
commandResign &&
|
|
||||||
_command.status !== "REPORTED" &&
|
|
||||||
(_command.status !== "WAITING" || today < executeDate)
|
|
||||||
) {
|
|
||||||
await reOrderCommandRecivesAndDelete(commandResign!.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _commandYear = item.commandYear;
|
|
||||||
if (item.commandYear) {
|
|
||||||
_commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
|
|
||||||
}
|
|
||||||
const dest_item = await this.salaryRepo.findOne({
|
|
||||||
where: { profileEmployeeId: item.profileId },
|
|
||||||
order: { order: "DESC" },
|
|
||||||
});
|
|
||||||
const before = null;
|
|
||||||
const data = new ProfileSalary();
|
|
||||||
data.posNumCodeSit = _posNumCodeSit;
|
|
||||||
data.posNumCodeSitAbb = _posNumCodeSitAbb;
|
|
||||||
const meta = {
|
|
||||||
order: dest_item == null ? 1 : dest_item.order + 1,
|
|
||||||
createdUserId: req.user.sub,
|
|
||||||
createdFullName: req.user.name,
|
|
||||||
lastUpdateUserId: req.user.sub,
|
|
||||||
lastUpdateFullName: req.user.name,
|
|
||||||
createdAt: new Date(),
|
|
||||||
lastUpdatedAt: new Date(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.assign(data, {
|
|
||||||
...item,
|
|
||||||
...meta,
|
|
||||||
profileEmployeeId: item.profileId,
|
|
||||||
profileId: undefined,
|
|
||||||
});
|
|
||||||
const history = new ProfileSalaryHistory();
|
|
||||||
Object.assign(history, { ...data, id: undefined });
|
|
||||||
data.dateGovernment = item.commandDateAffect ?? meta.createdAt;
|
|
||||||
await this.salaryRepo.save(data, { data: req });
|
|
||||||
setLogDataDiff(req, { before, after: data });
|
|
||||||
history.profileSalaryId = data.id;
|
|
||||||
await this.salaryHistoryRepo.save(history, { data: req });
|
|
||||||
|
|
||||||
const _null: any = null;
|
|
||||||
profile.isLeave = item.isLeave;
|
|
||||||
profile.leaveReason = item.leaveReason ?? _null;
|
|
||||||
profile.dateLeave = item.dateLeave ?? _null;
|
|
||||||
profile.lastUpdateUserId = req.user.sub;
|
|
||||||
profile.lastUpdateFullName = req.user.name;
|
|
||||||
profile.lastUpdatedAt = new Date();
|
|
||||||
// บันทึกประวัติก่อนลบตำแหน่ง
|
|
||||||
const clearProfile = await checkCommandType(String(item.commandId));
|
|
||||||
const curRevision = await this.orgRevisionRepo.findOne({
|
|
||||||
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
|
||||||
});
|
|
||||||
let orgRootRef = null;
|
|
||||||
let orgChild1Ref = null;
|
|
||||||
let orgChild2Ref = null;
|
|
||||||
let orgChild3Ref = null;
|
|
||||||
let orgChild4Ref = null;
|
|
||||||
if (curRevision) {
|
|
||||||
const curPosMaster = await this.employeePosMasterRepository.findOne({
|
|
||||||
where: {
|
|
||||||
current_holderId: profile.id,
|
|
||||||
orgRevisionId: curRevision.id,
|
|
||||||
},
|
|
||||||
relations: {
|
|
||||||
orgRoot: true,
|
|
||||||
orgChild1: true,
|
|
||||||
orgChild2: true,
|
|
||||||
orgChild3: true,
|
|
||||||
orgChild4: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
orgRootRef = curPosMaster?.orgRoot ?? null;
|
|
||||||
orgChild1Ref = curPosMaster?.orgChild1 ?? null;
|
|
||||||
orgChild2Ref = curPosMaster?.orgChild2 ?? null;
|
|
||||||
orgChild3Ref = curPosMaster?.orgChild3 ?? null;
|
|
||||||
orgChild4Ref = curPosMaster?.orgChild4 ?? null;
|
|
||||||
if (curPosMaster) {
|
|
||||||
await CreatePosMasterHistoryEmployee(curPosMaster.id, req, "DELETE");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ลบตำแหน่ง
|
|
||||||
if (item.isLeave == true) {
|
|
||||||
await removeProfileInOrganize(profile.id, "EMPLOYEE");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clearProfile.status) {
|
|
||||||
if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
|
|
||||||
const delUserKeycloak = await deleteUser(profile.keycloak);
|
|
||||||
if (delUserKeycloak) {
|
|
||||||
// Task #228
|
|
||||||
// profile.keycloak = _null;
|
|
||||||
profile.roleKeycloaks = [];
|
|
||||||
profile.isActive = false;
|
|
||||||
profile.isDelete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
profile.leaveCommandId = item.commandId ?? _null;
|
|
||||||
profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
|
|
||||||
profile.leaveRemark = clearProfile.leaveRemark ?? _null;
|
|
||||||
profile.leaveDate = item.commandDateAffect ?? _null;
|
|
||||||
profile.leaveType = clearProfile.LeaveType ?? _null;
|
|
||||||
//ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
|
|
||||||
// profile.position = _null;
|
|
||||||
// profile.posTypeId = _null;
|
|
||||||
// profile.posLevelId = _null;
|
|
||||||
}
|
|
||||||
await this.profileEmployeeRepository.save(profile);
|
|
||||||
|
|
||||||
// if (profile.id) {
|
|
||||||
// await this.keycloakAttributeService.clearOrgDnaAttributes(
|
|
||||||
// [profile.id],
|
|
||||||
// "PROFILE_EMPLOYEE",
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Task #2190
|
|
||||||
if (code && ["C-PM-23", "C-PM-43"].includes(code)) {
|
|
||||||
let organizeName = "";
|
|
||||||
if (orgRootRef) {
|
|
||||||
const names = [
|
|
||||||
orgChild4Ref?.orgChild4Name,
|
|
||||||
orgChild3Ref?.orgChild3Name,
|
|
||||||
orgChild2Ref?.orgChild2Name,
|
|
||||||
orgChild1Ref?.orgChild1Name,
|
|
||||||
orgRootRef?.orgRootName,
|
|
||||||
].filter(Boolean);
|
|
||||||
organizeName = names.join(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return new HttpSuccess();
|
return new HttpSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* API สร้าง ProfileSalary ข้าราชการ + handle leave/ออกจากราชการ/ช่วยราชการ
|
|
||||||
*
|
|
||||||
* Thin wrapper — เรียก ExecuteSalaryService (C-PM-13, 15, 16)
|
|
||||||
* ทั้ง endpoint นี้และ consumer ใน rabbitmq ใช้ service ตัวเดียวกัน (Linear Flow)
|
|
||||||
*
|
|
||||||
* @summary API สร้าง ProfileSalary ข้าราชการ (leave/โอน/ช่วยราชการ)
|
|
||||||
*/
|
|
||||||
@Post("excexute/salary")
|
@Post("excexute/salary")
|
||||||
public async newSalaryAndUpdate(
|
public async newSalaryAndUpdate(
|
||||||
@Request() req: RequestWithUser,
|
@Request() req: RequestWithUser,
|
||||||
|
|
|
||||||
321
src/services/ExecuteSalaryEmployeeLeaveService.ts
Normal file
321
src/services/ExecuteSalaryEmployeeLeaveService.ts
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
import { Double } from "typeorm";
|
||||||
|
import { AppDataSource } from "../database/data-source";
|
||||||
|
import HttpError from "../interfaces/http-error";
|
||||||
|
import HttpStatus from "../interfaces/http-status";
|
||||||
|
import { Profile } from "../entities/Profile";
|
||||||
|
import { ProfileEmployee } from "../entities/ProfileEmployee";
|
||||||
|
import { ProfileSalary } from "../entities/ProfileSalary";
|
||||||
|
import { ProfileSalaryHistory } from "../entities/ProfileSalaryHistory";
|
||||||
|
import { OrgRoot } from "../entities/OrgRoot";
|
||||||
|
import { OrgRevision } from "../entities/OrgRevision";
|
||||||
|
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
|
||||||
|
import { CommandRecive } from "../entities/CommandRecive";
|
||||||
|
import { Command } from "../entities/Command";
|
||||||
|
import { checkCommandType, removeProfileInOrganize, setLogDataDiff } from "../interfaces/utils";
|
||||||
|
import { reOrderCommandRecivesAndDelete } from "./CommandService";
|
||||||
|
import { CreatePosMasterHistoryEmployee } from "./PositionService";
|
||||||
|
import { deleteUser } from "../keycloak";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input: ข้อมูล 1 คนสำหรับ endpoint excexute/salary-employee-leave
|
||||||
|
* (C-PM-23, 42, 43 — ลาออก/ยกเลิกลาออก/กลับเข้าราชการ ของลูกจ้าง)
|
||||||
|
*/
|
||||||
|
export interface SalaryEmployeeLeaveItem {
|
||||||
|
profileId: string;
|
||||||
|
amount?: Double | null;
|
||||||
|
amountSpecial?: Double | null;
|
||||||
|
positionSalaryAmount?: Double | null;
|
||||||
|
mouthSalaryAmount?: Double | null;
|
||||||
|
positionType: string | null;
|
||||||
|
positionLevel: string | null;
|
||||||
|
isLeave: boolean;
|
||||||
|
leaveReason?: string | null;
|
||||||
|
dateLeave?: Date | string | null;
|
||||||
|
isGovernment?: boolean | null;
|
||||||
|
commandId?: string | null;
|
||||||
|
orgRoot?: string | null;
|
||||||
|
orgChild1?: string | null;
|
||||||
|
orgChild2?: string | null;
|
||||||
|
orgChild3?: string | null;
|
||||||
|
orgChild4?: string | null;
|
||||||
|
positionExecutive?: string | null;
|
||||||
|
positionExecutiveField?: string | null;
|
||||||
|
positionArea?: string | null;
|
||||||
|
commandNo: string | null;
|
||||||
|
commandYear: number | null;
|
||||||
|
posNo: string | null;
|
||||||
|
posNoAbb: string | null;
|
||||||
|
commandDateAffect?: Date | string | null;
|
||||||
|
commandDateSign?: Date | string | null;
|
||||||
|
positionName: string | null;
|
||||||
|
commandCode?: string | null;
|
||||||
|
commandName?: string | null;
|
||||||
|
remark: string | null;
|
||||||
|
resignId: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context สำหรับ audit/log
|
||||||
|
*/
|
||||||
|
export interface SalaryEmployeeLeaveExecutionContext {
|
||||||
|
user: { sub: string; name: string };
|
||||||
|
req?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service สำหรับสร้าง ProfileSalary ลูกจ้าง + handle leave/กลับเข้าราชการ
|
||||||
|
*
|
||||||
|
* ใช้กับ commandType: C-PM-23, 42, 43
|
||||||
|
*
|
||||||
|
* - endpoint /org/command/excexute/salary-employee-leave เรียกผ่าน service นี้ (thin wrapper)
|
||||||
|
* - consumer ใน rabbitmq handler เรียกผ่าน service นี้โดยตรง (Linear Flow)
|
||||||
|
*
|
||||||
|
* Behavior ทั้งหมด preserve จาก CommandController.newSalaryEmployeeAndUpdateLeave ต้นฉบับ
|
||||||
|
*/
|
||||||
|
export class ExecuteSalaryEmployeeLeaveService {
|
||||||
|
private commandRepository = AppDataSource.getRepository(Command);
|
||||||
|
private commandReciveRepository = AppDataSource.getRepository(CommandRecive);
|
||||||
|
private profileRepository = AppDataSource.getRepository(Profile);
|
||||||
|
private profileEmployeeRepository = AppDataSource.getRepository(ProfileEmployee);
|
||||||
|
private salaryRepo = AppDataSource.getRepository(ProfileSalary);
|
||||||
|
private salaryHistoryRepo = AppDataSource.getRepository(ProfileSalaryHistory);
|
||||||
|
private employeePosMasterRepository = AppDataSource.getRepository(EmployeePosMaster);
|
||||||
|
private orgRootRepository = AppDataSource.getRepository(OrgRoot);
|
||||||
|
private orgRevisionRepo = AppDataSource.getRepository(OrgRevision);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ประมวลผลสร้าง ProfileSalary + handle leave ของลูกจ้าง
|
||||||
|
*/
|
||||||
|
async executeSalaryEmployeeLeave(
|
||||||
|
data: SalaryEmployeeLeaveItem[],
|
||||||
|
ctx: SalaryEmployeeLeaveExecutionContext,
|
||||||
|
): Promise<void> {
|
||||||
|
console.log("[ExecuteSalaryEmployeeLeaveService] Starting executeSalaryEmployeeLeave");
|
||||||
|
console.log("[ExecuteSalaryEmployeeLeaveService] Request body count:", data?.length);
|
||||||
|
|
||||||
|
const req = ctx.req;
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Normalize date fields (ผ่าน handler จะได้ string → ต้องแปลงเป็น Date)
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
const toDate = (v: any): Date | null => {
|
||||||
|
if (v == null || v === "") return null;
|
||||||
|
if (v instanceof Date) return isNaN(v.getTime()) ? null : v;
|
||||||
|
const d = new Date(v);
|
||||||
|
return isNaN(d.getTime()) ? null : d;
|
||||||
|
};
|
||||||
|
for (const item of data ?? []) {
|
||||||
|
const it = item as any;
|
||||||
|
it.dateLeave = toDate(it.dateLeave);
|
||||||
|
it.commandDateAffect = toDate(it.commandDateAffect);
|
||||||
|
it.commandDateSign = toDate(it.commandDateSign);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _posNumCodeSit: string = "";
|
||||||
|
let _posNumCodeSitAbb: string = "";
|
||||||
|
const _command = await this.commandRepository.findOne({
|
||||||
|
where: { id: data.find((x) => x.commandId)?.commandId ?? "" },
|
||||||
|
relations: { commandType: true },
|
||||||
|
});
|
||||||
|
if (_command) {
|
||||||
|
if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
|
||||||
|
const orgRootDeputy = await this.orgRootRepository.findOne({
|
||||||
|
where: {
|
||||||
|
isDeputy: true,
|
||||||
|
orgRevision: {
|
||||||
|
orgRevisionIsCurrent: true,
|
||||||
|
orgRevisionIsDraft: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: ["orgRevision"],
|
||||||
|
});
|
||||||
|
_posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
|
||||||
|
_posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
|
||||||
|
} else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
|
||||||
|
_posNumCodeSit = "กรุงเทพมหานคร";
|
||||||
|
_posNumCodeSitAbb = "กทม.";
|
||||||
|
} else {
|
||||||
|
let _profileAdmin = await this.profileRepository.findOne({
|
||||||
|
where: {
|
||||||
|
keycloak: _command?.createdUserId.toString(),
|
||||||
|
current_holders: {
|
||||||
|
orgRevision: {
|
||||||
|
orgRevisionIsCurrent: true,
|
||||||
|
orgRevisionIsDraft: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
|
||||||
|
});
|
||||||
|
_posNumCodeSit =
|
||||||
|
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
|
||||||
|
"";
|
||||||
|
_posNumCodeSitAbb =
|
||||||
|
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
|
||||||
|
.orgRootShortName ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const today = new Date().setHours(0, 0, 0, 0);
|
||||||
|
await Promise.all(
|
||||||
|
data.map(async (item) => {
|
||||||
|
const profile = await this.profileEmployeeRepository.findOne({
|
||||||
|
where: { id: item.profileId },
|
||||||
|
relations: {
|
||||||
|
roleKeycloaks: true,
|
||||||
|
posType: true,
|
||||||
|
posLevel: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!profile) {
|
||||||
|
throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
|
||||||
|
}
|
||||||
|
const code = _command?.commandType?.code;
|
||||||
|
//ออกคำสั่งยกเลิกลาออก ลบเฉพาะคนที่ขอยกเลิกลาออก
|
||||||
|
if (item.resignId && code && ["C-PM-42"].includes(code)) {
|
||||||
|
const commandResign = await this.commandReciveRepository.findOne({
|
||||||
|
where: { refId: item.resignId },
|
||||||
|
relations: { command: true },
|
||||||
|
});
|
||||||
|
const executeDate = commandResign
|
||||||
|
? new Date(commandResign.command.commandExcecuteDate).setHours(0, 0, 0, 0)
|
||||||
|
: today;
|
||||||
|
if (
|
||||||
|
commandResign &&
|
||||||
|
_command.status !== "REPORTED" &&
|
||||||
|
(_command.status !== "WAITING" || today < executeDate)
|
||||||
|
) {
|
||||||
|
await reOrderCommandRecivesAndDelete(commandResign!.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _commandYear = item.commandYear;
|
||||||
|
if (item.commandYear) {
|
||||||
|
_commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
|
||||||
|
}
|
||||||
|
const dest_item = await this.salaryRepo.findOne({
|
||||||
|
where: { profileEmployeeId: item.profileId },
|
||||||
|
order: { order: "DESC" },
|
||||||
|
});
|
||||||
|
const before = null;
|
||||||
|
const dataSalary = new ProfileSalary();
|
||||||
|
dataSalary.posNumCodeSit = _posNumCodeSit;
|
||||||
|
dataSalary.posNumCodeSitAbb = _posNumCodeSitAbb;
|
||||||
|
const meta = {
|
||||||
|
order: dest_item == null ? 1 : dest_item.order + 1,
|
||||||
|
createdUserId: ctx.user.sub,
|
||||||
|
createdFullName: ctx.user.name,
|
||||||
|
lastUpdateUserId: ctx.user.sub,
|
||||||
|
lastUpdateFullName: ctx.user.name,
|
||||||
|
createdAt: new Date(),
|
||||||
|
lastUpdatedAt: new Date(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(dataSalary, {
|
||||||
|
...item,
|
||||||
|
...meta,
|
||||||
|
profileEmployeeId: item.profileId,
|
||||||
|
profileId: undefined,
|
||||||
|
});
|
||||||
|
const history = new ProfileSalaryHistory();
|
||||||
|
Object.assign(history, { ...dataSalary, id: undefined });
|
||||||
|
dataSalary.dateGovernment = (item.commandDateAffect as Date) ?? meta.createdAt;
|
||||||
|
await this.salaryRepo.save(dataSalary, { data: req });
|
||||||
|
setLogDataDiff(req, { before, after: dataSalary });
|
||||||
|
history.profileSalaryId = dataSalary.id;
|
||||||
|
await this.salaryHistoryRepo.save(history, { data: req });
|
||||||
|
|
||||||
|
const _null: any = null;
|
||||||
|
profile.isLeave = item.isLeave;
|
||||||
|
profile.leaveReason = item.leaveReason ?? _null;
|
||||||
|
profile.dateLeave = item.dateLeave ?? _null;
|
||||||
|
profile.lastUpdateUserId = ctx.user.sub;
|
||||||
|
profile.lastUpdateFullName = ctx.user.name;
|
||||||
|
profile.lastUpdatedAt = new Date();
|
||||||
|
// บันทึกประวัติก่อนลบตำแหน่ง
|
||||||
|
const clearProfile = await checkCommandType(String(item.commandId));
|
||||||
|
const curRevision = await this.orgRevisionRepo.findOne({
|
||||||
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
||||||
|
});
|
||||||
|
let orgRootRef = null;
|
||||||
|
let orgChild1Ref = null;
|
||||||
|
let orgChild2Ref = null;
|
||||||
|
let orgChild3Ref = null;
|
||||||
|
let orgChild4Ref = null;
|
||||||
|
if (curRevision) {
|
||||||
|
const curPosMaster = await this.employeePosMasterRepository.findOne({
|
||||||
|
where: {
|
||||||
|
current_holderId: profile.id,
|
||||||
|
orgRevisionId: curRevision.id,
|
||||||
|
},
|
||||||
|
relations: {
|
||||||
|
orgRoot: true,
|
||||||
|
orgChild1: true,
|
||||||
|
orgChild2: true,
|
||||||
|
orgChild3: true,
|
||||||
|
orgChild4: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
orgRootRef = curPosMaster?.orgRoot ?? null;
|
||||||
|
orgChild1Ref = curPosMaster?.orgChild1 ?? null;
|
||||||
|
orgChild2Ref = curPosMaster?.orgChild2 ?? null;
|
||||||
|
orgChild3Ref = curPosMaster?.orgChild3 ?? null;
|
||||||
|
orgChild4Ref = curPosMaster?.orgChild4 ?? null;
|
||||||
|
if (curPosMaster) {
|
||||||
|
await CreatePosMasterHistoryEmployee(curPosMaster.id, req, "DELETE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ลบตำแหน่ง
|
||||||
|
if (item.isLeave == true) {
|
||||||
|
await removeProfileInOrganize(profile.id, "EMPLOYEE");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clearProfile.status) {
|
||||||
|
if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
|
||||||
|
const delUserKeycloak = await deleteUser(profile.keycloak);
|
||||||
|
if (delUserKeycloak) {
|
||||||
|
// Task #228
|
||||||
|
// profile.keycloak = _null;
|
||||||
|
profile.roleKeycloaks = [];
|
||||||
|
profile.isActive = false;
|
||||||
|
profile.isDelete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
profile.leaveCommandId = item.commandId ?? _null;
|
||||||
|
profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
|
||||||
|
profile.leaveRemark = clearProfile.leaveRemark ?? _null;
|
||||||
|
profile.leaveDate = item.commandDateAffect ?? _null;
|
||||||
|
profile.leaveType = clearProfile.LeaveType ?? _null;
|
||||||
|
//ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
|
||||||
|
// profile.position = _null;
|
||||||
|
// profile.posTypeId = _null;
|
||||||
|
// profile.posLevelId = _null;
|
||||||
|
}
|
||||||
|
await this.profileEmployeeRepository.save(profile);
|
||||||
|
|
||||||
|
// if (profile.id) {
|
||||||
|
// await this.keycloakAttributeService.clearOrgDnaAttributes(
|
||||||
|
// [profile.id],
|
||||||
|
// "PROFILE_EMPLOYEE",
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Task #2190
|
||||||
|
if (code && ["C-PM-23", "C-PM-43"].includes(code)) {
|
||||||
|
let organizeName = "";
|
||||||
|
if (orgRootRef) {
|
||||||
|
const names = [
|
||||||
|
orgChild4Ref?.orgChild4Name,
|
||||||
|
orgChild3Ref?.orgChild3Name,
|
||||||
|
orgChild2Ref?.orgChild2Name,
|
||||||
|
orgChild1Ref?.orgChild1Name,
|
||||||
|
orgRootRef?.orgRootName,
|
||||||
|
].filter(Boolean);
|
||||||
|
organizeName = names.join(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("[ExecuteSalaryEmployeeLeaveService] executeSalaryEmployeeLeave completed successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
628
src/services/ExecuteSalaryLeaveService.ts
Normal file
628
src/services/ExecuteSalaryLeaveService.ts
Normal file
|
|
@ -0,0 +1,628 @@
|
||||||
|
import { Double, In, Like } from "typeorm";
|
||||||
|
import { AppDataSource } from "../database/data-source";
|
||||||
|
import HttpError from "../interfaces/http-error";
|
||||||
|
import HttpStatusCode from "../interfaces/http-status";
|
||||||
|
import { Profile } from "../entities/Profile";
|
||||||
|
import { ProfileSalary } from "../entities/ProfileSalary";
|
||||||
|
import { ProfileSalaryHistory } from "../entities/ProfileSalaryHistory";
|
||||||
|
import { OrgRoot } from "../entities/OrgRoot";
|
||||||
|
import { OrgRevision } from "../entities/OrgRevision";
|
||||||
|
import { PosMaster } from "../entities/PosMaster";
|
||||||
|
import { Position } from "../entities/Position";
|
||||||
|
import { RoleKeycloak } from "../entities/RoleKeycloak";
|
||||||
|
import { CommandRecive } from "../entities/CommandRecive";
|
||||||
|
import { Command } from "../entities/Command";
|
||||||
|
import {
|
||||||
|
checkCommandType,
|
||||||
|
checkReturnCommandType,
|
||||||
|
removePostMasterAct,
|
||||||
|
removeProfileInOrganize,
|
||||||
|
setLogDataDiff,
|
||||||
|
} from "../interfaces/utils";
|
||||||
|
import { reOrderCommandRecivesAndDelete } from "./CommandService";
|
||||||
|
import { CreatePosMasterHistoryOfficer } from "./PositionService";
|
||||||
|
import { getOrgFullName, getPosMasterNo } from "../utils/org-formatting";
|
||||||
|
import {
|
||||||
|
addUserRoles,
|
||||||
|
createUser,
|
||||||
|
deleteUser,
|
||||||
|
getRoleMappings,
|
||||||
|
getRoles,
|
||||||
|
getUserByUsername,
|
||||||
|
updateUserAttributes,
|
||||||
|
} from "../keycloak";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input: ข้อมูล 1 คนสำหรับ endpoint excexute/salary-leave
|
||||||
|
* (C-PM-08, 09, 17, 18, 41, 48 — ลาออก/พักราชการ/กลับเข้าราชการ ของข้าราชการ)
|
||||||
|
*/
|
||||||
|
export interface SalaryLeaveItem {
|
||||||
|
profileId: string;
|
||||||
|
amount?: Double | null;
|
||||||
|
amountSpecial?: Double | null;
|
||||||
|
positionSalaryAmount?: Double | null;
|
||||||
|
mouthSalaryAmount?: Double | null;
|
||||||
|
positionExecutive: string | null;
|
||||||
|
positionExecutiveField?: string | null;
|
||||||
|
positionArea?: string | null;
|
||||||
|
positionType: string | null;
|
||||||
|
positionLevel: string | null;
|
||||||
|
isLeave: boolean;
|
||||||
|
leaveReason?: string | null;
|
||||||
|
dateLeave?: Date | string | null;
|
||||||
|
posExecutiveId?: string | null;
|
||||||
|
positionField?: string | null;
|
||||||
|
commandId?: string | null;
|
||||||
|
isGovernment?: boolean | null;
|
||||||
|
orgRoot?: string | null;
|
||||||
|
orgChild1?: string | null;
|
||||||
|
orgChild2?: string | null;
|
||||||
|
orgChild3?: string | null;
|
||||||
|
orgChild4?: string | null;
|
||||||
|
commandNo: string | null;
|
||||||
|
commandYear: number | null;
|
||||||
|
posNo: string | null;
|
||||||
|
posNoAbb: string | null;
|
||||||
|
commandDateAffect?: Date | string | null;
|
||||||
|
commandDateSign?: Date | string | null;
|
||||||
|
positionName: string | null;
|
||||||
|
commandCode?: string | null;
|
||||||
|
commandName?: string | null;
|
||||||
|
remark: string | null;
|
||||||
|
positionId?: string | null;
|
||||||
|
positionTypeNew?: string | null;
|
||||||
|
positionLevelNew?: string | null;
|
||||||
|
positionNameNew?: string | null;
|
||||||
|
posmasterId?: string | null;
|
||||||
|
posTypeNameNew?: string | null;
|
||||||
|
posLevelNameNew?: string | null;
|
||||||
|
posNoNew?: string | null;
|
||||||
|
posNoAbbNew?: string | null;
|
||||||
|
orgRootNew?: string | null;
|
||||||
|
orgChild1New?: string | null;
|
||||||
|
orgChild2New?: string | null;
|
||||||
|
orgChild3New?: string | null;
|
||||||
|
orgChild4New?: string | null;
|
||||||
|
resignId?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context สำหรับ audit/log
|
||||||
|
*/
|
||||||
|
export interface SalaryLeaveExecutionContext {
|
||||||
|
user: { sub: string; name: string };
|
||||||
|
req?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service สำหรับสร้าง ProfileSalary ข้าราชการ + handle leave/กลับเข้าราชการ
|
||||||
|
*
|
||||||
|
* ใช้กับ commandType: C-PM-08, 09, 17, 18, 41, 48
|
||||||
|
*
|
||||||
|
* - endpoint /org/command/excexute/salary-leave เรียกผ่าน service นี้ (thin wrapper)
|
||||||
|
* - consumer ใน rabbitmq handler เรียกผ่าน service นี้โดยตรง (Linear Flow)
|
||||||
|
*
|
||||||
|
* Behavior ทั้งหมด preserve จาก CommandController.newSalaryAndUpdateLeave ต้นฉบับ
|
||||||
|
*/
|
||||||
|
export class ExecuteSalaryLeaveService {
|
||||||
|
private commandRepository = AppDataSource.getRepository(Command);
|
||||||
|
private commandReciveRepository = AppDataSource.getRepository(CommandRecive);
|
||||||
|
private profileRepository = AppDataSource.getRepository(Profile);
|
||||||
|
private salaryRepo = AppDataSource.getRepository(ProfileSalary);
|
||||||
|
private salaryHistoryRepo = AppDataSource.getRepository(ProfileSalaryHistory);
|
||||||
|
private posMasterRepository = AppDataSource.getRepository(PosMaster);
|
||||||
|
private positionRepository = AppDataSource.getRepository(Position);
|
||||||
|
private orgRootRepository = AppDataSource.getRepository(OrgRoot);
|
||||||
|
private orgRevisionRepo = AppDataSource.getRepository(OrgRevision);
|
||||||
|
private roleKeycloakRepo = AppDataSource.getRepository(RoleKeycloak);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ประมวลผลสร้าง ProfileSalary + handle leave/กลับเข้าราชการ ของข้าราชการ
|
||||||
|
*/
|
||||||
|
async executeSalaryLeave(data: SalaryLeaveItem[], ctx: SalaryLeaveExecutionContext): Promise<void> {
|
||||||
|
console.log("[ExecuteSalaryLeaveService] Starting executeSalaryLeave");
|
||||||
|
console.log("[ExecuteSalaryLeaveService] Request body count:", data?.length);
|
||||||
|
|
||||||
|
const req = ctx.req;
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// Normalize date fields (ผ่าน handler จะได้ string → ต้องแปลงเป็น Date)
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
const toDate = (v: any): Date | null => {
|
||||||
|
if (v == null || v === "") return null;
|
||||||
|
if (v instanceof Date) return isNaN(v.getTime()) ? null : v;
|
||||||
|
const d = new Date(v);
|
||||||
|
return isNaN(d.getTime()) ? null : d;
|
||||||
|
};
|
||||||
|
for (const item of data ?? []) {
|
||||||
|
const it = item as any;
|
||||||
|
it.dateLeave = toDate(it.dateLeave);
|
||||||
|
it.commandDateAffect = toDate(it.commandDateAffect);
|
||||||
|
it.commandDateSign = toDate(it.commandDateSign);
|
||||||
|
}
|
||||||
|
|
||||||
|
const roleKeycloak = await this.roleKeycloakRepo.findOne({
|
||||||
|
where: { name: Like("USER") },
|
||||||
|
});
|
||||||
|
let _posNumCodeSit: string = "";
|
||||||
|
let _posNumCodeSitAbb: string = "";
|
||||||
|
const _command = await this.commandRepository.findOne({
|
||||||
|
relations: ["commandType"],
|
||||||
|
where: { id: data.find((x) => x.commandId)?.commandId ?? "" },
|
||||||
|
});
|
||||||
|
if (_command) {
|
||||||
|
if (_command?.isBangkok?.toLocaleUpperCase() == "OFFICE") {
|
||||||
|
const orgRootDeputy = await this.orgRootRepository.findOne({
|
||||||
|
where: {
|
||||||
|
isDeputy: true,
|
||||||
|
orgRevision: {
|
||||||
|
orgRevisionIsCurrent: true,
|
||||||
|
orgRevisionIsDraft: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: ["orgRevision"],
|
||||||
|
});
|
||||||
|
_posNumCodeSit = orgRootDeputy ? orgRootDeputy?.orgRootName : "สำนักปลัดกรุงเทพมหานคร";
|
||||||
|
_posNumCodeSitAbb = orgRootDeputy ? orgRootDeputy?.orgRootShortName : "สนป.";
|
||||||
|
} else if (_command?.isBangkok?.toLocaleUpperCase() == "BANGKOK") {
|
||||||
|
_posNumCodeSit = "กรุงเทพมหานคร";
|
||||||
|
_posNumCodeSitAbb = "กทม.";
|
||||||
|
} else {
|
||||||
|
let _profileAdmin = await this.profileRepository.findOne({
|
||||||
|
where: {
|
||||||
|
keycloak: _command?.createdUserId.toString(),
|
||||||
|
current_holders: {
|
||||||
|
orgRevision: {
|
||||||
|
orgRevisionIsCurrent: true,
|
||||||
|
orgRevisionIsDraft: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: ["current_holders", "current_holders.orgRevision", "current_holders.orgRoot"],
|
||||||
|
});
|
||||||
|
_posNumCodeSit =
|
||||||
|
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootName)?.orgRoot.orgRootName ??
|
||||||
|
"";
|
||||||
|
_posNumCodeSitAbb =
|
||||||
|
_profileAdmin?.current_holders.find((x) => x.orgRoot.orgRootShortName)?.orgRoot
|
||||||
|
.orgRootShortName ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const today = new Date().setHours(0, 0, 0, 0);
|
||||||
|
await Promise.all(
|
||||||
|
data.map(async (item) => {
|
||||||
|
const profile = await this.profileRepository.findOne({
|
||||||
|
where: { id: item.profileId },
|
||||||
|
relations: {
|
||||||
|
roleKeycloaks: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!profile) {
|
||||||
|
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลทะเบียนประวัตินี้");
|
||||||
|
}
|
||||||
|
//ลบตำแหน่งที่รักษาการแทน
|
||||||
|
const code = _command?.commandType?.code;
|
||||||
|
if (code && ["C-PM-08", "C-PM-17", "C-PM-18", "C-PM-48"].includes(code)) {
|
||||||
|
removePostMasterAct(profile.id);
|
||||||
|
}
|
||||||
|
//ออกคำสั่งยกเลิกลาออก ลบเฉพาะคนที่ขอยกเลิกลาออก
|
||||||
|
else if (item.resignId && code && ["C-PM-41"].includes(code)) {
|
||||||
|
const commandResign = await this.commandReciveRepository.findOne({
|
||||||
|
where: { refId: item.resignId },
|
||||||
|
relations: { command: true },
|
||||||
|
});
|
||||||
|
const executeDate = commandResign
|
||||||
|
? new Date(commandResign.command.commandExcecuteDate).setHours(0, 0, 0, 0)
|
||||||
|
: today;
|
||||||
|
if (
|
||||||
|
commandResign &&
|
||||||
|
_command.status !== "REPORTED" &&
|
||||||
|
(_command.status !== "WAITING" || today < executeDate)
|
||||||
|
) {
|
||||||
|
await reOrderCommandRecivesAndDelete(commandResign!.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _commandYear = item.commandYear;
|
||||||
|
if (item.commandYear) {
|
||||||
|
_commandYear = item.commandYear > 2500 ? item.commandYear : item.commandYear + 543;
|
||||||
|
}
|
||||||
|
const returnWork = await checkReturnCommandType(String(item.commandId));
|
||||||
|
const dest_item = await this.salaryRepo.findOne({
|
||||||
|
where: { profileId: item.profileId },
|
||||||
|
order: { order: "DESC" },
|
||||||
|
});
|
||||||
|
const before = null;
|
||||||
|
const dataSalary = new ProfileSalary();
|
||||||
|
dataSalary.posNumCodeSit = _posNumCodeSit;
|
||||||
|
dataSalary.posNumCodeSitAbb = _posNumCodeSitAbb;
|
||||||
|
dataSalary.dateGovernment = (item.commandDateAffect as Date) ?? new Date();
|
||||||
|
dataSalary.order = dest_item == null ? 1 : dest_item.order + 1;
|
||||||
|
const meta = {
|
||||||
|
createdUserId: ctx.user.sub,
|
||||||
|
createdFullName: ctx.user.name,
|
||||||
|
lastUpdateUserId: ctx.user.sub,
|
||||||
|
lastUpdateFullName: ctx.user.name,
|
||||||
|
createdAt: new Date(),
|
||||||
|
lastUpdatedAt: new Date(),
|
||||||
|
};
|
||||||
|
if (!returnWork) {
|
||||||
|
Object.assign(dataSalary, { ...item, ...meta });
|
||||||
|
const history = new ProfileSalaryHistory();
|
||||||
|
Object.assign(history, { ...dataSalary, id: undefined });
|
||||||
|
await this.salaryRepo.save(dataSalary, { data: req });
|
||||||
|
setLogDataDiff(req, { before, after: dataSalary });
|
||||||
|
history.profileSalaryId = dataSalary.id;
|
||||||
|
await this.salaryHistoryRepo.save(history, { data: req });
|
||||||
|
}
|
||||||
|
const _null: any = null;
|
||||||
|
profile.isLeave = item.isLeave;
|
||||||
|
profile.leaveReason = item.leaveReason ?? _null;
|
||||||
|
profile.dateLeave = item.dateLeave ?? _null;
|
||||||
|
profile.lastUpdateUserId = ctx.user.sub;
|
||||||
|
profile.lastUpdateFullName = ctx.user.name;
|
||||||
|
profile.lastUpdatedAt = new Date();
|
||||||
|
const clearProfile = await checkCommandType(String(item.commandId));
|
||||||
|
|
||||||
|
//ปั๊มประวัติก่อนลบตำแหน่ง
|
||||||
|
const curRevision = await this.orgRevisionRepo.findOne({
|
||||||
|
where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
|
||||||
|
});
|
||||||
|
let orgRootRef = null;
|
||||||
|
let orgChild1Ref = null;
|
||||||
|
let orgChild2Ref = null;
|
||||||
|
let orgChild3Ref = null;
|
||||||
|
let orgChild4Ref = null;
|
||||||
|
if (curRevision) {
|
||||||
|
const curPosMaster = await this.posMasterRepository.findOne({
|
||||||
|
where: {
|
||||||
|
current_holderId: profile.id,
|
||||||
|
orgRevisionId: curRevision.id,
|
||||||
|
},
|
||||||
|
relations: {
|
||||||
|
orgRoot: true,
|
||||||
|
orgChild1: true,
|
||||||
|
orgChild2: true,
|
||||||
|
orgChild3: true,
|
||||||
|
orgChild4: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
orgRootRef = curPosMaster?.orgRoot ?? null;
|
||||||
|
orgChild1Ref = curPosMaster?.orgChild1 ?? null;
|
||||||
|
orgChild2Ref = curPosMaster?.orgChild2 ?? null;
|
||||||
|
orgChild3Ref = curPosMaster?.orgChild3 ?? null;
|
||||||
|
orgChild4Ref = curPosMaster?.orgChild4 ?? null;
|
||||||
|
if (curPosMaster && clearProfile.LeaveType != "RETIRE_OUT_EMP") {
|
||||||
|
await CreatePosMasterHistoryOfficer(curPosMaster.id, req, "DELETE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ลบตำแหน่ง
|
||||||
|
if (item.isLeave == true) {
|
||||||
|
await removeProfileInOrganize(profile.id, "OFFICER");
|
||||||
|
}
|
||||||
|
if (clearProfile.status) {
|
||||||
|
if (profile.keycloak != null && profile.keycloak != "" && profile.isDelete === false) {
|
||||||
|
const delUserKeycloak = await deleteUser(profile.keycloak);
|
||||||
|
if (delUserKeycloak) {
|
||||||
|
// Task #228
|
||||||
|
// profile.keycloak = _null;
|
||||||
|
profile.roleKeycloaks = [];
|
||||||
|
profile.isActive = false;
|
||||||
|
profile.isDelete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
profile.leaveCommandId = item.commandId ?? _null;
|
||||||
|
profile.leaveCommandNo = `${item.commandNo}/${_commandYear}`;
|
||||||
|
profile.leaveRemark = clearProfile.leaveRemark ?? _null;
|
||||||
|
profile.leaveDate = item.commandDateAffect ?? _null;
|
||||||
|
profile.leaveType = clearProfile.LeaveType ?? _null;
|
||||||
|
//ออกจากราชการ ไม่ต้องลบตำแหน่งในทะเบียน (issue #1516)
|
||||||
|
// profile.position = _null;
|
||||||
|
// profile.posTypeId = _null;
|
||||||
|
// profile.posLevelId = _null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.isGovernment == true) {
|
||||||
|
if (returnWork) {
|
||||||
|
//ปลดตำแหน่งเดิมที่ไม่ถูกปลดออกจากกิ่งครั้งเมื่อออกคำสั่งพักราชการหรือออกราชการไว้
|
||||||
|
await removeProfileInOrganize(profile.id, "OFFICER");
|
||||||
|
//ปั๊มตำแหน่งใหม่
|
||||||
|
// หา posMaster และเช็ค orgRevisionIsCurrent
|
||||||
|
let posMaster = await this.posMasterRepository.findOne({
|
||||||
|
where: { id: item.posmasterId?.toString() },
|
||||||
|
relations: {
|
||||||
|
orgRevision: true,
|
||||||
|
orgRoot: true,
|
||||||
|
orgChild1: true,
|
||||||
|
orgChild2: true,
|
||||||
|
orgChild3: true,
|
||||||
|
orgChild4: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// เช็คว่า posMaster ที่หามาอยู่ในโครงสร้างปัจจุบันหรือไม่
|
||||||
|
const isCurrent =
|
||||||
|
posMaster?.orgRevision?.orgRevisionIsCurrent === true &&
|
||||||
|
posMaster?.orgRevision?.orgRevisionIsDraft === false;
|
||||||
|
|
||||||
|
// ถ้าไม่อยู่ในโครงสร้างปัจจุบัน ให้หาตัวใหม่จาก ancestorDNA
|
||||||
|
if (!isCurrent && posMaster?.ancestorDNA) {
|
||||||
|
posMaster = await this.posMasterRepository.findOne({
|
||||||
|
where: {
|
||||||
|
ancestorDNA: posMaster.ancestorDNA,
|
||||||
|
orgRevision: {
|
||||||
|
orgRevisionIsCurrent: true,
|
||||||
|
orgRevisionIsDraft: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: {
|
||||||
|
orgRevision: true,
|
||||||
|
orgRoot: true,
|
||||||
|
orgChild1: true,
|
||||||
|
orgChild2: true,
|
||||||
|
orgChild3: true,
|
||||||
|
orgChild4: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (posMaster) {
|
||||||
|
const checkPosition = await this.positionRepository.find({
|
||||||
|
where: {
|
||||||
|
posMasterId: posMaster.id,
|
||||||
|
positionIsSelected: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (checkPosition.length > 0) {
|
||||||
|
const clearPosition = checkPosition.map((positions) => ({
|
||||||
|
...positions,
|
||||||
|
positionIsSelected: false,
|
||||||
|
}));
|
||||||
|
await this.positionRepository.save(clearPosition);
|
||||||
|
}
|
||||||
|
posMaster.current_holderId = profile.id;
|
||||||
|
posMaster.lastUpdatedAt = new Date();
|
||||||
|
// posMaster.conditionReason = _null;
|
||||||
|
// posMaster.isCondition = false;
|
||||||
|
await this.posMasterRepository.save(posMaster);
|
||||||
|
|
||||||
|
// Match position ตามลำดับ priority:
|
||||||
|
// Condition 1: match จาก positionId
|
||||||
|
// Condition 2: match 7 ฟิลด์ (positionName, posTypeId, posLevelId, positionField, positionArea, positionExecutiveField, posExecutiveId)
|
||||||
|
// Condition 3: match 3 ฟิลด์ (positionName, posTypeId, posLevelId)
|
||||||
|
// Fallback: เลือก position แรกใน posMaster
|
||||||
|
|
||||||
|
let positionNew: Position | null = null;
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// CONDITION 1: เช็คจาก positionId ตรง
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
if (item.positionId) {
|
||||||
|
const positionById = await this.positionRepository.findOne({
|
||||||
|
where: {
|
||||||
|
id: item.positionId,
|
||||||
|
posMasterId: posMaster.id, // ต้องอยู่ใน posMaster ที่ถูกต้อง
|
||||||
|
},
|
||||||
|
relations: ["posExecutive"],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (positionById) {
|
||||||
|
positionNew = positionById;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// CONDITION 2: Match 7 ฟิลด์ (ถ้า Condition 1 ไม่ match)
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
if (!positionNew && item.positionNameNew && item.positionTypeNew && item.positionLevelNew) {
|
||||||
|
// สร้าง where clause แบบ dynamic - ใส่เฉพาะฟิลด์ที่มีค่า
|
||||||
|
const whereCondition: any = {
|
||||||
|
posMasterId: posMaster.id,
|
||||||
|
positionName: item.positionNameNew,
|
||||||
|
posTypeId: item.positionTypeNew,
|
||||||
|
posLevelId: item.positionLevelNew,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (item.positionField) {
|
||||||
|
whereCondition.positionField = item.positionField;
|
||||||
|
}
|
||||||
|
if (item.posExecutiveId) {
|
||||||
|
whereCondition.posExecutiveId = item.posExecutiveId;
|
||||||
|
}
|
||||||
|
if (item.positionExecutiveField) {
|
||||||
|
whereCondition.positionExecutiveField = item.positionExecutiveField;
|
||||||
|
}
|
||||||
|
if (item.positionArea) {
|
||||||
|
whereCondition.positionArea = item.positionArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
const positionBy7Fields = await this.positionRepository.findOne({
|
||||||
|
where: whereCondition,
|
||||||
|
relations: ["posExecutive"],
|
||||||
|
order: { orderNo: "ASC" },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (positionBy7Fields) {
|
||||||
|
positionNew = positionBy7Fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// CONDITION 3: Match 3 ฟิลด์ (ถ้า Condition 2 ไม่ match)
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
if (!positionNew && item.positionNameNew && item.positionTypeNew && item.positionLevelNew) {
|
||||||
|
const positionBy3Fields = await this.positionRepository.findOne({
|
||||||
|
where: {
|
||||||
|
posMasterId: posMaster.id,
|
||||||
|
positionName: item.positionNameNew,
|
||||||
|
posTypeId: item.positionTypeNew,
|
||||||
|
posLevelId: item.positionLevelNew,
|
||||||
|
},
|
||||||
|
relations: ["posExecutive"],
|
||||||
|
order: { orderNo: "ASC" },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (positionBy3Fields) {
|
||||||
|
positionNew = positionBy3Fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // FALLBACK: เลือก position แรก (ถ้าไม่เจอทั้ง 2 condition)
|
||||||
|
// if (!positionNew) {
|
||||||
|
// const fallbackPositions = await this.positionRepository.find({
|
||||||
|
// where: {
|
||||||
|
// posMasterId: posMaster.id,
|
||||||
|
// },
|
||||||
|
// relations: ["posExecutive"],
|
||||||
|
// order: {
|
||||||
|
// orderNo: "ASC",
|
||||||
|
// },
|
||||||
|
// take: 1,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (fallbackPositions.length > 0) {
|
||||||
|
// positionNew = fallbackPositions[0];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (positionNew) {
|
||||||
|
positionNew.positionIsSelected = true;
|
||||||
|
await this.positionRepository.save(positionNew, { data: req });
|
||||||
|
}
|
||||||
|
await CreatePosMasterHistoryOfficer(posMaster.id, req);
|
||||||
|
profile.posMasterNo = getPosMasterNo(posMaster);
|
||||||
|
profile.org = getOrgFullName(posMaster);
|
||||||
|
}
|
||||||
|
const newMapProfileSalary = {
|
||||||
|
profileId: profile.id,
|
||||||
|
commandId: item.commandId,
|
||||||
|
positionName: item.positionNameNew ?? null,
|
||||||
|
positionType: item.posTypeNameNew ?? null,
|
||||||
|
positionLevel: item.posLevelNameNew ?? null,
|
||||||
|
amount: item.amount ? item.amount : null,
|
||||||
|
positionSalaryAmount: item.positionSalaryAmount ? item.positionSalaryAmount : null,
|
||||||
|
amountSpecial: item.amountSpecial ? item.amountSpecial : null,
|
||||||
|
mouthSalaryAmount: item.mouthSalaryAmount ? item.mouthSalaryAmount : null,
|
||||||
|
posNo: item.posNoNew,
|
||||||
|
posNoAbb: item.posNoAbbNew,
|
||||||
|
orgRoot: item.orgRootNew,
|
||||||
|
orgChild1: item.orgChild1New,
|
||||||
|
orgChild2: item.orgChild2New,
|
||||||
|
orgChild3: item.orgChild3New,
|
||||||
|
orgChild4: item.orgChild4New,
|
||||||
|
isGovernment: item.isGovernment,
|
||||||
|
commandNo: item.commandNo,
|
||||||
|
commandYear: item.commandYear,
|
||||||
|
commandDateAffect: item.commandDateAffect,
|
||||||
|
commandDateSign: item.commandDateSign,
|
||||||
|
commandCode: item.commandCode,
|
||||||
|
commandName: item.commandName,
|
||||||
|
remark: item.remark,
|
||||||
|
};
|
||||||
|
Object.assign(dataSalary, { ...newMapProfileSalary, ...meta });
|
||||||
|
const history = new ProfileSalaryHistory();
|
||||||
|
Object.assign(history, { ...dataSalary, id: undefined });
|
||||||
|
await this.salaryRepo.save(dataSalary);
|
||||||
|
history.profileSalaryId = dataSalary.id;
|
||||||
|
await this.salaryHistoryRepo.save(history);
|
||||||
|
profile.leaveReason = _null;
|
||||||
|
profile.leaveCommandId = _null;
|
||||||
|
profile.leaveCommandNo = _null;
|
||||||
|
profile.leaveRemark = _null;
|
||||||
|
profile.leaveDate = _null;
|
||||||
|
profile.leaveType = _null;
|
||||||
|
profile.position = item.positionNameNew ?? _null;
|
||||||
|
profile.posTypeId = item.positionTypeNew ?? _null;
|
||||||
|
profile.posLevelId = item.positionLevelNew ?? _null;
|
||||||
|
}
|
||||||
|
let userKeycloakId;
|
||||||
|
const checkUser = await getUserByUsername(profile.citizenId);
|
||||||
|
//ถ้ายังไม่มี user keycloak ให้สร้างใหม่
|
||||||
|
if (checkUser.length == 0) {
|
||||||
|
let password = profile.citizenId;
|
||||||
|
if (profile.birthDate != null) {
|
||||||
|
const _date = new Date(profile.birthDate.toDateString())
|
||||||
|
.getDate()
|
||||||
|
.toString()
|
||||||
|
.padStart(2, "0");
|
||||||
|
const _month = (new Date(profile.birthDate.toDateString()).getMonth() + 1)
|
||||||
|
.toString()
|
||||||
|
.padStart(2, "0");
|
||||||
|
const _year = new Date(profile.birthDate.toDateString()).getFullYear() + 543;
|
||||||
|
password = `${_date}${_month}${_year}`;
|
||||||
|
}
|
||||||
|
// กรอง "." ออกจาก firstName ก่อนส่งไป keycloak
|
||||||
|
const sanitizedFirstName = profile.firstName?.replace(/\./g, "") ?? "";
|
||||||
|
userKeycloakId = await createUser(profile.citizenId, password, {
|
||||||
|
firstName: sanitizedFirstName,
|
||||||
|
lastName: profile.lastName,
|
||||||
|
});
|
||||||
|
const list = await getRoles();
|
||||||
|
let result = false;
|
||||||
|
if (Array.isArray(list) && userKeycloakId) {
|
||||||
|
result = await addUserRoles(
|
||||||
|
userKeycloakId,
|
||||||
|
list
|
||||||
|
.filter((v) => v.name === "USER")
|
||||||
|
.map((x) => ({
|
||||||
|
id: x.id,
|
||||||
|
name: x.name,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
profile.roleKeycloaks = result && roleKeycloak ? [roleKeycloak] : [];
|
||||||
|
profile.keycloak =
|
||||||
|
userKeycloakId && typeof userKeycloakId === "string" ? userKeycloakId : "";
|
||||||
|
}
|
||||||
|
//ถ้ามีอยู่แล้วให้ใช้อันเดิม
|
||||||
|
else {
|
||||||
|
const rolesData = await getRoleMappings(checkUser[0].id);
|
||||||
|
if (rolesData) {
|
||||||
|
const _roleKeycloak = await this.roleKeycloakRepo.find({
|
||||||
|
where: { name: In(rolesData.map((x: any) => x.name)) },
|
||||||
|
});
|
||||||
|
profile.roleKeycloaks =
|
||||||
|
_roleKeycloak && _roleKeycloak.length > 0 ? _roleKeycloak : [];
|
||||||
|
}
|
||||||
|
profile.keycloak = checkUser[0].id;
|
||||||
|
}
|
||||||
|
profile.amount = item.amount ?? _null;
|
||||||
|
profile.amountSpecial = item.amountSpecial ?? _null;
|
||||||
|
profile.isActive = true;
|
||||||
|
profile.isDelete = false;
|
||||||
|
}
|
||||||
|
await this.profileRepository.save(profile);
|
||||||
|
|
||||||
|
// if (profile.id) {
|
||||||
|
// await this.keycloakAttributeService.clearOrgDnaAttributes(
|
||||||
|
// [profile.id],
|
||||||
|
// "PROFILE",
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// update user attribute in keycloak
|
||||||
|
await updateUserAttributes(profile.keycloak ?? "", {
|
||||||
|
profileId: [profile.id],
|
||||||
|
prefix: [profile.prefix || ""],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Task #2190
|
||||||
|
if (code && ["C-PM-17", "C-PM-18", "C-PM-48"].includes(code)) {
|
||||||
|
let organizeName = "";
|
||||||
|
if (orgRootRef) {
|
||||||
|
const names = [
|
||||||
|
orgChild4Ref?.orgChild4Name,
|
||||||
|
orgChild3Ref?.orgChild3Name,
|
||||||
|
orgChild2Ref?.orgChild2Name,
|
||||||
|
orgChild1Ref?.orgChild1Name,
|
||||||
|
orgRootRef?.orgRootName,
|
||||||
|
].filter(Boolean);
|
||||||
|
organizeName = names.join(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("[ExecuteSalaryLeaveService] executeSalaryLeave completed successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,8 @@ import { ExecuteOfficerProfileService } from "./ExecuteOfficerProfileService";
|
||||||
import { ExecuteSalaryService } from "./ExecuteSalaryService";
|
import { ExecuteSalaryService } from "./ExecuteSalaryService";
|
||||||
import { ExecuteSalaryCurrentService } from "./ExecuteSalaryCurrentService";
|
import { ExecuteSalaryCurrentService } from "./ExecuteSalaryCurrentService";
|
||||||
import { ExecuteSalaryEmployeeCurrentService } from "./ExecuteSalaryEmployeeCurrentService";
|
import { ExecuteSalaryEmployeeCurrentService } from "./ExecuteSalaryEmployeeCurrentService";
|
||||||
|
import { ExecuteSalaryLeaveService } from "./ExecuteSalaryLeaveService";
|
||||||
|
import { ExecuteSalaryEmployeeLeaveService } from "./ExecuteSalaryEmployeeLeaveService";
|
||||||
|
|
||||||
const redis = require("redis");
|
const redis = require("redis");
|
||||||
const REDIS_HOST = process.env.REDIS_HOST;
|
const REDIS_HOST = process.env.REDIS_HOST;
|
||||||
|
|
@ -326,11 +328,13 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
// Linear Flow
|
// Linear Flow
|
||||||
// รับ resultData จาก .NET แล้วเรียก Service ตรงๆ ตาม commandType (ไม่ผ่าน HTTP loopback)
|
// รับ resultData จาก .NET แล้วเรียก Service ตรงๆ ตาม commandType (ไม่ผ่าน HTTP loopback)
|
||||||
// - ExecuteOfficerProfileService : C-PM-01, 02, 14 (บรรจุ/รับโอน)
|
// - ExecuteOfficerProfileService : C-PM-01, 02, 14 (บรรจุ/รับโอน)
|
||||||
// - ExecuteSalaryCurrentService : C-PM-03, 04, 05, 06, 07, 39, 47 (แต่งตั้ง-เลื่อน-ย้าย)
|
// - ExecuteSalaryCurrentService : C-PM-03, 04, 05, 06, 07, 39, 47 (แต่งตั้ง-เลื่อน-ย้าย)
|
||||||
// - ExecuteSalaryEmployeeCurrent : C-PM-22, 24 (ลูกจ้าง ปรับระดับชั้นงาน-ย้าย)
|
// - ExecuteSalaryEmployeeCurrentService : C-PM-22, 24 (ลูกจ้าง ปรับระดับชั้นงาน-ย้าย)
|
||||||
// - ExecuteSalaryService : C-PM-13, 15, 16 (ให้โอน/ให้ช่วยราชการ/ให้กลับเข้าราชการ)
|
// - ExecuteSalaryService : C-PM-13, 15, 16 (ให้โอน/ให้ช่วยราชการ/ให้กลับเข้าราชการ)
|
||||||
|
// - ExecuteSalaryLeaveService : C-PM-08, 09, 17, 18, 41, 48 (ข้าราชการ leave/กลับเข้าราชการ)
|
||||||
|
// - ExecuteSalaryEmployeeLeaveService : C-PM-23, 42, 43 (ลูกจ้าง leave)
|
||||||
// - คำสั่งอื่น ยังใช้ Circular Flow เดิม
|
// - คำสั่งอื่น ยังใช้ Circular Flow เดิม
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
const code = command.commandType?.code;
|
const code = command.commandType?.code;
|
||||||
|
|
@ -338,7 +342,15 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
|
||||||
const isSalaryCurrent = ["C-PM-03", "C-PM-04", "C-PM-05", "C-PM-06", "C-PM-07", "C-PM-39", "C-PM-47"].includes(code);
|
const isSalaryCurrent = ["C-PM-03", "C-PM-04", "C-PM-05", "C-PM-06", "C-PM-07", "C-PM-39", "C-PM-47"].includes(code);
|
||||||
const isSalaryEmployeeCurrent = ["C-PM-22", "C-PM-24"].includes(code);
|
const isSalaryEmployeeCurrent = ["C-PM-22", "C-PM-24"].includes(code);
|
||||||
const isSalary = ["C-PM-13", "C-PM-15", "C-PM-16"].includes(code);
|
const isSalary = ["C-PM-13", "C-PM-15", "C-PM-16"].includes(code);
|
||||||
const isLinearFlow = isOfficerProfile || isSalaryCurrent || isSalaryEmployeeCurrent || isSalary;
|
const isSalaryLeave = ["C-PM-08", "C-PM-09", "C-PM-17", "C-PM-18", "C-PM-41", "C-PM-48"].includes(code);
|
||||||
|
const isSalaryEmployeeLeave = ["C-PM-23", "C-PM-42", "C-PM-43"].includes(code);
|
||||||
|
const isLinearFlow =
|
||||||
|
isOfficerProfile ||
|
||||||
|
isSalaryCurrent ||
|
||||||
|
isSalaryEmployeeCurrent ||
|
||||||
|
isSalary ||
|
||||||
|
isSalaryLeave ||
|
||||||
|
isSalaryEmployeeLeave;
|
||||||
|
|
||||||
if (isLinearFlow) {
|
if (isLinearFlow) {
|
||||||
console.log(`[AMQ] Linear Flow (${code})`);
|
console.log(`[AMQ] Linear Flow (${code})`);
|
||||||
|
|
@ -384,6 +396,12 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
|
||||||
} else if (isSalary) {
|
} else if (isSalary) {
|
||||||
await new ExecuteSalaryService().executeSalary(resultData, ctx);
|
await new ExecuteSalaryService().executeSalary(resultData, ctx);
|
||||||
console.log(`[AMQ] Processed ${resultData.length} profiles via ExecuteSalaryService`);
|
console.log(`[AMQ] Processed ${resultData.length} profiles via ExecuteSalaryService`);
|
||||||
|
} else if (isSalaryLeave) {
|
||||||
|
await new ExecuteSalaryLeaveService().executeSalaryLeave(resultData, ctx);
|
||||||
|
console.log(`[AMQ] Processed ${resultData.length} profiles via ExecuteSalaryLeaveService`);
|
||||||
|
} else if (isSalaryEmployeeLeave) {
|
||||||
|
await new ExecuteSalaryEmployeeLeaveService().executeSalaryEmployeeLeave(resultData, ctx);
|
||||||
|
console.log(`[AMQ] Processed ${resultData.length} profiles via ExecuteSalaryEmployeeLeaveService`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue