f
This commit is contained in:
@@ -41,10 +41,12 @@ type CertificationApplicationService interface {
|
||||
AdminListSubmitRecords(ctx context.Context, query *queries.AdminListSubmitRecordsQuery) (*responses.AdminSubmitRecordsListResponse, error)
|
||||
// AdminGetSubmitRecordByID 管理端获取单条提交记录详情
|
||||
AdminGetSubmitRecordByID(ctx context.Context, recordID string) (*responses.AdminSubmitRecordDetail, error)
|
||||
// AdminApproveSubmitRecord 管理端审核通过
|
||||
// AdminApproveSubmitRecord 管理端审核通过(按提交记录 ID)
|
||||
AdminApproveSubmitRecord(ctx context.Context, recordID, adminID, remark string) error
|
||||
// AdminRejectSubmitRecord 管理端审核拒绝
|
||||
// AdminRejectSubmitRecord 管理端审核拒绝(按提交记录 ID)
|
||||
AdminRejectSubmitRecord(ctx context.Context, recordID, adminID, remark string) error
|
||||
// AdminTransitionCertificationStatus 管理端按用户变更认证状态(以状态机为准:info_submitted=通过 / info_rejected=拒绝)
|
||||
AdminTransitionCertificationStatus(ctx context.Context, cmd *commands.AdminTransitionCertificationStatusCommand) error
|
||||
|
||||
// ================ e签宝回调处理 ================
|
||||
|
||||
|
||||
@@ -109,11 +109,14 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
|
||||
s.logger.Info("开始提交企业信息",
|
||||
zap.String("user_id", cmd.UserID))
|
||||
|
||||
// 0. 若该用户已有待审核的提交记录,则不允许重复提交
|
||||
// 0. 若该用户已有待审核(认证状态仍在待审核),则不允许重复提交
|
||||
latestRecord, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cmd.UserID)
|
||||
if err == nil && latestRecord != nil && latestRecord.ManualReviewStatus == "pending" {
|
||||
if err == nil && latestRecord != nil {
|
||||
cert, loadErr := s.aggregateService.LoadCertificationByUserID(ctx, cmd.UserID)
|
||||
if loadErr == nil && cert != nil && cert.Status == enums.StatusInfoPendingReview {
|
||||
return nil, fmt.Errorf("您已有待审核的提交,请等待管理员审核后再操作")
|
||||
}
|
||||
}
|
||||
|
||||
// 1.5 插入企业信息提交记录(包含扩展字段)
|
||||
record := entities.NewEnterpriseInfoSubmitRecord(
|
||||
@@ -259,16 +262,7 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
|
||||
return fmt.Errorf("加载认证信息失败: %s", err.Error())
|
||||
}
|
||||
|
||||
// 已是「已提交企业信息」:说明已通过人工审核,直接返回当前认证数据,前端可刷新到企业认证步骤
|
||||
if cert.Status == enums.StatusInfoSubmitted {
|
||||
response = s.convertToResponse(cert)
|
||||
response.Metadata = map[string]interface{}{
|
||||
"next_action": "您已通过审核,请完成企业认证步骤",
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 4. 提交企业信息进入人工审核(不调用 e签宝,不生成认证链接)
|
||||
// 4. 提交企业信息进入人工审核(不在此处推断审核是否通过)
|
||||
err = cert.SubmitEnterpriseInfoForReview(enterpriseInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("提交企业信息失败: %s", err.Error())
|
||||
@@ -303,6 +297,25 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// 审核状态检查(步骤二)
|
||||
// 规则:企业信息提交成功后进入待审核;审核通过后才允许进行企业认证确认(ConfirmAuth)。
|
||||
func (s *CertificationApplicationServiceImpl) checkAuditStatus(ctx context.Context, cert *entities.Certification) error {
|
||||
switch cert.Status {
|
||||
case enums.StatusInfoSubmitted,
|
||||
enums.StatusEnterpriseVerified,
|
||||
enums.StatusContractApplied,
|
||||
enums.StatusContractSigned,
|
||||
enums.StatusCompleted:
|
||||
return nil
|
||||
case enums.StatusInfoPendingReview:
|
||||
return fmt.Errorf("企业信息已提交,正在审核中")
|
||||
case enums.StatusInfoRejected:
|
||||
return fmt.Errorf("企业信息审核未通过")
|
||||
default:
|
||||
return fmt.Errorf("认证状态不正确,当前状态: %s", enums.GetStatusName(cert.Status))
|
||||
}
|
||||
}
|
||||
|
||||
// ConfirmAuth 确认认证状态
|
||||
func (s *CertificationApplicationServiceImpl) ConfirmAuth(
|
||||
ctx context.Context,
|
||||
@@ -314,9 +327,9 @@ func (s *CertificationApplicationServiceImpl) ConfirmAuth(
|
||||
return nil, fmt.Errorf("加载认证信息失败: %s", err.Error())
|
||||
}
|
||||
|
||||
// 企业认证
|
||||
if cert.Status != enums.StatusInfoSubmitted {
|
||||
return nil, fmt.Errorf("认证状态不正确,当前状态: %s", enums.GetStatusName(cert.Status))
|
||||
// 步骤二:审核状态检查(审核通过后才能进入企业认证确认)
|
||||
if err := s.checkAuditStatus(ctx, cert); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cert.UserID)
|
||||
if err != nil {
|
||||
@@ -732,7 +745,7 @@ func (s *CertificationApplicationServiceImpl) AdminListSubmitRecords(
|
||||
filter := repositories.ListSubmitRecordsFilter{
|
||||
Page: query.Page,
|
||||
PageSize: query.PageSize,
|
||||
ManualReviewStatus: query.ManualReviewStatus,
|
||||
CertificationStatus: query.CertificationStatus,
|
||||
CompanyName: query.CompanyName,
|
||||
LegalPersonPhone: query.LegalPersonPhone,
|
||||
LegalPersonName: query.LegalPersonName,
|
||||
@@ -755,8 +768,6 @@ func (s *CertificationApplicationServiceImpl) AdminListSubmitRecords(
|
||||
LegalPersonName: r.LegalPersonName,
|
||||
SubmitAt: r.SubmitAt,
|
||||
Status: r.Status,
|
||||
ManualReviewStatus: r.ManualReviewStatus,
|
||||
ManualReviewedAt: r.ManualReviewedAt,
|
||||
CertificationStatus: certStatus,
|
||||
})
|
||||
}
|
||||
@@ -805,10 +816,6 @@ func (s *CertificationApplicationServiceImpl) AdminGetSubmitRecordByID(ctx conte
|
||||
VerifiedAt: record.VerifiedAt,
|
||||
FailedAt: record.FailedAt,
|
||||
FailureReason: record.FailureReason,
|
||||
ManualReviewStatus: record.ManualReviewStatus,
|
||||
ManualReviewRemark: record.ManualReviewRemark,
|
||||
ManualReviewedAt: record.ManualReviewedAt,
|
||||
ManualReviewerID: record.ManualReviewerID,
|
||||
CertificationStatus: certStatus,
|
||||
CreatedAt: record.CreatedAt,
|
||||
UpdatedAt: record.UpdatedAt,
|
||||
@@ -821,17 +828,12 @@ func (s *CertificationApplicationServiceImpl) AdminApproveSubmitRecord(ctx conte
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取提交记录失败: %w", err)
|
||||
}
|
||||
if record.ManualReviewStatus != "pending" {
|
||||
return fmt.Errorf("该记录已审核,当前状态: %s", record.ManualReviewStatus)
|
||||
}
|
||||
cert, err := s.aggregateService.LoadCertificationByUserID(ctx, record.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载认证信息失败: %w", err)
|
||||
}
|
||||
|
||||
// 兼容线上脏数据:认证已进入「已提交企业信息」或更后续状态,但提交记录仍是 pending,
|
||||
// 此时无需再走「待审核->通过」的状态机,只需要把提交记录补齐为 approved,避免管理端无法操作。
|
||||
// 说明:后续状态(如已企业认证/合同状态/完成)都意味着企业信息审核已经通过。
|
||||
// 幂等:认证已进入「已提交企业信息」或更后续状态,说明已通过审核,无需重复操作
|
||||
switch cert.Status {
|
||||
case enums.StatusInfoSubmitted,
|
||||
enums.StatusEnterpriseVerified,
|
||||
@@ -840,32 +842,12 @@ func (s *CertificationApplicationServiceImpl) AdminApproveSubmitRecord(ctx conte
|
||||
enums.StatusCompleted,
|
||||
enums.StatusContractRejected,
|
||||
enums.StatusContractExpired:
|
||||
record.MarkManualApproved(adminID, remark)
|
||||
if err := s.enterpriseInfoSubmitRecordService.Save(ctx, record); err != nil {
|
||||
return fmt.Errorf("保存提交记录失败: %w", err)
|
||||
}
|
||||
s.logger.Info("已补齐提交记录人工审核为通过(认证已进入后续状态)",
|
||||
zap.String("record_id", recordID),
|
||||
zap.String("admin_id", adminID),
|
||||
zap.String("user_id", record.UserID),
|
||||
zap.String("certification_status", string(cert.Status)),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 兼容线上脏数据:提交记录已落库但当时事务失败导致认证仍为「待认证」,先同步为待审核再执行通过
|
||||
if cert.Status != enums.StatusInfoPendingReview {
|
||||
if err := s.syncCertToPendingReviewIfRecordPending(ctx, cert, record); err != nil {
|
||||
return err
|
||||
}
|
||||
cert, err = s.aggregateService.LoadCertificationByUserID(ctx, record.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载认证信息失败: %w", err)
|
||||
}
|
||||
if cert.Status != enums.StatusInfoPendingReview {
|
||||
return fmt.Errorf("认证状态不是待审核,当前: %s", enums.GetStatusName(cert.Status))
|
||||
}
|
||||
}
|
||||
enterpriseInfo := &certification_value_objects.EnterpriseInfo{
|
||||
CompanyName: record.CompanyName,
|
||||
UnifiedSocialCode: record.UnifiedSocialCode,
|
||||
@@ -886,10 +868,6 @@ func (s *CertificationApplicationServiceImpl) AdminApproveSubmitRecord(ctx conte
|
||||
if err != nil {
|
||||
return fmt.Errorf("生成企业认证链接失败: %w", err)
|
||||
}
|
||||
record.MarkManualApproved(adminID, remark)
|
||||
if err := s.enterpriseInfoSubmitRecordService.Save(ctx, record); err != nil {
|
||||
return fmt.Errorf("保存提交记录失败: %w", err)
|
||||
}
|
||||
if err := cert.ApproveEnterpriseInfoReview(authURL.AuthShortURL, authURL.AuthFlowID, adminID); err != nil {
|
||||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||||
}
|
||||
@@ -909,30 +887,25 @@ func (s *CertificationApplicationServiceImpl) AdminRejectSubmitRecord(ctx contex
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取提交记录失败: %w", err)
|
||||
}
|
||||
if record.ManualReviewStatus != "pending" {
|
||||
return fmt.Errorf("该记录已审核,当前状态: %s", record.ManualReviewStatus)
|
||||
}
|
||||
cert, err := s.aggregateService.LoadCertificationByUserID(ctx, record.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载认证信息失败: %w", err)
|
||||
}
|
||||
// 兼容线上脏数据:提交记录已落库但当时事务失败导致认证仍为「待认证」,先同步为待审核再执行拒绝
|
||||
if cert.Status != enums.StatusInfoPendingReview {
|
||||
if err := s.syncCertToPendingReviewIfRecordPending(ctx, cert, record); err != nil {
|
||||
return err
|
||||
}
|
||||
cert, err = s.aggregateService.LoadCertificationByUserID(ctx, record.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载认证信息失败: %w", err)
|
||||
|
||||
// 幂等:认证已处于拒绝或后续状态,无需重复拒绝
|
||||
switch cert.Status {
|
||||
case enums.StatusInfoRejected,
|
||||
enums.StatusEnterpriseVerified,
|
||||
enums.StatusContractApplied,
|
||||
enums.StatusContractSigned,
|
||||
enums.StatusCompleted,
|
||||
enums.StatusContractRejected,
|
||||
enums.StatusContractExpired:
|
||||
return nil
|
||||
}
|
||||
if cert.Status != enums.StatusInfoPendingReview {
|
||||
return fmt.Errorf("认证状态不是待审核,当前: %s", enums.GetStatusName(cert.Status))
|
||||
}
|
||||
}
|
||||
record.MarkManualRejected(adminID, remark)
|
||||
if err := s.enterpriseInfoSubmitRecordService.Save(ctx, record); err != nil {
|
||||
return fmt.Errorf("保存提交记录失败: %w", err)
|
||||
}
|
||||
if err := cert.RejectEnterpriseInfoReview(adminID, remark); err != nil {
|
||||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||||
}
|
||||
@@ -943,35 +916,75 @@ func (s *CertificationApplicationServiceImpl) AdminRejectSubmitRecord(ctx contex
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================ 辅助方法 ================
|
||||
|
||||
// syncCertToPendingReviewIfRecordPending 兼容历史脏数据:当认证为「待认证」或「已拒绝」且存在待审核提交记录时,
|
||||
// 用该记录的企业信息把认证同步为「待审核」,便于管理员直接审核通过/拒绝。
|
||||
func (s *CertificationApplicationServiceImpl) syncCertToPendingReviewIfRecordPending(ctx context.Context, cert *entities.Certification, record *entities.EnterpriseInfoSubmitRecord) error {
|
||||
if record.ManualReviewStatus != "pending" {
|
||||
// AdminTransitionCertificationStatus 管理端按用户变更认证状态(以状态机为准)
|
||||
func (s *CertificationApplicationServiceImpl) AdminTransitionCertificationStatus(ctx context.Context, cmd *commands.AdminTransitionCertificationStatusCommand) error {
|
||||
cert, err := s.aggregateService.LoadCertificationByUserID(ctx, cmd.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载认证信息失败: %w", err)
|
||||
}
|
||||
record, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cmd.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找企业信息提交记录失败: %w", err)
|
||||
}
|
||||
if record == nil {
|
||||
return fmt.Errorf("未找到该用户的企业信息提交记录")
|
||||
}
|
||||
switch cmd.TargetStatus {
|
||||
case string(enums.StatusInfoSubmitted):
|
||||
// 审核通过:与 AdminApproveSubmitRecord 一致,推状态并生成企业认证链接
|
||||
switch cert.Status {
|
||||
case enums.StatusInfoSubmitted, enums.StatusEnterpriseVerified, enums.StatusContractApplied,
|
||||
enums.StatusContractSigned, enums.StatusCompleted, enums.StatusContractRejected, enums.StatusContractExpired:
|
||||
return nil
|
||||
}
|
||||
if cert.Status != enums.StatusPending && cert.Status != enums.StatusInfoRejected {
|
||||
if cert.Status != enums.StatusInfoPendingReview {
|
||||
return fmt.Errorf("认证状态不是待审核,当前: %s", enums.GetStatusName(cert.Status))
|
||||
}
|
||||
enterpriseInfo := &certification_value_objects.EnterpriseInfo{
|
||||
CompanyName: record.CompanyName,
|
||||
UnifiedSocialCode: record.UnifiedSocialCode,
|
||||
LegalPersonName: record.LegalPersonName,
|
||||
LegalPersonID: record.LegalPersonID,
|
||||
LegalPersonPhone: record.LegalPersonPhone,
|
||||
EnterpriseAddress: record.EnterpriseAddress,
|
||||
CompanyName: record.CompanyName, UnifiedSocialCode: record.UnifiedSocialCode,
|
||||
LegalPersonName: record.LegalPersonName, LegalPersonID: record.LegalPersonID,
|
||||
LegalPersonPhone: record.LegalPersonPhone, EnterpriseAddress: record.EnterpriseAddress,
|
||||
}
|
||||
if err := cert.SubmitEnterpriseInfoForReview(enterpriseInfo); err != nil {
|
||||
return fmt.Errorf("同步认证为待审核失败: %w", err)
|
||||
authURL, err := s.esignClient.GenerateEnterpriseAuth(&esign.EnterpriseAuthRequest{
|
||||
CompanyName: enterpriseInfo.CompanyName, UnifiedSocialCode: enterpriseInfo.UnifiedSocialCode,
|
||||
LegalPersonName: enterpriseInfo.LegalPersonName, LegalPersonID: enterpriseInfo.LegalPersonID,
|
||||
TransactorName: enterpriseInfo.LegalPersonName, TransactorMobile: enterpriseInfo.LegalPersonPhone, TransactorID: enterpriseInfo.LegalPersonID,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("生成企业认证链接失败: %w", err)
|
||||
}
|
||||
if err := cert.ApproveEnterpriseInfoReview(authURL.AuthShortURL, authURL.AuthFlowID, cmd.AdminID); err != nil {
|
||||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||||
}
|
||||
if err := s.aggregateService.SaveCertification(ctx, cert); err != nil {
|
||||
return fmt.Errorf("保存认证信息失败: %w", err)
|
||||
}
|
||||
s.logger.Info("已同步认证为待审核(兼容历史脏数据)", zap.String("user_id", cert.UserID), zap.String("record_id", record.ID))
|
||||
s.logger.Info("管理端变更认证状态为通过", zap.String("user_id", cmd.UserID), zap.String("admin_id", cmd.AdminID))
|
||||
return nil
|
||||
case string(enums.StatusInfoRejected):
|
||||
// 审核拒绝
|
||||
if cert.Status == enums.StatusInfoRejected || cert.Status == enums.StatusEnterpriseVerified ||
|
||||
cert.Status == enums.StatusContractApplied || cert.Status == enums.StatusContractSigned || cert.Status == enums.StatusCompleted {
|
||||
return nil
|
||||
}
|
||||
if cert.Status != enums.StatusInfoPendingReview {
|
||||
return fmt.Errorf("认证状态不是待审核,当前: %s", enums.GetStatusName(cert.Status))
|
||||
}
|
||||
if err := cert.RejectEnterpriseInfoReview(cmd.AdminID, cmd.Remark); err != nil {
|
||||
return fmt.Errorf("更新认证状态失败: %w", err)
|
||||
}
|
||||
if err := s.aggregateService.SaveCertification(ctx, cert); err != nil {
|
||||
return fmt.Errorf("保存认证信息失败: %w", err)
|
||||
}
|
||||
s.logger.Info("管理端变更认证状态为拒绝", zap.String("user_id", cmd.UserID), zap.String("admin_id", cmd.AdminID))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("不支持的目标状态: %s", cmd.TargetStatus)
|
||||
}
|
||||
}
|
||||
|
||||
// ================ 辅助方法 ================
|
||||
|
||||
// convertToResponse 转换实体为响应DTO
|
||||
func (s *CertificationApplicationServiceImpl) convertToResponse(cert *entities.Certification) *responses.CertificationResponse {
|
||||
response := &responses.CertificationResponse{
|
||||
|
||||
@@ -94,6 +94,14 @@ type ForceTransitionStatusCommand struct {
|
||||
Force bool `json:"force,omitempty"` // 是否强制执行,跳过业务规则验证
|
||||
}
|
||||
|
||||
// AdminTransitionCertificationStatusCommand 管理端变更认证状态(以状态机为准,用于审核通过/拒绝等)
|
||||
type AdminTransitionCertificationStatusCommand struct {
|
||||
AdminID string `json:"-"`
|
||||
UserID string `json:"user_id" validate:"required"`
|
||||
TargetStatus string `json:"target_status" validate:"required,oneof=info_submitted info_rejected"` // 审核通过 -> info_submitted;审核拒绝 -> info_rejected
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
// SubmitEnterpriseInfoCommand 提交企业信息命令
|
||||
type SubmitEnterpriseInfoCommand struct {
|
||||
UserID string `json:"-" comment:"用户唯一标识,从JWT token获取,不在JSON中暴露"`
|
||||
|
||||
@@ -193,11 +193,11 @@ func (q *GetSystemMonitoringQuery) ShouldIncludeMetric(metric string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// AdminListSubmitRecordsQuery 管理端企业信息提交记录列表查询
|
||||
// AdminListSubmitRecordsQuery 管理端企业信息提交记录列表查询(以状态机 certification_status 为准,不做审核状态筛选)
|
||||
type AdminListSubmitRecordsQuery struct {
|
||||
Page int `json:"page" form:"page"`
|
||||
PageSize int `json:"page_size" form:"page_size"`
|
||||
ManualReviewStatus string `json:"manual_review_status" form:"manual_review_status"` // pending, approved, rejected,空为全部
|
||||
CertificationStatus string `json:"certification_status" form:"certification_status"` // 按认证状态筛选,如 info_pending_review / info_submitted / info_rejected,空为全部
|
||||
CompanyName string `json:"company_name" form:"company_name"` // 企业名称(模糊搜索)
|
||||
LegalPersonPhone string `json:"legal_person_phone" form:"legal_person_phone"` // 法人手机号
|
||||
LegalPersonName string `json:"legal_person_name" form:"legal_person_name"` // 法人姓名(模糊搜索)
|
||||
|
||||
@@ -119,9 +119,7 @@ type AdminSubmitRecordItem struct {
|
||||
LegalPersonName string `json:"legal_person_name"`
|
||||
SubmitAt time.Time `json:"submit_at"`
|
||||
Status string `json:"status"`
|
||||
ManualReviewStatus string `json:"manual_review_status"`
|
||||
ManualReviewedAt *time.Time `json:"manual_reviewed_at,omitempty"`
|
||||
CertificationStatus string `json:"certification_status,omitempty"` // 该用户当前认证状态,用于前端判断是否已完成企业认证并显示「已审核」
|
||||
CertificationStatus string `json:"certification_status,omitempty"` // 以状态机为准:info_pending_review/info_submitted/info_rejected 等
|
||||
}
|
||||
|
||||
// AdminSubmitRecordDetail 管理端提交记录详情(含完整信息与图片 URL)
|
||||
@@ -147,11 +145,7 @@ type AdminSubmitRecordDetail struct {
|
||||
VerifiedAt *time.Time `json:"verified_at,omitempty"`
|
||||
FailedAt *time.Time `json:"failed_at,omitempty"`
|
||||
FailureReason string `json:"failure_reason,omitempty"`
|
||||
ManualReviewStatus string `json:"manual_review_status"`
|
||||
ManualReviewRemark string `json:"manual_review_remark,omitempty"`
|
||||
ManualReviewedAt *time.Time `json:"manual_reviewed_at,omitempty"`
|
||||
ManualReviewerID string `json:"manual_reviewer_id,omitempty"`
|
||||
CertificationStatus string `json:"certification_status,omitempty"` // 该用户当前认证状态,用于前端显示「已审核」
|
||||
CertificationStatus string `json:"certification_status,omitempty"` // 以状态机为准
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"tyapi-server/internal/domains/certification/entities"
|
||||
)
|
||||
|
||||
// ListSubmitRecordsFilter 提交记录列表筛选
|
||||
// ListSubmitRecordsFilter 提交记录列表筛选(以状态机 certification 状态为准)
|
||||
type ListSubmitRecordsFilter struct {
|
||||
ManualReviewStatus string // pending, approved, rejected,空表示全部
|
||||
CertificationStatus string // 认证状态筛选,如 info_pending_review / info_submitted / info_rejected,空为全部
|
||||
CompanyName string // 企业名称(模糊搜索)
|
||||
LegalPersonPhone string // 法人手机号
|
||||
LegalPersonName string // 法人姓名(模糊搜索)
|
||||
|
||||
@@ -82,12 +82,12 @@ func (s *EnterpriseInfoSubmitRecordService) ValidateWithWestdex(ctx context.Cont
|
||||
}
|
||||
|
||||
// 开发环境下跳过外部验证
|
||||
// if s.appConfig.IsDevelopment() {
|
||||
// s.logger.Info("开发环境:跳过企业信息外部验证",
|
||||
// zap.String("company_name", info.CompanyName),
|
||||
// zap.String("legal_person", info.LegalPersonName))
|
||||
// return nil
|
||||
// }
|
||||
if s.appConfig.IsDevelopment() {
|
||||
s.logger.Info("开发环境:跳过企业信息外部验证",
|
||||
zap.String("company_name", info.CompanyName),
|
||||
zap.String("legal_person", info.LegalPersonName))
|
||||
return nil
|
||||
}
|
||||
|
||||
// 构建QYGL5CMP请求参数
|
||||
reqDto := dto.QYGL5CMPReq{
|
||||
|
||||
@@ -91,21 +91,22 @@ func (r *GormEnterpriseInfoSubmitRecordRepository) ExistsByUnifiedSocialCodeExcl
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) List(ctx context.Context, filter repositories.ListSubmitRecordsFilter) (*repositories.ListSubmitRecordsResult, error) {
|
||||
db := r.GetDB(ctx).Model(&entities.EnterpriseInfoSubmitRecord{})
|
||||
if filter.ManualReviewStatus != "" {
|
||||
db = db.Where("manual_review_status = ?", filter.ManualReviewStatus)
|
||||
base := r.GetDB(ctx).Model(&entities.EnterpriseInfoSubmitRecord{})
|
||||
if filter.CertificationStatus != "" {
|
||||
base = base.Joins("JOIN certifications ON certifications.user_id = enterprise_info_submit_records.user_id AND certifications.deleted_at IS NULL").
|
||||
Where("certifications.status = ?", filter.CertificationStatus)
|
||||
}
|
||||
if filter.CompanyName != "" {
|
||||
db = db.Where("company_name LIKE ?", "%"+filter.CompanyName+"%")
|
||||
base = base.Where("enterprise_info_submit_records.company_name LIKE ?", "%"+filter.CompanyName+"%")
|
||||
}
|
||||
if filter.LegalPersonPhone != "" {
|
||||
db = db.Where("legal_person_phone = ?", filter.LegalPersonPhone)
|
||||
base = base.Where("enterprise_info_submit_records.legal_person_phone = ?", filter.LegalPersonPhone)
|
||||
}
|
||||
if filter.LegalPersonName != "" {
|
||||
db = db.Where("legal_person_name LIKE ?", "%"+filter.LegalPersonName+"%")
|
||||
base = base.Where("enterprise_info_submit_records.legal_person_name LIKE ?", "%"+filter.LegalPersonName+"%")
|
||||
}
|
||||
var total int64
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
if err := base.Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if filter.PageSize <= 0 {
|
||||
@@ -116,20 +117,21 @@ func (r *GormEnterpriseInfoSubmitRecordRepository) List(ctx context.Context, fil
|
||||
}
|
||||
offset := (filter.Page - 1) * filter.PageSize
|
||||
var records []*entities.EnterpriseInfoSubmitRecord
|
||||
q := r.GetDB(ctx)
|
||||
if filter.ManualReviewStatus != "" {
|
||||
q = q.Where("manual_review_status = ?", filter.ManualReviewStatus)
|
||||
q := r.GetDB(ctx).Model(&entities.EnterpriseInfoSubmitRecord{})
|
||||
if filter.CertificationStatus != "" {
|
||||
q = q.Joins("JOIN certifications ON certifications.user_id = enterprise_info_submit_records.user_id AND certifications.deleted_at IS NULL").
|
||||
Where("certifications.status = ?", filter.CertificationStatus)
|
||||
}
|
||||
if filter.CompanyName != "" {
|
||||
q = q.Where("company_name LIKE ?", "%"+filter.CompanyName+"%")
|
||||
q = q.Where("enterprise_info_submit_records.company_name LIKE ?", "%"+filter.CompanyName+"%")
|
||||
}
|
||||
if filter.LegalPersonPhone != "" {
|
||||
q = q.Where("legal_person_phone = ?", filter.LegalPersonPhone)
|
||||
q = q.Where("enterprise_info_submit_records.legal_person_phone = ?", filter.LegalPersonPhone)
|
||||
}
|
||||
if filter.LegalPersonName != "" {
|
||||
q = q.Where("legal_person_name LIKE ?", "%"+filter.LegalPersonName+"%")
|
||||
q = q.Where("enterprise_info_submit_records.legal_person_name LIKE ?", "%"+filter.LegalPersonName+"%")
|
||||
}
|
||||
err := q.Order("submit_at DESC").Offset(offset).Limit(filter.PageSize).Find(&records).Error
|
||||
err := q.Order("enterprise_info_submit_records.submit_at DESC").Offset(offset).Limit(filter.PageSize).Find(&records).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ func (h *CertificationHandler) AdminCompleteCertificationWithoutContract(c *gin.
|
||||
// @Security Bearer
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "每页条数"
|
||||
// @Param manual_review_status query string false "审核状态 pending/approved/rejected"
|
||||
// @Param certification_status query string false "按状态机筛选:info_pending_review/info_submitted/info_rejected,空为全部"
|
||||
// @Success 200 {object} responses.AdminSubmitRecordsListResponse
|
||||
// @Router /api/v1/certifications/admin/submit-records [get]
|
||||
func (h *CertificationHandler) AdminListSubmitRecords(c *gin.Context) {
|
||||
@@ -564,6 +564,34 @@ func (h *CertificationHandler) AdminRejectSubmitRecord(c *gin.Context) {
|
||||
h.response.Success(c, nil, "已拒绝")
|
||||
}
|
||||
|
||||
// AdminTransitionCertificationStatus 管理端按用户变更认证状态(以状态机为准)
|
||||
// @Summary 管理端变更认证状态
|
||||
// @Tags 认证管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param request body commands.AdminTransitionCertificationStatusCommand true "user_id, target_status(info_submitted/info_rejected), remark"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /api/v1/certifications/admin/transition-status [post]
|
||||
func (h *CertificationHandler) AdminTransitionCertificationStatus(c *gin.Context) {
|
||||
adminID := h.getCurrentUserID(c)
|
||||
if adminID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
var cmd commands.AdminTransitionCertificationStatusCommand
|
||||
if err := c.ShouldBindJSON(&cmd); err != nil {
|
||||
h.response.BadRequest(c, "参数错误")
|
||||
return
|
||||
}
|
||||
cmd.AdminID = adminID
|
||||
if err := h.appService.AdminTransitionCertificationStatus(c.Request.Context(), &cmd); err != nil {
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, nil, "状态已更新")
|
||||
}
|
||||
|
||||
// ================ 回调处理 ================
|
||||
|
||||
// HandleEsignCallback 处理e签宝回调
|
||||
|
||||
@@ -77,10 +77,14 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
|
||||
|
||||
}
|
||||
|
||||
// 管理端企业审核(需管理员权限)
|
||||
adminCertGroup := certificationGroup.Group("/admin/submit-records")
|
||||
adminCertGroup.Use(r.auth.Handle())
|
||||
adminCertGroup.Use(r.admin.Handle())
|
||||
// 管理端企业审核(需管理员权限,以状态机状态为准)
|
||||
adminGroup := certificationGroup.Group("/admin")
|
||||
adminGroup.Use(r.auth.Handle())
|
||||
adminGroup.Use(r.admin.Handle())
|
||||
{
|
||||
adminGroup.POST("/transition-status", r.handler.AdminTransitionCertificationStatus)
|
||||
}
|
||||
adminCertGroup := adminGroup.Group("/submit-records")
|
||||
{
|
||||
adminCertGroup.GET("", r.handler.AdminListSubmitRecords)
|
||||
adminCertGroup.GET("/:id", r.handler.AdminGetSubmitRecordByID)
|
||||
|
||||
@@ -240,7 +240,7 @@ func (m *ComprehensiveLoggerMiddleware) logErrors(c *gin.Context, requestID, tra
|
||||
zap.String("user_id", userID),
|
||||
zap.String("method", c.Request.Method),
|
||||
zap.String("path", c.Request.URL.Path),
|
||||
zap.String("error_type", string(ginErr.Type)),
|
||||
zap.Uint64("error_type", uint64(ginErr.Type)),
|
||||
zap.Error(ginErr.Err),
|
||||
zap.Time("timestamp", time.Now()),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user