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 }