2024-10-09 14:14:36 +07:00
|
|
|
import { Body, Controller, Post, Request, Route, Security, Tags } from "tsoa";
|
|
|
|
|
import { AppDataSource } from "../database/data-source";
|
|
|
|
|
import { RequestWithUser } from "../middlewares/user";
|
|
|
|
|
import HttpError from "../interfaces/http-error";
|
|
|
|
|
import HttpStatus from "../interfaces/http-status";
|
|
|
|
|
import HttpSuccess from "../interfaces/http-success";
|
|
|
|
|
import { Workflow } from "../entities/Workflow";
|
|
|
|
|
import { State } from "../entities/State";
|
|
|
|
|
import { StateOperator } from "../entities/StateOperator";
|
2024-10-09 16:20:43 +07:00
|
|
|
import { StateOperatorUser } from "../entities/StateOperatorUser";
|
|
|
|
|
import CallAPI from "../interfaces/call-api";
|
|
|
|
|
import { Profile } from "../entities/Profile";
|
2024-10-09 14:14:36 +07:00
|
|
|
|
|
|
|
|
@Route("api/v1/org/workflow")
|
|
|
|
|
@Tags("AuthRole")
|
|
|
|
|
@Security("bearerAuth")
|
|
|
|
|
export class WorkflowController extends Controller {
|
|
|
|
|
private workflowRepo = AppDataSource.getRepository(Workflow);
|
|
|
|
|
private stateRepo = AppDataSource.getRepository(State);
|
|
|
|
|
private stateOperatorRepo = AppDataSource.getRepository(StateOperator);
|
2024-10-09 16:20:43 +07:00
|
|
|
private stateOperatorUserRepo = AppDataSource.getRepository(StateOperatorUser);
|
|
|
|
|
private profileRepo = AppDataSource.getRepository(Profile);
|
|
|
|
|
|
|
|
|
|
@Post("check-workflow")
|
|
|
|
|
public async checkWorkflow(
|
|
|
|
|
@Request() req: RequestWithUser,
|
|
|
|
|
@Body()
|
|
|
|
|
body: {
|
|
|
|
|
sysName: string;
|
|
|
|
|
posLevelName: string;
|
|
|
|
|
posTypeName: string;
|
|
|
|
|
profiles: {
|
|
|
|
|
profile: string;
|
|
|
|
|
operator: string;
|
|
|
|
|
order: number;
|
|
|
|
|
}[];
|
|
|
|
|
},
|
|
|
|
|
) {
|
|
|
|
|
const workflow = await this.workflowRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
sysName: body.sysName,
|
|
|
|
|
posLevelName: body.posLevelName,
|
|
|
|
|
posTypeName: body.posTypeName,
|
|
|
|
|
},
|
|
|
|
|
relations: ["states"],
|
|
|
|
|
});
|
|
|
|
|
if (!workflow) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบกระบวนการนี้ได้");
|
|
|
|
|
await Promise.all(
|
|
|
|
|
body.profiles.map(async (item) => {
|
|
|
|
|
const operatoeUser = new StateOperatorUser();
|
|
|
|
|
operatoeUser.profile = item.profile;
|
|
|
|
|
operatoeUser.operator = item.operator.trim().toLocaleUpperCase();
|
|
|
|
|
operatoeUser.order = item.order;
|
|
|
|
|
operatoeUser.workflowId = workflow.id;
|
|
|
|
|
operatoeUser.createdUserId = req.user.sub;
|
|
|
|
|
operatoeUser.createdFullName = req.user.name;
|
|
|
|
|
operatoeUser.createdAt = new Date();
|
|
|
|
|
operatoeUser.lastUpdateUserId = req.user.sub;
|
|
|
|
|
operatoeUser.lastUpdateFullName = req.user.name;
|
|
|
|
|
operatoeUser.lastUpdatedAt = new Date();
|
|
|
|
|
await this.stateOperatorUserRepo.save(operatoeUser);
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
return new HttpSuccess({
|
|
|
|
|
workflowId: workflow.id,
|
|
|
|
|
stateId: workflow.states.sort((a, b) => a.order - b.order)[0].id,
|
|
|
|
|
// stateName: workflow.states.sort((a, b) => a.order - b.order)[0].name,
|
|
|
|
|
// stateType: workflow.states.sort((a, b) => a.order - b.order)[0].type,
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-10-09 14:14:36 +07:00
|
|
|
|
|
|
|
|
@Post("check-iscan")
|
|
|
|
|
public async checkIsCan(
|
|
|
|
|
@Request() req: RequestWithUser,
|
|
|
|
|
@Body()
|
|
|
|
|
body: {
|
|
|
|
|
workflowId: string;
|
|
|
|
|
stateId: string;
|
2024-10-09 16:20:43 +07:00
|
|
|
profile: string;
|
2024-10-09 14:14:36 +07:00
|
|
|
action: string;
|
|
|
|
|
},
|
|
|
|
|
) {
|
2024-10-09 16:20:43 +07:00
|
|
|
const stateOperatorUser = await this.stateOperatorUserRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
profile: body.profile,
|
|
|
|
|
workflowId: body.workflowId,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
if (!stateOperatorUser)
|
|
|
|
|
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่สามารถดำเนินการกระบวนการนี้ได้");
|
|
|
|
|
|
2024-10-09 14:14:36 +07:00
|
|
|
const operator = await this.stateOperatorRepo.findOne({
|
|
|
|
|
where: {
|
2024-10-09 16:20:43 +07:00
|
|
|
operator: stateOperatorUser.operator,
|
2024-10-09 14:14:36 +07:00
|
|
|
state: { id: body.stateId, workflow: { id: body.workflowId } },
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
if (!operator) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
|
|
|
|
|
|
|
|
|
let isCan = false;
|
2024-10-09 16:20:43 +07:00
|
|
|
switch (body.action.trim().toLocaleUpperCase()) {
|
2024-10-09 14:14:36 +07:00
|
|
|
case "VIEW":
|
|
|
|
|
isCan = operator.canView;
|
|
|
|
|
case "UPDATE":
|
|
|
|
|
isCan = operator.canUpdate;
|
|
|
|
|
case "DELETE":
|
|
|
|
|
isCan = operator.canDelete;
|
|
|
|
|
case "CANCEL":
|
|
|
|
|
isCan = operator.canCancel;
|
|
|
|
|
case "OPERATE":
|
|
|
|
|
isCan = operator.canOperate;
|
|
|
|
|
case "CHANGESTATE":
|
|
|
|
|
isCan = operator.canChangeState;
|
|
|
|
|
case "COMMENT":
|
|
|
|
|
isCan = operator.canComment;
|
|
|
|
|
case "SIGN":
|
|
|
|
|
isCan = operator.canSign;
|
|
|
|
|
default:
|
|
|
|
|
isCan = false;
|
|
|
|
|
}
|
|
|
|
|
if (isCan == false) {
|
|
|
|
|
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่สามารถดำเนินการได้");
|
|
|
|
|
} else {
|
|
|
|
|
return new HttpSuccess();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 16:20:43 +07:00
|
|
|
@Post("check-iscan-all")
|
|
|
|
|
public async checkIsCanAll(
|
2024-10-09 14:14:36 +07:00
|
|
|
@Request() req: RequestWithUser,
|
|
|
|
|
@Body()
|
|
|
|
|
body: {
|
2024-10-09 16:20:43 +07:00
|
|
|
workflowId: string;
|
|
|
|
|
stateId: string;
|
2024-10-09 14:14:36 +07:00
|
|
|
},
|
|
|
|
|
) {
|
2024-10-09 16:20:43 +07:00
|
|
|
const profile = await this.profileRepo.findOne({
|
2024-10-09 14:14:36 +07:00
|
|
|
where: {
|
2024-10-09 16:20:43 +07:00
|
|
|
keycloak: req.user.sub,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
|
|
|
|
const stateOperatorUser = await this.stateOperatorUserRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
profile: profile.id,
|
|
|
|
|
workflowId: body.workflowId,
|
2024-10-09 14:14:36 +07:00
|
|
|
},
|
|
|
|
|
});
|
2024-10-09 16:20:43 +07:00
|
|
|
if (!stateOperatorUser)
|
|
|
|
|
throw new HttpError(HttpStatus.NOT_FOUND, "ไม่สามารถดำเนินการกระบวนการนี้ได้");
|
2024-10-09 14:14:36 +07:00
|
|
|
|
2024-10-09 16:20:43 +07:00
|
|
|
const operator = await this.stateOperatorRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
operator: stateOperatorUser.operator,
|
|
|
|
|
state: { id: body.stateId, workflow: { id: body.workflowId } },
|
|
|
|
|
},
|
2024-10-09 14:14:36 +07:00
|
|
|
});
|
2024-10-09 16:20:43 +07:00
|
|
|
if (!operator) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
|
|
|
|
return new HttpSuccess(operator);
|
2024-10-09 14:14:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post("state-next")
|
|
|
|
|
public async stateNext(
|
|
|
|
|
@Request() req: RequestWithUser,
|
|
|
|
|
@Body()
|
|
|
|
|
body: {
|
|
|
|
|
stateId: string;
|
|
|
|
|
},
|
|
|
|
|
) {
|
|
|
|
|
const state = await this.stateRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
id: body.stateId,
|
|
|
|
|
},
|
2024-10-09 16:20:43 +07:00
|
|
|
relations: ["stateOperators", "workflow", "workflow.stateOperatorUsers"],
|
2024-10-09 14:14:36 +07:00
|
|
|
});
|
|
|
|
|
if (!state) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
|
|
|
|
const _state = await this.stateRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
order: state.order + 1,
|
|
|
|
|
workflowId: state.workflowId,
|
|
|
|
|
},
|
2024-10-09 16:20:43 +07:00
|
|
|
relations: ["stateOperators"],
|
2024-10-09 14:14:36 +07:00
|
|
|
});
|
2024-10-09 16:20:43 +07:00
|
|
|
//noti
|
|
|
|
|
let profileNow = state.workflow.stateOperatorUsers
|
|
|
|
|
.filter((x) => state.stateOperators.map((s) => s.operator).includes(x.operator))
|
|
|
|
|
.map((x) => x.profile);
|
|
|
|
|
await new CallAPI()
|
|
|
|
|
.PostData(req, "/placement/noti/profiles", {
|
|
|
|
|
subject: `รายการถูกส่ง`,
|
|
|
|
|
body: `รายการถูกส่ง`,
|
2024-10-11 13:39:41 +07:00
|
|
|
receiverUserIds: profileNow,
|
2024-10-09 16:20:43 +07:00
|
|
|
payload: "", //แนบไฟล์
|
|
|
|
|
isSendMail: true,
|
|
|
|
|
isSendInbox: true,
|
2024-10-11 10:17:44 +07:00
|
|
|
isSendNotification: true,
|
2024-10-09 16:20:43 +07:00
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
console.error("Error calling API:", error);
|
|
|
|
|
});
|
|
|
|
|
if (_state != null) {
|
|
|
|
|
let profileNext = state.workflow.stateOperatorUsers
|
|
|
|
|
.filter((x) => _state.stateOperators.map((s) => s.operator).includes(x.operator))
|
|
|
|
|
.map((x) => x.profile);
|
|
|
|
|
await new CallAPI()
|
|
|
|
|
.PostData(req, "/placement/noti/profiles", {
|
|
|
|
|
subject: `ได้รับรายการ`,
|
|
|
|
|
body: `ได้รับรายการ`,
|
2024-10-11 13:39:41 +07:00
|
|
|
receiverUserIds: profileNext,
|
2024-10-09 16:20:43 +07:00
|
|
|
payload: "", //แนบไฟล์
|
|
|
|
|
isSendMail: true,
|
|
|
|
|
isSendInbox: true,
|
2024-10-11 10:17:44 +07:00
|
|
|
isSendNotification: true,
|
2024-10-09 16:20:43 +07:00
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
console.error("Error calling API:", error);
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-10-09 14:14:36 +07:00
|
|
|
|
|
|
|
|
return new HttpSuccess({
|
|
|
|
|
stateId: _state?.id || null,
|
|
|
|
|
stateName: _state?.name || null,
|
|
|
|
|
stateType: _state?.type || null,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Post("state-back")
|
|
|
|
|
public async stateBack(
|
|
|
|
|
@Request() req: RequestWithUser,
|
|
|
|
|
@Body()
|
|
|
|
|
body: {
|
|
|
|
|
stateId: string;
|
|
|
|
|
},
|
|
|
|
|
) {
|
|
|
|
|
const state = await this.stateRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
id: body.stateId,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
if (!state) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
|
|
|
|
|
const _state = await this.stateRepo.findOne({
|
|
|
|
|
where: {
|
|
|
|
|
order: state.order - 1,
|
|
|
|
|
workflowId: state.workflowId,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return new HttpSuccess({
|
|
|
|
|
stateId: _state?.id || null,
|
|
|
|
|
stateName: _state?.name || null,
|
|
|
|
|
stateType: _state?.type || null,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|