Files
tyapi-server/internal/application/certification/certification_application_service_impl.go

732 lines
23 KiB
Go
Raw Normal View History

2025-07-13 16:36:20 +08:00
package certification
import (
"context"
"fmt"
"tyapi-server/internal/application/certification/dto/commands"
"tyapi-server/internal/application/certification/dto/queries"
"tyapi-server/internal/application/certification/dto/responses"
"tyapi-server/internal/domains/certification/entities"
2025-07-20 20:53:26 +08:00
"tyapi-server/internal/domains/certification/enums"
2025-07-21 15:13:26 +08:00
"tyapi-server/internal/domains/certification/repositories"
2025-07-13 16:36:20 +08:00
"tyapi-server/internal/domains/certification/services"
2025-07-21 15:13:26 +08:00
"tyapi-server/internal/domains/certification/services/state_machine"
"go.uber.org/zap"
2025-07-13 16:36:20 +08:00
)
// CertificationApplicationServiceImpl 认证应用服务实现
2025-07-21 15:13:26 +08:00
// 负责用例协调DTO转换是应用层的核心组件
2025-07-13 16:36:20 +08:00
type CertificationApplicationServiceImpl struct {
2025-07-21 15:13:26 +08:00
// 领域服务依赖
aggregateService services.CertificationAggregateService
workflowOrchestrator services.CertificationWorkflowOrchestrator
// 仓储依赖
queryRepository repositories.CertificationQueryRepository
// 基础设施依赖
callbackHandler *state_machine.EsignCallbackHandler
logger *zap.Logger
2025-07-13 16:36:20 +08:00
}
// NewCertificationApplicationService 创建认证应用服务
func NewCertificationApplicationService(
2025-07-21 15:13:26 +08:00
aggregateService services.CertificationAggregateService,
workflowOrchestrator services.CertificationWorkflowOrchestrator,
queryRepository repositories.CertificationQueryRepository,
callbackHandler *state_machine.EsignCallbackHandler,
2025-07-13 16:36:20 +08:00
logger *zap.Logger,
) CertificationApplicationService {
return &CertificationApplicationServiceImpl{
2025-07-21 15:13:26 +08:00
aggregateService: aggregateService,
workflowOrchestrator: workflowOrchestrator,
queryRepository: queryRepository,
callbackHandler: callbackHandler,
logger: logger,
2025-07-13 16:36:20 +08:00
}
}
2025-07-21 15:13:26 +08:00
// ================ 用户操作用例 ================
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
// CreateCertification 创建认证申请
func (s *CertificationApplicationServiceImpl) CreateCertification(
ctx context.Context,
cmd *commands.CreateCertificationCommand,
) (*responses.CertificationResponse, error) {
s.logger.Info("开始创建认证申请", zap.String("user_id", cmd.UserID))
// 1. 调用聚合服务创建认证
cert, err := s.aggregateService.CreateCertification(ctx, cmd.UserID)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("创建认证申请失败", zap.Error(err), zap.String("user_id", cmd.UserID))
return nil, fmt.Errorf("创建认证申请失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 2. 转换为响应DTO
response := s.convertToResponse(cert)
s.logger.Info("认证申请创建成功",
zap.String("user_id", cmd.UserID),
zap.String("certification_id", cert.ID))
return response, nil
}
// SubmitEnterpriseInfo 提交企业信息
func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
ctx context.Context,
cmd *commands.SubmitEnterpriseInfoCommand,
) (*responses.CertificationResponse, error) {
s.logger.Info("开始提交企业信息",
zap.String("certification_id", cmd.CertificationID),
zap.String("user_id", cmd.UserID))
// 1. 构建工作流命令
workflowCmd := &services.SubmitEnterpriseInfoCommand{
CertificationID: cmd.CertificationID,
UserID: cmd.UserID,
EnterpriseInfo: cmd.EnterpriseInfo,
}
// 2. 执行工作流
workflowResult, err := s.workflowOrchestrator.SubmitEnterpriseInfo(ctx, workflowCmd)
if err != nil {
s.logger.Error("提交企业信息失败", zap.Error(err))
return nil, fmt.Errorf("提交企业信息失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 加载最新的认证信息
cert, err := s.aggregateService.LoadCertification(ctx, cmd.CertificationID)
2025-07-20 20:53:26 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("加载认证信息失败", zap.Error(err))
return nil, fmt.Errorf("加载认证信息失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 4. 转换为响应DTO
response := s.convertToResponse(cert)
// 5. 添加工作流结果信息
if workflowResult.Data != nil {
response.Metadata = workflowResult.Data
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
s.logger.Info("企业信息提交成功", zap.String("certification_id", cmd.CertificationID))
return response, nil
}
// ApplyContract 申请合同签署
func (s *CertificationApplicationServiceImpl) ApplyContract(
ctx context.Context,
cmd *commands.ApplyContractCommand,
) (*responses.ContractSignUrlResponse, error) {
s.logger.Info("开始申请合同签署",
zap.String("certification_id", cmd.CertificationID),
zap.String("user_id", cmd.UserID))
// 1. 构建工作流命令
workflowCmd := &services.ApplyContractCommand{
CertificationID: cmd.CertificationID,
UserID: cmd.UserID,
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 2. 执行工作流
workflowResult, err := s.workflowOrchestrator.ApplyContract(ctx, workflowCmd)
if err != nil {
s.logger.Error("申请合同签署失败", zap.Error(err))
return nil, fmt.Errorf("申请合同签署失败: %w", err)
}
// 3. 从工作流结果提取签署URL信息
signURL, _ := workflowResult.Data["contract_sign_url"].(string)
contractURL, _ := workflowResult.Data["contract_url"].(string)
nextAction, _ := workflowResult.Data["next_action"].(string)
// 4. 构建响应
response := responses.NewContractSignUrlResponse(
cmd.CertificationID,
signURL,
contractURL,
nextAction,
workflowResult.Message,
2025-07-13 16:36:20 +08:00
)
2025-07-21 15:13:26 +08:00
s.logger.Info("合同申请成功", zap.String("certification_id", cmd.CertificationID))
return response, nil
}
// RetryOperation 重试失败操作
func (s *CertificationApplicationServiceImpl) RetryOperation(
ctx context.Context,
cmd *commands.RetryOperationCommand,
) (*responses.CertificationResponse, error) {
s.logger.Info("开始重试操作",
zap.String("certification_id", cmd.CertificationID),
zap.String("operation", cmd.Operation))
// 1. 执行重试工作流
workflowResult, err := s.workflowOrchestrator.RetryOperation(ctx, cmd.CertificationID, cmd.Operation)
2025-07-20 20:53:26 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("重试操作失败", zap.Error(err))
return nil, fmt.Errorf("重试操作失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 2. 加载最新的认证信息
cert, err := s.aggregateService.LoadCertification(ctx, cmd.CertificationID)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("加载认证信息失败", zap.Error(err))
return nil, fmt.Errorf("加载认证信息失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 转换为响应DTO
response := s.convertToResponse(cert)
// 4. 添加重试结果信息
if workflowResult.Data != nil {
response.Metadata = workflowResult.Data
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
s.logger.Info("重试操作成功", zap.String("certification_id", cmd.CertificationID))
return response, nil
2025-07-20 20:53:26 +08:00
}
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
// ================ 查询用例 ================
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
// GetCertification 获取认证详情
func (s *CertificationApplicationServiceImpl) GetCertification(
ctx context.Context,
query *queries.GetCertificationQuery,
) (*responses.CertificationResponse, error) {
s.logger.Debug("获取认证详情", zap.String("certification_id", query.CertificationID))
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
// 1. 从查询仓储获取认证信息
cert, err := s.queryRepository.GetByID(ctx, query.CertificationID)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("获取认证信息失败", zap.Error(err))
return nil, fmt.Errorf("认证信息不存在: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 2. 权限验证如果提供了用户ID
if query.UserID != "" && cert.UserID != query.UserID {
return nil, fmt.Errorf("无权限访问此认证信息")
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 转换为响应DTO
response := s.convertToResponse(cert)
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
return response, nil
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// GetUserCertifications 获取用户认证列表
func (s *CertificationApplicationServiceImpl) GetUserCertifications(
ctx context.Context,
query *queries.GetUserCertificationsQuery,
) (*responses.CertificationListResponse, error) {
s.logger.Debug("获取用户认证列表", zap.String("user_id", query.UserID))
// 1. 转换为通用列表查询对象
domainQuery := &queries.ListCertificationsQuery{
Page: query.Page,
PageSize: query.PageSize,
UserID: query.UserID,
Status: query.Status,
}
// 根据包含选项设置状态过滤
if !query.IncludeCompleted && !query.IncludeFailed {
// 只显示进行中的认证
domainQuery.Statuses = []enums.CertificationStatus{
enums.StatusPending,
enums.StatusInfoSubmitted,
enums.StatusEnterpriseVerified,
enums.StatusContractApplied,
}
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 转换为领域查询对象
listQuery := domainQuery.ToDomainQuery()
// 2. 执行查询
certs, total, err := s.queryRepository.List(ctx, listQuery)
2025-07-20 20:53:26 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("查询用户认证列表失败", zap.Error(err))
return nil, fmt.Errorf("查询用户认证列表失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 转换为响应DTO
items := make([]*responses.CertificationResponse, len(certs))
for i, cert := range certs {
items[i] = s.convertToResponse(cert)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 4. 构建列表响应
response := responses.NewCertificationListResponse(items, total, query.Page, query.PageSize)
return response, nil
}
// ListCertifications 获取认证列表(管理员)
func (s *CertificationApplicationServiceImpl) ListCertifications(
ctx context.Context,
query *queries.ListCertificationsQuery,
) (*responses.CertificationListResponse, error) {
s.logger.Debug("获取认证列表(管理员)")
// 1. 转换为领域查询对象
domainQuery := query.ToDomainQuery()
// 2. 执行查询
certs, total, err := s.queryRepository.List(ctx, domainQuery)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("查询认证列表失败", zap.Error(err))
return nil, fmt.Errorf("查询认证列表失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 转换为响应DTO
items := make([]*responses.CertificationResponse, len(certs))
for i, cert := range certs {
items[i] = s.convertToResponse(cert)
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
// 4. 构建列表响应
response := responses.NewCertificationListResponse(items, total, query.Page, query.PageSize)
return response, nil
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// SearchCertifications 搜索认证
func (s *CertificationApplicationServiceImpl) SearchCertifications(
ctx context.Context,
query *queries.SearchCertificationsQuery,
) (*responses.CertificationListResponse, error) {
s.logger.Debug("搜索认证", zap.String("keyword", query.Keyword))
// 1. 转换为领域查询对象
domainQuery := query.ToDomainQuery()
// 2. 根据搜索字段选择不同的搜索方法
var certs []*entities.Certification
var total int64
var err error
if len(domainQuery.SearchFields) == 1 {
switch domainQuery.SearchFields[0] {
case "company_name":
certs, err = s.queryRepository.SearchByCompanyName(ctx, domainQuery.Keyword, domainQuery.GetLimit())
total = int64(len(certs)) // 简化实现,实际应该有单独的计数方法
case "legal_person_name":
certs, err = s.queryRepository.SearchByLegalPerson(ctx, domainQuery.Keyword, domainQuery.GetLimit())
total = int64(len(certs))
default:
// 通用搜索,这里简化为按公司名搜索
certs, err = s.queryRepository.SearchByCompanyName(ctx, domainQuery.Keyword, domainQuery.GetLimit())
total = int64(len(certs))
}
} else {
// 多字段搜索,这里简化为按公司名搜索
certs, err = s.queryRepository.SearchByCompanyName(ctx, domainQuery.Keyword, domainQuery.GetLimit())
total = int64(len(certs))
}
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("搜索认证失败", zap.Error(err))
return nil, fmt.Errorf("搜索认证失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 转换为响应DTO
items := make([]*responses.CertificationResponse, len(certs))
for i, cert := range certs {
items[i] = s.convertToResponse(cert)
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
// 4. 构建列表响应
response := responses.NewCertificationListResponse(items, total, query.Page, query.PageSize)
return response, nil
}
// GetCertificationStatistics 获取认证统计
func (s *CertificationApplicationServiceImpl) GetCertificationStatistics(
ctx context.Context,
query *queries.GetCertificationStatisticsQuery,
) (*responses.CertificationStatisticsResponse, error) {
s.logger.Debug("获取认证统计", zap.String("period", query.Period))
// 1. 转换为领域查询对象
domainQuery := query.ToDomainQuery()
// 2. 验证查询参数
if err := domainQuery.Validate(); err != nil {
return nil, fmt.Errorf("统计查询参数无效: %w", err)
}
// 3. 确定时间周期
var period repositories.CertificationTimePeriod
switch query.Period {
case "daily":
period = repositories.PeriodDaily
case "weekly":
period = repositories.PeriodWeekly
case "monthly":
period = repositories.PeriodMonthly
case "yearly":
period = repositories.PeriodYearly
default:
period = repositories.PeriodDaily
}
// 4. 获取统计数据
stats, err := s.queryRepository.GetStatistics(ctx, period)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("获取认证统计失败", zap.Error(err))
return nil, fmt.Errorf("获取认证统计失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 5. 获取进度统计(如果需要)
var progressStats *repositories.CertificationProgressStats
if query.IncludeProgressStats {
progressStats, err = s.queryRepository.GetProgressStatistics(ctx)
if err != nil {
s.logger.Warn("获取进度统计失败", zap.Error(err))
}
2025-07-20 20:53:26 +08:00
}
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
// 6. 构建响应
response := &responses.CertificationStatisticsResponse{
Period: query.Period,
TimeRange: domainQuery.GetTimeRange(),
Statistics: stats,
ProgressStats: progressStats,
GeneratedAt: domainQuery.StartDate,
Charts: s.generateChartsData(stats, progressStats),
2025-07-20 20:53:26 +08:00
}
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
return response, nil
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// ================ e签宝回调处理 ================
// HandleEsignCallback 处理e签宝回调
func (s *CertificationApplicationServiceImpl) HandleEsignCallback(
ctx context.Context,
cmd *commands.EsignCallbackCommand,
) (*responses.CallbackResponse, error) {
s.logger.Info("开始处理e签宝回调",
zap.String("certification_id", cmd.CertificationID),
zap.String("callback_type", cmd.CallbackType))
// 1. 解析回调数据
callbackData, err := s.callbackHandler.ParseCallbackData(cmd.RawData)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("解析回调数据失败", zap.Error(err))
return responses.NewCallbackResponse(false, cmd.CertificationID, cmd.CallbackType,
fmt.Sprintf("解析回调数据失败: %s", err.Error())), err
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 2. 构建工作流回调命令
workflowCmd := &services.EsignCallbackCommand{
CertificationID: cmd.CertificationID,
CallbackType: cmd.CallbackType,
CallbackData: callbackData,
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 根据回调类型分发处理
var workflowResult *services.WorkflowResult
switch cmd.CallbackType {
case "auth_result":
workflowResult, err = s.workflowOrchestrator.HandleEnterpriseVerificationCallback(ctx, workflowCmd)
case "sign_result":
workflowResult, err = s.workflowOrchestrator.HandleContractSignCallback(ctx, workflowCmd)
default:
err = fmt.Errorf("不支持的回调类型: %s", cmd.CallbackType)
2025-07-13 16:36:20 +08:00
}
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("处理回调失败", zap.Error(err))
return responses.NewCallbackResponse(false, cmd.CertificationID, cmd.CallbackType,
fmt.Sprintf("处理回调失败: %s", err.Error())), err
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 4. 构建成功响应
response := responses.NewCallbackResponse(true, cmd.CertificationID, cmd.CallbackType, workflowResult.Message)
2025-07-20 20:53:26 +08:00
2025-07-21 15:13:26 +08:00
// 5. 设置状态转换信息
if workflowResult.StateTransition != nil {
response.StateTransition = workflowResult.StateTransition
response.OldStatus = workflowResult.StateTransition.OldStatus
response.NewStatus = workflowResult.StateTransition.NewStatus
}
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
s.logger.Info("e签宝回调处理成功", zap.String("certification_id", cmd.CertificationID))
return response, nil
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// ================ 管理员操作 ================
// ForceTransitionStatus 强制状态转换(管理员)
func (s *CertificationApplicationServiceImpl) ForceTransitionStatus(
ctx context.Context,
cmd *commands.ForceTransitionStatusCommand,
) (*responses.CertificationResponse, error) {
s.logger.Info("开始强制状态转换",
zap.String("certification_id", cmd.CertificationID),
zap.String("admin_id", cmd.AdminID),
zap.String("target_status", string(cmd.TargetStatus)))
// 1. 权限验证(这里简化,实际应该有更复杂的权限验证)
// TODO: 实现管理员权限验证逻辑
// 2. 执行状态转换
result, err := s.aggregateService.TransitionState(
ctx,
cmd.CertificationID,
cmd.TargetStatus,
enums.ActorTypeAdmin,
cmd.AdminID,
cmd.Reason,
map[string]interface{}{
"force": cmd.Force,
},
)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("强制状态转换失败", zap.Error(err))
return nil, fmt.Errorf("强制状态转换失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 3. 加载最新的认证信息
cert, err := s.aggregateService.LoadCertification(ctx, cmd.CertificationID)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("加载认证信息失败", zap.Error(err))
return nil, fmt.Errorf("加载认证信息失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 4. 转换为响应DTO
response := s.convertToResponse(cert)
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
// 5. 添加状态转换信息
if result != nil {
response.Metadata = map[string]interface{}{
"state_transition": result,
"admin_operation": true,
2025-07-13 16:36:20 +08:00
}
}
2025-07-21 15:13:26 +08:00
s.logger.Info("强制状态转换成功", zap.String("certification_id", cmd.CertificationID))
2025-07-13 16:36:20 +08:00
return response, nil
}
2025-07-21 15:13:26 +08:00
// GetSystemMonitoring 获取系统监控数据
func (s *CertificationApplicationServiceImpl) GetSystemMonitoring(
ctx context.Context,
query *queries.GetSystemMonitoringQuery,
) (*responses.SystemMonitoringResponse, error) {
s.logger.Debug("获取系统监控数据", zap.String("time_range", query.TimeRange))
// 1. 获取基础统计数据
stats, err := s.queryRepository.GetStatistics(ctx, repositories.PeriodDaily)
2025-07-13 16:36:20 +08:00
if err != nil {
2025-07-21 15:13:26 +08:00
s.logger.Error("获取基础统计失败", zap.Error(err))
return nil, fmt.Errorf("获取系统监控数据失败: %w", err)
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// 2. 构建监控指标
metrics := make(map[string]interface{})
2025-07-13 16:36:20 +08:00
2025-07-21 15:13:26 +08:00
if query.ShouldIncludeMetric("certification_count") {
metrics["certification_count"] = stats.TotalCertifications
}
if query.ShouldIncludeMetric("success_rate") {
metrics["success_rate"] = stats.SuccessRate
}
if query.ShouldIncludeMetric("failure_rate") {
metrics["failure_rate"] = 1.0 - stats.SuccessRate
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
if query.ShouldIncludeMetric("avg_processing_time") {
metrics["avg_processing_time"] = stats.AvgProcessingTime.String()
}
if query.ShouldIncludeMetric("status_distribution") {
metrics["status_distribution"] = stats.StatusDistribution
}
// 3. 生成系统警告
alerts := s.generateSystemAlerts(stats)
// 4. 评估系统健康状态
systemHealth := s.evaluateSystemHealth(stats, alerts)
// 5. 构建响应
response := &responses.SystemMonitoringResponse{
TimeRange: query.TimeRange,
Metrics: metrics,
Alerts: alerts,
SystemHealth: systemHealth,
LastUpdatedAt: stats.StartDate,
}
return response, nil
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// ================ 辅助方法 ================
// convertToResponse 转换实体为响应DTO
func (s *CertificationApplicationServiceImpl) convertToResponse(cert *entities.Certification) *responses.CertificationResponse {
response := &responses.CertificationResponse{
ID: cert.ID,
UserID: cert.UserID,
Status: cert.Status,
StatusName: enums.GetStatusName(cert.Status),
Progress: cert.GetProgress(),
CreatedAt: cert.CreatedAt,
UpdatedAt: cert.UpdatedAt,
InfoSubmittedAt: cert.InfoSubmittedAt,
EnterpriseVerifiedAt: cert.EnterpriseVerifiedAt,
ContractAppliedAt: cert.ContractAppliedAt,
ContractSignedAt: cert.ContractSignedAt,
IsCompleted: cert.IsCompleted(),
IsFailed: enums.IsFailureStatus(cert.Status),
IsUserActionRequired: cert.IsUserActionRequired(),
NextAction: enums.GetUserActionHint(cert.Status),
AvailableActions: cert.GetAvailableActions(),
RetryCount: cert.RetryCount,
Metadata: make(map[string]interface{}),
}
// 设置企业信息(从认证实体中构建)
// TODO: 这里需要从企业信息服务或其他地方获取完整的企业信息
// response.EnterpriseInfo = cert.EnterpriseInfo
// 设置合同信息(从认证实体中构建)
if cert.ContractFileID != "" || cert.EsignFlowID != "" {
// TODO: 从认证实体字段构建合同信息值对象
// response.ContractInfo = &value_objects.ContractInfo{...}
}
// 设置失败信息
if enums.IsFailureStatus(cert.Status) {
response.FailureReason = cert.FailureReason
response.FailureReasonName = enums.GetFailureReasonName(cert.FailureReason)
response.FailureMessage = cert.FailureMessage
response.CanRetry = enums.IsRetryable(cert.FailureReason)
}
return response
}
// generateChartsData 生成图表数据
func (s *CertificationApplicationServiceImpl) generateChartsData(
stats *repositories.CertificationStatistics,
progressStats *repositories.CertificationProgressStats,
) map[string]interface{} {
charts := make(map[string]interface{})
// 状态分布饼图
if stats.StatusDistribution != nil {
statusChart := make(map[string]interface{})
statusChart["type"] = "pie"
statusChart["data"] = stats.StatusDistribution
charts["status_distribution"] = statusChart
}
// 失败原因分布
if stats.FailureDistribution != nil {
failureChart := make(map[string]interface{})
failureChart["type"] = "bar"
failureChart["data"] = stats.FailureDistribution
charts["failure_distribution"] = failureChart
}
// 进度分布
if progressStats != nil && progressStats.ProgressDistribution != nil {
progressChart := make(map[string]interface{})
progressChart["type"] = "histogram"
progressChart["data"] = progressStats.ProgressDistribution
charts["progress_distribution"] = progressChart
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
return charts
2025-07-13 16:36:20 +08:00
}
2025-07-21 15:13:26 +08:00
// generateSystemAlerts 生成系统警告
func (s *CertificationApplicationServiceImpl) generateSystemAlerts(stats *repositories.CertificationStatistics) []responses.SystemAlert {
var alerts []responses.SystemAlert
// 成功率警告
if stats.SuccessRate < 0.8 {
level := "warning"
if stats.SuccessRate < 0.6 {
level = "critical"
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
alert := responses.SystemAlert{
Level: level,
Type: "success_rate_low",
Message: fmt.Sprintf("认证成功率过低:%.1f%%", stats.SuccessRate*100),
Metric: "success_rate",
Value: stats.SuccessRate,
Threshold: 0.8,
CreatedAt: stats.StartDate,
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
alerts = append(alerts, alert)
}
// 处理时间警告
if stats.AvgProcessingTime.Hours() > 24 {
alert := responses.SystemAlert{
Level: "warning",
Type: "processing_time_high",
Message: fmt.Sprintf("平均处理时间过长:%.1f小时", stats.AvgProcessingTime.Hours()),
Metric: "avg_processing_time",
Value: stats.AvgProcessingTime.String(),
Threshold: "24h",
CreatedAt: stats.StartDate,
2025-07-20 20:53:26 +08:00
}
2025-07-21 15:13:26 +08:00
alerts = append(alerts, alert)
}
return alerts
}
// evaluateSystemHealth 评估系统健康状态
func (s *CertificationApplicationServiceImpl) evaluateSystemHealth(
stats *repositories.CertificationStatistics,
alerts []responses.SystemAlert,
) responses.SystemHealthStatus {
overall := "healthy"
components := map[string]string{
"certification_service": "healthy",
"esign_integration": "healthy",
"database": "healthy",
"state_machine": "healthy",
}
// 根据警告判断健康状态
for _, alert := range alerts {
if alert.Level == "critical" {
overall = "critical"
break
} else if alert.Level == "warning" && overall == "healthy" {
overall = "warning"
}
}
// 根据统计数据评估组件状态
if stats.SuccessRate < 0.6 {
components["certification_service"] = "critical"
components["esign_integration"] = "warning"
} else if stats.SuccessRate < 0.8 {
components["certification_service"] = "warning"
}
return responses.SystemHealthStatus{
Overall: overall,
Components: components,
LastCheck: stats.StartDate,
Details: map[string]interface{}{
"total_certifications": stats.TotalCertifications,
"success_rate": stats.SuccessRate,
"avg_processing_time": stats.AvgProcessingTime.String(),
},
2025-07-13 16:36:20 +08:00
}
}