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
|
|
|
|
}
|
|
|
|
|
|
}
|