170 lines
6.2 KiB
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
|
|
}
|