f and add

This commit is contained in:
Mrx
2026-03-18 11:44:37 +08:00
parent 12ed1c81e3
commit 0ce793ac61
8 changed files with 328 additions and 42 deletions

View File

@@ -109,6 +109,12 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
s.logger.Info("开始提交企业信息",
zap.String("user_id", cmd.UserID))
// 0. 若该用户已有待审核的提交记录,则不允许重复提交
latestRecord, err := s.enterpriseInfoSubmitRecordRepo.FindLatestByUserID(ctx, cmd.UserID)
if err == nil && latestRecord != nil && latestRecord.ManualReviewStatus == "pending" {
return nil, fmt.Errorf("您已有待审核的提交,请等待管理员审核后再操作")
}
// 1.5 插入企业信息提交记录(包含扩展字段)
record := entities.NewEnterpriseInfoSubmitRecord(
cmd.UserID,
@@ -164,7 +170,8 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
}
s.logger.Info("开始处理企业信息提交",
zap.String("user_id", cmd.UserID))
// 1. 检查企业信息是否重复(统一社会信用代码,已经认证了的,不能重复提交
// 1. 检查企业信息是否重复(统一社会信用代码:已认证或已提交待审核的都不能重复)
// 1.1 已写入用户域 enterprise_infos 的(已完成认证)
exists, err := s.userAggregateService.CheckUnifiedSocialCodeExists(ctx, cmd.UnifiedSocialCode, cmd.UserID)
if err != nil {
record.MarkAsFailed(err.Error())
@@ -174,7 +181,6 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
}
return nil, fmt.Errorf("检查企业信息失败: %s", err.Error())
}
if exists {
record.MarkAsFailed("该企业信息已被其他用户使用,请确认企业信息是否正确")
saveErr := s.enterpriseInfoSubmitRecordService.Save(ctx, record)
@@ -182,7 +188,24 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
return nil, fmt.Errorf("保存企业信息提交记录失败: %s", saveErr.Error())
}
return nil, fmt.Errorf("该企业信息已被其他用户使用,请确认企业信息是否正确")
}
// 1.2 已提交/已通过验证的提交记录(尚未完成认证但已占用的信用代码)
existsInSubmit, err := s.enterpriseInfoSubmitRecordRepo.ExistsByUnifiedSocialCodeExcludeUser(ctx, cmd.UnifiedSocialCode, cmd.UserID)
if err != nil {
record.MarkAsFailed(err.Error())
saveErr := s.enterpriseInfoSubmitRecordService.Save(ctx, record)
if saveErr != nil {
return nil, fmt.Errorf("保存企业信息提交记录失败: %s", saveErr.Error())
}
return nil, fmt.Errorf("检查企业信息失败: %s", err.Error())
}
if existsInSubmit {
record.MarkAsFailed("该企业信息已被其他用户使用,请确认企业信息是否正确")
saveErr := s.enterpriseInfoSubmitRecordService.Save(ctx, record)
if saveErr != nil {
return nil, fmt.Errorf("保存企业信息提交记录失败: %s", saveErr.Error())
}
return nil, fmt.Errorf("该企业信息已被其他用户使用,请确认企业信息是否正确")
}
enterpriseInfo := &certification_value_objects.EnterpriseInfo{
@@ -214,10 +237,6 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
return nil, fmt.Errorf("企业信息验证失败, %s", err.Error())
}
record.MarkAsVerified()
saveErr := s.enterpriseInfoSubmitRecordService.Save(ctx, record)
if saveErr != nil {
return nil, fmt.Errorf("保存企业信息提交记录失败: %s", saveErr.Error())
}
var response *responses.CertificationResponse
err = s.txManager.ExecuteInTx(ctx, func(txCtx context.Context) error {
@@ -255,23 +274,25 @@ func (s *CertificationApplicationServiceImpl) SubmitEnterpriseInfo(
return fmt.Errorf("提交企业信息失败: %s", err.Error())
}
respMeta := map[string]interface{}{
"enterprise_info": enterpriseInfo,
"next_action": "请等待管理员审核企业信息",
}
err = s.aggregateService.SaveCertification(txCtx, cert)
if err != nil {
return fmt.Errorf("保存认证信息失败: %s", err.Error())
}
// 5. 转换为响应DTO
response = s.convertToResponse(cert)
// 6. 添加工作流结果信息
// 5. 提交记录与认证状态在同一事务内保存,避免出现「有记录但认证未变待审核」的不一致
if saveErr := s.enterpriseInfoSubmitRecordService.Save(txCtx, record); saveErr != nil {
return fmt.Errorf("保存企业信息提交记录失败: %s", saveErr.Error())
}
respMeta := map[string]interface{}{
"enterprise_info": enterpriseInfo,
"next_action": "请等待管理员审核企业信息",
}
// 6. 转换为响应 DTO
response = s.convertToResponse(cert)
if respMeta != nil {
response.Metadata = respMeta
}
return nil
})
if err != nil {
@@ -804,8 +825,18 @@ func (s *CertificationApplicationServiceImpl) AdminApproveSubmitRecord(ctx conte
if err != nil {
return fmt.Errorf("加载认证信息失败: %w", err)
}
// 兼容线上脏数据:提交记录已落库但当时事务失败导致认证仍为「待认证」,先同步为待审核再执行通过
if cert.Status != enums.StatusInfoPendingReview {
return fmt.Errorf("认证状态不是待审核,当前: %s", enums.GetStatusName(cert.Status))
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,
@@ -857,8 +888,18 @@ func (s *CertificationApplicationServiceImpl) AdminRejectSubmitRecord(ctx contex
if err != nil {
return fmt.Errorf("加载认证信息失败: %w", err)
}
// 兼容线上脏数据:提交记录已落库但当时事务失败导致认证仍为「待认证」,先同步为待审核再执行拒绝
if cert.Status != enums.StatusInfoPendingReview {
return fmt.Errorf("认证状态不是待审核,当前: %s", enums.GetStatusName(cert.Status))
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))
}
}
record.MarkManualRejected(adminID, remark)
if err := s.enterpriseInfoSubmitRecordService.Save(ctx, record); err != nil {
@@ -876,6 +917,33 @@ func (s *CertificationApplicationServiceImpl) AdminRejectSubmitRecord(ctx contex
// ================ 辅助方法 ================
// syncCertToPendingReviewIfRecordPending 兼容历史脏数据:当认证为「待认证」或「已拒绝」且存在待审核提交记录时,
// 用该记录的企业信息把认证同步为「待审核」,便于管理员直接审核通过/拒绝。
func (s *CertificationApplicationServiceImpl) syncCertToPendingReviewIfRecordPending(ctx context.Context, cert *entities.Certification, record *entities.EnterpriseInfoSubmitRecord) error {
if record.ManualReviewStatus != "pending" {
return nil
}
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{