259 lines
7.3 KiB
Go
259 lines
7.3 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"tyapi-server/internal/domains/certification/entities"
|
|
"tyapi-server/internal/domains/certification/enums"
|
|
"tyapi-server/internal/domains/certification/repositories"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// CertificationStateMachine 认证状态机
|
|
type CertificationStateMachine struct {
|
|
stateManager *CertificationStateManager
|
|
certRepo repositories.CertificationRepository
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewCertificationStateMachine 创建认证状态机
|
|
func NewCertificationStateMachine(
|
|
certRepo repositories.CertificationRepository,
|
|
logger *zap.Logger,
|
|
) *CertificationStateMachine {
|
|
return &CertificationStateMachine{
|
|
stateManager: NewCertificationStateManager(),
|
|
certRepo: certRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// CanTransition 检查是否可以转换到指定状态
|
|
func (sm *CertificationStateMachine) CanTransition(
|
|
from enums.CertificationStatus,
|
|
to enums.CertificationStatus,
|
|
isUser bool,
|
|
isAdmin bool,
|
|
) (bool, string) {
|
|
return sm.stateManager.CanTransition(from, to, isUser, isAdmin)
|
|
}
|
|
|
|
// TransitionTo 执行状态转换
|
|
func (sm *CertificationStateMachine) TransitionTo(
|
|
ctx context.Context,
|
|
certificationID string,
|
|
targetStatus enums.CertificationStatus,
|
|
isUser bool,
|
|
isAdmin bool,
|
|
metadata map[string]interface{},
|
|
) error {
|
|
// 获取当前认证记录
|
|
cert, err := sm.certRepo.GetByID(ctx, certificationID)
|
|
if err != nil {
|
|
return fmt.Errorf("获取认证记录失败: %w", err)
|
|
}
|
|
|
|
// 检查是否可以转换
|
|
canTransition, reason := sm.CanTransition(cert.Status, targetStatus, isUser, isAdmin)
|
|
if !canTransition {
|
|
return fmt.Errorf("状态转换失败: %s", reason)
|
|
}
|
|
|
|
// 更新状态和时间戳
|
|
oldStatus := cert.Status
|
|
cert.Status = targetStatus
|
|
sm.updateTimestamp(&cert, targetStatus)
|
|
|
|
// 更新其他字段
|
|
sm.updateCertificationFields(&cert, targetStatus, metadata)
|
|
|
|
// 保存到数据库
|
|
if err := sm.certRepo.Update(ctx, cert); err != nil {
|
|
return fmt.Errorf("保存状态转换失败: %w", err)
|
|
}
|
|
|
|
sm.logger.Info("认证状态转换成功",
|
|
zap.String("certification_id", certificationID),
|
|
zap.String("from_status", string(oldStatus)),
|
|
zap.String("to_status", string(targetStatus)),
|
|
zap.Bool("is_user", isUser),
|
|
zap.Bool("is_admin", isAdmin),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// updateTimestamp 更新对应的时间戳字段
|
|
func (sm *CertificationStateMachine) updateTimestamp(cert *entities.Certification, status enums.CertificationStatus) {
|
|
stateConfig := sm.stateManager.GetStateConfig(status)
|
|
if stateConfig == nil || stateConfig.TimestampField == "" {
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
switch stateConfig.TimestampField {
|
|
case "InfoSubmittedAt":
|
|
cert.InfoSubmittedAt = &now
|
|
case "EnterpriseVerifiedAt":
|
|
cert.EnterpriseVerifiedAt = &now
|
|
case "ContractAppliedAt":
|
|
cert.ContractAppliedAt = &now
|
|
case "ContractSignedAt":
|
|
cert.ContractSignedAt = &now
|
|
case "CompletedAt":
|
|
cert.CompletedAt = &now
|
|
}
|
|
}
|
|
|
|
// updateCertificationFields 根据状态更新认证记录的其他字段
|
|
func (sm *CertificationStateMachine) updateCertificationFields(
|
|
cert *entities.Certification,
|
|
status enums.CertificationStatus,
|
|
metadata map[string]interface{},
|
|
) {
|
|
switch status {
|
|
case enums.StatusContractSigned:
|
|
if contractURL, ok := metadata["contract_url"].(string); ok {
|
|
cert.ContractURL = contractURL
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetValidNextStatuses 获取当前状态可以转换到的下一个状态列表
|
|
func (sm *CertificationStateMachine) GetValidNextStatuses(
|
|
currentStatus enums.CertificationStatus,
|
|
isUser bool,
|
|
isAdmin bool,
|
|
) []enums.CertificationStatus {
|
|
return sm.stateManager.GetNextValidStatuses(currentStatus)
|
|
}
|
|
|
|
// GetTransitionAction 获取状态转换对应的操作名称
|
|
func (sm *CertificationStateMachine) GetTransitionAction(
|
|
from enums.CertificationStatus,
|
|
to enums.CertificationStatus,
|
|
) string {
|
|
transitions := sm.stateManager.GetTransitionConfigs(from)
|
|
for _, transition := range transitions {
|
|
if transition.To == to {
|
|
return transition.Action
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetTransitionActionName 获取状态转换对应的操作中文名称
|
|
func (sm *CertificationStateMachine) GetTransitionActionName(
|
|
from enums.CertificationStatus,
|
|
to enums.CertificationStatus,
|
|
) string {
|
|
transitions := sm.stateManager.GetTransitionConfigs(from)
|
|
for _, transition := range transitions {
|
|
if transition.To == to {
|
|
return transition.ActionName
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetStateConfig 获取状态配置
|
|
func (sm *CertificationStateMachine) GetStateConfig(status enums.CertificationStatus) *StateConfig {
|
|
return sm.stateManager.GetStateConfig(status)
|
|
}
|
|
|
|
// GetProgressPercentage 获取进度百分比
|
|
func (sm *CertificationStateMachine) GetProgressPercentage(status enums.CertificationStatus) int {
|
|
return sm.stateManager.GetProgressPercentage(status)
|
|
}
|
|
|
|
// IsUserActionRequired 检查是否需要用户操作
|
|
func (sm *CertificationStateMachine) IsUserActionRequired(status enums.CertificationStatus) bool {
|
|
return sm.stateManager.IsUserActionRequired(status)
|
|
}
|
|
|
|
// IsAdminActionRequired 检查是否需要管理员操作
|
|
func (sm *CertificationStateMachine) IsAdminActionRequired(status enums.CertificationStatus) bool {
|
|
return sm.stateManager.IsAdminActionRequired(status)
|
|
}
|
|
|
|
// GetTransitionHistory 获取状态转换历史
|
|
func (sm *CertificationStateMachine) GetTransitionHistory(ctx context.Context, certificationID string) ([]map[string]interface{}, error) {
|
|
cert, err := sm.certRepo.GetByID(ctx, certificationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("获取认证记录失败: %w", err)
|
|
}
|
|
|
|
history := []map[string]interface{}{}
|
|
|
|
// 添加创建时间
|
|
history = append(history, map[string]interface{}{
|
|
"status": "CREATED",
|
|
"timestamp": cert.CreatedAt,
|
|
"action": "create",
|
|
"performer": "system",
|
|
"metadata": map[string]interface{}{},
|
|
})
|
|
|
|
// 添加各个时间节点的状态转换
|
|
if cert.InfoSubmittedAt != nil {
|
|
history = append(history, map[string]interface{}{
|
|
"status": string(enums.StatusInfoSubmitted),
|
|
"timestamp": *cert.InfoSubmittedAt,
|
|
"action": "submit_info",
|
|
"performer": "user",
|
|
"metadata": map[string]interface{}{},
|
|
})
|
|
}
|
|
|
|
if cert.EnterpriseVerifiedAt != nil {
|
|
history = append(history, map[string]interface{}{
|
|
"status": string(enums.StatusEnterpriseVerified),
|
|
"timestamp": *cert.EnterpriseVerifiedAt,
|
|
"action": "enterprise_verify",
|
|
"performer": "user",
|
|
"metadata": map[string]interface{}{},
|
|
})
|
|
}
|
|
|
|
if cert.ContractAppliedAt != nil {
|
|
history = append(history, map[string]interface{}{
|
|
"status": string(enums.StatusContractApplied),
|
|
"timestamp": *cert.ContractAppliedAt,
|
|
"action": "apply_contract",
|
|
"performer": "user",
|
|
"metadata": map[string]interface{}{},
|
|
})
|
|
}
|
|
|
|
if cert.ContractSignedAt != nil {
|
|
metadata := map[string]interface{}{}
|
|
if cert.ContractURL != "" {
|
|
metadata["contract_url"] = cert.ContractURL
|
|
}
|
|
|
|
history = append(history, map[string]interface{}{
|
|
"status": string(enums.StatusContractSigned),
|
|
"timestamp": *cert.ContractSignedAt,
|
|
"action": "sign_contract",
|
|
"performer": "user",
|
|
"metadata": metadata,
|
|
})
|
|
}
|
|
|
|
if cert.CompletedAt != nil {
|
|
history = append(history, map[string]interface{}{
|
|
"status": string(enums.StatusCompleted),
|
|
"timestamp": *cert.CompletedAt,
|
|
"action": "complete",
|
|
"performer": "system",
|
|
"metadata": map[string]interface{}{},
|
|
})
|
|
}
|
|
|
|
return history, nil
|
|
}
|