2024-11-14 17:02:41 +08:00
|
|
|
package flow_definition
|
|
|
|
|
|
|
|
import (
|
|
|
|
"approveflow/app/base"
|
2024-11-15 16:53:35 +08:00
|
|
|
"approveflow/app/provider/abstract/connect"
|
|
|
|
"approveflow/app/utils"
|
2024-11-14 17:02:41 +08:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ApprovalStep 审批步骤表
|
|
|
|
type ApprovalStep struct {
|
2024-11-15 16:53:35 +08:00
|
|
|
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"` // 主键ID
|
|
|
|
FlowID int64 `gorm:"index;not null" json:"flow_id"` // 所属流程ID
|
|
|
|
Name string `gorm:"type:varchar(100);not null" json:"name"` // 步骤名称
|
|
|
|
StepCode string `gorm:"type:varchar(100)" json:"step_code"` // 步骤编号用于标识特殊的审批节点
|
|
|
|
Rules []*ApprovalRule `gorm:"foreignKey:StepID;constraint:OnDelete:CASCADE" json:"rules"` // Foreign key for Rules
|
|
|
|
DynamicConfig *DynamicApprovalStepConfig `gorm:"foreignKey:StepID;constraint:OnDelete:CASCADE" json:"dynamic_config"` // One-to-one with DynamicConfig
|
|
|
|
PathConfigs []*ApprovalPathConfig `gorm:"foreignKey:NodeID;constraint:OnDelete:CASCADE" json:"path_configs"` // 路径配置集合
|
|
|
|
base.Model
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) GetPathConfigs() []connect.AbstractNodePathConfig {
|
|
|
|
abstractConfigs := make([]connect.AbstractNodePathConfig, len(step.PathConfigs))
|
|
|
|
for i, config := range step.PathConfigs {
|
|
|
|
abstractConfigs[i] = config // 直接赋值,因为 ApprovalPathConfig 实现了 AbstractNodePathConfig
|
|
|
|
}
|
|
|
|
return abstractConfigs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) SetPathConfigs(configs []connect.AbstractNodePathConfig) {
|
|
|
|
convertedConfigs, err := utils.ConvertToSpecificType(configs, func(item connect.AbstractNodePathConfig) (*ApprovalPathConfig, bool) {
|
|
|
|
specificConfig, ok := item.(*ApprovalPathConfig)
|
|
|
|
return specificConfig, ok
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("Error in SetPathConfigs: %v", err))
|
|
|
|
}
|
2024-11-19 17:03:12 +08:00
|
|
|
for _, path := range step.PathConfigs {
|
|
|
|
path.Delete()
|
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
step.PathConfigs = convertedConfigs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) GetKey() string {
|
|
|
|
return step.Key
|
2024-11-14 17:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) MarshalBinary() ([]byte, error) {
|
|
|
|
return json.Marshal(step)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) UnmarshalBinary(data []byte) error {
|
|
|
|
return json.Unmarshal(data, step)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewApprovalStep(name string) *ApprovalStep {
|
|
|
|
step := &ApprovalStep{
|
|
|
|
Name: name,
|
|
|
|
Rules: make([]*ApprovalRule, 0),
|
|
|
|
PathConfigs: make([]*ApprovalPathConfig, 0),
|
|
|
|
}
|
|
|
|
step.Key = uuid.New().String()
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewStepWithDynamicConfig(name string, DynamicConfig *DynamicApprovalStepConfig) *ApprovalStep {
|
|
|
|
step := &ApprovalStep{
|
|
|
|
Name: name,
|
|
|
|
DynamicConfig: DynamicConfig,
|
|
|
|
Rules: make([]*ApprovalRule, 0),
|
|
|
|
PathConfigs: make([]*ApprovalPathConfig, 0),
|
|
|
|
}
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) AddDynamicConfig(config *DynamicApprovalStepConfig) *ApprovalStep {
|
|
|
|
step.DynamicConfig = config
|
|
|
|
return step
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) GetPathById(pathID int64) (*ApprovalPathConfig, error) {
|
|
|
|
for _, path := range step.PathConfigs {
|
|
|
|
if path.ID == pathID {
|
|
|
|
return path, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("Path not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) GetRuleById(ruleId int64) (*ApprovalRule, error) {
|
|
|
|
for _, rule := range step.Rules {
|
|
|
|
if rule.ID == ruleId {
|
|
|
|
return rule, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("rule not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddRule 添加审批规则
|
|
|
|
func (step *ApprovalStep) AddRule(rule *ApprovalRule) error {
|
|
|
|
for _, r := range step.Rules {
|
|
|
|
if r.ID == rule.ID {
|
|
|
|
return fmt.Errorf("rule with ID %d already exists in step", rule.ID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
step.Rules = append(step.Rules, rule)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveRule 删除审批规则
|
|
|
|
func (step *ApprovalStep) RemoveRule(ruleID int64) error {
|
|
|
|
for i, r := range step.Rules {
|
|
|
|
if r.ID == ruleID {
|
|
|
|
step.Rules = append(step.Rules[:i], step.Rules[i+1:]...)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fmt.Errorf("rule with ID %d not found in step", ruleID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetDynamicConfig 设置动态审批配置
|
|
|
|
func (step *ApprovalStep) SetDynamicConfig(config *DynamicApprovalStepConfig) {
|
|
|
|
step.DynamicConfig = config
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddPathConfig 添加路径配置
|
|
|
|
func (step *ApprovalStep) AddPathConfig(pathConfig *ApprovalPathConfig) error {
|
|
|
|
for _, p := range step.PathConfigs {
|
|
|
|
if p.ID == pathConfig.ID {
|
|
|
|
return fmt.Errorf("path config with ID %d already exists in step", pathConfig.ID)
|
|
|
|
}
|
|
|
|
}
|
2024-11-15 16:53:35 +08:00
|
|
|
pathConfig.NodeID = step.ID
|
2024-11-14 17:02:41 +08:00
|
|
|
step.PathConfigs = append(step.PathConfigs, pathConfig)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemovePathConfig 删除路径配置
|
|
|
|
func (step *ApprovalStep) RemovePathConfig(pathConfigID int64) error {
|
|
|
|
for i, p := range step.PathConfigs {
|
|
|
|
if p.ID == pathConfigID {
|
|
|
|
step.PathConfigs = append(step.PathConfigs[:i], step.PathConfigs[i+1:]...)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fmt.Errorf("path config with ID %d not found in step", pathConfigID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNextStepIDs 根据条件获取下一步审批步骤ID列表
|
|
|
|
func (step *ApprovalStep) GetNextStepIDs(data map[string]interface{}) ([]string, error) {
|
|
|
|
var nextStepKeys []string
|
|
|
|
for _, pathConfig := range step.PathConfigs {
|
|
|
|
met, err := pathConfig.IsConditionMet(data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if met {
|
2024-11-15 16:53:35 +08:00
|
|
|
nextStepKeys = append(nextStepKeys, pathConfig.ToNodeKey)
|
2024-11-14 17:02:41 +08:00
|
|
|
if !pathConfig.IsParallel {
|
|
|
|
break // 非并行时,只取第一个满足条件的路径
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nextStepKeys, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (step *ApprovalStep) GetPathByToKey(toStepKey string) (*ApprovalPathConfig, bool) {
|
|
|
|
for _, pathConfig := range step.PathConfigs {
|
2024-11-15 16:53:35 +08:00
|
|
|
if pathConfig.ToNodeKey == toStepKey {
|
2024-11-14 17:02:41 +08:00
|
|
|
return pathConfig, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, false
|
|
|
|
}
|