2024-11-14 17:02:41 +08:00
|
|
|
package model
|
|
|
|
|
|
|
|
import (
|
|
|
|
"approveflow/app/base"
|
2024-11-15 16:53:35 +08:00
|
|
|
"approveflow/app/provider/abstract/connect"
|
2024-11-14 17:02:41 +08:00
|
|
|
"approveflow/app/provider/flow_definition"
|
2024-11-15 16:53:35 +08:00
|
|
|
"approveflow/app/utils"
|
2024-11-14 17:02:41 +08:00
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"github.com/Superdanda/hade/framework/gin"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
StatusCreated = "Created" // 审批实例已创建
|
2024-11-19 17:03:12 +08:00
|
|
|
StatusReject = "Reject" // 审批实例已创建
|
2024-11-14 17:02:41 +08:00
|
|
|
StatusInProgress = "InProgress" // 审批进行中
|
|
|
|
StatusCompleted = "Completed" // 审批完成
|
|
|
|
StatusCancelled = "Cancelled" // 审批取消
|
|
|
|
)
|
|
|
|
|
|
|
|
// ApprovalInstance 审批实例表
|
|
|
|
type ApprovalInstance struct {
|
2024-11-19 17:03:12 +08:00
|
|
|
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"` // 主键ID
|
|
|
|
FlowID int64 `gorm:"type:bigint;index;not null" json:"flow_id"` // 流程ID
|
|
|
|
ApplicantKey string `gorm:"type:bigint;index;not null" json:"approver_id"` //申请人ID
|
|
|
|
CreatorKey string `gorm:"type:bigint;not null" json:"creator_id"` // 创建者ID
|
|
|
|
Status string `gorm:"-" json:"status"` // 审批状态
|
|
|
|
CurrentStepIDs []*CurrentStep `gorm:"foreignKey:InstanceID;constraint:OnDelete:CASCADE" json:"current_step_ids"` // 当前步骤ID
|
|
|
|
Steps []*InstanceStep `gorm:"foreignKey:InstanceID;constraint:OnDelete:CASCADE" json:"steps"` // 实例步骤
|
|
|
|
StatusEvents []*InstanceStatusEvent `gorm:"foreignKey:InstanceID;constraint:OnDelete:CASCADE" json:"status_events"` // 实例步骤
|
|
|
|
Data string `gorm:"type:json" json:"data"`
|
|
|
|
NodeMap map[string]connect.AbstractNode `gorm:"-" json:"node_map"` // 保存审批数据的 JSON
|
|
|
|
TenantKey string `gorm:"type:varchar(50);not null" json:"tenant_key"`
|
|
|
|
AssociateKey string `gorm:"type:varchar(50);not null" json:"associate_key"`
|
2024-11-14 17:02:41 +08:00
|
|
|
sync.RWMutex
|
|
|
|
base.Model
|
|
|
|
}
|
|
|
|
|
2024-11-19 17:03:12 +08:00
|
|
|
// InstanceStatusEvent 审批实例状态表
|
|
|
|
type InstanceStatusEvent struct {
|
|
|
|
InstanceID int64 `gorm:"type:bigint;not null" json:"instance_id"`
|
|
|
|
Status string `gorm:"type:varchar(50);not null" json:"status"`
|
|
|
|
Extension string `gorm:"type:varchar(50);not null" json:"extension"`
|
|
|
|
base.Model
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) CheckIfComplete() bool {
|
|
|
|
currentSteps := instance.GetCurrentSteps()
|
|
|
|
if instance.GetStatus() == StatusCompleted {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if len(currentSteps) == 1 && currentSteps[0].StepCode == flow_definition.StepEnd {
|
|
|
|
currentSteps[0].AddCompletedEvent()
|
|
|
|
instance.AddCompletedEvent()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) MarshalBinary() ([]byte, error) {
|
|
|
|
return json.Marshal(instance)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) UnmarshalBinary(data []byte) error {
|
|
|
|
return json.Unmarshal(data, instance)
|
|
|
|
}
|
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
func (instance *ApprovalInstance) GetNodes() []connect.AbstractNode {
|
|
|
|
return utils.ConvertToAbstractNodes(instance.Steps, func(step *InstanceStep) connect.AbstractNode {
|
|
|
|
return step
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) SetNodes(nodes []connect.AbstractNode) {
|
2024-11-19 17:03:12 +08:00
|
|
|
specificType, _ := utils.ConvertToSpecificType[*InstanceStep, connect.AbstractNode](nodes, func(node connect.AbstractNode) (*InstanceStep, bool) {
|
|
|
|
return node.(*InstanceStep), true
|
|
|
|
})
|
|
|
|
instance.Steps = specificType
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetNodeMap() map[string]connect.AbstractNode {
|
2024-11-19 17:03:12 +08:00
|
|
|
if instance.NodeMap == nil {
|
|
|
|
instance.NodeMap = map[string]connect.AbstractNode{}
|
|
|
|
connect.InitializeNodeMap(instance)
|
|
|
|
}
|
|
|
|
return instance.NodeMap
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) NewNodePathConfig(fromNodeKey, toNodeKey string) connect.AbstractNodePathConfig {
|
2024-11-19 17:03:12 +08:00
|
|
|
fromStep, err := instance.GetStepByKey(fromNodeKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return NewDynamicPathConfig(instance.ID, fromStep.ID, fromNodeKey, toNodeKey, false)
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
|
|
|
|
2024-11-14 17:02:41 +08:00
|
|
|
// CurrentStep 目前审批中的节点
|
|
|
|
type CurrentStep struct {
|
|
|
|
CurrentStepId int64 `gorm:"type:bigint;index;not null" json:"current_step_id"`
|
|
|
|
InstanceID int64 `gorm:"type:bigint;index;not null" json:"instance_id"`
|
2024-11-19 17:03:12 +08:00
|
|
|
base.Model
|
|
|
|
}
|
|
|
|
|
|
|
|
func (current *CurrentStep) MarshalBinary() ([]byte, error) {
|
|
|
|
return json.Marshal(current)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (current *CurrentStep) UnmarshalBinary(data []byte) error {
|
|
|
|
return json.Unmarshal(data, current)
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewApprovalInstance 初始化创建一个审批流实例
|
|
|
|
func NewApprovalInstance(
|
|
|
|
ctx *gin.Context,
|
|
|
|
approvalFlow *flow_definition.ApprovalFlow,
|
|
|
|
data map[string]interface{}) (*ApprovalInstance, error) {
|
|
|
|
|
|
|
|
bytes, err := json.Marshal(data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
instance := &ApprovalInstance{
|
2024-11-15 16:53:35 +08:00
|
|
|
FlowID: approvalFlow.ID,
|
|
|
|
ApplicantKey: data[base.ApplicantKey].(string),
|
|
|
|
CreatorKey: data[base.CreatorKey].(string),
|
|
|
|
Steps: []*InstanceStep{},
|
|
|
|
Data: string(bytes),
|
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
|
|
|
|
// 保存租户键和关联键
|
|
|
|
if value, ok := data[base.TenantKey]; ok {
|
|
|
|
instance.TenantKey = value.(string)
|
|
|
|
}
|
|
|
|
if value, ok := data[base.AssociateKey]; ok {
|
|
|
|
instance.TenantKey = value.(string)
|
|
|
|
}
|
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
// Get the first step of the approval flow
|
|
|
|
firstStep, err := approvalFlow.FirstStep()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// Build the steps recursively
|
|
|
|
processedSteps := make(map[string]*InstanceStep)
|
2024-11-19 17:03:12 +08:00
|
|
|
err = buildInstanceSteps(ctx, approvalFlow, instance, firstStep, nil, data, processedSteps)
|
2024-11-15 16:53:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
|
|
|
|
// 赋予创建状态
|
|
|
|
instance.AddCreatedEvent()
|
2024-11-15 16:53:35 +08:00
|
|
|
return instance, nil
|
|
|
|
}
|
2024-11-14 17:02:41 +08:00
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
// buildInstanceSteps recursively builds instance steps from approval steps
|
2024-11-19 17:03:12 +08:00
|
|
|
func buildInstanceSteps(ctx *gin.Context, approvalFlow *flow_definition.ApprovalFlow,
|
|
|
|
instance *ApprovalInstance, currentApprovalStep *flow_definition.ApprovalStep,
|
2024-11-15 16:53:35 +08:00
|
|
|
previousInstanceStep *InstanceStep, data map[string]interface{}, processedSteps map[string]*InstanceStep) error {
|
|
|
|
// Check if this step has already been processed to avoid cycles
|
|
|
|
if existingInstanceStep, ok := processedSteps[currentApprovalStep.Key]; ok {
|
|
|
|
if previousInstanceStep != nil {
|
|
|
|
connect.InsertNodeAfter(instance, previousInstanceStep, existingInstanceStep)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
var approverKey string
|
2024-11-19 17:03:12 +08:00
|
|
|
if currentApprovalStep.DynamicConfig != nil {
|
|
|
|
approver, err := currentApprovalStep.DynamicConfig.GetApprover(ctx, data)
|
|
|
|
if err != nil {
|
|
|
|
approverKey = ""
|
|
|
|
} else {
|
|
|
|
approverKey = approver.Key
|
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
} else {
|
2024-11-19 17:03:12 +08:00
|
|
|
approverKey = ""
|
2024-11-15 16:53:35 +08:00
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
currentInstanceStep := NewInstanceStep(currentApprovalStep, approverKey, false)
|
2024-11-19 17:03:12 +08:00
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
// Insert the instance step into the instance
|
|
|
|
if previousInstanceStep == nil {
|
|
|
|
connect.InsertNodeFirst(instance, currentInstanceStep)
|
|
|
|
} else {
|
|
|
|
connect.InsertNodeAfter(instance, previousInstanceStep, currentInstanceStep)
|
|
|
|
}
|
|
|
|
// Mark this step as processed
|
|
|
|
processedSteps[currentApprovalStep.Key] = currentInstanceStep
|
2024-11-19 17:03:12 +08:00
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
// Get the next steps and recursively build them
|
2024-11-19 17:03:12 +08:00
|
|
|
flowStep, err := approvalFlow.GetStep(currentInstanceStep.StepID)
|
|
|
|
nextFlowSteps, err := connect.GetNextNodes(approvalFlow, flowStep)
|
2024-11-15 16:53:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
for _, nextStep := range nextFlowSteps {
|
2024-11-15 16:53:35 +08:00
|
|
|
nextApprovalStep := nextStep.(*flow_definition.ApprovalStep)
|
2024-11-19 17:03:12 +08:00
|
|
|
err := buildInstanceSteps(ctx, approvalFlow, instance, nextApprovalStep, currentInstanceStep, data, processedSteps)
|
2024-11-14 17:02:41 +08:00
|
|
|
if err != nil {
|
2024-11-15 16:53:35 +08:00
|
|
|
return err
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
return nil
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// SendApprovalNotification 发送审批通知给第一个审批人的方法
|
|
|
|
func (instance *ApprovalInstance) SendApprovalNotification(step *InstanceStep, ctx context.Context) error {
|
|
|
|
|
|
|
|
// 向消息队列发送审批开始事件
|
|
|
|
|
|
|
|
//userService := container.MustMake(userProvider.Key).(userProvider.Service)
|
|
|
|
//approver, err := userService.GetUserByID(step.ApproverID)
|
|
|
|
//if err != nil {
|
|
|
|
// return fmt.Errorf("获取审批人失败: %v", err)
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//// 构建通知内容
|
|
|
|
//notification := fmt.Sprintf("审批流程已启动,请您审批步骤: %s", step.Name)
|
|
|
|
//
|
|
|
|
//// 发送通知
|
|
|
|
//err = sendNotificationToUser(approver, notification)
|
|
|
|
//if err != nil {
|
|
|
|
// return fmt.Errorf("发送通知失败: %v", err)
|
|
|
|
//}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start 开始审批流程,设置第一个步骤为当前步骤
|
|
|
|
func (instance *ApprovalInstance) Start(ctx context.Context) error {
|
|
|
|
instance.RLock()
|
|
|
|
defer instance.RUnlock()
|
|
|
|
|
2024-11-19 17:03:12 +08:00
|
|
|
if instance.GetStatus() != StatusCreated && instance.GetStatus() != StatusReject {
|
2024-11-14 17:02:41 +08:00
|
|
|
return fmt.Errorf("审批流程已启动或已完成,无法再次启动")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取第一个审批步骤
|
2024-11-15 16:53:35 +08:00
|
|
|
firstStep, err := instance.getFirstStep()
|
2024-11-14 17:02:41 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// 设置当前步骤为第一个步骤,并更改状态
|
|
|
|
instance.AddCurrentStepID(firstStep)
|
2024-11-19 17:03:12 +08:00
|
|
|
instance.AddInProgressEvent()
|
2024-11-14 17:02:41 +08:00
|
|
|
|
|
|
|
err = instance.SendApprovalNotification(firstStep, ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// getFirstStep 获取第一个审批步骤
|
2024-11-15 16:53:35 +08:00
|
|
|
func (instance *ApprovalInstance) getFirstStep() (*InstanceStep, error) {
|
2024-11-14 17:02:41 +08:00
|
|
|
for _, step := range instance.Steps {
|
2024-11-15 16:53:35 +08:00
|
|
|
if step.StepCode == flow_definition.StepStart {
|
|
|
|
return step, nil
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
return nil, errors.New("未找到起点")
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// MoveToNextStep 移动到下一个步骤
|
|
|
|
func (instance *ApprovalInstance) MoveToNextStep() error {
|
|
|
|
instance.Lock()
|
|
|
|
defer instance.Unlock()
|
|
|
|
|
|
|
|
currentStepSlice := instance.GetCurrentSteps()
|
|
|
|
|
|
|
|
if currentStepSlice == nil || len(currentStepSlice) == 0 {
|
|
|
|
return fmt.Errorf("当前步骤不存在")
|
|
|
|
}
|
|
|
|
|
|
|
|
dataMap, err := instance.DataToMap()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
currentStep := currentStepSlice[0]
|
|
|
|
// 完成当前步骤
|
2024-11-19 17:03:12 +08:00
|
|
|
currentStep.AddCompletedEvent()
|
2024-11-14 17:02:41 +08:00
|
|
|
|
|
|
|
// 获取下一个步骤
|
|
|
|
var nextStep *InstanceStep
|
|
|
|
nextStepArr, err := instance.getNextStep(currentStep, dataMap)
|
2024-11-19 17:03:12 +08:00
|
|
|
if nextStepArr != nil && len(nextStepArr) == 1 {
|
2024-11-14 17:02:41 +08:00
|
|
|
nextStep = nextStepArr[0]
|
|
|
|
} else {
|
|
|
|
return errors.New("暂时不支持并行审批")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2024-11-19 17:03:12 +08:00
|
|
|
instance.AddCompletedEvent() // 流程结束
|
2024-11-14 17:02:41 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 设置新的当前步骤
|
|
|
|
instance.RemoveCurrentStepID(currentStep.ID)
|
|
|
|
instance.AddCurrentStepID(nextStep)
|
|
|
|
|
2024-11-19 17:03:12 +08:00
|
|
|
nextStep.AddPendingEvent()
|
|
|
|
|
2024-11-14 17:02:41 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// getNextStep 获取下一个步骤
|
|
|
|
func (instance *ApprovalInstance) getNextStep(currentStep *InstanceStep, data map[string]interface{}) ([]*InstanceStep, error) {
|
2024-11-15 16:53:35 +08:00
|
|
|
pathConfigs := currentStep.InstancePathConfigs
|
|
|
|
var nextSteps []*InstanceStep
|
|
|
|
for _, pathConfig := range pathConfigs {
|
|
|
|
met, err := pathConfig.IsConditionMet(data)
|
|
|
|
if err != nil || !met {
|
|
|
|
continue
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
nextStep, err := instance.GetStepByKey(pathConfig.GetToNodeKey())
|
2024-11-14 17:02:41 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
nextSteps = append(nextSteps, nextStep)
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
return nextSteps, nil
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) findStepByID(id int64) (*InstanceStep, error) {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.ID == id {
|
|
|
|
return step, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) findStepByKey(key string) (*InstanceStep, error) {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.Key == key {
|
|
|
|
return step, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) getStepByFlowStepID(flowStepId int64) *InstanceStep {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.StepID == flowStepId {
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DataToMap 将 Data 字段转为 map[string]interface{}
|
|
|
|
func (instance *ApprovalInstance) DataToMap() (map[string]interface{}, error) {
|
|
|
|
var dataMap map[string]interface{}
|
|
|
|
if err := json.Unmarshal([]byte(instance.Data), &dataMap); err != nil {
|
|
|
|
return nil, fmt.Errorf("解析 Data 字段失败: %v", err)
|
|
|
|
}
|
|
|
|
return dataMap, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetStep(id int64) (*InstanceStep, error) {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.ID == id {
|
|
|
|
return step, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("step with ID %d not found in approval flow", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetStepByKey(key string) (*InstanceStep, error) {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.Key == key {
|
|
|
|
return step, nil
|
|
|
|
}
|
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
return nil, fmt.Errorf("step with key %s not found in approval flow", key)
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddCurrentStepID adds a new CurrentStep to the CurrentStepIDs slice if it does not already exist
|
|
|
|
func (instance *ApprovalInstance) AddCurrentStepID(step *InstanceStep) {
|
|
|
|
// Check if the step already exists
|
|
|
|
for _, s := range instance.CurrentStepIDs {
|
|
|
|
if s.CurrentStepId == step.ID {
|
|
|
|
return // Step already exists, do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add the new step
|
|
|
|
instance.CurrentStepIDs = append(instance.CurrentStepIDs, &CurrentStep{CurrentStepId: step.ID, InstanceID: instance.ID})
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveCurrentStepID removes a CurrentStep from the CurrentStepIDs slice based on its ID
|
|
|
|
func (instance *ApprovalInstance) RemoveCurrentStepID(stepID int64) {
|
|
|
|
// Find the index of the step to remove
|
|
|
|
for i, s := range instance.CurrentStepIDs {
|
|
|
|
if s.CurrentStepId == stepID {
|
|
|
|
// Remove the step by slicing
|
2024-11-19 17:03:12 +08:00
|
|
|
s.Delete()
|
2024-11-14 17:02:41 +08:00
|
|
|
instance.CurrentStepIDs = append(instance.CurrentStepIDs[:i], instance.CurrentStepIDs[i+1:]...)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// HasCurrentStepID checks if a CurrentStep with a given ID exists in the CurrentStepIDs slice
|
|
|
|
func (instance *ApprovalInstance) HasCurrentStepID(stepID int64) bool {
|
|
|
|
for _, s := range instance.CurrentStepIDs {
|
|
|
|
if s.CurrentStepId == stepID {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCurrentSteps returns a copy of the CurrentSteps slice
|
|
|
|
func (instance *ApprovalInstance) GetCurrentSteps() []*InstanceStep {
|
|
|
|
// Return a copy of the slice to avoid modifications
|
2024-11-19 17:03:12 +08:00
|
|
|
var currentSteps []*InstanceStep
|
2024-11-14 17:02:41 +08:00
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if instance.HasCurrentStepID(step.ID) {
|
|
|
|
currentSteps = append(currentSteps, step)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return currentSteps
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetCurrentStepsById(id int64) *InstanceStep {
|
|
|
|
currentSteps := instance.GetCurrentSteps()
|
|
|
|
for _, step := range currentSteps {
|
|
|
|
if step.ID == id {
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-11-19 17:03:12 +08:00
|
|
|
func (instance *ApprovalInstance) ExecuteApprovalReversal(reversal *ApprovalReversal) error {
|
|
|
|
step, err := instance.GetStepByKey(reversal.StepKey)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
currentStep := instance.GetCurrentStepsById(step.ID)
|
|
|
|
if currentStep == nil {
|
|
|
|
return errors.New("当前反转节点不是正在审批的节点")
|
|
|
|
}
|
|
|
|
switch reversal.FixAction {
|
|
|
|
case FixActionReApproveAndUpdateData:
|
|
|
|
err := currentStep.Reject(reversal.Reason)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// 移除当前所有节点,替换为开始节点
|
|
|
|
for _, step := range instance.GetCurrentSteps() {
|
|
|
|
instance.RemoveCurrentStepID(step.ID)
|
|
|
|
}
|
|
|
|
reversalStep, err := instance.GetStepByKey(reversal.ReversedStepKey)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
// 所有节点重新加入待审批事件
|
|
|
|
if step.GetStatus() == StepStatusApproved {
|
|
|
|
// 如果是通过的话要再审批
|
|
|
|
step.AddPendingEvent()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
instance.AddCurrentStepID(reversalStep)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) Reversal(step *InstanceStep, reversedStep *InstanceStep, reason string, fixAction string) error {
|
|
|
|
reversal := NewReversal(step, reversedStep, reason, fixAction)
|
|
|
|
step.addApprovalReversal(reversal)
|
|
|
|
instance.AddRejectEvent()
|
|
|
|
return instance.ExecuteApprovalReversal(reversal)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExecuteApprovalStep 执行审批步骤规则
|
|
|
|
func (instance *ApprovalInstance) ExecuteApprovalStep(approvalFlow *flow_definition.ApprovalFlow) error {
|
|
|
|
currentSteps := instance.GetCurrentSteps()
|
|
|
|
for _, instanceStep := range currentSteps {
|
|
|
|
|
|
|
|
// 只对待审批的节点进行处理
|
|
|
|
if instanceStep.GetStatus() != StepStatusPending {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
flowStep, err := approvalFlow.GetStep(instanceStep.StepID)
|
2024-11-14 17:02:41 +08:00
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, rule := range flowStep.Rules {
|
|
|
|
// 评估条件表达式是否满足
|
|
|
|
dataToMap, err := instance.DataToMap()
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
conditionMet, err := rule.EvaluateCondition(dataToMap)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if conditionMet {
|
|
|
|
switch rule.Action {
|
|
|
|
case flow_definition.ActionAutoApprove:
|
|
|
|
// 自动通过
|
|
|
|
err := instanceStep.Approve("自动通过")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
//case ActionAutoReject:
|
|
|
|
// // 自动驳回
|
|
|
|
// err := instanceService.RejectStep(ctx, instance, step, "自动驳回")
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
// return nil
|
|
|
|
//case ActionReassignApprover:
|
|
|
|
// // 重新指定审批人
|
|
|
|
// newApprover, err := getNewApprover(container, data)
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
// step.ApproverID = newApprover.ID
|
|
|
|
// // 更新步骤信息
|
|
|
|
// err = updateApprovalStep(step)
|
|
|
|
// if err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
// return nil
|
|
|
|
// 可以添加更多的 Action 处理逻辑
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unsupported action: %s", rule.Action)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
return instance.CheckIfMoveToNextStep(currentSteps)
|
|
|
|
}
|
2024-11-14 17:02:41 +08:00
|
|
|
|
2024-11-19 17:03:12 +08:00
|
|
|
func (instance *ApprovalInstance) CheckIfMoveToNextStep(currentSteps []*InstanceStep) error {
|
|
|
|
if instance.CheckIfComplete() {
|
|
|
|
return errors.New("当前审批流已结束")
|
|
|
|
}
|
|
|
|
|
|
|
|
// 如果当前节点所有的处理完毕,那么当前节点将向后移动
|
|
|
|
currentIsCompleted := true
|
|
|
|
for _, step := range currentSteps {
|
|
|
|
if step.GetStatus() != StepStatusCompleted && step.GetStatus() != StepStatusApproved {
|
|
|
|
currentIsCompleted = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if currentIsCompleted {
|
|
|
|
err := instance.MoveToNextStep()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
instance.CheckIfComplete()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return nil
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
func (instance *ApprovalInstance) GetPathByFromStepKey(fromStepKey string) (*InstancePathConfig, error) {
|
2024-11-14 17:02:41 +08:00
|
|
|
|
2024-11-15 16:53:35 +08:00
|
|
|
return nil, nil
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetStartStep() *InstanceStep {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.StepCode == flow_definition.StepStart {
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetEndStep() *InstanceStep {
|
|
|
|
for _, step := range instance.Steps {
|
|
|
|
if step.StepCode == flow_definition.StepEnd {
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) GetStatus() string {
|
|
|
|
return instance.StatusEvents[len(instance.StatusEvents)-1].Status
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) AddStatusEvent(status string) {
|
|
|
|
if instance.StatusEvents == nil {
|
|
|
|
instance.StatusEvents = make([]*InstanceStatusEvent, 0)
|
|
|
|
}
|
|
|
|
if len(instance.StatusEvents) > 0 && instance.GetStatus() == status {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
instance.StatusEvents = append(instance.StatusEvents, &InstanceStatusEvent{
|
|
|
|
InstanceID: instance.ID, Status: status, Extension: "",
|
|
|
|
})
|
|
|
|
instance.Status = status
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) AddCreatedEvent() {
|
|
|
|
instance.AddStatusEvent(StatusCreated)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) AddRejectEvent() {
|
|
|
|
instance.AddStatusEvent(StatusReject)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) AddInProgressEvent() {
|
|
|
|
instance.AddStatusEvent(StatusInProgress)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) AddCompletedEvent() {
|
|
|
|
instance.AddStatusEvent(StatusCompleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (instance *ApprovalInstance) AddCancelledEvent() {
|
|
|
|
instance.AddStatusEvent(StatusCancelled)
|
|
|
|
}
|