93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
import { Injectable, BadRequestException } from '@nestjs/common';
|
|
import {
|
|
WorkflowStep,
|
|
WorkflowAction,
|
|
StepStatus,
|
|
TransitionResult,
|
|
} from './interfaces/workflow.interface.js';
|
|
|
|
@Injectable()
|
|
export class WorkflowEngineService {
|
|
/**
|
|
* คำนวณสถานะถัดไป (Next State Transition)
|
|
* @param currentSequence ลำดับปัจจุบัน
|
|
* @param totalSteps จำนวนขั้นตอนทั้งหมด
|
|
* @param action การกระทำ (Approve/Reject/Return)
|
|
* @param returnToSequence (Optional) ถ้า Return จะให้กลับไปขั้นไหน
|
|
*/
|
|
processAction(
|
|
currentSequence: number,
|
|
totalSteps: number,
|
|
action: WorkflowAction,
|
|
returnToSequence?: number,
|
|
): TransitionResult {
|
|
switch (action) {
|
|
case WorkflowAction.APPROVE:
|
|
case WorkflowAction.ACKNOWLEDGE:
|
|
// ถ้าเป็นขั้นตอนสุดท้าย -> จบ Workflow
|
|
if (currentSequence >= totalSteps) {
|
|
return {
|
|
nextStepSequence: null, // ไม่มีขั้นต่อไปแล้ว
|
|
shouldUpdateStatus: true,
|
|
documentStatus: 'COMPLETED', // หรือ APPROVED
|
|
};
|
|
}
|
|
// ถ้ายังไม่จบ -> ไปขั้นต่อไป
|
|
return {
|
|
nextStepSequence: currentSequence + 1,
|
|
shouldUpdateStatus: false,
|
|
};
|
|
|
|
case WorkflowAction.REJECT:
|
|
// จบ Workflow ทันทีแบบไม่สวย
|
|
return {
|
|
nextStepSequence: null,
|
|
shouldUpdateStatus: true,
|
|
documentStatus: 'REJECTED',
|
|
};
|
|
|
|
case WorkflowAction.RETURN:
|
|
// ย้อนกลับไปขั้นตอนก่อนหน้า (หรือที่ระบุ)
|
|
const targetStep = returnToSequence || currentSequence - 1;
|
|
if (targetStep < 1) {
|
|
throw new BadRequestException('Cannot return beyond the first step');
|
|
}
|
|
return {
|
|
nextStepSequence: targetStep,
|
|
shouldUpdateStatus: true,
|
|
documentStatus: 'REVISE_REQUIRED', // สถานะเอกสารเป็น "รอแก้ไข"
|
|
};
|
|
|
|
default:
|
|
throw new BadRequestException(`Invalid action: ${action}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ตรวจสอบว่า User คนนี้ มีสิทธิ์กด Action ในขั้นตอนนี้ไหม
|
|
* (Logic เบื้องต้น - เดี๋ยวเราจะเชื่อมกับ RBAC จริงๆ ใน Service หลัก)
|
|
*/
|
|
validateAccess(
|
|
step: WorkflowStep,
|
|
userOrgId: number,
|
|
userId: number,
|
|
): boolean {
|
|
// ถ้าขั้นตอนนี้ยังไม่ Active (เช่น PENDING หรือ SKIPPED) -> ห้ามยุ่ง
|
|
if (step.status !== StepStatus.IN_PROGRESS) {
|
|
return false;
|
|
}
|
|
|
|
// เช็คว่าตรงกับ Organization ที่กำหนดไหม
|
|
if (step.organizationId && step.organizationId !== userOrgId) {
|
|
return false;
|
|
}
|
|
|
|
// เช็คว่าตรงกับ User ที่กำหนดไหม (ถ้าระบุ)
|
|
if (step.assigneeId && step.assigneeId !== userId) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|