approveflow/app/provider/flow_instance/model/instance_step.go

170 lines
6.2 KiB
Go

package model
import (
"approveflow/app/base"
"approveflow/app/provider/abstract/connect"
"approveflow/app/provider/flow_definition"
"approveflow/app/utils"
"encoding/json"
"fmt"
"github.com/google/uuid"
)
const (
StepStatusPending = "Pending" // 待审批
StepStatusApproved = "Approved" // 已批准
StepStatusRejected = "Rejected" // 已驳回
StepStatusReversed = "Reversed" // 已反转
StepStatusCompleted = "Completed" // 步骤已完成
)
// InstanceStep 审批步骤实例表
type InstanceStep struct {
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"` // 主键ID
InstanceID int64 `gorm:"index;not null" json:"instance_id"` // 所属审批实例ID
StepID int64 `gorm:"type:bigint;not null" json:"step_id"` // 关联的流程步骤ID
StepName string `gorm:"type:varchar(50);not null" json:"step_name"`
StepCode string `gorm:"type:varchar(100)" json:"step_code"` // 步骤编号用于标识特殊的审批节点
ApproverKey string `gorm:"type:varchar(50);not null" json:"approver_id"` // 审批人ID
Status string `gorm:"-" json:"status"` // 审批状态
ApproverComments string `gorm:"type:text" json:"approver_comments"` // 审批意见
IsDynamic bool `gorm:"not null;default:false" json:"is_dynamic"` // 是否为动态步骤
StatusEvents []*InstanceStepStatusEvent `gorm:"foreignKey:StepID;constraint:OnDelete:CASCADE" json:"status_events"` // 状态事件表
InstancePathConfigs []*InstancePathConfig `gorm:"foreignKey:NodeID;constraint:OnDelete:CASCADE" json:"instance_path_configs"` // 动态路径配置,自定义,不直接存储
Records []*ApprovalRecord `gorm:"foreignKey:InstanceStepID;constraint:OnDelete:CASCADE" json:"records"` // 审批记录
Reversals []*ApprovalReversal `gorm:"foreignKey:StepID;constraint:OnDelete:CASCADE" json:"reversals"` // 反转记录
base.Model
}
// InstanceStepStatusEvent 审批步骤状态表
type InstanceStepStatusEvent struct {
StepID int64 `gorm:"type:bigint;not null" json:"step_id"`
Status string `gorm:"type:varchar(50);not null" json:"status"`
Extension string `gorm:"type:varchar(50);not null" json:"extension"`
base.Model
}
type ByCreatedAt []*InstanceStepStatusEvent
func (a ByCreatedAt) Len() int { return len(a) }
func (a ByCreatedAt) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByCreatedAt) Less(i, j int) bool { return a[i].CreatedAt.After(a[j].CreatedAt) }
func (step *InstanceStep) GetStatus() string {
return step.StatusEvents[len(step.StatusEvents)-1].Status
}
func (step *InstanceStep) AddStatusEvent(status string) {
if step.StatusEvents == nil {
step.StatusEvents = make([]*InstanceStepStatusEvent, 0)
}
if len(step.StatusEvents) > 0 && step.GetStatus() == status {
return
}
step.StatusEvents = append(step.StatusEvents, &InstanceStepStatusEvent{
StepID: step.ID, Status: status, Extension: "",
})
step.Status = status
}
func (step *InstanceStep) AddPendingEvent() {
step.AddStatusEvent(StepStatusPending)
}
func (step *InstanceStep) AddApprovedEvent() {
step.AddStatusEvent(StepStatusApproved)
}
func (step *InstanceStep) AddRejectedEvent() {
step.AddStatusEvent(StepStatusRejected)
}
func (step *InstanceStep) AddReversedEvent() {
step.AddStatusEvent(StepStatusReversed)
}
func (step *InstanceStep) AddCompletedEvent() {
step.AddStatusEvent(StepStatusCompleted)
}
func (step *InstanceStep) MarshalBinary() ([]byte, error) {
return json.Marshal(step)
}
func (step *InstanceStep) UnmarshalBinary(data []byte) error {
return json.Unmarshal(data, step)
}
func (step *InstanceStep) GetPathConfigs() []connect.AbstractNodePathConfig {
return utils.ConvertToAbstractNodes(step.InstancePathConfigs, func(t *InstancePathConfig) connect.AbstractNodePathConfig {
return t
})
}
func (step *InstanceStep) SetPathConfigs(configs []connect.AbstractNodePathConfig) {
convertedConfigs, err := utils.ConvertToSpecificType(configs, func(item connect.AbstractNodePathConfig) (*InstancePathConfig, bool) {
specificConfig, ok := item.(*InstancePathConfig)
return specificConfig, ok
})
if err != nil {
panic(fmt.Sprintf("Error in SetPathConfigs: %v", err))
}
step.InstancePathConfigs = convertedConfigs
}
func (step *InstanceStep) GetKey() string {
return step.Key
}
func NewInstanceStep(flowStep *flow_definition.ApprovalStep, approverKey string, isDynamic bool) *InstanceStep {
instanceStep := &InstanceStep{
StepID: flowStep.ID,
StepName: flowStep.Name,
StepCode: flowStep.StepCode,
ApproverKey: approverKey,
IsDynamic: isDynamic,
}
instanceStep.AddPendingEvent()
instanceStep.Key = uuid.New().String()
return instanceStep
}
// Approve 审批通过
func (step *InstanceStep) Approve(comments string) error {
if step.GetStatus() != StepStatusPending {
return fmt.Errorf("当前步骤不是待审批状态")
}
step.AddApprovedEvent()
step.ApproverComments = comments
step.addApprovalRecord(StepStatusApproved, comments)
return nil
}
// Reject 审批驳回
func (step *InstanceStep) Reject(comments string) error {
//if step.GetStatus() != StepStatusPending {
// return fmt.Errorf("当前步骤不是待审批状态")
//}
step.AddRejectedEvent()
step.ApproverComments = comments
step.addApprovalRecord(StepStatusRejected, comments)
return nil
}
// addApprovalRecord 添加审批记录
func (step *InstanceStep) addApprovalRecord(status string, comments string) {
record := &ApprovalRecord{
InstanceStepID: step.ID,
ApproverKey: step.ApproverKey,
Status: status,
Comments: comments,
}
step.Records = append(step.Records, record)
}
func (step *InstanceStep) addApprovalReversal(reversal *ApprovalReversal) {
var reversals []*ApprovalReversal
reversals = append(reversals, reversal)
step.Reversals = reversals
}