cdhแก้คิวรี่ให้เร็วขึ้น สร้าง workflow

This commit is contained in:
mamoss 2025-10-09 23:24:04 +07:00
parent fd17f366b8
commit 847d9c302f
2 changed files with 241 additions and 265 deletions

View file

@ -73,29 +73,10 @@ export class OrganizationDotnetController extends Controller {
role?: string | null; role?: string | null;
nodeId?: string | null; nodeId?: string | null;
node?: number | null; node?: number | null;
page: number;
pageSize: number;
}, },
) { ) {
// const profileRepository = AppDataSource.getRepository(Profile);
// const queryBuilder = profileRepository
// .createQueryBuilder("profile")
// .leftJoinAndSelect("profile.posLevel", "posLevel")
// .leftJoinAndSelect("profile.posType", "posType")
// if (body.citizenId || body.firstName || body.lastName) {
// queryBuilder.where(
// new Brackets((qb) => {
// if (body.citizenId) {
// qb.orWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` });
// }
// if (body.firstName) {
// qb.orWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` });
// }
// if (body.lastName) {
// qb.orWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` });
// }
// }),
// );
// }
// const profiles = await queryBuilder.getMany();
let condition = "1=1"; let condition = "1=1";
let conditionParams = {}; let conditionParams = {};
if (body.role === "CHILD") { if (body.role === "CHILD") {
@ -156,7 +137,7 @@ export class OrganizationDotnetController extends Controller {
if (!findRevision) { if (!findRevision) {
throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision"); throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
} }
const profiles = await this.profileRepo const [profiles, total] = await this.profileRepo
.createQueryBuilder("profile") .createQueryBuilder("profile")
.leftJoinAndSelect("profile.posLevel", "posLevel") .leftJoinAndSelect("profile.posLevel", "posLevel")
.leftJoinAndSelect("profile.posType", "posType") .leftJoinAndSelect("profile.posType", "posType")
@ -170,20 +151,22 @@ export class OrganizationDotnetController extends Controller {
.andWhere( .andWhere(
new Brackets((qb) => { new Brackets((qb) => {
if (body.citizenId) { if (body.citizenId) {
qb.orWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` }); qb.andWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` });
} }
if (body.firstName) { if (body.firstName) {
qb.orWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` }); qb.andWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` });
} }
if (body.lastName) { if (body.lastName) {
qb.orWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` }); qb.andWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` });
} }
}), }),
) )
.andWhere(condition, conditionParams) .andWhere(condition, conditionParams)
.getMany(); .skip((body.page - 1) * body.pageSize)
.take(body.pageSize)
.getManyAndCount();
return new HttpSuccess(profiles); return new HttpSuccess({ data: profiles, total: total });
} }
/** /**
@ -202,40 +185,10 @@ export class OrganizationDotnetController extends Controller {
role?: string | null; role?: string | null;
nodeId?: string | null; nodeId?: string | null;
node?: number | null; node?: number | null;
page: number;
pageSize: number;
}, },
) { ) {
// const profileRepository = AppDataSource.getRepository(ProfileEmployee);
// const queryBuilder = profileRepository
// .createQueryBuilder("profile")
// .leftJoinAndSelect("profile.posLevel", "posLevel")
// .leftJoinAndSelect("profile.posType", "posType")
// .leftJoinAndSelect("profile.profileSalary", "profileSalary")
// .leftJoinAndSelect("profile.current_holders", "current_holders")
// .leftJoinAndSelect("current_holders.orgRoot", "orgRoot")
// .leftJoinAndSelect("current_holders.orgChild1", "orgChild1")
// .leftJoinAndSelect("current_holders.orgChild2", "orgChild2")
// .leftJoinAndSelect("current_holders.orgChild3", "orgChild3")
// .leftJoinAndSelect("current_holders.orgChild4", "orgChild4")
// .orderBy("profileSalary.order", "DESC");
// if (body.citizenId || body.firstName || body.lastName) {
// queryBuilder.where(
// new Brackets((qb) => {
// if (body.citizenId) {
// qb.orWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` });
// }
// if (body.firstName) {
// qb.orWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` });
// }
// if (body.lastName) {
// qb.orWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` });
// }
// }),
// );
// }
// const profileEmp = await queryBuilder.getMany();
let condition = "1=1"; let condition = "1=1";
let conditionParams = {}; let conditionParams = {};
if (body.role === "CHILD") { if (body.role === "CHILD") {
@ -296,7 +249,7 @@ export class OrganizationDotnetController extends Controller {
if (!findRevision) { if (!findRevision) {
throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision"); throw new HttpError(HttpStatus.NOT_FOUND, "not found. OrgRevision");
} }
const profileEmp = await this.profileEmpRepo const [profileEmp, total] = await this.profileEmpRepo
.createQueryBuilder("profile") .createQueryBuilder("profile")
.leftJoinAndSelect("profile.posLevel", "posLevel") .leftJoinAndSelect("profile.posLevel", "posLevel")
.leftJoinAndSelect("profile.posType", "posType") .leftJoinAndSelect("profile.posType", "posType")
@ -311,110 +264,112 @@ export class OrganizationDotnetController extends Controller {
.andWhere( .andWhere(
new Brackets((qb) => { new Brackets((qb) => {
if (body.citizenId) { if (body.citizenId) {
qb.orWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` }); qb.andWhere("profile.citizenId LIKE :citizenId", { citizenId: `%${body.citizenId}%` });
} }
if (body.firstName) { if (body.firstName) {
qb.orWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` }); qb.andWhere("profile.firstName LIKE :firstName", { firstName: `%${body.firstName}%` });
} }
if (body.lastName) { if (body.lastName) {
qb.orWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` }); qb.andWhere("profile.lastName LIKE :lastName", { lastName: `%${body.lastName}%` });
} }
}), }),
) )
.andWhere(condition, conditionParams) .andWhere(condition, conditionParams)
.orderBy("profileSalary.order", "DESC") .orderBy("profileSalary.order", "DESC")
.getMany(); .skip((body.page - 1) * body.pageSize)
.take(body.pageSize)
.getManyAndCount();
const profileEmp_ = await Promise.all( // const profileEmp_ = await Promise.all(
profileEmp.map((item: ProfileEmployee) => { // profileEmp.map((item: ProfileEmployee) => {
const rootName = // const rootName =
item.current_holders.length == 0 // item.current_holders.length == 0
? null // ? null
: item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot
?.orgRootName; // ?.orgRootName;
const shortName = // const shortName =
item.current_holders.length == 0 // item.current_holders.length == 0
? null // ? null
: item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 != // item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4 !=
null // null
? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` // ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild4.orgChild4ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
: item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) // item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
?.orgChild3 != null // ?.orgChild3 != null
? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` // ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild3.orgChild3ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
: item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) // item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
?.orgChild2 != null // ?.orgChild2 != null
? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` // ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild2.orgChild2ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
: item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null && // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != null &&
item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) // item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
?.orgChild1 != null // ?.orgChild1 != null
? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` // ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgChild1.orgChild1ShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
: item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) != // : item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) !=
null && // null &&
item.current_holders.find((x) => x.orgRevisionId == findRevision?.id) // item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)
?.orgRoot != null // ?.orgRoot != null
? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}` // ? `${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.orgRoot.orgRootShortName} ${item.current_holders.find((x) => x.orgRevisionId == findRevision?.id)?.posMasterNo}`
: null; // : null;
return { // return {
oc: rootName, // oc: rootName,
id: item.id, // id: item.id,
createdAt: item.createdAt, // createdAt: item.createdAt,
createdUserId: item.createdUserId, // createdUserId: item.createdUserId,
lastUpdatedAt: item.lastUpdatedAt, // lastUpdatedAt: item.lastUpdatedAt,
lastUpdateUserId: item.lastUpdateUserId, // lastUpdateUserId: item.lastUpdateUserId,
createdFullName: item.createdFullName, // createdFullName: item.createdFullName,
lastUpdateFullName: item.lastUpdateFullName, // lastUpdateFullName: item.lastUpdateFullName,
avatar: item.avatar, // avatar: item.avatar,
avatarName: item.avatarName, // avatarName: item.avatarName,
rank: item.rank, // rank: item.rank,
prefix: item.prefix, // prefix: item.prefix,
firstName: item.firstName, // firstName: item.firstName,
lastName: item.lastName, // lastName: item.lastName,
citizenId: item.citizenId, // citizenId: item.citizenId,
position: item.position, // position: item.position,
posLevelId: item.posLevelId, // posLevelId: item.posLevelId,
posTypeId: item.posTypeId, // posTypeId: item.posTypeId,
email: item.email, // email: item.email,
phone: item.phone, // phone: item.phone,
keycloak: item.keycloak, // keycloak: item.keycloak,
isProbation: item.isProbation, // isProbation: item.isProbation,
isLeave: item.isLeave, // isLeave: item.isLeave,
leaveReason: item.leaveReason, // leaveReason: item.leaveReason,
dateLeave: item.dateLeave, // dateLeave: item.dateLeave,
dateRetire: item.dateRetire, // dateRetire: item.dateRetire,
dateAppoint: item.dateAppoint, // dateAppoint: item.dateAppoint,
dateRetireLaw: item.dateRetireLaw, // dateRetireLaw: item.dateRetireLaw,
dateStart: item.dateStart, // dateStart: item.dateStart,
govAgeAbsent: item.govAgeAbsent, // govAgeAbsent: item.govAgeAbsent,
govAgePlus: item.govAgePlus, // govAgePlus: item.govAgePlus,
birthDate: item.birthDate ?? new Date(), // birthDate: item.birthDate ?? new Date(),
reasonSameDate: item.reasonSameDate, // reasonSameDate: item.reasonSameDate,
ethnicity: item.ethnicity, // ethnicity: item.ethnicity,
telephoneNumber: item.phone, // telephoneNumber: item.phone,
nationality: item.nationality, // nationality: item.nationality,
gender: item.gender, // gender: item.gender,
relationship: item.relationship, // relationship: item.relationship,
religion: item.religion, // religion: item.religion,
bloodGroup: item.bloodGroup, // bloodGroup: item.bloodGroup,
registrationAddress: item.registrationAddress, // registrationAddress: item.registrationAddress,
registrationProvinceId: item.registrationProvinceId, // registrationProvinceId: item.registrationProvinceId,
registrationDistrictId: item.registrationDistrictId, // registrationDistrictId: item.registrationDistrictId,
registrationSubDistrictId: item.registrationSubDistrictId, // registrationSubDistrictId: item.registrationSubDistrictId,
registrationZipCode: item.registrationZipCode, // registrationZipCode: item.registrationZipCode,
currentAddress: item.currentAddress, // currentAddress: item.currentAddress,
currentProvinceId: item.currentProvinceId, // currentProvinceId: item.currentProvinceId,
currentDistrictId: item.currentDistrictId, // currentDistrictId: item.currentDistrictId,
currentSubDistrictId: item.currentSubDistrictId, // currentSubDistrictId: item.currentSubDistrictId,
currentZipCode: item.currentZipCode, // currentZipCode: item.currentZipCode,
posLevel: item.posLevel, // posLevel: item.posLevel,
posType: item.posType, // posType: item.posType,
posNo: shortName, // posNo: shortName,
}; // };
}), // }),
); // );
return new HttpSuccess(profileEmp_); return new HttpSuccess({ data: profileEmp, total: total });
} }
/** /**

View file

@ -55,29 +55,35 @@ export class WorkflowController extends Controller {
fullName?: string | null; fullName?: string | null;
}, },
) { ) {
// ขั้นที่ 1: ทำการค้นหา profile และ metaWorkflow แบบ parallel
const [userProfileOfficer, userProfileEmployee, metaWorkflow] = await Promise.all([
this.profileRepo.findOne({
where: { keycloak: req.user.sub },
select: ["id", "keycloak"],
}),
this.profileEmployeeRepo.findOne({
where: { keycloak: req.user.sub },
select: ["id", "keycloak"],
}),
this.metaWorkflowRepo.findOne({
where: {
sysName: body.sysName,
posLevelName: body.posLevelName,
posTypeName: body.posTypeName,
},
}),
]);
// กำหนด profile type และ profile
let profileType = "OFFICER"; let profileType = "OFFICER";
let profile: any = await this.profileRepo.findOne({ let profile: any = userProfileOfficer;
where: {
keycloak: req.user.sub,
},
});
if (!profile) { if (!profile) {
profileType = "EMPLOYEE"; profileType = "EMPLOYEE";
profile = await this.profileEmployeeRepo.findOne({ profile = userProfileEmployee;
where: {
keycloak: req.user.sub,
},
});
if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งาน"); if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลผู้ใช้งาน");
} }
const metaWorkflow = await this.metaWorkflowRepo.findOne({
where: {
sysName: body.sysName,
posLevelName: body.posLevelName,
posTypeName: body.posTypeName,
},
});
if (!metaWorkflow) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบกระบวนการนี้ได้"); if (!metaWorkflow) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบกระบวนการนี้ได้");
const meta = { const meta = {
@ -88,6 +94,8 @@ export class WorkflowController extends Controller {
createdAt: new Date(), createdAt: new Date(),
lastUpdatedAt: new Date(), lastUpdatedAt: new Date(),
}; };
// ขั้นที่ 2: สร้าง workflow และดึง metaState แบบ parallel
const workflow = new Workflow(); const workflow = new Workflow();
Object.assign(workflow, { Object.assign(workflow, {
...metaWorkflow, ...metaWorkflow,
@ -97,117 +105,130 @@ export class WorkflowController extends Controller {
profileType: profileType, profileType: profileType,
system: body.sysName, system: body.sysName,
}); });
await this.workflowRepo.save(workflow);
const metaState = await this.metaStateRepo.find({ const [savedWorkflow, metaStates] = await Promise.all([
where: { this.workflowRepo.save(workflow),
metaWorkflowId: metaWorkflow.id, this.metaStateRepo.find({
}, where: { metaWorkflowId: metaWorkflow.id },
order: { order: "ASC" }, order: { order: "ASC" },
}),
]);
// ขั้นที่ 3: สร้าง states ทั้งหมดในครั้งเดียว
const statesToCreate = metaStates.map((item) => {
const state = new State();
Object.assign(state, { ...item, id: undefined, workflowId: savedWorkflow.id, ...meta });
return state;
}); });
await Promise.all( const savedStates = await this.stateRepo.save(statesToCreate);
metaState.map(async (item) => {
const state = new State(); // ขั้นที่ 4: อัปเดต workflow.stateId กับ state แรก
Object.assign(state, { ...item, id: undefined, workflowId: workflow.id, ...meta }); const firstState = savedStates.find((state) => state.order === 1);
await this.stateRepo.save(state); if (firstState) {
if (state.order == 1) { savedWorkflow.stateId = firstState.id;
workflow.stateId = state.id; await this.workflowRepo.save(savedWorkflow);
await this.workflowRepo.save(workflow); }
}
const metaStateOperator = await this.metaStateOperatorRepo.find({ // ขั้นที่ 5: ดึง metaStateOperators ทั้งหมดและสร้าง stateOperators
where: { const metaStateIds = metaStates.map((item) => item.id);
metaStateId: item.id, const allMetaStateOperators = await this.metaStateOperatorRepo.find({
}, where: { metaStateId: In(metaStateIds) },
});
// สร้าง stateOperators ทั้งหมดในครั้งเดียว
const stateOperatorsToCreate: StateOperator[] = [];
allMetaStateOperators.forEach((metaStateOp) => {
const correspondingState = savedStates.find(
(state) =>
metaStates.find((metaState) => metaState.id === metaStateOp.metaStateId)?.order ===
state.order,
);
if (correspondingState) {
const stateOperator = new StateOperator();
Object.assign(stateOperator, {
...metaStateOp,
id: undefined,
stateId: correspondingState.id,
...meta,
}); });
await Promise.all( stateOperatorsToCreate.push(stateOperator);
metaStateOperator.map(async (item1) => { }
const stateOperator = new StateOperator(); });
Object.assign(stateOperator, { ...item1, id: undefined, stateId: state.id, ...meta });
await this.stateOperatorRepo.save(stateOperator); await this.stateOperatorRepo.save(stateOperatorsToCreate);
}), // ขั้นที่ 6: สร้าง StateOperatorUsers แบบ bulk
); const stateOperatorUsersToCreate: StateOperatorUser[] = [];
}), let orderNum = 1;
);
let num = 1; // เพิ่ม Owner ก่อน
const stateOperatorUser = new StateOperatorUser();
if (profile) { if (profile) {
Object.assign(stateOperatorUser, { const ownerStateOperatorUser = new StateOperatorUser();
profileId: profileType == "OFFICER" ? profile.id : null, Object.assign(ownerStateOperatorUser, {
profileEmployeeId: profileType != "OFFICER" ? profile.id : null, profileId: profileType === "OFFICER" ? profile.id : null,
profileEmployeeId: profileType !== "OFFICER" ? profile.id : null,
profileType: profileType, profileType: profileType,
operator: "Owner", operator: "Owner",
order: num, order: orderNum,
workflowId: workflow.id, workflowId: savedWorkflow.id,
...meta, ...meta,
}); });
stateOperatorUsersToCreate.push(ownerStateOperatorUser);
} }
await this.stateOperatorUserRepo.save(stateOperatorUser);
const profileOfficer = await this.posMasterRepo.find({ // ดึงข้อมูล profileOfficers และสร้าง StateOperatorUsers
const profileOfficers = await this.posMasterRepo.find({
where: { where: {
posMasterAssigns: { assignId: body.sysName }, posMasterAssigns: { assignId: body.sysName },
orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true }, orgRevision: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true },
current_holderId: Not(IsNull()), // เพิ่มเงื่อนไขนี้เพื่อกรองเฉพาะที่มี current_holder
}, },
relations: ["orgChild1"], relations: ["orgChild1"],
select: ["current_holderId", "orgChild1"], // เลือกเฉพาะ field ที่จำเป็น
}); });
await Promise.all(
profileOfficer.map(async (item, i) => { // สร้าง StateOperatorUsers สำหรับ officers
if (item.current_holderId) { profileOfficers.forEach((item) => {
num = num + 1; if (item.current_holderId) {
if (item.orgChild1 == null || item.orgChild1.isOfficer == false) { orderNum += 1;
const stateOperatorUser = new StateOperatorUser(); const isPersonnelOfficer = item.orgChild1?.isOfficer === true;
Object.assign(stateOperatorUser, {
profileId: item.current_holderId, const officerStateOperatorUser = new StateOperatorUser();
operator: "Officer", Object.assign(officerStateOperatorUser, {
profileType: "OFFICER", profileId: item.current_holderId,
order: num, operator: isPersonnelOfficer ? "PersonnelOfficer" : "Officer",
workflowId: workflow.id, profileType: "OFFICER",
...meta, order: orderNum,
}); workflowId: savedWorkflow.id,
await this.stateOperatorUserRepo.save(stateOperatorUser); ...meta,
} else { });
const stateOperatorUser = new StateOperatorUser(); stateOperatorUsersToCreate.push(officerStateOperatorUser);
Object.assign(stateOperatorUser, { }
profileId: item.current_holderId, });
operator: "PersonnelOfficer",
profileType: "OFFICER", // บันทึก StateOperatorUsers ทั้งหมดในครั้งเดียว
order: num, await this.stateOperatorUserRepo.save(stateOperatorUsersToCreate);
workflowId: workflow.id,
...meta, // ขั้นที่ 7: ส่ง notification (ใช้ข้อมูลที่มีอยู่แล้วแทนการ query ใหม่)
}); const firstStateOperators = stateOperatorsToCreate.filter((so) =>
await this.stateOperatorUserRepo.save(stateOperatorUser); savedStates.find((state) => state.id === so.stateId && state.order === 1),
}
}
}),
); );
const _workflow = await this.workflowRepo.findOne({ const notificationReceivers = stateOperatorUsersToCreate
where: { id: workflow.id }, .filter((user) => firstStateOperators.some((op) => op.operator === user.operator))
relations: ["stateOperatorUsers"], .map((user) => ({
}); receiverUserId: user.profileType === "OFFICER" ? user.profileId : user.profileEmployeeId,
if (!_workflow) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่สามารถดำเนินการกระบวนการนี้ได้");
const _state = await this.stateRepo.findOne({
where: {
id: _workflow.stateId,
},
relations: ["stateOperators"],
});
if (!_state) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลขั้นตอนการอนุมัติ");
let profileNow = _workflow.stateOperatorUsers
.filter((x) => _state.stateOperators.map((s) => s.operator).includes(x.operator))
.map((x) => ({
receiverUserId: x.profileType == "OFFICER" ? x.profileId : x.profileEmployeeId,
notiLink: "", notiLink: "",
})); }));
await new CallAPI()
// ส่ง notification แบบ fire-and-forget
new CallAPI()
.PostData(req, "/placement/noti/profiles", { .PostData(req, "/placement/noti/profiles", {
// subject: `รายการถูกส่ง`, subject: `แจ้ง${savedWorkflow.name}ของ ${body.fullName}`,
// body: `รายการถูกส่ง`, body: `แจ้ง${savedWorkflow.name}ของ ${body.fullName}`,
subject: `แจ้ง${workflow.name}ของ ${body.fullName}`, receiverUserIds: notificationReceivers,
body: `แจ้ง${workflow.name}ของ ${body.fullName}`, payload: "",
receiverUserIds: profileNow,
payload: "", //แนบไฟล์
isSendMail: true, isSendMail: true,
isSendInbox: true, isSendInbox: true,
isSendNotification: true, isSendNotification: true,
@ -809,8 +830,8 @@ export class WorkflowController extends Controller {
pageSize: number; pageSize: number;
keycloakId?: string | null; keycloakId?: string | null;
type?: string | null; type?: string | null;
sortBy?: string | null, sortBy?: string | null;
descending?: boolean, descending?: boolean;
}, },
) { ) {
const userKeycloak = body.keycloakId ?? request.user.sub; const userKeycloak = body.keycloakId ?? request.user.sub;
@ -990,10 +1011,10 @@ export class WorkflowController extends Controller {
if (body.sortBy) { if (body.sortBy) {
queryBuilder = queryBuilder.orderBy( queryBuilder = queryBuilder.orderBy(
`entity.${body.sortBy}`, `entity.${body.sortBy}`,
body.descending ? "DESC" : "ASC" body.descending ? "DESC" : "ASC",
); );
} }
// 7. Execute พร้อมกัน - ใช้ Promise.all // 7. Execute พร้อมกัน - ใช้ Promise.all
const [data, total] = await Promise.all([ const [data, total] = await Promise.all([
queryBuilder queryBuilder