Files
tyapi-server/internal/domains/certification/services/state_machine/state_config.go
2025-07-21 15:13:26 +08:00

438 lines
16 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package state_machine
import (
"fmt"
"tyapi-server/internal/domains/certification/enums"
)
// StateConfig 状态配置
type StateConfig struct {
Status enums.CertificationStatus `json:"status"`
Name string `json:"name"`
ProgressPercentage int `json:"progress_percentage"`
IsUserActionRequired bool `json:"is_user_action_required"`
IsSystemAction bool `json:"is_system_action"`
TimestampField string `json:"timestamp_field,omitempty"`
Description string `json:"description"`
NextValidStatuses []enums.CertificationStatus `json:"next_valid_statuses"`
AllowedActors []enums.ActorType `json:"allowed_actors"`
}
// StateTransitionRule 状态转换规则
type StateTransitionRule struct {
FromStatus enums.CertificationStatus `json:"from_status"`
ToStatus enums.CertificationStatus `json:"to_status"`
TransitionName string `json:"transition_name"`
AllowedActors []enums.ActorType `json:"allowed_actors"`
RequiresValidation bool `json:"requires_validation"`
Description string `json:"description"`
BusinessRules []string `json:"business_rules"`
}
// StateConfigManager 状态配置管理器
type StateConfigManager struct {
stateConfigs map[enums.CertificationStatus]*StateConfig
transitionRules map[string]*StateTransitionRule // key: "from_status->to_status"
actorPermissions map[enums.ActorType][]string // actor允许的操作
}
// NewStateConfigManager 创建状态配置管理器
func NewStateConfigManager() *StateConfigManager {
manager := &StateConfigManager{
stateConfigs: make(map[enums.CertificationStatus]*StateConfig),
transitionRules: make(map[string]*StateTransitionRule),
actorPermissions: make(map[enums.ActorType][]string),
}
manager.initializeStateConfigs()
manager.initializeTransitionRules()
manager.initializeActorPermissions()
return manager
}
// initializeStateConfigs 初始化状态配置
func (m *StateConfigManager) initializeStateConfigs() {
configs := []*StateConfig{
{
Status: enums.StatusPending,
Name: "待认证",
ProgressPercentage: 0,
IsUserActionRequired: true,
IsSystemAction: false,
Description: "等待用户提交企业信息",
NextValidStatuses: []enums.CertificationStatus{enums.StatusInfoSubmitted},
AllowedActors: []enums.ActorType{enums.ActorTypeUser},
},
{
Status: enums.StatusInfoSubmitted,
Name: "已提交企业信息",
ProgressPercentage: 25,
IsUserActionRequired: false,
IsSystemAction: true,
TimestampField: "InfoSubmittedAt",
Description: "企业信息已提交等待e签宝验证",
NextValidStatuses: []enums.CertificationStatus{enums.StatusEnterpriseVerified, enums.StatusInfoRejected},
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
},
{
Status: enums.StatusEnterpriseVerified,
Name: "已企业认证",
ProgressPercentage: 50,
IsUserActionRequired: true,
IsSystemAction: false,
TimestampField: "EnterpriseVerifiedAt",
Description: "企业认证完成,用户可申请合同",
NextValidStatuses: []enums.CertificationStatus{enums.StatusContractApplied},
AllowedActors: []enums.ActorType{enums.ActorTypeUser},
},
{
Status: enums.StatusContractApplied,
Name: "已申请签署合同",
ProgressPercentage: 75,
IsUserActionRequired: true,
IsSystemAction: true,
TimestampField: "ContractAppliedAt",
Description: "合同已生成,等待用户签署",
NextValidStatuses: []enums.CertificationStatus{enums.StatusContractSigned, enums.StatusContractRejected, enums.StatusContractExpired},
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
},
{
Status: enums.StatusContractSigned,
Name: "认证完成",
ProgressPercentage: 100,
IsUserActionRequired: false,
IsSystemAction: false,
TimestampField: "ContractSignedAt",
Description: "认证流程已完成",
NextValidStatuses: []enums.CertificationStatus{},
AllowedActors: []enums.ActorType{},
},
// 失败状态
{
Status: enums.StatusInfoRejected,
Name: "企业信息被拒绝",
ProgressPercentage: 25,
IsUserActionRequired: true,
IsSystemAction: false,
Description: "企业信息验证失败,需要重新提交",
NextValidStatuses: []enums.CertificationStatus{enums.StatusInfoSubmitted},
AllowedActors: []enums.ActorType{enums.ActorTypeUser},
},
{
Status: enums.StatusContractRejected,
Name: "合同被拒签",
ProgressPercentage: 75,
IsUserActionRequired: true,
IsSystemAction: false,
Description: "用户拒绝签署合同",
NextValidStatuses: []enums.CertificationStatus{enums.StatusEnterpriseVerified},
AllowedActors: []enums.ActorType{enums.ActorTypeUser, enums.ActorTypeSystem},
},
{
Status: enums.StatusContractExpired,
Name: "合同签署超时",
ProgressPercentage: 75,
IsUserActionRequired: true,
IsSystemAction: false,
Description: "合同签署链接已过期",
NextValidStatuses: []enums.CertificationStatus{enums.StatusEnterpriseVerified},
AllowedActors: []enums.ActorType{enums.ActorTypeUser, enums.ActorTypeSystem},
},
}
for _, config := range configs {
m.stateConfigs[config.Status] = config
}
}
// initializeTransitionRules 初始化状态转换规则
func (m *StateConfigManager) initializeTransitionRules() {
rules := []*StateTransitionRule{
// 用户提交企业信息
{
FromStatus: enums.StatusPending,
ToStatus: enums.StatusInfoSubmitted,
TransitionName: "submit_enterprise_info",
AllowedActors: []enums.ActorType{enums.ActorTypeUser},
RequiresValidation: true,
Description: "用户提交企业信息",
BusinessRules: []string{"enterprise_info_complete", "enterprise_info_valid"},
},
// e签宝企业认证成功
{
FromStatus: enums.StatusInfoSubmitted,
ToStatus: enums.StatusEnterpriseVerified,
TransitionName: "enterprise_verification_success",
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
RequiresValidation: false,
Description: "e签宝企业认证成功",
BusinessRules: []string{"auth_flow_id_exists"},
},
// e签宝企业认证失败
{
FromStatus: enums.StatusInfoSubmitted,
ToStatus: enums.StatusInfoRejected,
TransitionName: "enterprise_verification_failed",
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
RequiresValidation: false,
Description: "e签宝企业认证失败",
BusinessRules: []string{"failure_reason_provided"},
},
// 用户申请合同
{
FromStatus: enums.StatusEnterpriseVerified,
ToStatus: enums.StatusContractApplied,
TransitionName: "apply_contract",
AllowedActors: []enums.ActorType{enums.ActorTypeUser},
RequiresValidation: true,
Description: "用户申请合同签署",
BusinessRules: []string{"enterprise_verified", "auth_flow_id_exists"},
},
// e签宝合同签署成功
{
FromStatus: enums.StatusContractApplied,
ToStatus: enums.StatusContractSigned,
TransitionName: "contract_sign_success",
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
RequiresValidation: false,
Description: "e签宝合同签署成功",
BusinessRules: []string{"contract_info_complete"},
},
// 合同签署失败
{
FromStatus: enums.StatusContractApplied,
ToStatus: enums.StatusContractRejected,
TransitionName: "contract_sign_rejected",
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
RequiresValidation: false,
Description: "用户拒绝签署合同",
BusinessRules: []string{"failure_reason_provided"},
},
// 合同签署超时
{
FromStatus: enums.StatusContractApplied,
ToStatus: enums.StatusContractExpired,
TransitionName: "contract_sign_expired",
AllowedActors: []enums.ActorType{enums.ActorTypeEsign, enums.ActorTypeSystem},
RequiresValidation: false,
Description: "合同签署超时",
BusinessRules: []string{"failure_reason_provided"},
},
// 重新提交企业信息
{
FromStatus: enums.StatusInfoRejected,
ToStatus: enums.StatusInfoSubmitted,
TransitionName: "resubmit_enterprise_info",
AllowedActors: []enums.ActorType{enums.ActorTypeUser},
RequiresValidation: true,
Description: "用户重新提交企业信息",
BusinessRules: []string{"enterprise_info_complete", "enterprise_info_valid", "retry_limit_check"},
},
// 从合同失败状态恢复
{
FromStatus: enums.StatusContractRejected,
ToStatus: enums.StatusEnterpriseVerified,
TransitionName: "reset_from_contract_rejected",
AllowedActors: []enums.ActorType{enums.ActorTypeSystem, enums.ActorTypeUser},
RequiresValidation: false,
Description: "从合同拒签状态恢复",
BusinessRules: []string{"retry_limit_check"},
},
{
FromStatus: enums.StatusContractExpired,
ToStatus: enums.StatusEnterpriseVerified,
TransitionName: "reset_from_contract_expired",
AllowedActors: []enums.ActorType{enums.ActorTypeSystem, enums.ActorTypeUser},
RequiresValidation: false,
Description: "从合同超时状态恢复",
BusinessRules: []string{"retry_limit_check"},
},
}
for _, rule := range rules {
key := string(rule.FromStatus) + "->" + string(rule.ToStatus)
m.transitionRules[key] = rule
}
}
// initializeActorPermissions 初始化操作者权限
func (m *StateConfigManager) initializeActorPermissions() {
m.actorPermissions = map[enums.ActorType][]string{
enums.ActorTypeUser: {
"submit_enterprise_info",
"apply_contract",
"view_certification",
"retry_from_failure",
},
enums.ActorTypeSystem: {
"auto_transition",
"system_recovery",
"timeout_handling",
"data_cleanup",
},
enums.ActorTypeEsign: {
"verification_callback",
"sign_callback",
"status_notification",
},
enums.ActorTypeAdmin: {
"manual_intervention",
"force_transition",
"view_all_certifications",
"system_configuration",
},
}
}
// GetStateConfig 获取状态配置
func (m *StateConfigManager) GetStateConfig(status enums.CertificationStatus) *StateConfig {
return m.stateConfigs[status]
}
// GetTransitionRule 获取状态转换规则
func (m *StateConfigManager) GetTransitionRule(fromStatus, toStatus enums.CertificationStatus) *StateTransitionRule {
key := string(fromStatus) + "->" + string(toStatus)
return m.transitionRules[key]
}
// CanTransition 检查是否可以执行状态转换
func (m *StateConfigManager) CanTransition(fromStatus, toStatus enums.CertificationStatus, actor enums.ActorType) (bool, string) {
// 获取转换规则
rule := m.GetTransitionRule(fromStatus, toStatus)
if rule == nil {
return false, "不支持的状态转换"
}
// 检查操作者权限
allowed := false
for _, allowedActor := range rule.AllowedActors {
if actor == allowedActor {
allowed = true
break
}
}
if !allowed {
return false, "操作者无权限执行此转换"
}
return true, ""
}
// GetAllowedTransitions 获取指定状态下允许的转换
func (m *StateConfigManager) GetAllowedTransitions(fromStatus enums.CertificationStatus, actor enums.ActorType) []*StateTransitionRule {
var allowedTransitions []*StateTransitionRule
config := m.GetStateConfig(fromStatus)
if config == nil {
return allowedTransitions
}
for _, toStatus := range config.NextValidStatuses {
if canTransition, _ := m.CanTransition(fromStatus, toStatus, actor); canTransition {
if rule := m.GetTransitionRule(fromStatus, toStatus); rule != nil {
allowedTransitions = append(allowedTransitions, rule)
}
}
}
return allowedTransitions
}
// GetActorPermissions 获取操作者权限
func (m *StateConfigManager) GetActorPermissions(actor enums.ActorType) []string {
if permissions, exists := m.actorPermissions[actor]; exists {
return permissions
}
return []string{}
}
// HasPermission 检查操作者是否有指定权限
func (m *StateConfigManager) HasPermission(actor enums.ActorType, permission string) bool {
permissions := m.GetActorPermissions(actor)
for _, p := range permissions {
if p == permission {
return true
}
}
return false
}
// ValidateBusinessRules 验证业务规则
func (m *StateConfigManager) ValidateBusinessRules(rule *StateTransitionRule, context map[string]interface{}) error {
for _, businessRule := range rule.BusinessRules {
if err := m.validateSingleBusinessRule(businessRule, context); err != nil {
return err
}
}
return nil
}
// validateSingleBusinessRule 验证单个业务规则
func (m *StateConfigManager) validateSingleBusinessRule(ruleName string, context map[string]interface{}) error {
switch ruleName {
case "enterprise_info_complete":
if enterpriseInfo, exists := context["enterprise_info"]; !exists || enterpriseInfo == nil {
return fmt.Errorf("企业信息不能为空")
}
case "enterprise_info_valid":
// 这里可以添加更复杂的企业信息验证逻辑
return nil
case "auth_flow_id_exists":
if authFlowID, exists := context["auth_flow_id"]; !exists || authFlowID == "" {
return fmt.Errorf("认证流程ID不能为空")
}
case "failure_reason_provided":
if reason, exists := context["failure_reason"]; !exists || reason == "" {
return fmt.Errorf("失败原因不能为空")
}
case "enterprise_verified":
if status, exists := context["current_status"]; !exists || status != string(enums.StatusEnterpriseVerified) {
return fmt.Errorf("企业必须先完成认证")
}
case "contract_info_complete":
if contractInfo, exists := context["contract_info"]; !exists || contractInfo == nil {
return fmt.Errorf("合同信息不能为空")
}
case "retry_limit_check":
if retryCount, exists := context["retry_count"]; exists {
if count, ok := retryCount.(int); ok && count >= 3 {
return fmt.Errorf("已达到最大重试次数限制")
}
}
}
return nil
}
// GetStateProgress 获取状态进度信息
func (m *StateConfigManager) GetStateProgress(status enums.CertificationStatus) int {
if config := m.GetStateConfig(status); config != nil {
return config.ProgressPercentage
}
return 0
}
// IsUserActionRequired 检查是否需要用户操作
func (m *StateConfigManager) IsUserActionRequired(status enums.CertificationStatus) bool {
if config := m.GetStateConfig(status); config != nil {
return config.IsUserActionRequired
}
return false
}
// IsSystemAction 检查是否为系统操作状态
func (m *StateConfigManager) IsSystemAction(status enums.CertificationStatus) bool {
if config := m.GetStateConfig(status); config != nil {
return config.IsSystemAction
}
return false
}
// GetTimestampField 获取状态对应的时间戳字段
func (m *StateConfigManager) GetTimestampField(status enums.CertificationStatus) string {
if config := m.GetStateConfig(status); config != nil {
return config.TimestampField
}
return ""
}