feat: 代理商资金可见性重构(agent-fund-visibility)
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m10s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m10s
- 将 GET /shops/commission-summary 重命名为 GET /shops/fund-summary, 响应新增 main_balance、main_frozen_balance 两个预充值钱包字段 - 新增 GET /shops/:id/main-wallet/transactions 预充值钱包流水接口 - 将佣金统计、每日统计、发起提现从 /my/ 路径迁移至 /shops/:id/ 路径: GET /shops/:id/commission-stats GET /shops/:id/commission-daily-stats POST /shops/:id/withdrawal-requests - 删除 MyCommissionService、MyCommissionHandler 及全部 /my/ 路由 - 补齐 ListShopWithdrawalRequests、ListShopCommissionRecords 的 CanManageShop 越权校验(安全修复) - 提现接口增加严格权限:仅代理账号本人可为自己店铺发起提现 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -233,6 +233,31 @@ func (s *AgentWalletStore) GetShopCommissionSummaryBatch(ctx context.Context, sh
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetShopMainWalletBatch 批量获取店铺主钱包(预充值钱包)
|
||||
// 返回 map[shopID]*AgentWallet,未找到的店铺不会出现在结果中
|
||||
func (s *AgentWalletStore) GetShopMainWalletBatch(ctx context.Context, shopIDs []uint) (map[uint]*model.AgentWallet, error) {
|
||||
if len(shopIDs) == 0 {
|
||||
return make(map[uint]*model.AgentWallet), nil
|
||||
}
|
||||
|
||||
var wallets []model.AgentWallet
|
||||
query := s.db.WithContext(ctx).
|
||||
Where("shop_id IN ? AND wallet_type = ?", shopIDs, constants.AgentWalletTypeMain)
|
||||
// 对齐 GetShopCommissionSummaryBatch 的防御式过滤
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
err := query.Find(&wallets).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint]*model.AgentWallet, len(wallets))
|
||||
for i := range wallets {
|
||||
result[wallets[i].ShopID] = &wallets[i]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// clearWalletCache 清除钱包缓存
|
||||
func (s *AgentWalletStore) clearWalletCache(ctx context.Context, walletID uint) {
|
||||
// 查询钱包信息以获取 shop_id 和 wallet_type
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -23,36 +22,39 @@ func NewAgentWalletTransactionStore(db *gorm.DB, redis *redis.Client) *AgentWall
|
||||
}
|
||||
}
|
||||
|
||||
// AgentWalletTransactionListFilters 主钱包流水过滤条件
|
||||
type AgentWalletTransactionListFilters struct {
|
||||
// TransactionType 按交易类型过滤,空字符串表示不过滤
|
||||
TransactionType string
|
||||
// StartDate 开始日期,格式 YYYY-MM-DD
|
||||
StartDate string
|
||||
// EndDate 结束日期,格式 YYYY-MM-DD
|
||||
EndDate string
|
||||
}
|
||||
|
||||
// CreateWithTx 创建代理钱包交易记录(带事务)
|
||||
func (s *AgentWalletTransactionStore) CreateWithTx(ctx context.Context, tx *gorm.DB, transaction *model.AgentWalletTransaction) error {
|
||||
return tx.WithContext(ctx).Create(transaction).Error
|
||||
}
|
||||
|
||||
// ListByShopID 按店铺查询交易记录(支持分页)
|
||||
func (s *AgentWalletTransactionStore) ListByShopID(ctx context.Context, shopID uint, offset, limit int) ([]*model.AgentWalletTransaction, error) {
|
||||
// ListByWalletIDWithFilters 按钱包ID查询交易记录(支持分页和过滤)
|
||||
// 按 created_at DESC 排序
|
||||
func (s *AgentWalletTransactionStore) ListByWalletIDWithFilters(ctx context.Context, walletID uint, offset, limit int, filters *AgentWalletTransactionListFilters) ([]*model.AgentWalletTransaction, error) {
|
||||
var transactions []*model.AgentWalletTransaction
|
||||
query := s.db.WithContext(ctx).
|
||||
Where("shop_id = ?", shopID)
|
||||
// 应用数据权限过滤
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
err := query.Order("created_at DESC").
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
Find(&transactions).Error
|
||||
query := s.db.WithContext(ctx).Where("agent_wallet_id = ?", walletID)
|
||||
query = applyWalletTransactionFilters(query, filters)
|
||||
err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&transactions).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return transactions, nil
|
||||
}
|
||||
|
||||
// CountByShopID 统计店铺的交易记录数量
|
||||
func (s *AgentWalletTransactionStore) CountByShopID(ctx context.Context, shopID uint) (int64, error) {
|
||||
// CountByWalletID 统计指定钱包的交易记录数量(支持过滤)
|
||||
func (s *AgentWalletTransactionStore) CountByWalletID(ctx context.Context, walletID uint, filters *AgentWalletTransactionListFilters) (int64, error) {
|
||||
var count int64
|
||||
query := s.db.WithContext(ctx).
|
||||
Model(&model.AgentWalletTransaction{}).
|
||||
Where("shop_id = ?", shopID)
|
||||
// 应用数据权限过滤
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
query := s.db.WithContext(ctx).Model(&model.AgentWalletTransaction{}).Where("agent_wallet_id = ?", walletID)
|
||||
query = applyWalletTransactionFilters(query, filters)
|
||||
err := query.Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
@@ -60,14 +62,8 @@ func (s *AgentWalletTransactionStore) CountByShopID(ctx context.Context, shopID
|
||||
// ListByWalletID 按钱包查询交易记录(支持分页)
|
||||
func (s *AgentWalletTransactionStore) ListByWalletID(ctx context.Context, walletID uint, offset, limit int) ([]*model.AgentWalletTransaction, error) {
|
||||
var transactions []*model.AgentWalletTransaction
|
||||
query := s.db.WithContext(ctx).
|
||||
Where("agent_wallet_id = ?", walletID)
|
||||
// 应用数据权限过滤
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
err := query.Order("created_at DESC").
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
Find(&transactions).Error
|
||||
query := s.db.WithContext(ctx).Where("agent_wallet_id = ?", walletID)
|
||||
err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&transactions).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,13 +73,27 @@ func (s *AgentWalletTransactionStore) ListByWalletID(ctx context.Context, wallet
|
||||
// GetByReference 根据关联业务查询交易记录
|
||||
func (s *AgentWalletTransactionStore) GetByReference(ctx context.Context, referenceType string, referenceID uint) (*model.AgentWalletTransaction, error) {
|
||||
var transaction model.AgentWalletTransaction
|
||||
query := s.db.WithContext(ctx).
|
||||
Where("reference_type = ? AND reference_id = ?", referenceType, referenceID)
|
||||
// 应用数据权限过滤
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
query := s.db.WithContext(ctx).Where("reference_type = ? AND reference_id = ?", referenceType, referenceID)
|
||||
err := query.First(&transaction).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &transaction, nil
|
||||
}
|
||||
|
||||
// applyWalletTransactionFilters 应用过滤条件到查询
|
||||
func applyWalletTransactionFilters(query *gorm.DB, filters *AgentWalletTransactionListFilters) *gorm.DB {
|
||||
if filters == nil {
|
||||
return query
|
||||
}
|
||||
if filters.TransactionType != "" {
|
||||
query = query.Where("transaction_type = ?", filters.TransactionType)
|
||||
}
|
||||
if filters.StartDate != "" {
|
||||
query = query.Where("created_at >= ?", filters.StartDate+" 00:00:00")
|
||||
}
|
||||
if filters.EndDate != "" {
|
||||
query = query.Where("created_at <= ?", filters.EndDate+" 23:59:59")
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user