| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | package entities | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	"errors" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	"time" | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	"tyapi-server/internal/domains/certification/entities/value_objects" | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	"tyapi-server/internal/domains/certification/enums" | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	"github.com/google/uuid" | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	"gorm.io/gorm" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // Certification 认证聚合根 | 
					
						
							|  |  |  |  | // 这是企业认证流程的核心聚合根,封装了完整的认证业务逻辑和状态管理 | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | type Certification struct { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// === 基础信息 === | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	ID     string                    `gorm:"primaryKey;type:varchar(64)" json:"id" comment:"认证申请唯一标识"` | 
					
						
							|  |  |  |  | 	UserID string                    `gorm:"type:varchar(36);not null;unique" json:"user_id" comment:"申请用户ID"` | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	Status enums.CertificationStatus `gorm:"type:varchar(50);not null;index" json:"status" comment:"当前认证状态"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// === 流程时间戳 - 记录每个关键步骤的完成时间 === | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	InfoSubmittedAt       *time.Time `json:"info_submitted_at,omitempty" comment:"企业信息提交时间"` | 
					
						
							|  |  |  |  | 	EnterpriseVerifiedAt  *time.Time `json:"enterprise_verified_at,omitempty" comment:"企业认证完成时间"` | 
					
						
							|  |  |  |  | 	ContractAppliedAt     *time.Time `json:"contract_applied_at,omitempty" comment:"合同申请时间"` | 
					
						
							|  |  |  |  | 	ContractSignedAt      *time.Time `json:"contract_signed_at,omitempty" comment:"合同签署完成时间"` | 
					
						
							|  |  |  |  | 	CompletedAt           *time.Time `json:"completed_at,omitempty" comment:"认证完成时间"` | 
					
						
							|  |  |  |  | 	ContractFileCreatedAt *time.Time `json:"contract_file_created_at,omitempty" comment:"合同文件生成时间"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// === e签宝相关信息 === | 
					
						
							|  |  |  |  | 	AuthFlowID      string `gorm:"type:varchar(500)" json:"auth_flow_id,omitempty" comment:"企业认证流程ID"` | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	AuthURL         string `gorm:"type:varchar(500)" json:"auth_url,omitempty" comment:"企业认证链接"` | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	ContractFileID  string `gorm:"type:varchar(500)" json:"contract_file_id,omitempty" comment:"合同文件ID"` | 
					
						
							|  |  |  |  | 	EsignFlowID     string `gorm:"type:varchar(500)" json:"esign_flow_id,omitempty" comment:"签署流程ID"` | 
					
						
							|  |  |  |  | 	ContractURL     string `gorm:"type:varchar(500)" json:"contract_url,omitempty" comment:"合同文件访问链接"` | 
					
						
							|  |  |  |  | 	ContractSignURL string `gorm:"type:varchar(500)" json:"contract_sign_url,omitempty" comment:"合同签署链接"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// === 失败信息 === | 
					
						
							|  |  |  |  | 	FailureReason  enums.FailureReason `gorm:"type:varchar(100)" json:"failure_reason,omitempty" comment:"失败原因"` | 
					
						
							|  |  |  |  | 	FailureMessage string              `gorm:"type:text" json:"failure_message,omitempty" comment:"失败详细信息"` | 
					
						
							|  |  |  |  | 	RetryCount     int                 `gorm:"default:0" json:"retry_count" comment:"重试次数"` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// === 审计信息 === | 
					
						
							|  |  |  |  | 	LastTransitionAt    *time.Time      `json:"last_transition_at,omitempty" comment:"最后状态转换时间"` | 
					
						
							|  |  |  |  | 	LastTransitionBy    enums.ActorType `gorm:"type:varchar(20)" json:"last_transition_by,omitempty" comment:"最后操作者类型"` | 
					
						
							|  |  |  |  | 	LastTransitionActor string          `gorm:"type:varchar(100)" json:"last_transition_actor,omitempty" comment:"最后操作者ID"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// === 系统字段 === | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	CreatedAt time.Time      `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"` | 
					
						
							|  |  |  |  | 	UpdatedAt time.Time      `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"` | 
					
						
							|  |  |  |  | 	DeletedAt gorm.DeletedAt `gorm:"index" json:"-" comment:"软删除时间"` | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// === 领域事件 (不持久化) === | 
					
						
							|  |  |  |  | 	domainEvents []interface{} `gorm:"-" json:"-"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // TableName 指定数据库表名 | 
					
						
							|  |  |  |  | func (Certification) TableName() string { | 
					
						
							|  |  |  |  | 	return "certifications" | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | // BeforeCreate GORM钩子:创建前自动生成UUID | 
					
						
							|  |  |  |  | func (c *Certification) BeforeCreate(tx *gorm.DB) error { | 
					
						
							|  |  |  |  | 	if c.ID == "" { | 
					
						
							|  |  |  |  | 		c.ID = uuid.New().String() | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置初始状态 | 
					
						
							|  |  |  |  | 	if c.Status == "" { | 
					
						
							|  |  |  |  | 		c.Status = enums.StatusPending | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-13 16:36:20 +08:00
										 |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 工厂方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewCertification 创建新的认证申请 | 
					
						
							|  |  |  |  | func NewCertification(userID string) (*Certification, error) { | 
					
						
							|  |  |  |  | 	if userID == "" { | 
					
						
							|  |  |  |  | 		return nil, errors.New("用户ID不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	certification := &Certification{ | 
					
						
							|  |  |  |  | 		ID:           uuid.New().String(), | 
					
						
							|  |  |  |  | 		UserID:       userID, | 
					
						
							|  |  |  |  | 		Status:       enums.StatusPending, | 
					
						
							|  |  |  |  | 		RetryCount:   0, | 
					
						
							|  |  |  |  | 		domainEvents: make([]interface{}, 0), | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加领域事件 | 
					
						
							|  |  |  |  | 	certification.addDomainEvent(&CertificationCreatedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: certification.ID, | 
					
						
							|  |  |  |  | 		UserID:          userID, | 
					
						
							|  |  |  |  | 		CreatedAt:       time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return certification, nil | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 状态转换方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CanTransitionTo 检查是否可以转换到目标状态 | 
					
						
							|  |  |  |  | func (c *Certification) CanTransitionTo(targetStatus enums.CertificationStatus, actor enums.ActorType) (bool, string) { | 
					
						
							|  |  |  |  | 	// 检查状态转换规则 | 
					
						
							|  |  |  |  | 	if !enums.CanTransitionTo(c.Status, targetStatus) { | 
					
						
							|  |  |  |  | 		return false, fmt.Sprintf("不允许从 %s 转换到 %s", enums.GetStatusName(c.Status), enums.GetStatusName(targetStatus)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查操作者权限 | 
					
						
							|  |  |  |  | 	if !c.validateActorPermission(targetStatus, actor) { | 
					
						
							|  |  |  |  | 		return false, fmt.Sprintf("%s 无权执行此状态转换", enums.GetActorTypeName(actor)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return true, "" | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // TransitionTo 执行状态转换 | 
					
						
							|  |  |  |  | func (c *Certification) TransitionTo(targetStatus enums.CertificationStatus, actor enums.ActorType, actorID string, reason string) error { | 
					
						
							|  |  |  |  | 	// 验证转换合法性 | 
					
						
							|  |  |  |  | 	canTransition, message := c.CanTransitionTo(targetStatus, actor) | 
					
						
							|  |  |  |  | 	if !canTransition { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("状态转换失败: %s", message) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	oldStatus := c.Status | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 执行状态转换 | 
					
						
							|  |  |  |  | 	c.Status = targetStatus | 
					
						
							|  |  |  |  | 	c.updateTimestampByStatus(targetStatus) | 
					
						
							|  |  |  |  | 	c.updateTransitionAudit(actor, actorID) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 清除失败信息(如果转换到成功状态) | 
					
						
							|  |  |  |  | 	if !enums.IsFailureStatus(targetStatus) { | 
					
						
							|  |  |  |  | 		c.clearFailureInfo() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加状态转换事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&CertificationStatusChangedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		FromStatus:      oldStatus, | 
					
						
							|  |  |  |  | 		ToStatus:        targetStatus, | 
					
						
							|  |  |  |  | 		Actor:           actor, | 
					
						
							|  |  |  |  | 		ActorID:         actorID, | 
					
						
							|  |  |  |  | 		Reason:          reason, | 
					
						
							|  |  |  |  | 		TransitionedAt:  time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 业务操作方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // SubmitEnterpriseInfo 提交企业信息 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | func (c *Certification) SubmitEnterpriseInfo(enterpriseInfo *value_objects.EnterpriseInfo, authURL string, authFlowID string) error { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusPending && c.Status != enums.StatusInfoRejected { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许提交企业信息", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 验证企业信息 | 
					
						
							|  |  |  |  | 	if err := enterpriseInfo.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("企业信息验证失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if authURL != "" { | 
					
						
							|  |  |  |  | 		c.AuthURL = authURL | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if authFlowID != "" { | 
					
						
							|  |  |  |  | 		c.AuthFlowID = authFlowID | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 状态转换 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(enums.StatusInfoSubmitted, enums.ActorTypeUser, c.UserID, "用户提交企业信息"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加业务事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&EnterpriseInfoSubmittedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		EnterpriseInfo:  enterpriseInfo, | 
					
						
							|  |  |  |  | 		SubmittedAt:     time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // 完成企业认证 | 
					
						
							|  |  |  |  | func (c *Certification) CompleteEnterpriseVerification() error { | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusInfoSubmitted { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许完成企业认证", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(enums.StatusEnterpriseVerified, enums.ActorTypeSystem, "system", "企业认证成功"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&EnterpriseVerificationSuccessEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		AuthFlowID:      "", | 
					
						
							|  |  |  |  | 		VerifiedAt:      time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // HandleEnterpriseVerificationCallback 处理企业认证回调 | 
					
						
							|  |  |  |  | func (c *Certification) HandleEnterpriseVerificationCallback(success bool, authFlowID string, failureReason enums.FailureReason, message string) error { | 
					
						
							|  |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusInfoSubmitted { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许处理企业认证回调", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	c.AuthFlowID = authFlowID | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if success { | 
					
						
							|  |  |  |  | 		// 认证成功 | 
					
						
							|  |  |  |  | 		if err := c.TransitionTo(enums.StatusEnterpriseVerified, enums.ActorTypeEsign, "esign_system", "企业认证成功"); err != nil { | 
					
						
							|  |  |  |  | 			return err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		c.addDomainEvent(&EnterpriseVerificationSuccessEvent{ | 
					
						
							|  |  |  |  | 			CertificationID: c.ID, | 
					
						
							|  |  |  |  | 			UserID:          c.UserID, | 
					
						
							|  |  |  |  | 			AuthFlowID:      authFlowID, | 
					
						
							|  |  |  |  | 			VerifiedAt:      time.Now(), | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		// 认证失败 | 
					
						
							|  |  |  |  | 		c.setFailureInfo(failureReason, message) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if err := c.TransitionTo(enums.StatusInfoRejected, enums.ActorTypeEsign, "esign_system", "企业认证失败"); err != nil { | 
					
						
							|  |  |  |  | 			return err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		c.addDomainEvent(&EnterpriseVerificationFailedEvent{ | 
					
						
							|  |  |  |  | 			CertificationID: c.ID, | 
					
						
							|  |  |  |  | 			UserID:          c.UserID, | 
					
						
							|  |  |  |  | 			AuthFlowID:      authFlowID, | 
					
						
							|  |  |  |  | 			FailureReason:   failureReason, | 
					
						
							|  |  |  |  | 			FailureMessage:  message, | 
					
						
							|  |  |  |  | 			FailedAt:        time.Now(), | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ApplyContract 申请合同签署 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | func (c *Certification) ApplyContract(EsignFlowID string, ContractSignURL string) error { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusEnterpriseVerified { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许申请合同", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// 状态转换 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(enums.StatusContractApplied, enums.ActorTypeUser, c.UserID, "用户申请合同签署"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	c.EsignFlowID = EsignFlowID | 
					
						
							|  |  |  |  | 	c.ContractSignURL = ContractSignURL | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							|  |  |  |  | 	c.ContractFileCreatedAt = &now | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 添加业务事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&ContractAppliedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		AppliedAt:       time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // AddContractFileID 生成合同文件 | 
					
						
							|  |  |  |  | func (c *Certification) AddContractFileID(contractFileID string, contractURL string) error { | 
					
						
							|  |  |  |  | 	c.ContractFileID = contractFileID | 
					
						
							|  |  |  |  | 	c.ContractURL = contractURL | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							|  |  |  |  | 	c.ContractFileCreatedAt = &now | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // UpdateContractInfo 更新合同信息 | 
					
						
							|  |  |  |  | func (c *Certification) UpdateContractInfo(contractInfo *value_objects.ContractInfo) error { | 
					
						
							|  |  |  |  | 	// 验证合同信息 | 
					
						
							|  |  |  |  | 	if err := contractInfo.Validate(); err != nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("合同信息验证失败: %w", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 更新合同相关字段 | 
					
						
							|  |  |  |  | 	c.ContractFileID = contractInfo.ContractFileID | 
					
						
							|  |  |  |  | 	c.EsignFlowID = contractInfo.EsignFlowID | 
					
						
							|  |  |  |  | 	c.ContractURL = contractInfo.ContractURL | 
					
						
							|  |  |  |  | 	c.ContractSignURL = contractInfo.ContractSignURL | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // SignSuccess 签署成功 | 
					
						
							|  |  |  |  | func (c *Certification) SignSuccess() error { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusContractApplied { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许处理合同签署回调", enums.GetStatusName(c.Status)) | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	if err := c.TransitionTo(enums.StatusContractSigned, enums.ActorTypeEsign, "esign_system", "合同签署成功"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	c.addDomainEvent(&ContractSignedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		SignedAt:        time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // ContractRejection 处理合同拒签 | 
					
						
							|  |  |  |  | func (c *Certification) ContractRejection(message string) error { | 
					
						
							|  |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusContractApplied { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许处理合同拒签", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 设置失败信息 | 
					
						
							|  |  |  |  | 	c.setFailureInfo(enums.FailureReasonContractRejectedByUser, message) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 状态转换 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(enums.StatusContractRejected, enums.ActorTypeEsign, "esign_system", "合同签署被拒绝"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 添加业务事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&ContractSignFailedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		FailureReason:   enums.FailureReasonContractRejectedByUser, | 
					
						
							|  |  |  |  | 		FailureMessage:  message, | 
					
						
							|  |  |  |  | 		FailedAt:        time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ContractExpiration 处理合同过期 | 
					
						
							|  |  |  |  | func (c *Certification) ContractExpiration() error { | 
					
						
							|  |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusContractApplied { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许处理合同过期", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 设置失败信息 | 
					
						
							|  |  |  |  | 	c.setFailureInfo(enums.FailureReasonContractExpired, "合同签署已超时") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 状态转换 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(enums.StatusContractExpired, enums.ActorTypeSystem, "system", "合同签署超时"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	// 添加业务事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&ContractSignFailedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		FailureReason:   enums.FailureReasonContractExpired, | 
					
						
							|  |  |  |  | 		FailureMessage:  "合同签署已超时", | 
					
						
							|  |  |  |  | 		FailedAt:        time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // RetryFromFailure 从失败状态重试 | 
					
						
							|  |  |  |  | func (c *Certification) RetryFromFailure(actor enums.ActorType, actorID string) error { | 
					
						
							|  |  |  |  | 	if !enums.IsFailureStatus(c.Status) { | 
					
						
							|  |  |  |  | 		return errors.New("当前状态不是失败状态,无需重试") | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 检查重试次数限制 | 
					
						
							|  |  |  |  | 	if c.RetryCount >= 3 { | 
					
						
							|  |  |  |  | 		return errors.New("已达到最大重试次数限制") | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查失败原因是否可重试 | 
					
						
							|  |  |  |  | 	if !enums.IsRetryable(c.FailureReason) { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("失败原因 %s 不支持重试", enums.GetFailureReasonName(c.FailureReason)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var targetStatus enums.CertificationStatus | 
					
						
							|  |  |  |  | 	var reason string | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch c.Status { | 
					
						
							|  |  |  |  | 	case enums.StatusInfoRejected: | 
					
						
							|  |  |  |  | 		targetStatus = enums.StatusInfoSubmitted | 
					
						
							|  |  |  |  | 		reason = "重新提交企业信息" | 
					
						
							|  |  |  |  | 	case enums.StatusContractRejected, enums.StatusContractExpired: | 
					
						
							|  |  |  |  | 		targetStatus = enums.StatusEnterpriseVerified | 
					
						
							|  |  |  |  | 		reason = "重置状态,准备重新申请合同" | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return fmt.Errorf("不支持从状态 %s 重试", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 增加重试次数 | 
					
						
							|  |  |  |  | 	c.RetryCount++ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 状态转换 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(targetStatus, actor, actorID, reason); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加重试事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&CertificationRetryEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		FromStatus:      c.Status, | 
					
						
							|  |  |  |  | 		ToStatus:        targetStatus, | 
					
						
							|  |  |  |  | 		RetryCount:      c.RetryCount, | 
					
						
							|  |  |  |  | 		RetriedAt:       time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // CompleteCertification 完成认证 | 
					
						
							|  |  |  |  | func (c *Certification) CompleteCertification() error { | 
					
						
							|  |  |  |  | 	// 验证当前状态 | 
					
						
							|  |  |  |  | 	if c.Status != enums.StatusContractSigned { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("当前状态 %s 不允许完成认证", enums.GetStatusName(c.Status)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 验证合同信息完整性 | 
					
						
							|  |  |  |  | 	if c.ContractFileID == "" || c.EsignFlowID == "" || c.ContractURL == "" { | 
					
						
							|  |  |  |  | 		return errors.New("合同信息不完整,无法完成认证") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 状态转换 | 
					
						
							|  |  |  |  | 	if err := c.TransitionTo(enums.StatusCompleted, enums.ActorTypeSystem, "system", "系统处理完成,认证成功"); err != nil { | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 添加业务事件 | 
					
						
							|  |  |  |  | 	c.addDomainEvent(&CertificationCompletedEvent{ | 
					
						
							|  |  |  |  | 		CertificationID: c.ID, | 
					
						
							|  |  |  |  | 		UserID:          c.UserID, | 
					
						
							|  |  |  |  | 		CompletedAt:     time.Now(), | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 查询方法 ================ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // GetDataByStatus 根据当前状态获取对应的数据 | 
					
						
							|  |  |  |  | func (c *Certification) GetDataByStatus() map[string]interface{} { | 
					
						
							|  |  |  |  | 	data := map[string]interface{}{} | 
					
						
							|  |  |  |  | 	switch c.Status { | 
					
						
							|  |  |  |  | 	case enums.StatusInfoSubmitted: | 
					
						
							|  |  |  |  | 		data["auth_url"] = c.AuthURL | 
					
						
							|  |  |  |  | 	case enums.StatusInfoRejected: | 
					
						
							|  |  |  |  | 		data["failure_reason"] = c.FailureReason | 
					
						
							|  |  |  |  | 		data["failure_message"] = c.FailureMessage | 
					
						
							|  |  |  |  | 	case enums.StatusEnterpriseVerified: | 
					
						
							|  |  |  |  | 		data["ContractURL"] = c.ContractURL | 
					
						
							|  |  |  |  | 	case enums.StatusContractApplied: | 
					
						
							|  |  |  |  | 		data["contract_sign_url"] = c.ContractSignURL | 
					
						
							|  |  |  |  | 	case enums.StatusContractSigned: | 
					
						
							|  |  |  |  | 	case enums.StatusCompleted: | 
					
						
							|  |  |  |  | 		data["completed_at"] = c.CompletedAt | 
					
						
							|  |  |  |  | 	case enums.StatusContractRejected: | 
					
						
							|  |  |  |  | 		data["failure_reason"] = c.FailureReason | 
					
						
							|  |  |  |  | 		data["failure_message"] = c.FailureMessage | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return data | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetProgress 获取认证进度百分比 | 
					
						
							|  |  |  |  | func (c *Certification) GetProgress() int { | 
					
						
							|  |  |  |  | 	return enums.GetProgressPercentage(c.Status) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsUserActionRequired 是否需要用户操作 | 
					
						
							|  |  |  |  | func (c *Certification) IsUserActionRequired() bool { | 
					
						
							|  |  |  |  | 	return enums.IsUserActionRequired(c.Status) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetCurrentStatusName 获取当前状态名称 | 
					
						
							|  |  |  |  | func (c *Certification) GetCurrentStatusName() string { | 
					
						
							|  |  |  |  | 	return enums.GetStatusName(c.Status) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetUserActionHint 获取用户操作提示 | 
					
						
							|  |  |  |  | func (c *Certification) GetUserActionHint() string { | 
					
						
							|  |  |  |  | 	return enums.GetUserActionHint(c.Status) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetAvailableActions 获取当前可执行的操作 | 
					
						
							|  |  |  |  | func (c *Certification) GetAvailableActions() []string { | 
					
						
							|  |  |  |  | 	actions := make([]string, 0) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch c.Status { | 
					
						
							|  |  |  |  | 	case enums.StatusPending: | 
					
						
							|  |  |  |  | 		actions = append(actions, "submit_enterprise_info") | 
					
						
							|  |  |  |  | 	case enums.StatusEnterpriseVerified: | 
					
						
							|  |  |  |  | 		actions = append(actions, "apply_contract") | 
					
						
							|  |  |  |  | 	case enums.StatusInfoRejected, enums.StatusContractRejected, enums.StatusContractExpired: | 
					
						
							|  |  |  |  | 		if enums.IsRetryable(c.FailureReason) && c.RetryCount < 3 { | 
					
						
							|  |  |  |  | 			actions = append(actions, "retry") | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return actions | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsFinalStatus 是否为最终状态 | 
					
						
							|  |  |  |  | func (c *Certification) IsFinalStatus() bool { | 
					
						
							|  |  |  |  | 	return enums.IsFinalStatus(c.Status) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // IsCompleted 是否已完成 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | func (c *Certification) IsCompleted() bool { | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	return c.Status == enums.StatusCompleted | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | // GetNextValidStatuses 获取下一个有效状态 | 
					
						
							|  |  |  |  | func (c *Certification) GetNextValidStatuses() []enums.CertificationStatus { | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	return enums.GetNextValidStatuses(c.Status) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetFailureInfo 获取失败信息 | 
					
						
							|  |  |  |  | func (c *Certification) GetFailureInfo() (enums.FailureReason, string) { | 
					
						
							|  |  |  |  | 	return c.FailureReason, c.FailureMessage | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | // IsContractFileExpired 判断合同文件是否过期(生成后50分钟过期) | 
					
						
							|  |  |  |  | func (c *Certification) IsContractFileExpired() bool { | 
					
						
							|  |  |  |  | 	if c.ContractFileCreatedAt == nil && c.Status == enums.StatusEnterpriseVerified { | 
					
						
							|  |  |  |  | 		// 60分钟前 | 
					
						
							|  |  |  |  | 		t := time.Now().Add(-60 * time.Minute) | 
					
						
							|  |  |  |  | 		c.ContractFileCreatedAt = &t | 
					
						
							|  |  |  |  | 		return true | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if c.ContractFileCreatedAt != nil { | 
					
						
							|  |  |  |  | 		return time.Since(*c.ContractFileCreatedAt) > 50*time.Minute | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsContractFileNeedUpdate 是否需要更新合同文件 | 
					
						
							|  |  |  |  | func (c *Certification) IsContractFileNeedUpdate() bool { | 
					
						
							|  |  |  |  | 	if c.IsContractFileExpired() && c.Status == enums.StatusEnterpriseVerified { | 
					
						
							|  |  |  |  | 		return true | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // ================ 业务规则验证 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateBusinessRules 验证业务规则 | 
					
						
							|  |  |  |  | func (c *Certification) ValidateBusinessRules() error { | 
					
						
							|  |  |  |  | 	// 基础验证 | 
					
						
							|  |  |  |  | 	if c.UserID == "" { | 
					
						
							|  |  |  |  | 		return errors.New("用户ID不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !enums.IsValidStatus(c.Status) { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("无效的认证状态: %s", c.Status) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 状态相关验证 | 
					
						
							|  |  |  |  | 	switch c.Status { | 
					
						
							|  |  |  |  | 	case enums.StatusEnterpriseVerified: | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		if c.ContractURL == "" { | 
					
						
							|  |  |  |  | 			return errors.New("企业认证成功后,合同文件ID和合同URL不能为空") | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case enums.StatusContractSigned: | 
					
						
							|  |  |  |  | 		if c.ContractFileID == "" || c.EsignFlowID == "" { | 
					
						
							|  |  |  |  | 			return errors.New("合同签署状态下必须有完整的合同信息") | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	case enums.StatusCompleted: | 
					
						
							|  |  |  |  | 		if c.ContractFileID == "" || c.EsignFlowID == "" || c.ContractURL == "" { | 
					
						
							|  |  |  |  | 			return errors.New("认证完成状态下必须有完整的合同信息") | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if c.CompletedAt == nil { | 
					
						
							|  |  |  |  | 			return errors.New("认证完成状态下必须有完成时间") | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	// 失败状态验证 | 
					
						
							|  |  |  |  | 	if enums.IsFailureStatus(c.Status) { | 
					
						
							|  |  |  |  | 		if c.FailureReason == "" { | 
					
						
							|  |  |  |  | 			return errors.New("失败状态下必须有失败原因") | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if !enums.IsValidFailureReason(c.FailureReason) { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("无效的失败原因: %s", c.FailureReason) | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | // validateActorPermission 验证操作者权限 | 
					
						
							|  |  |  |  | func (c *Certification) validateActorPermission(targetStatus enums.CertificationStatus, actor enums.ActorType) bool { | 
					
						
							|  |  |  |  | 	// 定义状态转换的权限规则 | 
					
						
							|  |  |  |  | 	permissions := map[enums.CertificationStatus][]enums.ActorType{ | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		enums.StatusInfoSubmitted:      {enums.ActorTypeUser, enums.ActorTypeAdmin}, | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		enums.StatusEnterpriseVerified: {enums.ActorTypeEsign, enums.ActorTypeSystem, enums.ActorTypeAdmin}, | 
					
						
							|  |  |  |  | 		enums.StatusInfoRejected:       {enums.ActorTypeEsign, enums.ActorTypeSystem, enums.ActorTypeAdmin}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		enums.StatusContractApplied:    {enums.ActorTypeUser, enums.ActorTypeAdmin}, | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 		enums.StatusContractSigned:     {enums.ActorTypeEsign, enums.ActorTypeSystem, enums.ActorTypeAdmin}, | 
					
						
							|  |  |  |  | 		enums.StatusContractRejected:   {enums.ActorTypeEsign, enums.ActorTypeSystem, enums.ActorTypeAdmin}, | 
					
						
							|  |  |  |  | 		enums.StatusContractExpired:    {enums.ActorTypeEsign, enums.ActorTypeSystem, enums.ActorTypeAdmin}, | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 		enums.StatusCompleted:          {enums.ActorTypeSystem, enums.ActorTypeAdmin}, | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	allowedActors, exists := permissions[targetStatus] | 
					
						
							|  |  |  |  | 	if !exists { | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for _, allowedActor := range allowedActors { | 
					
						
							|  |  |  |  | 		if actor == allowedActor { | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 辅助方法 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // updateTimestampByStatus 根据状态更新对应的时间戳 | 
					
						
							|  |  |  |  | func (c *Certification) updateTimestampByStatus(status enums.CertificationStatus) { | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch status { | 
					
						
							|  |  |  |  | 	case enums.StatusInfoSubmitted: | 
					
						
							|  |  |  |  | 		c.InfoSubmittedAt = &now | 
					
						
							|  |  |  |  | 	case enums.StatusEnterpriseVerified: | 
					
						
							|  |  |  |  | 		c.EnterpriseVerifiedAt = &now | 
					
						
							|  |  |  |  | 	case enums.StatusContractApplied: | 
					
						
							|  |  |  |  | 		c.ContractAppliedAt = &now | 
					
						
							|  |  |  |  | 	case enums.StatusContractSigned: | 
					
						
							|  |  |  |  | 		c.ContractSignedAt = &now | 
					
						
							| 
									
										
										
										
											2025-07-28 01:46:39 +08:00
										 |  |  |  | 	case enums.StatusCompleted: | 
					
						
							|  |  |  |  | 		c.CompletedAt = &now | 
					
						
							| 
									
										
										
										
											2025-07-21 15:13:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // updateTransitionAudit 更新状态转换审计信息 | 
					
						
							|  |  |  |  | func (c *Certification) updateTransitionAudit(actor enums.ActorType, actorID string) { | 
					
						
							|  |  |  |  | 	now := time.Now() | 
					
						
							|  |  |  |  | 	c.LastTransitionAt = &now | 
					
						
							|  |  |  |  | 	c.LastTransitionBy = actor | 
					
						
							|  |  |  |  | 	c.LastTransitionActor = actorID | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // setFailureInfo 设置失败信息 | 
					
						
							|  |  |  |  | func (c *Certification) setFailureInfo(reason enums.FailureReason, message string) { | 
					
						
							|  |  |  |  | 	c.FailureReason = reason | 
					
						
							|  |  |  |  | 	c.FailureMessage = message | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // clearFailureInfo 清除失败信息 | 
					
						
							|  |  |  |  | func (c *Certification) clearFailureInfo() { | 
					
						
							|  |  |  |  | 	c.FailureReason = "" | 
					
						
							|  |  |  |  | 	c.FailureMessage = "" | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 领域事件管理 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // addDomainEvent 添加领域事件 | 
					
						
							|  |  |  |  | func (c *Certification) addDomainEvent(event interface{}) { | 
					
						
							|  |  |  |  | 	if c.domainEvents == nil { | 
					
						
							|  |  |  |  | 		c.domainEvents = make([]interface{}, 0) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	c.domainEvents = append(c.domainEvents, event) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // GetDomainEvents 获取领域事件 | 
					
						
							|  |  |  |  | func (c *Certification) GetDomainEvents() []interface{} { | 
					
						
							|  |  |  |  | 	return c.domainEvents | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ClearDomainEvents 清除领域事件 | 
					
						
							|  |  |  |  | func (c *Certification) ClearDomainEvents() { | 
					
						
							|  |  |  |  | 	c.domainEvents = make([]interface{}, 0) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ================ 领域事件定义 ================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CertificationCreatedEvent 认证创建事件 | 
					
						
							|  |  |  |  | type CertificationCreatedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string    `json:"user_id"` | 
					
						
							|  |  |  |  | 	CreatedAt       time.Time `json:"created_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CertificationStatusChangedEvent 认证状态变更事件 | 
					
						
							|  |  |  |  | type CertificationStatusChangedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string                    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string                    `json:"user_id"` | 
					
						
							|  |  |  |  | 	FromStatus      enums.CertificationStatus `json:"from_status"` | 
					
						
							|  |  |  |  | 	ToStatus        enums.CertificationStatus `json:"to_status"` | 
					
						
							|  |  |  |  | 	Actor           enums.ActorType           `json:"actor"` | 
					
						
							|  |  |  |  | 	ActorID         string                    `json:"actor_id"` | 
					
						
							|  |  |  |  | 	Reason          string                    `json:"reason"` | 
					
						
							|  |  |  |  | 	TransitionedAt  time.Time                 `json:"transitioned_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // EnterpriseInfoSubmittedEvent 企业信息提交事件 | 
					
						
							|  |  |  |  | type EnterpriseInfoSubmittedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string                        `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string                        `json:"user_id"` | 
					
						
							|  |  |  |  | 	EnterpriseInfo  *value_objects.EnterpriseInfo `json:"enterprise_info"` | 
					
						
							|  |  |  |  | 	SubmittedAt     time.Time                     `json:"submitted_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // EnterpriseVerificationSuccessEvent 企业认证成功事件 | 
					
						
							|  |  |  |  | type EnterpriseVerificationSuccessEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string    `json:"user_id"` | 
					
						
							|  |  |  |  | 	AuthFlowID      string    `json:"auth_flow_id"` | 
					
						
							|  |  |  |  | 	VerifiedAt      time.Time `json:"verified_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // EnterpriseVerificationFailedEvent 企业认证失败事件 | 
					
						
							|  |  |  |  | type EnterpriseVerificationFailedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string              `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string              `json:"user_id"` | 
					
						
							|  |  |  |  | 	AuthFlowID      string              `json:"auth_flow_id"` | 
					
						
							|  |  |  |  | 	FailureReason   enums.FailureReason `json:"failure_reason"` | 
					
						
							|  |  |  |  | 	FailureMessage  string              `json:"failure_message"` | 
					
						
							|  |  |  |  | 	FailedAt        time.Time           `json:"failed_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ContractAppliedEvent 合同申请事件 | 
					
						
							|  |  |  |  | type ContractAppliedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string    `json:"user_id"` | 
					
						
							|  |  |  |  | 	AppliedAt       time.Time `json:"applied_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ContractSignedEvent 合同签署成功事件 | 
					
						
							|  |  |  |  | type ContractSignedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string    `json:"user_id"` | 
					
						
							|  |  |  |  | 	ContractURL     string    `json:"contract_url"` | 
					
						
							|  |  |  |  | 	SignedAt        time.Time `json:"signed_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ContractSignFailedEvent 合同签署失败事件 | 
					
						
							|  |  |  |  | type ContractSignFailedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string              `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string              `json:"user_id"` | 
					
						
							|  |  |  |  | 	FailureReason   enums.FailureReason `json:"failure_reason"` | 
					
						
							|  |  |  |  | 	FailureMessage  string              `json:"failure_message"` | 
					
						
							|  |  |  |  | 	FailedAt        time.Time           `json:"failed_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CertificationCompletedEvent 认证完成事件 | 
					
						
							|  |  |  |  | type CertificationCompletedEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string    `json:"user_id"` | 
					
						
							|  |  |  |  | 	CompletedAt     time.Time `json:"completed_at"` | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CertificationRetryEvent 认证重试事件 | 
					
						
							|  |  |  |  | type CertificationRetryEvent struct { | 
					
						
							|  |  |  |  | 	CertificationID string                    `json:"certification_id"` | 
					
						
							|  |  |  |  | 	UserID          string                    `json:"user_id"` | 
					
						
							|  |  |  |  | 	FromStatus      enums.CertificationStatus `json:"from_status"` | 
					
						
							|  |  |  |  | 	ToStatus        enums.CertificationStatus `json:"to_status"` | 
					
						
							|  |  |  |  | 	RetryCount      int                       `json:"retry_count"` | 
					
						
							|  |  |  |  | 	RetriedAt       time.Time                 `json:"retried_at"` | 
					
						
							| 
									
										
										
										
											2025-07-11 21:05:58 +08:00
										 |  |  |  | } |