feat: 新增微信参数配置模块(Model、DTO、Store、Service)
- wechat_config.go: WechatConfig GORM 模型,含 ProviderTypeWechat/Fuiou 常量 - wechat_config_dto.go: Create/Update/List 请求 DTO,响应 DTO 含脱敏逻辑 - wechat_config_store.go: CRUD、GetActive、ActivateInTx(事务内唯一激活)、软删除保护查询 - service.go: 业务逻辑,按渠道校验必填字段、Redis 缓存管理(wechat:config:active)、删除保护、审计日志 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
145
internal/store/postgres/wechat_config_store.go
Normal file
145
internal/store/postgres/wechat_config_store.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// WechatConfigStore 微信参数配置数据访问层
|
||||
type WechatConfigStore struct {
|
||||
db *gorm.DB
|
||||
rdb *redis.Client
|
||||
}
|
||||
|
||||
// NewWechatConfigStore 创建微信参数配置 Store 实例
|
||||
func NewWechatConfigStore(db *gorm.DB, rdb *redis.Client) *WechatConfigStore {
|
||||
return &WechatConfigStore{db: db, rdb: rdb}
|
||||
}
|
||||
|
||||
// Create 创建微信参数配置
|
||||
func (s *WechatConfigStore) Create(ctx context.Context, config *model.WechatConfig) error {
|
||||
return s.db.WithContext(ctx).Create(config).Error
|
||||
}
|
||||
|
||||
// GetByID 根据 ID 获取配置(遵循软删除)
|
||||
func (s *WechatConfigStore) GetByID(ctx context.Context, id uint) (*model.WechatConfig, error) {
|
||||
var config model.WechatConfig
|
||||
if err := s.db.WithContext(ctx).First(&config, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// GetByIDUnscoped 根据 ID 获取配置(包含已软删除的记录,用于回调处理)
|
||||
func (s *WechatConfigStore) GetByIDUnscoped(ctx context.Context, id uint) (*model.WechatConfig, error) {
|
||||
var config model.WechatConfig
|
||||
if err := s.db.WithContext(ctx).Unscoped().First(&config, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// List 查询配置列表,支持按 provider_type 和 is_active 过滤
|
||||
func (s *WechatConfigStore) List(ctx context.Context, opts *store.QueryOptions, filters map[string]interface{}) ([]*model.WechatConfig, int64, error) {
|
||||
var configs []*model.WechatConfig
|
||||
var total int64
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.WechatConfig{})
|
||||
|
||||
if providerType, ok := filters["provider_type"].(string); ok && providerType != "" {
|
||||
query = query.Where("provider_type = ?", providerType)
|
||||
}
|
||||
if isActive, ok := filters["is_active"].(*bool); ok && isActive != nil {
|
||||
query = query.Where("is_active = ?", *isActive)
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
opts = store.DefaultQueryOptions()
|
||||
}
|
||||
offset := (opts.Page - 1) * opts.PageSize
|
||||
query = query.Offset(offset).Limit(opts.PageSize)
|
||||
|
||||
if opts.OrderBy != "" {
|
||||
query = query.Order(opts.OrderBy)
|
||||
}
|
||||
|
||||
if err := query.Find(&configs).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return configs, total, nil
|
||||
}
|
||||
|
||||
// Update 更新微信参数配置
|
||||
func (s *WechatConfigStore) Update(ctx context.Context, config *model.WechatConfig) error {
|
||||
return s.db.WithContext(ctx).Save(config).Error
|
||||
}
|
||||
|
||||
// SoftDelete 软删除微信参数配置
|
||||
func (s *WechatConfigStore) SoftDelete(ctx context.Context, id uint) error {
|
||||
return s.db.WithContext(ctx).Delete(&model.WechatConfig{}, id).Error
|
||||
}
|
||||
|
||||
// GetActive 获取当前激活的配置
|
||||
// 返回 gorm.ErrRecordNotFound 如果没有激活的配置
|
||||
func (s *WechatConfigStore) GetActive(ctx context.Context) (*model.WechatConfig, error) {
|
||||
var config model.WechatConfig
|
||||
if err := s.db.WithContext(ctx).Where("is_active = ? AND deleted_at IS NULL", true).First(&config).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// ActivateInTx 在事务内激活指定配置(先停用所有,再激活指定记录)
|
||||
func (s *WechatConfigStore) ActivateInTx(ctx context.Context, tx *gorm.DB, id uint) error {
|
||||
// 先停用所有激活的配置
|
||||
if err := tx.WithContext(ctx).Model(&model.WechatConfig{}).
|
||||
Where("is_active = ?", true).
|
||||
Update("is_active", false).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 再激活指定配置
|
||||
return tx.WithContext(ctx).Model(&model.WechatConfig{}).
|
||||
Where("id = ?", id).
|
||||
Update("is_active", true).Error
|
||||
}
|
||||
|
||||
// DB 返回底层数据库连接,用于事务操作
|
||||
func (s *WechatConfigStore) DB() *gorm.DB {
|
||||
return s.db
|
||||
}
|
||||
|
||||
// Deactivate 停用指定配置
|
||||
func (s *WechatConfigStore) Deactivate(ctx context.Context, id uint) error {
|
||||
return s.db.WithContext(ctx).Model(&model.WechatConfig{}).
|
||||
Where("id = ?", id).
|
||||
Update("is_active", false).Error
|
||||
}
|
||||
|
||||
// CountPendingOrdersByConfigID 统计指定配置的待支付订单数
|
||||
func (s *WechatConfigStore) CountPendingOrdersByConfigID(ctx context.Context, configID uint) (int64, error) {
|
||||
var count int64
|
||||
err := s.db.WithContext(ctx).
|
||||
Table("tb_order").
|
||||
Where("payment_config_id = ? AND payment_status = ? AND deleted_at IS NULL", configID, 1).
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
// CountPendingRechargesByConfigID 统计指定配置的待支付充值记录数
|
||||
func (s *WechatConfigStore) CountPendingRechargesByConfigID(ctx context.Context, configID uint) (int64, error) {
|
||||
var count int64
|
||||
err := s.db.WithContext(ctx).
|
||||
Table("tb_asset_recharge_record").
|
||||
Where("payment_config_id = ? AND status = ? AND deleted_at IS NULL", configID, 1).
|
||||
Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
Reference in New Issue
Block a user