f
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
package certification
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"hyapi-server/internal/domains/certification/entities"
|
||||
"hyapi-server/internal/domains/certification/enums"
|
||||
"hyapi-server/internal/domains/certification/repositories"
|
||||
"hyapi-server/internal/shared/database"
|
||||
"hyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
// ================ 常量定义 ================
|
||||
|
||||
const (
|
||||
// 表名常量
|
||||
CertificationsTable = "certifications"
|
||||
|
||||
// 缓存时间常量
|
||||
CacheTTLPrimaryQuery = 30 * time.Minute // 主键查询缓存时间
|
||||
CacheTTLBusinessQuery = 15 * time.Minute // 业务查询缓存时间
|
||||
CacheTTLUserQuery = 10 * time.Minute // 用户相关查询缓存时间
|
||||
CacheTTLWarmupLong = 30 * time.Minute // 预热长期缓存
|
||||
CacheTTLWarmupMedium = 15 * time.Minute // 预热中期缓存
|
||||
|
||||
// 缓存键模式常量
|
||||
CachePatternTable = "gorm_cache:certifications:*"
|
||||
CachePatternUser = "certification:user_id:*"
|
||||
)
|
||||
|
||||
// ================ Repository 实现 ================
|
||||
|
||||
// GormCertificationCommandRepository 认证命令仓储GORM实现
|
||||
//
|
||||
// 特性说明:
|
||||
// - 基于 CachedBaseRepositoryImpl 实现自动缓存管理
|
||||
// - 支持多级缓存策略(主键查询30分钟,业务查询15分钟)
|
||||
// - 自动缓存失效:写操作时自动清理相关缓存
|
||||
// - 智能缓存选择:根据查询复杂度自动选择缓存策略
|
||||
// - 内置监控支持:提供缓存统计和性能监控
|
||||
type GormCertificationCommandRepository struct {
|
||||
*database.CachedBaseRepositoryImpl
|
||||
}
|
||||
|
||||
// 编译时检查接口实现
|
||||
var _ repositories.CertificationCommandRepository = (*GormCertificationCommandRepository)(nil)
|
||||
|
||||
// NewGormCertificationCommandRepository 创建认证命令仓储
|
||||
//
|
||||
// 参数:
|
||||
// - db: GORM数据库连接实例
|
||||
// - logger: 日志记录器
|
||||
//
|
||||
// 返回:
|
||||
// - repositories.CertificationCommandRepository: 仓储接口实现
|
||||
func NewGormCertificationCommandRepository(db *gorm.DB, logger *zap.Logger) repositories.CertificationCommandRepository {
|
||||
return &GormCertificationCommandRepository{
|
||||
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, CertificationsTable),
|
||||
}
|
||||
}
|
||||
|
||||
// ================ 基础CRUD操作 ================
|
||||
|
||||
// Create 创建认证
|
||||
//
|
||||
// 业务说明:
|
||||
// - 创建新的认证申请
|
||||
// - 自动触发相关缓存失效
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - cert: 认证实体
|
||||
//
|
||||
// 返回:
|
||||
// - error: 创建失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) Create(ctx context.Context, cert entities.Certification) error {
|
||||
r.GetLogger().Info("创建认证申请",
|
||||
zap.String("user_id", cert.UserID),
|
||||
zap.String("status", string(cert.Status)))
|
||||
|
||||
return r.CreateEntity(ctx, &cert)
|
||||
}
|
||||
|
||||
// Update 更新认证
|
||||
//
|
||||
// 缓存影响:
|
||||
// - GORM缓存插件会自动失效相关缓存
|
||||
// - 无需手动管理缓存一致性
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - cert: 认证实体
|
||||
//
|
||||
// 返回:
|
||||
// - error: 更新失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) Update(ctx context.Context, cert entities.Certification) error {
|
||||
r.GetLogger().Info("更新认证",
|
||||
zap.String("id", cert.ID),
|
||||
zap.String("status", string(cert.Status)))
|
||||
|
||||
return r.UpdateEntity(ctx, &cert)
|
||||
}
|
||||
|
||||
// Delete 删除认证
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - id: 认证ID
|
||||
//
|
||||
// 返回:
|
||||
// - error: 删除失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) Delete(ctx context.Context, id string) error {
|
||||
r.GetLogger().Info("删除认证", zap.String("id", id))
|
||||
return r.DeleteEntity(ctx, id, &entities.Certification{})
|
||||
}
|
||||
|
||||
// ================ 业务特定的更新操作 ================
|
||||
|
||||
// UpdateStatus 更新认证状态
|
||||
//
|
||||
// 业务说明:
|
||||
// - 更新认证的状态
|
||||
// - 自动更新时间戳
|
||||
//
|
||||
// 缓存影响:
|
||||
// - GORM缓存插件会自动失效表相关的缓存
|
||||
// - 状态更新会影响列表查询和统计结果
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - id: 认证ID
|
||||
// - status: 新状态
|
||||
//
|
||||
// 返回:
|
||||
// - error: 更新失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) UpdateStatus(ctx context.Context, id string, status enums.CertificationStatus) error {
|
||||
r.GetLogger().Info("更新认证状态",
|
||||
zap.String("id", id),
|
||||
zap.String("status", string(status)))
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
"updated_at": time.Now(),
|
||||
}
|
||||
|
||||
return r.GetDB(ctx).Model(&entities.Certification{}).
|
||||
Where("id = ?", id).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
// UpdateAuthFlowID 更新认证流程ID
|
||||
//
|
||||
// 业务说明:
|
||||
// - 记录e签宝企业认证流程ID
|
||||
// - 用于回调处理和状态跟踪
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - id: 认证ID
|
||||
// - authFlowID: 认证流程ID
|
||||
//
|
||||
// 返回:
|
||||
// - error: 更新失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) UpdateAuthFlowID(ctx context.Context, id string, authFlowID string) error {
|
||||
r.GetLogger().Info("更新认证流程ID",
|
||||
zap.String("id", id),
|
||||
zap.String("auth_flow_id", authFlowID))
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"auth_flow_id": authFlowID,
|
||||
"updated_at": time.Now(),
|
||||
}
|
||||
|
||||
return r.GetDB(ctx).Model(&entities.Certification{}).
|
||||
Where("id = ?", id).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
// UpdateContractInfo 更新合同信息
|
||||
//
|
||||
// 业务说明:
|
||||
// - 记录合同相关的ID和URL信息
|
||||
// - 用于合同管理和用户下载
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - id: 认证ID
|
||||
// - contractFileID: 合同文件ID
|
||||
// - esignFlowID: e签宝流程ID
|
||||
// - contractURL: 合同URL
|
||||
// - contractSignURL: 合同签署URL
|
||||
//
|
||||
// 返回:
|
||||
// - error: 更新失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) UpdateContractInfo(ctx context.Context, id string, contractFileID, esignFlowID, contractURL, contractSignURL string) error {
|
||||
r.GetLogger().Info("更新合同信息",
|
||||
zap.String("id", id),
|
||||
zap.String("contract_file_id", contractFileID),
|
||||
zap.String("esign_flow_id", esignFlowID))
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"contract_file_id": contractFileID,
|
||||
"esign_flow_id": esignFlowID,
|
||||
"contract_url": contractURL,
|
||||
"contract_sign_url": contractSignURL,
|
||||
"updated_at": time.Now(),
|
||||
}
|
||||
|
||||
return r.GetDB(ctx).Model(&entities.Certification{}).
|
||||
Where("id = ?", id).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
// UpdateFailureInfo 更新失败信息
|
||||
//
|
||||
// 业务说明:
|
||||
// - 记录认证失败的原因和详细信息
|
||||
// - 用于错误分析和用户提示
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - id: 认证ID
|
||||
// - reason: 失败原因
|
||||
// - message: 失败详细信息
|
||||
//
|
||||
// 返回:
|
||||
// - error: 更新失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) UpdateFailureInfo(ctx context.Context, id string, reason enums.FailureReason, message string) error {
|
||||
r.GetLogger().Info("更新失败信息",
|
||||
zap.String("id", id),
|
||||
zap.String("reason", string(reason)),
|
||||
zap.String("message", message))
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"failure_reason": reason,
|
||||
"failure_message": message,
|
||||
"updated_at": time.Now(),
|
||||
}
|
||||
|
||||
return r.GetDB(ctx).Model(&entities.Certification{}).
|
||||
Where("id = ?", id).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
// ================ 批量操作 ================
|
||||
|
||||
// BatchUpdateStatus 批量更新状态
|
||||
//
|
||||
// 业务说明:
|
||||
// - 批量更新多个认证的状态
|
||||
// - 适用于管理员批量操作
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - ids: 认证ID列表
|
||||
// - status: 新状态
|
||||
//
|
||||
// 返回:
|
||||
// - error: 更新失败时的错误信息
|
||||
func (r *GormCertificationCommandRepository) BatchUpdateStatus(ctx context.Context, ids []string, status enums.CertificationStatus) error {
|
||||
if len(ids) == 0 {
|
||||
return fmt.Errorf("批量更新状态:ID列表不能为空")
|
||||
}
|
||||
|
||||
r.GetLogger().Info("批量更新认证状态",
|
||||
zap.Strings("ids", ids),
|
||||
zap.String("status", string(status)))
|
||||
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
"updated_at": time.Now(),
|
||||
}
|
||||
|
||||
result := r.GetDB(ctx).Model(&entities.Certification{}).
|
||||
Where("id IN ?", ids).
|
||||
Updates(updates)
|
||||
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("批量更新认证状态失败: %w", result.Error)
|
||||
}
|
||||
|
||||
r.GetLogger().Info("批量更新完成", zap.Int64("affected_rows", result.RowsAffected))
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================ 事务支持 ================
|
||||
|
||||
// WithTx 使用事务
|
||||
//
|
||||
// 业务说明:
|
||||
// - 返回支持事务的仓储实例
|
||||
// - 用于复杂业务操作的事务一致性保证
|
||||
//
|
||||
// 参数:
|
||||
// - tx: 事务对象
|
||||
//
|
||||
// 返回:
|
||||
// - repositories.CertificationCommandRepository: 支持事务的仓储实例
|
||||
func (r *GormCertificationCommandRepository) WithTx(tx interfaces.Transaction) repositories.CertificationCommandRepository {
|
||||
// 获取事务的底层*gorm.DB
|
||||
txDB := tx.GetDB()
|
||||
if gormDB, ok := txDB.(*gorm.DB); ok {
|
||||
return &GormCertificationCommandRepository{
|
||||
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(gormDB, r.GetLogger(), CertificationsTable),
|
||||
}
|
||||
}
|
||||
|
||||
r.GetLogger().Warn("不支持的事务类型,返回原始仓储")
|
||||
return r
|
||||
}
|
||||
|
||||
// ================ 缓存管理方法 ================
|
||||
|
||||
// WarmupCache 预热认证缓存
|
||||
//
|
||||
// 业务说明:
|
||||
// - 系统启动时预热常用查询的缓存
|
||||
// - 提升首次访问的响应速度
|
||||
//
|
||||
// 预热策略:
|
||||
// - 活跃认证:30分钟长期缓存
|
||||
// - 最近创建:15分钟中期缓存
|
||||
func (r *GormCertificationCommandRepository) WarmupCache(ctx context.Context) error {
|
||||
r.GetLogger().Info("开始预热认证缓存")
|
||||
|
||||
queries := []database.WarmupQuery{
|
||||
{
|
||||
Name: "active_certifications",
|
||||
TTL: CacheTTLWarmupLong,
|
||||
Dest: &[]entities.Certification{},
|
||||
},
|
||||
{
|
||||
Name: "recent_certifications",
|
||||
TTL: CacheTTLWarmupMedium,
|
||||
Dest: &[]entities.Certification{},
|
||||
},
|
||||
}
|
||||
|
||||
return r.WarmupCommonQueries(ctx, queries)
|
||||
}
|
||||
|
||||
// RefreshCache 刷新认证缓存
|
||||
//
|
||||
// 业务说明:
|
||||
// - 手动刷新认证相关的所有缓存
|
||||
// - 适用于数据迁移或批量更新后的缓存清理
|
||||
func (r *GormCertificationCommandRepository) RefreshCache(ctx context.Context) error {
|
||||
r.GetLogger().Info("刷新认证缓存")
|
||||
return r.CachedBaseRepositoryImpl.RefreshCache(ctx, CachePatternTable)
|
||||
}
|
||||
|
||||
// GetCacheStats 获取缓存统计信息
|
||||
//
|
||||
// 返回当前Repository的缓存使用统计,包括:
|
||||
// - 基础缓存信息(命中率、键数量等)
|
||||
// - 特定的缓存模式列表
|
||||
// - 性能指标
|
||||
func (r *GormCertificationCommandRepository) GetCacheStats() map[string]interface{} {
|
||||
stats := r.GetCacheInfo()
|
||||
stats["specific_patterns"] = []string{
|
||||
CachePatternTable,
|
||||
CachePatternUser,
|
||||
}
|
||||
return stats
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
package certification
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"hyapi-server/internal/domains/certification/entities"
|
||||
"hyapi-server/internal/domains/certification/enums"
|
||||
"hyapi-server/internal/domains/certification/repositories"
|
||||
"hyapi-server/internal/domains/certification/repositories/queries"
|
||||
"hyapi-server/internal/shared/database"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ================ 常量定义 ================
|
||||
|
||||
const (
|
||||
// 缓存时间常量
|
||||
QueryCacheTTLPrimaryQuery = 30 * time.Minute // 主键查询缓存时间
|
||||
QueryCacheTTLBusinessQuery = 15 * time.Minute // 业务查询缓存时间
|
||||
QueryCacheTTLUserQuery = 10 * time.Minute // 用户相关查询缓存时间
|
||||
QueryCacheTTLSearchQuery = 2 * time.Minute // 搜索查询缓存时间
|
||||
QueryCacheTTLActiveRecords = 5 * time.Minute // 活跃记录查询缓存时间
|
||||
QueryCacheTTLWarmupLong = 30 * time.Minute // 预热长期缓存
|
||||
QueryCacheTTLWarmupMedium = 15 * time.Minute // 预热中期缓存
|
||||
|
||||
// 缓存键模式常量
|
||||
QueryCachePatternTable = "gorm_cache:certifications:*"
|
||||
QueryCachePatternUser = "certification:user_id:*"
|
||||
)
|
||||
|
||||
// ================ Repository 实现 ================
|
||||
|
||||
// GormCertificationQueryRepository 认证查询仓储GORM实现
|
||||
//
|
||||
// 特性说明:
|
||||
// - 基于 CachedBaseRepositoryImpl 实现自动缓存管理
|
||||
// - 支持多级缓存策略(主键查询30分钟,业务查询15分钟,搜索2分钟)
|
||||
// - 自动缓存失效:写操作时自动清理相关缓存
|
||||
// - 智能缓存选择:根据查询复杂度自动选择缓存策略
|
||||
// - 内置监控支持:提供缓存统计和性能监控
|
||||
type GormCertificationQueryRepository struct {
|
||||
*database.CachedBaseRepositoryImpl
|
||||
}
|
||||
|
||||
// 编译时检查接口实现
|
||||
var _ repositories.CertificationQueryRepository = (*GormCertificationQueryRepository)(nil)
|
||||
|
||||
// NewGormCertificationQueryRepository 创建认证查询仓储
|
||||
//
|
||||
// 参数:
|
||||
// - db: GORM数据库连接实例
|
||||
// - logger: 日志记录器
|
||||
//
|
||||
// 返回:
|
||||
// - repositories.CertificationQueryRepository: 仓储接口实现
|
||||
func NewGormCertificationQueryRepository(
|
||||
db *gorm.DB,
|
||||
logger *zap.Logger,
|
||||
) repositories.CertificationQueryRepository {
|
||||
return &GormCertificationQueryRepository{
|
||||
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, CertificationsTable),
|
||||
}
|
||||
}
|
||||
|
||||
// ================ 基础查询操作 ================
|
||||
|
||||
// GetByID 根据ID获取认证
|
||||
//
|
||||
// 缓存策略:
|
||||
// - 使用智能主键查询,自动缓存30分钟
|
||||
// - 主键查询命中率高,适合长期缓存
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - id: 认证ID
|
||||
//
|
||||
// 返回:
|
||||
// - *entities.Certification: 查询到的认证,未找到时返回nil
|
||||
// - error: 查询失败时的错误信息
|
||||
func (r *GormCertificationQueryRepository) GetByID(ctx context.Context, id string) (*entities.Certification, error) {
|
||||
var cert entities.Certification
|
||||
if err := r.SmartGetByID(ctx, id, &cert); err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("认证记录不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("查询认证记录失败: %w", err)
|
||||
}
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
// GetByUserID 根据用户ID获取认证
|
||||
//
|
||||
// 缓存策略:
|
||||
// - 业务查询,缓存15分钟
|
||||
// - 用户查询频率较高,适合中期缓存
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - userID: 用户ID
|
||||
//
|
||||
// 返回:
|
||||
// - *entities.Certification: 查询到的认证,未找到时返回nil
|
||||
// - error: 查询失败时的错误信息
|
||||
func (r *GormCertificationQueryRepository) GetByUserID(ctx context.Context, userID string) (*entities.Certification, error) {
|
||||
var cert entities.Certification
|
||||
err := r.SmartGetByField(ctx, &cert, "user_id", userID, QueryCacheTTLUserQuery)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("用户尚未创建认证申请")
|
||||
}
|
||||
return nil, fmt.Errorf("查询用户认证记录失败: %w", err)
|
||||
}
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
// Exists 检查认证是否存在
|
||||
func (r *GormCertificationQueryRepository) Exists(ctx context.Context, id string) (bool, error) {
|
||||
return r.ExistsEntity(ctx, id, &entities.Certification{})
|
||||
}
|
||||
|
||||
func (r *GormCertificationQueryRepository) ExistsByUserID(ctx context.Context, userID string) (bool, error) {
|
||||
var count int64
|
||||
err := r.GetDB(ctx).Model(&entities.Certification{}).Where("user_id = ?", userID).Count(&count).Error
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("查询用户认证是否存在失败: %w", err)
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// ================ 列表查询 ================
|
||||
|
||||
// List 分页列表查询
|
||||
//
|
||||
// 缓存策略:
|
||||
// - 搜索查询:短期缓存2分钟(避免频繁数据库查询但保证实时性)
|
||||
// - 常规列表:智能缓存(根据查询复杂度自动选择缓存策略)
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - query: 列表查询条件
|
||||
//
|
||||
// 返回:
|
||||
// - []*entities.Certification: 查询结果列表
|
||||
// - int64: 总记录数
|
||||
// - error: 查询失败时的错误信息
|
||||
func (r *GormCertificationQueryRepository) List(ctx context.Context, query *queries.ListCertificationsQuery) ([]*entities.Certification, int64, error) {
|
||||
db := r.GetDB(ctx).Model(&entities.Certification{})
|
||||
|
||||
// 应用过滤条件
|
||||
if query.UserID != "" {
|
||||
db = db.Where("user_id = ?", query.UserID)
|
||||
}
|
||||
if query.Status != "" {
|
||||
db = db.Where("status = ?", query.Status)
|
||||
}
|
||||
if len(query.Statuses) > 0 {
|
||||
db = db.Where("status IN ?", query.Statuses)
|
||||
}
|
||||
|
||||
// 获取总数
|
||||
var total int64
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("查询认证总数失败: %w", err)
|
||||
}
|
||||
|
||||
// 应用排序和分页
|
||||
if query.SortBy != "" {
|
||||
orderClause := query.SortBy
|
||||
if query.SortOrder != "" {
|
||||
orderClause += " " + strings.ToUpper(query.SortOrder)
|
||||
}
|
||||
db = db.Order(orderClause)
|
||||
} else {
|
||||
db = db.Order("created_at DESC")
|
||||
}
|
||||
|
||||
offset := (query.Page - 1) * query.PageSize
|
||||
db = db.Offset(offset).Limit(query.PageSize)
|
||||
|
||||
// 执行查询
|
||||
var certifications []*entities.Certification
|
||||
if err := db.Find(&certifications).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("查询认证列表失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, total, nil
|
||||
}
|
||||
|
||||
// ListByUserIDs 根据用户ID列表查询
|
||||
func (r *GormCertificationQueryRepository) ListByUserIDs(ctx context.Context, userIDs []string) ([]*entities.Certification, error) {
|
||||
if len(userIDs) == 0 {
|
||||
return []*entities.Certification{}, nil
|
||||
}
|
||||
|
||||
var certifications []*entities.Certification
|
||||
if err := r.GetDB(ctx).Where("user_id IN ?", userIDs).Order("created_at DESC").Find(&certifications).Error; err != nil {
|
||||
return nil, fmt.Errorf("根据用户ID列表查询认证失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, nil
|
||||
}
|
||||
|
||||
// ListByStatus 根据状态查询
|
||||
func (r *GormCertificationQueryRepository) ListByStatus(ctx context.Context, status enums.CertificationStatus, limit int) ([]*entities.Certification, error) {
|
||||
db := r.GetDB(ctx).Where("status = ?", status).Order("created_at DESC")
|
||||
if limit > 0 {
|
||||
db = db.Limit(limit)
|
||||
}
|
||||
|
||||
var certifications []*entities.Certification
|
||||
if err := db.Find(&certifications).Error; err != nil {
|
||||
return nil, fmt.Errorf("根据状态查询认证失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, nil
|
||||
}
|
||||
|
||||
// ================ 业务查询 ================
|
||||
|
||||
// FindByAuthFlowID 根据认证流程ID查询
|
||||
//
|
||||
// 缓存策略:
|
||||
// - 业务查询,缓存15分钟
|
||||
// - 回调查询频率较高
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - authFlowID: 认证流程ID
|
||||
//
|
||||
// 返回:
|
||||
// - *entities.Certification: 查询到的认证,未找到时返回nil
|
||||
// - error: 查询失败时的错误信息
|
||||
func (r *GormCertificationQueryRepository) FindByAuthFlowID(ctx context.Context, authFlowID string) (*entities.Certification, error) {
|
||||
var cert entities.Certification
|
||||
err := r.SmartGetByField(ctx, &cert, "auth_flow_id", authFlowID, QueryCacheTTLBusinessQuery)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("认证流程不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("根据认证流程ID查询失败: %w", err)
|
||||
}
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
// FindByEsignFlowID 根据e签宝流程ID查询
|
||||
//
|
||||
// 缓存策略:
|
||||
// - 业务查询,缓存15分钟
|
||||
// - 回调查询频率较高
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - esignFlowID: e签宝流程ID
|
||||
//
|
||||
// 返回:
|
||||
// - *entities.Certification: 查询到的认证,未找到时返回nil
|
||||
// - error: 查询失败时的错误信息
|
||||
func (r *GormCertificationQueryRepository) FindByEsignFlowID(ctx context.Context, esignFlowID string) (*entities.Certification, error) {
|
||||
var cert entities.Certification
|
||||
err := r.SmartGetByField(ctx, &cert, "esign_flow_id", esignFlowID, QueryCacheTTLBusinessQuery)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("e签宝流程不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("根据e签宝流程ID查询失败: %w", err)
|
||||
}
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
// ListPendingRetry 查询待重试的认证
|
||||
//
|
||||
// 缓存策略:
|
||||
// - 管理查询,不缓存保证数据实时性
|
||||
//
|
||||
// 参数:
|
||||
// - ctx: 上下文
|
||||
// - maxRetryCount: 最大重试次数
|
||||
//
|
||||
// 返回:
|
||||
// - []*entities.Certification: 待重试的认证列表
|
||||
// - error: 查询失败时的错误信息
|
||||
func (r *GormCertificationQueryRepository) ListPendingRetry(ctx context.Context, maxRetryCount int) ([]*entities.Certification, error) {
|
||||
var certifications []*entities.Certification
|
||||
err := r.WithoutCache().GetDB(ctx).
|
||||
Where("status IN ? AND retry_count < ?",
|
||||
[]enums.CertificationStatus{
|
||||
enums.StatusInfoRejected,
|
||||
enums.StatusContractRejected,
|
||||
enums.StatusContractExpired,
|
||||
},
|
||||
maxRetryCount).
|
||||
Order("created_at ASC").
|
||||
Find(&certifications).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询待重试认证失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, nil
|
||||
}
|
||||
|
||||
// GetPendingCertifications 获取待处理认证
|
||||
func (r *GormCertificationQueryRepository) GetPendingCertifications(ctx context.Context) ([]*entities.Certification, error) {
|
||||
var certifications []*entities.Certification
|
||||
err := r.WithoutCache().GetDB(ctx).
|
||||
Where("status IN ?", []enums.CertificationStatus{
|
||||
enums.StatusPending,
|
||||
enums.StatusInfoSubmitted,
|
||||
}).
|
||||
Order("created_at ASC").
|
||||
Find(&certifications).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询待处理认证失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, nil
|
||||
}
|
||||
|
||||
// GetExpiredContracts 获取过期合同
|
||||
func (r *GormCertificationQueryRepository) GetExpiredContracts(ctx context.Context) ([]*entities.Certification, error) {
|
||||
var certifications []*entities.Certification
|
||||
err := r.WithoutCache().GetDB(ctx).
|
||||
Where("status = ?", enums.StatusContractExpired).
|
||||
Order("updated_at DESC").
|
||||
Find(&certifications).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询过期合同失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, nil
|
||||
}
|
||||
|
||||
// GetCertificationsByDateRange 根据日期范围获取认证
|
||||
func (r *GormCertificationQueryRepository) GetCertificationsByDateRange(ctx context.Context, startDate, endDate time.Time) ([]*entities.Certification, error) {
|
||||
var certifications []*entities.Certification
|
||||
err := r.GetDB(ctx).
|
||||
Where("created_at BETWEEN ? AND ?", startDate, endDate).
|
||||
Order("created_at DESC").
|
||||
Find(&certifications).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("根据日期范围查询认证失败: %w", err)
|
||||
}
|
||||
|
||||
return certifications, nil
|
||||
}
|
||||
|
||||
// GetUserActiveCertification 获取用户当前活跃认证
|
||||
func (r *GormCertificationQueryRepository) GetUserActiveCertification(ctx context.Context, userID string) (*entities.Certification, error) {
|
||||
var cert entities.Certification
|
||||
err := r.GetDB(ctx).
|
||||
Where("user_id = ? AND status NOT IN ?", userID, []enums.CertificationStatus{
|
||||
enums.StatusContractSigned,
|
||||
enums.StatusInfoRejected,
|
||||
enums.StatusContractRejected,
|
||||
enums.StatusContractExpired,
|
||||
}).
|
||||
First(&cert).Error
|
||||
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("用户没有活跃的认证申请")
|
||||
}
|
||||
return nil, fmt.Errorf("查询用户活跃认证失败: %w", err)
|
||||
}
|
||||
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
// ================ 统计查询 ================
|
||||
|
||||
|
||||
|
||||
// CountByFailureReason 按失败原因统计
|
||||
func (r *GormCertificationQueryRepository) CountByFailureReason(ctx context.Context, reason enums.FailureReason) (int64, error) {
|
||||
var count int64
|
||||
if err := r.WithShortCache().GetDB(ctx).Model(&entities.Certification{}).Where("failure_reason = ?", reason).Count(&count).Error; err != nil {
|
||||
return 0, fmt.Errorf("按失败原因统计认证失败: %w", err)
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetProgressStatistics 获取进度统计
|
||||
func (r *GormCertificationQueryRepository) GetProgressStatistics(ctx context.Context) (*repositories.CertificationProgressStats, error) {
|
||||
// 简化实现
|
||||
return &repositories.CertificationProgressStats{
|
||||
StatusProgress: make(map[enums.CertificationStatus]int64),
|
||||
ProgressDistribution: make(map[int]int64),
|
||||
StageTimeStats: make(map[string]*repositories.CertificationStageTimeInfo),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SearchByCompanyName 按公司名搜索
|
||||
func (r *GormCertificationQueryRepository) SearchByCompanyName(ctx context.Context, companyName string, limit int) ([]*entities.Certification, error) {
|
||||
// 简化实现,暂时返回空结果
|
||||
r.GetLogger().Warn("按公司名搜索功能待实现,需要企业信息服务支持")
|
||||
return []*entities.Certification{}, nil
|
||||
}
|
||||
|
||||
// SearchByLegalPerson 按法人搜索
|
||||
func (r *GormCertificationQueryRepository) SearchByLegalPerson(ctx context.Context, legalPersonName string, limit int) ([]*entities.Certification, error) {
|
||||
// 简化实现,暂时返回空结果
|
||||
r.GetLogger().Warn("按法人搜索功能待实现,需要企业信息服务支持")
|
||||
return []*entities.Certification{}, nil
|
||||
}
|
||||
|
||||
// InvalidateCache 清除缓存
|
||||
func (r *GormCertificationQueryRepository) InvalidateCache(ctx context.Context, keys ...string) error {
|
||||
// 简化实现,暂不处理缓存
|
||||
return nil
|
||||
}
|
||||
|
||||
// RefreshCache 刷新缓存
|
||||
func (r *GormCertificationQueryRepository) RefreshCache(ctx context.Context, certificationID string) error {
|
||||
// 简化实现,暂不处理缓存
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================ 缓存管理方法 ================
|
||||
|
||||
// WarmupCache 预热认证查询缓存
|
||||
//
|
||||
// 业务说明:
|
||||
// - 系统启动时预热常用查询的缓存
|
||||
// - 提升首次访问的响应速度
|
||||
//
|
||||
// 预热策略:
|
||||
// - 活跃认证:30分钟长期缓存
|
||||
// - 待处理认证:15分钟中期缓存
|
||||
func (r *GormCertificationQueryRepository) WarmupCache(ctx context.Context) error {
|
||||
r.GetLogger().Info("开始预热认证查询缓存")
|
||||
|
||||
queries := []database.WarmupQuery{
|
||||
{
|
||||
Name: "active_certifications",
|
||||
TTL: QueryCacheTTLWarmupLong,
|
||||
Dest: &[]entities.Certification{},
|
||||
},
|
||||
{
|
||||
Name: "pending_certifications",
|
||||
TTL: QueryCacheTTLWarmupMedium,
|
||||
Dest: &[]entities.Certification{},
|
||||
},
|
||||
}
|
||||
|
||||
return r.WarmupCommonQueries(ctx, queries)
|
||||
}
|
||||
|
||||
// GetCacheStats 获取缓存统计信息
|
||||
//
|
||||
// 返回当前Repository的缓存使用统计,包括:
|
||||
// - 基础缓存信息(命中率、键数量等)
|
||||
// - 特定的缓存模式列表
|
||||
// - 性能指标
|
||||
func (r *GormCertificationQueryRepository) GetCacheStats() map[string]interface{} {
|
||||
stats := r.GetCacheInfo()
|
||||
stats["specific_patterns"] = []string{
|
||||
QueryCachePatternTable,
|
||||
QueryCachePatternUser,
|
||||
}
|
||||
return stats
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package certification
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hyapi-server/internal/domains/certification/entities"
|
||||
"hyapi-server/internal/domains/certification/repositories"
|
||||
"hyapi-server/internal/shared/database"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
EnterpriseInfoSubmitRecordsTable = "enterprise_info_submit_records"
|
||||
)
|
||||
|
||||
type GormEnterpriseInfoSubmitRecordRepository struct {
|
||||
*database.CachedBaseRepositoryImpl
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) Delete(ctx context.Context, id string) error {
|
||||
return r.DeleteEntity(ctx, id, &entities.EnterpriseInfoSubmitRecord{})
|
||||
}
|
||||
|
||||
func NewGormEnterpriseInfoSubmitRecordRepository(db *gorm.DB, logger *zap.Logger) *GormEnterpriseInfoSubmitRecordRepository {
|
||||
return &GormEnterpriseInfoSubmitRecordRepository{
|
||||
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, EnterpriseInfoSubmitRecordsTable),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) Create(ctx context.Context, record *entities.EnterpriseInfoSubmitRecord) error {
|
||||
return r.CreateEntity(ctx, record)
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) Update(ctx context.Context, record *entities.EnterpriseInfoSubmitRecord) error {
|
||||
return r.UpdateEntity(ctx, record)
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) Exists(ctx context.Context, ID string) (bool, error) {
|
||||
return r.ExistsEntity(ctx, ID, &entities.EnterpriseInfoSubmitRecord{})
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) FindByID(ctx context.Context, id string) (*entities.EnterpriseInfoSubmitRecord, error) {
|
||||
var record entities.EnterpriseInfoSubmitRecord
|
||||
err := r.GetDB(ctx).Where("id = ?", id).First(&record).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) FindLatestByUserID(ctx context.Context, userID string) (*entities.EnterpriseInfoSubmitRecord, error) {
|
||||
var record entities.EnterpriseInfoSubmitRecord
|
||||
err := r.GetDB(ctx).
|
||||
Where("user_id = ?", userID).
|
||||
Order("submit_at DESC").
|
||||
First(&record).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) FindLatestVerifiedByUserID(ctx context.Context, userID string) (*entities.EnterpriseInfoSubmitRecord, error) {
|
||||
var record entities.EnterpriseInfoSubmitRecord
|
||||
err := r.GetDB(ctx).
|
||||
Where("user_id = ? AND status = ?", userID, "verified").
|
||||
Order("verified_at DESC").
|
||||
First(&record).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &record, nil
|
||||
}
|
||||
|
||||
// ExistsByUnifiedSocialCodeExcludeUser 检查该统一社会信用代码是否已被其他用户占用(已提交或已通过验证的记录)
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) ExistsByUnifiedSocialCodeExcludeUser(ctx context.Context, unifiedSocialCode string, excludeUserID string) (bool, error) {
|
||||
if unifiedSocialCode == "" {
|
||||
return false, nil
|
||||
}
|
||||
var count int64
|
||||
query := r.GetDB(ctx).Model(&entities.EnterpriseInfoSubmitRecord{}).
|
||||
Where("unified_social_code = ? AND status IN (?, ?)", unifiedSocialCode, "submitted", "verified")
|
||||
if excludeUserID != "" {
|
||||
query = query.Where("user_id != ?", excludeUserID)
|
||||
}
|
||||
if err := query.Count(&count).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (r *GormEnterpriseInfoSubmitRecordRepository) List(ctx context.Context, filter repositories.ListSubmitRecordsFilter) (*repositories.ListSubmitRecordsResult, error) {
|
||||
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 != "" {
|
||||
base = base.Where("enterprise_info_submit_records.company_name LIKE ?", "%"+filter.CompanyName+"%")
|
||||
}
|
||||
if filter.LegalPersonPhone != "" {
|
||||
base = base.Where("enterprise_info_submit_records.legal_person_phone = ?", filter.LegalPersonPhone)
|
||||
}
|
||||
if filter.LegalPersonName != "" {
|
||||
base = base.Where("enterprise_info_submit_records.legal_person_name LIKE ?", "%"+filter.LegalPersonName+"%")
|
||||
}
|
||||
var total int64
|
||||
if err := base.Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if filter.PageSize <= 0 {
|
||||
filter.PageSize = 10
|
||||
}
|
||||
if filter.Page <= 0 {
|
||||
filter.Page = 1
|
||||
}
|
||||
offset := (filter.Page - 1) * filter.PageSize
|
||||
var records []*entities.EnterpriseInfoSubmitRecord
|
||||
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("enterprise_info_submit_records.company_name LIKE ?", "%"+filter.CompanyName+"%")
|
||||
}
|
||||
if filter.LegalPersonPhone != "" {
|
||||
q = q.Where("enterprise_info_submit_records.legal_person_phone = ?", filter.LegalPersonPhone)
|
||||
}
|
||||
if filter.LegalPersonName != "" {
|
||||
q = q.Where("enterprise_info_submit_records.legal_person_name LIKE ?", "%"+filter.LegalPersonName+"%")
|
||||
}
|
||||
err := q.Order("enterprise_info_submit_records.submit_at DESC").Offset(offset).Limit(filter.PageSize).Find(&records).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &repositories.ListSubmitRecordsResult{Records: records, Total: total}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user