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