@@ -109,10 +109,13 @@ 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" {
return nil , fmt . Errorf ( "您已有待审核的提交,请等待管理员审核后再操作" )
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 插入企业信息提交记录(包含扩展字段)
@@ -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 c ert . Status ! = enum s. 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 {
@@ -730,12 +743,12 @@ func (s *CertificationApplicationServiceImpl) AdminListSubmitRecords(
query . Page = 1
}
filter := repositories . ListSubmitRecordsFilter {
Page : query . Page ,
PageSize : query . PageSize ,
ManualReview Status: query . ManualReview Status,
CompanyName : query . CompanyName ,
LegalPersonPhone : query . LegalPersonPhone ,
LegalPersonName : query . LegalPersonName ,
Page : query . Page ,
PageSize : query . PageSize ,
Certification Status: query . Certification Status,
CompanyName : query . CompanyName ,
LegalPersonPhone : query . LegalPersonPhone ,
LegalPersonName : query . LegalPersonName ,
}
result , err := s . enterpriseInfoSubmitRecordRepo . List ( ctx , filter )
if err != nil {
@@ -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,31 +842,11 @@ 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 ) )
}
return fmt . Errorf ( "认证状态不是待审核,当前: %s" , enums . GetStatusName ( cert . Status ) )
}
enterpriseInfo := & certification_value_objects . EnterpriseInfo {
CompanyName : record . CompanyName ,
@@ -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,29 +887,24 @@ 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 )
}
if cert . Status != enums . StatusInfoPendingReview {
return fmt . Errorf ( "认证状态不是待审核,当前: %s" , enums . GetStatusName ( cert . Status ) )
}
// 幂等:认证已处于拒绝或后续状态,无需重复拒绝
switch cert . Status {
case enums . StatusInfoRejected ,
enums . StatusEnterpriseVerified ,
enums . StatusContractApplied ,
enums . StatusContractSigned ,
enums . StatusCompleted ,
enums . StatusContractRejected ,
enums . StatusContractExpired :
return nil
}
record . MarkManualRejected ( adminID , remark )
if err := s . enterpriseInfoSubmitRecordService . Save ( ctx , record ) ; err != nil {
return fmt . Errorf ( "保存提交记录失败: %w" , err )
if cert . Status != enums . StatusInfoPendingReview {
return fmt . Errorf ( "认证状态不是待审核,当前: %s" , enums . GetStatusName ( cert . Status ) )
}
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 . 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 ,
}
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" , 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 )
}
if cert . Status != enums . StatusPending && cert . Status != enums . StatusInfoRejected {
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 ,
}
if err := cert . SubmitEnterpriseInfoForReview ( enterpriseInfo ) ; 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 ) )
return nil
}
// ================ 辅助方法 ================
// convertToResponse 转换实体为响应DTO
func ( s * CertificationApplicationServiceImpl ) convertToResponse ( cert * entities . Certification ) * responses . CertificationResponse {
response := & responses . CertificationResponse {