This commit is contained in:
2026-04-29 11:38:59 +08:00
parent e96e3f9583
commit 7d363f4e8a
30 changed files with 1135 additions and 215 deletions

View File

@@ -251,6 +251,7 @@ type (
AgentId *int64 `form:"agent_id,optional"` // 代理ID可选 AgentId *int64 `form:"agent_id,optional"` // 代理ID可选
RelationAgentId *int64 `form:"relation_agent_id,optional"` // 关联代理ID可选 RelationAgentId *int64 `form:"relation_agent_id,optional"` // 关联代理ID可选
Type *string `form:"type,optional"` // 奖励类型(可选) Type *string `form:"type,optional"` // 奖励类型(可选)
Status *int64 `form:"status,optional"` // 状态(可选)
} }
// 代理奖励列表项 // 代理奖励列表项
@@ -260,6 +261,8 @@ type (
RelationAgentId int64 `json:"relation_agent_id"` // 关联代理ID RelationAgentId int64 `json:"relation_agent_id"` // 关联代理ID
Amount float64 `json:"amount"` // 金额 Amount float64 `json:"amount"` // 金额
Type string `json:"type"` // 奖励类型 Type string `json:"type"` // 奖励类型
Status int64 `json:"status"` // 状态0=正常, 1=已取消
Remark string `json:"remark"` // 备注
CreateTime string `json:"create_time"` // 创建时间 CreateTime string `json:"create_time"` // 创建时间
} }
@@ -319,6 +322,7 @@ type (
AgentId int64 `json:"agent_id"` // 代理ID AgentId int64 `json:"agent_id"` // 代理ID
DeductedAgentId int64 `json:"deducted_agent_id"` // 被扣代理ID DeductedAgentId int64 `json:"deducted_agent_id"` // 被扣代理ID
Amount float64 `json:"amount"` // 金额 Amount float64 `json:"amount"` // 金额
RefundedAmount float64 `json:"refunded_amount"` // 已退款金额
ProductName string `json:"product_name"` // 产品名 ProductName string `json:"product_name"` // 产品名
Type string `json:"type"` // 类型cost/pricing Type string `json:"type"` // 类型cost/pricing
Status int64 `json:"status"` // 状态 Status int64 `json:"status"` // 状态

View File

@@ -61,7 +61,6 @@ Applepay:
LoadPrivateKeyPath: "etc/merchant/AuthKey_XXXXXXXXXXXX.p8" LoadPrivateKeyPath: "etc/merchant/AuthKey_XXXXXXXXXXXX.p8"
SystemConfig: SystemConfig:
ThreeVerify: true ThreeVerify: true
CommissionSafeMode: false # 佣金安全防御模式true-冻结模式false-直接结算模式
WechatH5: WechatH5:
AppID: "xxxx" AppID: "xxxx"
AppSecret: "xxxx" AppSecret: "xxxx"

View File

@@ -100,8 +100,7 @@ type YushanConfig struct {
Url string Url string
} }
type SystemConfig struct { type SystemConfig struct {
ThreeVerify bool // 是否开启三级实名认证 ThreeVerify bool // 是否开启三级实名认证
CommissionSafeMode bool // 佣金安全防御模式true-冻结模式(status=1,进入frozen_balance)false-直接结算(status=0,进入balance)
} }
type WechatH5Config struct { type WechatH5Config struct {
AppID string AppID string

View File

@@ -36,6 +36,9 @@ func (l *AdminGetAgentRewardListLogic) AdminGetAgentRewardList(req *types.AdminG
if req.Type != nil && *req.Type != "" { if req.Type != nil && *req.Type != "" {
builder = builder.Where(squirrel.Eq{"type": *req.Type}) builder = builder.Where(squirrel.Eq{"type": *req.Type})
} }
if req.Status != nil {
builder = builder.Where(squirrel.Eq{"status": *req.Status})
}
list, total, err := l.svcCtx.AgentRewardsModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC") list, total, err := l.svcCtx.AgentRewardsModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -25,7 +25,7 @@ func NewAdminGetSystemConfigLogic(ctx context.Context, svcCtx *svc.ServiceContex
func (l *AdminGetSystemConfigLogic) AdminGetSystemConfig() (resp *types.AdminGetSystemConfigResp, err error) { func (l *AdminGetSystemConfigLogic) AdminGetSystemConfig() (resp *types.AdminGetSystemConfigResp, err error) {
resp = &types.AdminGetSystemConfigResp{ resp = &types.AdminGetSystemConfigResp{
CommissionSafeMode: l.svcCtx.Config.SystemConfig.CommissionSafeMode, CommissionSafeMode: l.svcCtx.AgentConfigModel.IsCommissionSafeMode(l.ctx),
} }
return return
} }

View File

@@ -24,9 +24,11 @@ func NewAdminUpdateSystemConfigLogic(ctx context.Context, svcCtx *svc.ServiceCon
} }
func (l *AdminUpdateSystemConfigLogic) AdminUpdateSystemConfig(req *types.AdminUpdateSystemConfigReq) (resp *types.AdminUpdateSystemConfigResp, err error) { func (l *AdminUpdateSystemConfigLogic) AdminUpdateSystemConfig(req *types.AdminUpdateSystemConfigReq) (resp *types.AdminUpdateSystemConfigResp, err error) {
// 更新佣金安全防御模式配置
if req.CommissionSafeMode != nil { if req.CommissionSafeMode != nil {
l.svcCtx.Config.SystemConfig.CommissionSafeMode = *req.CommissionSafeMode if err := l.svcCtx.AgentConfigModel.SetCommissionSafeMode(l.ctx, *req.CommissionSafeMode); err != nil {
logx.Errorf("更新佣金安全防御模式失败: %v", err)
return nil, err
}
logx.Infof("更新系统配置:佣金安全防御模式设置为 %v", *req.CommissionSafeMode) logx.Infof("更新系统配置:佣金安全防御模式设置为 %v", *req.CommissionSafeMode)
} }

View File

@@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"time" "time"
paylogic "bdrp-server/app/main/api/internal/logic/pay"
"bdrp-server/app/main/api/internal/svc" "bdrp-server/app/main/api/internal/svc"
"bdrp-server/app/main/api/internal/types" "bdrp-server/app/main/api/internal/types"
"bdrp-server/app/main/model" "bdrp-server/app/main/model"
@@ -93,8 +92,8 @@ func (l *AdminRefundOrderLogic) handleAlipayRefund(order *model.Order, req *type
} }
// 退款成功后,按本次退款金额更新代理佣金状态并扣除钱包金额 // 退款成功后,按本次退款金额更新代理佣金状态并扣除钱包金额
// 注意refundAmount 为本次实际退款金额,可以是部分退款 // 使用 AgentService 中的共用退款扣款逻辑
_ = paylogic.HandleCommissionAndWalletDeduction(l.ctx, l.svcCtx, nil, order, req.RefundAmount) l.svcCtx.AgentService.HandleOrderRefundDeduction(l.ctx, nil, order, req.RefundAmount)
return &types.AdminRefundOrderResp{ return &types.AdminRefundOrderResp{
Status: model.OrderStatusRefunded, Status: model.OrderStatusRefunded,

View File

@@ -1,11 +1,13 @@
package agent package agent
import ( import (
"context" "bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/model" "bdrp-server/app/main/model"
"bdrp-server/common/ctxdata" "bdrp-server/common/ctxdata"
"bdrp-server/common/xerr" "bdrp-server/common/xerr"
"bdrp-server/pkg/lzkit/lzUtils" "bdrp-server/pkg/lzkit/lzUtils"
"context"
"time"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -40,6 +42,9 @@ func (l *GetAgentMembershipProductConfigLogic) GetAgentMembershipProductConfig(r
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取代理信息失败: %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取代理信息失败: %v", err)
} }
if service.IsMembershipExpired(agentModel, time.Now()) {
return nil, errors.Wrapf(xerr.NewErrMsg("会员已过期"), "获取会员用户报告配置,会员已过期: agent_id=%d", agentModel.Id)
}
if agentModel.LevelName == "" { if agentModel.LevelName == "" {
agentModel.LevelName = model.AgentLeveNameNormal agentModel.LevelName = model.AgentLeveNameNormal
} }

View File

@@ -1,11 +1,13 @@
package agent package agent
import ( import (
"context" "bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/model" "bdrp-server/app/main/model"
"bdrp-server/common/ctxdata" "bdrp-server/common/ctxdata"
"bdrp-server/common/xerr" "bdrp-server/common/xerr"
"context"
"math" "math"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/mr" "github.com/zeromicro/go-zero/core/mr"
@@ -104,6 +106,10 @@ func (l *GetAgentProductConfigLogic) GetAgentProductConfig() (resp *types.AgentP
cancel(findAncestorAgentErr) cancel(findAncestorAgentErr)
return return
} }
if service.IsMembershipExpired(ancestorAgentModel, time.Now()) {
writer.Write(&agentProductConfig)
return
}
if ancestorAgentModel.LevelName == "" { if ancestorAgentModel.LevelName == "" {
ancestorAgentModel.LevelName = model.AgentLeveNameNormal ancestorAgentModel.LevelName = model.AgentLeveNameNormal
} }

View File

@@ -175,6 +175,11 @@ func calculateActiveReward(rewards []*model.AgentRewards) types.ActiveReward {
last30dStart := now.AddDate(0, 0, -30) // 近30天 last30dStart := now.AddDate(0, 0, -30) // 近30天
for _, r := range rewards { for _, r := range rewards {
// 跳过已取消的奖励(退款取消)
if r.Status == 1 {
continue
}
createTime := r.CreateTime createTime := r.CreateTime
amount := r.Amount amount := r.Amount
@@ -219,11 +224,12 @@ func addToPeriods(res *types.ActiveReward, amount float64, today, last7d, last30
// 分类添加具体字段 // 分类添加具体字段
func addToData(data *types.ActiveRewardData, amount float64, t string) { func addToData(data *types.ActiveRewardData, amount float64, t string) {
// 所有类型都累加到总奖励
data.NewActiveReward += amount
switch t { switch t {
case "withdraw": case "withdraw":
data.SubWithdrawReward += amount data.SubWithdrawReward += amount
case "new_active":
data.NewActiveReward += amount
case "upgrade": case "upgrade":
data.SubUpgradeReward += amount data.SubUpgradeReward += amount
case "promotion": case "promotion":

View File

@@ -1,10 +1,12 @@
package agent package agent
import ( import (
"context" "bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/model" "bdrp-server/app/main/model"
"bdrp-server/common/ctxdata" "bdrp-server/common/ctxdata"
"bdrp-server/common/xerr" "bdrp-server/common/xerr"
"context"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -37,6 +39,9 @@ func (l *SaveAgentMembershipUserConfigLogic) SaveAgentMembershipUserConfig(req *
if err != nil { if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err) return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err)
} }
if service.IsMembershipExpired(agentModel, time.Now()) {
return errors.Wrapf(xerr.NewErrMsg("会员已过期"), "保存会员代理报告配置,会员已过期: agent_id=%d", agentModel.Id)
}
var agentMembershipUserConfigModel *model.AgentMembershipUserConfig var agentMembershipUserConfigModel *model.AgentMembershipUserConfig
agentMembershipUserConfigModel, err = l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentModel.Id, req.ProductID) agentMembershipUserConfigModel, err = l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentModel.Id, req.ProductID)

View File

@@ -11,7 +11,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic" "github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
@@ -22,153 +21,6 @@ func roundMoney(v float64) float64 {
return math.Round(v*100) / 100 return math.Round(v*100) / 100
} }
// HandleCommissionAndWalletDeduction 处理退款后的佣金状态更新和钱包金额扣除
// refundAmount 为本次实际退款金额(单位:元),从代理侧总共需要承担的金额
// 该函数会优先冲减当前订单相关的佣金(基于 RefundedAmount不足部分再从钱包余额/冻结余额中扣除
func HandleCommissionAndWalletDeduction(ctx context.Context, svcCtx *svc.ServiceContext, session sqlx.Session, order *model.Order, refundAmount float64) error {
refundAmount = roundMoney(refundAmount)
if refundAmount <= 0 {
return nil
}
// 查询当前订单关联的所有佣金记录(包括已结算和冻结),剔除已经完全退款的
commissionBuilder := svcCtx.AgentCommissionModel.SelectBuilder()
commissions, commissionsErr := svcCtx.AgentCommissionModel.FindAll(ctx, commissionBuilder.Where(squirrel.And{
squirrel.Eq{"order_id": order.Id},
squirrel.NotEq{"status": 2}, // 排除已全部退款的佣金
}), "")
if commissionsErr != nil {
logx.Errorf("查询代理佣金失败订单ID: %d, 错误: %v", order.Id, commissionsErr)
return nil // 返回 nil因为佣金更新失败不应影响退款流程
}
if len(commissions) == 0 {
return nil
}
// 剩余需要由佣金 + 钱包共同承担的退款金额
remainRefundAmount := refundAmount
// 记录每个代理本次需要从钱包扣除的金额,避免同一代理多条佣金时重复查钱包并产生多条流水
type walletAdjust struct {
agentId int64
amount float64 // 需要从该代理钱包扣除的金额(正数)
}
walletAdjustMap := make(map[int64]*walletAdjust)
// 1. 先在佣金记录上做冲减:增加 RefundedAmount必要时将状态置为已退款
for _, commission := range commissions {
available := roundMoney(commission.Amount - commission.RefundedAmount)
if available <= 0 {
continue
}
if remainRefundAmount <= 0 {
break
}
// 当前这条佣金最多可冲减 available本次实际冲减 currentRefund
currentRefund := available
if currentRefund > remainRefundAmount {
currentRefund = remainRefundAmount
}
currentRefund = roundMoney(currentRefund)
// 更新佣金的已退款金额
commission.RefundedAmount = roundMoney(commission.RefundedAmount + currentRefund)
// 如果这条佣金已经被完全冲减,则标记为已退款
if commission.RefundedAmount >= roundMoney(commission.Amount) {
commission.Status = 2
}
// 更新佣金状态到数据库
var updateCommissionErr error
if session != nil {
updateCommissionErr = svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, session, commission)
} else {
updateCommissionErr = svcCtx.AgentCommissionModel.UpdateWithVersion(ctx, nil, commission)
}
if updateCommissionErr != nil {
logx.Errorf("更新代理佣金状态失败佣金ID: %d, 订单ID: %d, 错误: %v", commission.Id, order.Id, updateCommissionErr)
continue // 如果佣金状态更新失败,就不继续计入本次冲减
}
// 记录该代理需要从钱包扣除的金额(可能后续还有其他佣金叠加)
wa, ok := walletAdjustMap[commission.AgentId]
if !ok {
wa = &walletAdjust{agentId: commission.AgentId}
walletAdjustMap[commission.AgentId] = wa
}
wa.amount = roundMoney(wa.amount + currentRefund)
remainRefundAmount = roundMoney(remainRefundAmount - currentRefund)
}
// 2. 再按代理维度,从钱包(冻结余额/可用余额)中扣除对应金额
for _, wa := range walletAdjustMap {
if wa.amount <= 0 {
continue
}
// 处理用户钱包的金额扣除
wallet, err := svcCtx.AgentWalletModel.FindOneByAgentId(ctx, wa.agentId)
if err != nil {
logx.Errorf("查询代理钱包失败代理ID: %d, 错误: %v", wa.agentId, err)
continue
}
// 记录变动前的余额
balanceBefore := wallet.Balance
frozenBalanceBefore := wallet.FrozenBalance
// 优先从冻结余额中扣除(与原先“冻结佣金优先使用冻结余额”的设计一致)
deduct := roundMoney(wa.amount)
if wallet.FrozenBalance >= deduct {
wallet.FrozenBalance = roundMoney(wallet.FrozenBalance - deduct)
} else {
remaining := roundMoney(deduct - wallet.FrozenBalance)
wallet.FrozenBalance = 0
// 可用余额可以为负数,由业务承担风险
wallet.Balance = roundMoney(wallet.Balance - remaining)
}
// 变动后余额和冻结余额
balanceAfter := roundMoney(wallet.Balance)
frozenBalanceAfter := roundMoney(wallet.FrozenBalance)
// 更新钱包
var updateWalletErr error
if session != nil {
updateWalletErr = svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
} else {
updateWalletErr = svcCtx.AgentWalletModel.UpdateWithVersion(ctx, nil, wallet)
}
if updateWalletErr != nil {
logx.Errorf("更新代理钱包失败代理ID: %d, 错误: %v", wa.agentId, updateWalletErr)
continue
}
// 创建钱包交易流水记录(退款)
transErr := svcCtx.AgentService.CreateWalletTransaction(
ctx,
session,
wa.agentId,
model.WalletTransactionTypeRefund,
roundMoney(-wa.amount*-1), // 钱包流水金额为负数
balanceBefore,
balanceAfter,
frozenBalanceBefore,
frozenBalanceAfter,
order.OrderNo,
0, // 这里不强绑到某一条具体佣金记录,按订单维度记录
"订单退款,佣金已扣除",
)
if transErr != nil {
logx.Errorf("创建代理钱包流水记录失败代理ID: %d, 错误: %v", wa.agentId, transErr)
continue
}
}
return nil
}
type WechatPayRefundCallbackLogic struct { type WechatPayRefundCallbackLogic struct {
logx.Logger logx.Logger
ctx context.Context ctx context.Context
@@ -227,8 +79,8 @@ func (l *WechatPayRefundCallbackLogic) handleQueryOrderRefund(orderNo string, st
return errors.Wrapf(err, "更新查询订单状态失败: %s", orderNo) return errors.Wrapf(err, "更新查询订单状态失败: %s", orderNo)
} }
// 退款成功时,按本次实际退款金额更新代理佣金状态并扣除钱包金额 // 退款成功时,按本次实际退款金额执行共用扣款流程
_ = HandleCommissionAndWalletDeduction(ctx, l.svcCtx, session, order, refundAmountYuan) l.svcCtx.AgentService.HandleOrderRefundDeduction(ctx, session, order, refundAmountYuan)
} }
// 查找最新的pending状态的退款记录 // 查找最新的pending状态的退款记录

View File

@@ -0,0 +1,67 @@
package middleware
import (
"net/http"
"time"
"bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/model"
jwtx "bdrp-server/common/jwt"
"github.com/zeromicro/go-zero/core/logx"
)
const (
HeaderMembershipExpired = "X-Membership-Expired"
)
// MembershipExpiredInterceptor 检测代理会员是否过期,过期则写入响应头
// 依赖 ctx 中的 claims由 AuthInterceptorMiddleware 注入)和 svcCtx 中的 AgentModel
type MembershipExpiredInterceptor struct {
AgentModel model.AgentModel
}
func NewMembershipExpiredInterceptor(agentModel model.AgentModel) *MembershipExpiredInterceptor {
return &MembershipExpiredInterceptor{
AgentModel: agentModel,
}
}
func (m *MembershipExpiredInterceptor) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 先执行业务逻辑
next(w, r)
// 业务完成后,尝试检测会员过期状态
claims, err := getClaimsFromRequest(r)
if err != nil || claims == nil {
return
}
// 只检查正式用户
if claims.UserType != model.UserTypeNormal {
return
}
agent, err := m.AgentModel.FindOneByUserId(r.Context(), claims.UserId)
if err != nil {
return
}
if service.IsMembershipExpired(agent, time.Now()) {
w.Header().Set(HeaderMembershipExpired, "true")
logx.Infof("检测到代理会员已过期写入响应头代理ID: %d, 用户ID: %d", agent.Id, claims.UserId)
}
}
}
func getClaimsFromRequest(r *http.Request) (*jwtx.JwtClaims, error) {
value := r.Context().Value(jwtx.ExtraKey)
if value == nil {
return nil, nil
}
if claims, ok := value.(*jwtx.JwtClaims); ok {
return claims, nil
}
return nil, nil
}

View File

@@ -0,0 +1,49 @@
package queue
import (
"context"
"encoding/json"
"fmt"
"time"
"bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/api/internal/svc"
"bdrp-server/app/main/api/internal/types"
"github.com/hibiken/asynq"
"github.com/zeromicro/go-zero/core/logx"
)
type AgentMembershipExpireHandleHandler struct {
svcCtx *svc.ServiceContext
}
func NewAgentMembershipExpireHandleHandler(svcCtx *svc.ServiceContext) *AgentMembershipExpireHandleHandler {
return &AgentMembershipExpireHandleHandler{
svcCtx: svcCtx,
}
}
func (l *AgentMembershipExpireHandleHandler) ProcessTask(ctx context.Context, t *asynq.Task) error {
var payload types.MsgAgentMembershipExpireHandlePayload
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
logx.Errorf("解析会员到期处理任务payload失败: %v", err)
return err
}
if payload.AgentID <= 0 {
return fmt.Errorf("无效代理ID: %d", payload.AgentID)
}
now := time.Now()
downgraded, err := service.DowngradeExpiredMembership(ctx, l.svcCtx.AgentModel, payload.AgentID, now)
if err != nil {
logx.Errorf("会员到期处理失败代理ID: %d, 错误: %v", payload.AgentID, err)
return err
}
if downgraded {
logx.Infof("会员到期处理成功代理ID: %d 已降级为普通代理", payload.AgentID)
} else {
logx.Infof("会员到期处理跳过代理ID: %d 当前无需降级", payload.AgentID)
}
return nil
}

View File

@@ -0,0 +1,68 @@
package queue
import (
"context"
"time"
"bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/api/internal/svc"
"github.com/hibiken/asynq"
"github.com/zeromicro/go-zero/core/logx"
)
type AgentMembershipExpireScanHandler struct {
svcCtx *svc.ServiceContext
}
func NewAgentMembershipExpireScanHandler(svcCtx *svc.ServiceContext) *AgentMembershipExpireScanHandler {
return &AgentMembershipExpireScanHandler{
svcCtx: svcCtx,
}
}
func (l *AgentMembershipExpireScanHandler) ProcessTask(ctx context.Context, t *asynq.Task) error {
now := time.Now()
dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
dayEnd := dayStart.Add(24*time.Hour - time.Second)
// 1. 扫描当天将到期会员,并为每个会员安排准点处理任务
todayAgents, err := service.ListTodayWillExpireAgents(ctx, l.svcCtx.AgentModel, dayStart, dayEnd)
if err != nil {
logx.Errorf("扫描当天到期会员失败: %v", err)
return err
}
for _, agent := range todayAgents {
processAt := agent.MembershipExpiryTime.Time
if processAt.Before(now) {
processAt = now
}
if l.svcCtx.AsynqService != nil {
if sendErr := l.svcCtx.AsynqService.SendAgentMembershipExpireHandleTask(agent.Id, processAt); sendErr != nil {
logx.Errorf("安排会员到期处理任务失败代理ID: %d, 错误: %v", agent.Id, sendErr)
}
}
}
// 2. 补偿处理:扫描已过期但尚未降级的会员并立即降级
expiredAgents, err := service.ListExpiredUnprocessedAgents(ctx, l.svcCtx.AgentModel, now)
if err != nil {
logx.Errorf("扫描已过期未处理会员失败: %v", err)
return err
}
downgradedCount := 0
for _, agent := range expiredAgents {
downgraded, degradeErr := service.DowngradeExpiredMembership(ctx, l.svcCtx.AgentModel, agent.Id, now)
if degradeErr != nil {
logx.Errorf("补偿降级失败代理ID: %d, 错误: %v", agent.Id, degradeErr)
continue
}
if downgraded {
downgradedCount++
}
}
logx.Infof("会员到期扫描完成,当天到期会员: %d, 补偿降级数量: %d", len(todayAgents), downgradedCount)
return nil
}

View File

@@ -10,7 +10,6 @@ import (
"path" "path"
"regexp" "regexp"
"strings" "strings"
paylogic "bdrp-server/app/main/api/internal/logic/pay"
"bdrp-server/app/main/api/internal/service" "bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/api/internal/svc" "bdrp-server/app/main/api/internal/svc"
"bdrp-server/app/main/api/internal/types" "bdrp-server/app/main/api/internal/types"
@@ -283,8 +282,8 @@ func (l *PaySuccessNotifyUserHandler) handleError(ctx context.Context, err error
return fmt.Errorf("更新订单状态失败: %v", updateOrderErr) return fmt.Errorf("更新订单状态失败: %v", updateOrderErr)
} }
// 使用公共函数按本次退款金额处理佣金和钱包扣除 // 使用 AgentService 中的共用退款扣款逻辑
_ = paylogic.HandleCommissionAndWalletDeduction(ctx, l.svcCtx, nil, order, order.Amount) l.svcCtx.AgentService.HandleOrderRefundDeduction(ctx, nil, order, order.Amount)
return asynq.SkipRetry return asynq.SkipRetry
} else { } else {

View File

@@ -1,12 +1,14 @@
package queue package queue
import ( import (
"context"
"fmt"
"bdrp-server/app/main/api/internal/svc" "bdrp-server/app/main/api/internal/svc"
"bdrp-server/app/main/api/internal/types" "bdrp-server/app/main/api/internal/types"
"context"
"fmt"
"time"
"github.com/hibiken/asynq" "github.com/hibiken/asynq"
"github.com/zeromicro/go-zero/core/logx"
) )
type CronJob struct { type CronJob struct {
@@ -14,6 +16,8 @@ type CronJob struct {
svcCtx *svc.ServiceContext svcCtx *svc.ServiceContext
} }
const AgentMembershipExpireScanTaskTime = "5 0 * * *"
func NewCronJob(ctx context.Context, svcCtx *svc.ServiceContext) *CronJob { func NewCronJob(ctx context.Context, svcCtx *svc.ServiceContext) *CronJob {
return &CronJob{ return &CronJob{
ctx: ctx, ctx: ctx,
@@ -31,6 +35,29 @@ func (l *CronJob) Register() *asynq.ServeMux {
if err != nil { if err != nil {
panic(fmt.Sprintf("定时任务注册失败:%v", err)) panic(fmt.Sprintf("定时任务注册失败:%v", err))
} }
// 注册会员到期扫描任务(每天凌晨执行)
expireScanTask := asynq.NewTask(types.MsgAgentMembershipExpireScan, nil, nil)
_, err = scheduler.Register(AgentMembershipExpireScanTaskTime, expireScanTask)
if err != nil {
panic(fmt.Sprintf("会员到期扫描任务注册失败:%v", err))
}
// 启动补偿:服务启动后立即触发一次扫描任务(按日期去重)
client := asynq.NewClient(redisClientOpt)
startupTaskID := fmt.Sprintf("agent_membership_expire_scan_startup_%s", time.Now().Format("20060102"))
_, enqueueErr := client.Enqueue(
asynq.NewTask(types.MsgAgentMembershipExpireScan, nil),
asynq.MaxRetry(1),
asynq.TaskID(startupTaskID),
)
if enqueueErr != nil {
logx.Errorf("启动补偿扫描任务入队失败: %v", enqueueErr)
}
if closeErr := client.Close(); closeErr != nil {
logx.Errorf("关闭启动补偿任务客户端失败: %v", closeErr)
}
scheduler.Start() scheduler.Start()
fmt.Println("定时任务启动!!!") fmt.Println("定时任务启动!!!")
@@ -38,6 +65,8 @@ func (l *CronJob) Register() *asynq.ServeMux {
mux.Handle(types.MsgPaySuccessQuery, NewPaySuccessNotifyUserHandler(l.svcCtx)) mux.Handle(types.MsgPaySuccessQuery, NewPaySuccessNotifyUserHandler(l.svcCtx))
mux.Handle(types.MsgCleanQueryData, NewCleanQueryDataHandler(l.svcCtx)) mux.Handle(types.MsgCleanQueryData, NewCleanQueryDataHandler(l.svcCtx))
mux.Handle(types.MsgUnfreezeCommission, NewUnfreezeCommissionHandler(l.svcCtx)) mux.Handle(types.MsgUnfreezeCommission, NewUnfreezeCommissionHandler(l.svcCtx))
mux.Handle(types.MsgAgentMembershipExpireScan, NewAgentMembershipExpireScanHandler(l.svcCtx))
mux.Handle(types.MsgAgentMembershipExpireHandle, NewAgentMembershipExpireHandleHandler(l.svcCtx))
return mux return mux
} }

View File

@@ -0,0 +1,70 @@
package service
import (
"context"
"database/sql"
"time"
"bdrp-server/app/main/model"
"bdrp-server/common/globalkey"
)
// IsMembershipExpired 判断代理会员是否已过期仅VIP/SVIP会被判定
func IsMembershipExpired(agent *model.Agent, now time.Time) bool {
if agent == nil {
return false
}
if agent.LevelName != model.AgentLeveNameVIP && agent.LevelName != model.AgentLeveNameSVIP {
return false
}
if !agent.MembershipExpiryTime.Valid {
return true
}
return !agent.MembershipExpiryTime.Time.After(now)
}
// DowngradeExpiredMembership 将已过期会员降级为普通代理,返回是否发生了降级
func DowngradeExpiredMembership(ctx context.Context, agentModel model.AgentModel, agentID int64, now time.Time) (bool, error) {
agent, err := agentModel.FindOne(ctx, agentID)
if err != nil {
return false, err
}
if !IsMembershipExpired(agent, now) {
return false, nil
}
agent.LevelName = model.AgentLeveNameNormal
ClearMembershipOnDowngrade(agent)
agent.UpdateTime = now
if err = agentModel.UpdateWithVersion(ctx, nil, agent); err != nil {
return false, err
}
return true, nil
}
// ListTodayWillExpireAgents 查询当天将到期的VIP/SVIP代理
func ListTodayWillExpireAgents(ctx context.Context, agentModel model.AgentModel, start, end time.Time) ([]*model.Agent, error) {
builder := agentModel.SelectBuilder().
Where("level_name IN (?, ?)", model.AgentLeveNameVIP, model.AgentLeveNameSVIP).
Where("membership_expiry_time IS NOT NULL").
Where("membership_expiry_time >= ?", start).
Where("membership_expiry_time <= ?", end).
Where("del_state = ?", globalkey.DelStateNo)
return agentModel.FindAll(ctx, builder, "membership_expiry_time ASC")
}
// ListExpiredUnprocessedAgents 查询已过期但仍为VIP/SVIP的代理
func ListExpiredUnprocessedAgents(ctx context.Context, agentModel model.AgentModel, now time.Time) ([]*model.Agent, error) {
builder := agentModel.SelectBuilder().
Where("level_name IN (?, ?)", model.AgentLeveNameVIP, model.AgentLeveNameSVIP).
Where("membership_expiry_time IS NOT NULL").
Where("membership_expiry_time <= ?", now).
Where("del_state = ?", globalkey.DelStateNo)
return agentModel.FindAll(ctx, builder, "membership_expiry_time ASC")
}
// ClearMembershipOnDowngrade 降级时清理会员有效期,避免脏状态
func ClearMembershipOnDowngrade(agent *model.Agent) {
agent.MembershipExpiryTime = sql.NullTime{}
}

View File

@@ -1,14 +1,17 @@
package service package service
import ( import (
"context"
"database/sql"
"fmt"
"bdrp-server/app/main/api/internal/config" "bdrp-server/app/main/api/internal/config"
"bdrp-server/app/main/model" "bdrp-server/app/main/model"
"bdrp-server/common/globalkey" "bdrp-server/common/globalkey"
"bdrp-server/pkg/lzkit/lzUtils" "bdrp-server/pkg/lzkit/lzUtils"
"context"
"database/sql"
"fmt"
"math"
"time"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
@@ -34,6 +37,7 @@ type AgentService struct {
AgentActiveStatModel model.AgentActiveStatModel AgentActiveStatModel model.AgentActiveStatModel
AgentWithdrawalModel model.AgentWithdrawalModel AgentWithdrawalModel model.AgentWithdrawalModel
AgentWalletTransactionModel model.AgentWalletTransactionModel AgentWalletTransactionModel model.AgentWalletTransactionModel
AgentConfigModel model.AgentConfigModel
AsynqService *AsynqService AsynqService *AsynqService
} }
@@ -44,7 +48,7 @@ func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel mo
agentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel, agentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel,
agentMembershipUserConfigModel model.AgentMembershipUserConfigModel, agentMembershipUserConfigModel model.AgentMembershipUserConfigModel,
agentProductConfigModel model.AgentProductConfigModel, agentPlatformDeductionModel model.AgentPlatformDeductionModel, agentProductConfigModel model.AgentProductConfigModel, agentPlatformDeductionModel model.AgentPlatformDeductionModel,
agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel, agentWalletTransactionModel model.AgentWalletTransactionModel, asynqService *AsynqService) *AgentService { agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel, agentWalletTransactionModel model.AgentWalletTransactionModel, agentConfigModel model.AgentConfigModel, asynqService *AsynqService) *AgentService {
return &AgentService{ return &AgentService{
config: c, config: c,
@@ -66,6 +70,7 @@ func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel mo
AgentActiveStatModel: agentActiveStatModel, AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel, AgentWithdrawalModel: agentWithdrawalModel,
AgentWalletTransactionModel: agentWalletTransactionModel, AgentWalletTransactionModel: agentWalletTransactionModel,
AgentConfigModel: agentConfigModel,
AsynqService: asynqService, AsynqService: asynqService,
} }
} }
@@ -113,6 +118,9 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
return findAgentModelErr return findAgentModelErr
} }
if AncestorModel != nil { if AncestorModel != nil {
if IsMembershipExpired(AncestorModel, time.Now()) {
AncestorModel.LevelName = model.AgentLeveNameNormal
}
if AncestorModel.LevelName == "" { if AncestorModel.LevelName == "" {
AncestorModel.LevelName = model.AgentLeveNameNormal AncestorModel.LevelName = model.AgentLeveNameNormal
} }
@@ -155,7 +163,7 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
// 根据安全防御模式配置决定佣金处理方式 // 根据安全防御模式配置决定佣金处理方式
var commissionStatus int64 var commissionStatus int64
if l.config.SystemConfig.CommissionSafeMode { if l.AgentConfigModel.IsCommissionSafeMode(ctx) {
// 安全防御模式佣金冻结在frozen_balance中 // 安全防御模式佣金冻结在frozen_balance中
ancestorWallet.FrozenBalance += ancestorCommissionAmount ancestorWallet.FrozenBalance += ancestorCommissionAmount
commissionStatus = 1 // 冻结状态 commissionStatus = 1 // 冻结状态
@@ -227,7 +235,7 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
// 在事务提交后,仅在安全防御模式下触发解冻任务 // 在事务提交后,仅在安全防御模式下触发解冻任务
// 注意:这里发送的是任务,实际解冻将在指定时间后由队列处理 // 注意:这里发送的是任务,实际解冻将在指定时间后由队列处理
if l.AsynqService != nil && l.config.SystemConfig.CommissionSafeMode { if l.AsynqService != nil && l.AgentConfigModel.IsCommissionSafeMode(ctx) {
// 仅在安全防御模式下,才需要发送解冻任务 // 仅在安全防御模式下,才需要发送解冻任务
// 获取刚创建的佣金记录ID // 获取刚创建的佣金记录ID
// 由于我们需要佣金记录ID来触发解冻任务但事务中无法获取我们可以在事务后查询 // 由于我们需要佣金记录ID来触发解冻任务但事务中无法获取我们可以在事务后查询
@@ -275,7 +283,7 @@ func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order
frozenBalanceBefore := agentWalletModel.FrozenBalance frozenBalanceBefore := agentWalletModel.FrozenBalance
// 根据安全防御模式配置决定佣金状态和钱包操作 // 根据安全防御模式配置决定佣金状态和钱包操作
if l.config.SystemConfig.CommissionSafeMode { if l.AgentConfigModel.IsCommissionSafeMode(ctx) {
// 安全防御模式佣金冻结在frozen_balance中 // 安全防御模式佣金冻结在frozen_balance中
agentWalletModel.FrozenBalance += finalCommission agentWalletModel.FrozenBalance += finalCommission
} else { } else {
@@ -286,7 +294,7 @@ func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order
// 根据安全防御模式配置决定佣金状态 // 根据安全防御模式配置决定佣金状态
commissionStatus := int64(1) // 默认为冻结状态 commissionStatus := int64(1) // 默认为冻结状态
if !l.config.SystemConfig.CommissionSafeMode { if !l.AgentConfigModel.IsCommissionSafeMode(ctx) {
commissionStatus = 0 // 非安全模式直接设置为已结算 commissionStatus = 0 // 非安全模式直接设置为已结算
} }
@@ -343,6 +351,9 @@ func (l *AgentService) AncestorCommission(ctx context.Context, descendantId int6
if err != nil { if err != nil {
return 0, err return 0, err
} }
if IsMembershipExpired(agentModel, time.Now()) {
agentModel.LevelName = model.AgentLeveNameNormal
}
if agentModel.LevelName == "" { if agentModel.LevelName == "" {
agentModel.LevelName = model.AgentLeveNameNormal agentModel.LevelName = model.AgentLeveNameNormal
} }
@@ -415,6 +426,17 @@ func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, order
// CommissionCost 上级底价成本 // CommissionCost 上级底价成本
func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, orderId int64, session sqlx.Session) (float64, error) { func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, orderId int64, session sqlx.Session) (float64, error) {
ancestorModel, findAncestorErr := l.AgentModel.FindOne(ctx, AncestorId)
if findAncestorErr != nil {
if errors.Is(findAncestorErr, model.ErrNotFound) {
return 0, nil
}
return 0, findAncestorErr
}
if IsMembershipExpired(ancestorModel, time.Now()) {
return 0, nil
}
if agentMembershipConfigModel.PriceIncreaseAmount.Valid { if agentMembershipConfigModel.PriceIncreaseAmount.Valid {
// 拥有则查看该上级设定的成本 // 拥有则查看该上级设定的成本
agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID)
@@ -449,6 +471,17 @@ func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, A
// CommissionPricing 上级提价成本 // CommissionPricing 上级提价成本
func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, pricing float64, orderId int64, session sqlx.Session) (float64, error) { func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, pricing float64, orderId int64, session sqlx.Session) (float64, error) {
ancestorModel, findAncestorErr := l.AgentModel.FindOne(ctx, AncestorId)
if findAncestorErr != nil {
if errors.Is(findAncestorErr, model.ErrNotFound) {
return 0, nil
}
return 0, findAncestorErr
}
if IsMembershipExpired(ancestorModel, time.Now()) {
return 0, nil
}
//看上级代理等级否有拥有定价标准收益功能 //看上级代理等级否有拥有定价标准收益功能
if agentMembershipConfigModel.PriceIncreaseMax.Valid && agentMembershipConfigModel.PriceRatio.Valid { if agentMembershipConfigModel.PriceIncreaseMax.Valid && agentMembershipConfigModel.PriceRatio.Valid {
// 拥有则查看该上级设定的成本 // 拥有则查看该上级设定的成本
@@ -517,6 +550,9 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
} }
// 获取上级代理的等级配置 // 获取上级代理的等级配置
if IsMembershipExpired(ancestorModel, time.Now()) {
ancestorModel.LevelName = model.AgentLeveNameNormal
}
if ancestorModel.LevelName == "" { if ancestorModel.LevelName == "" {
ancestorModel.LevelName = model.AgentLeveNameNormal ancestorModel.LevelName = model.AgentLeveNameNormal
} }
@@ -661,6 +697,9 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
} }
// 获取上级代理的等级配置 // 获取上级代理的等级配置
if IsMembershipExpired(ancestorModel, time.Now()) {
ancestorModel.LevelName = model.AgentLeveNameNormal
}
if ancestorModel.LevelName == "" { if ancestorModel.LevelName == "" {
ancestorModel.LevelName = model.AgentLeveNameNormal ancestorModel.LevelName = model.AgentLeveNameNormal
} }
@@ -848,3 +887,211 @@ func (l *AgentService) CreateWalletTransaction(ctx context.Context, session sqlx
} }
return nil return nil
} }
// HandleOrderRefundDeduction 处理订单退款后的佣金扣款流程
// refundAmount: 本次实际退款金额
// 扣款顺序:
// 1. 扣减推广代理佣金(先扣冻结,再扣余额)
// 2. 扣减上级抽佣
// 3. 取消上级推广奖励(无论退多少都取消)
// 4. 不足部分继续从推广代理钱包扣
// 平台抽佣不受影响
func (l *AgentService) HandleOrderRefundDeduction(ctx context.Context, session sqlx.Session, order *model.Order, refundAmount float64) {
refundAmount = roundRefundMoney(refundAmount)
if refundAmount <= 0 {
return
}
remainRefundAmount := refundAmount
// 查找订单关联的代理订单获取推广人代理ID
agentOrder, err := l.AgentOrderModel.FindOneByOrderId(ctx, order.Id)
if err != nil || agentOrder == nil {
logx.Errorf("退款扣款查询代理订单失败订单ID: %d, 错误: %v", order.Id, err)
return
}
promoterAgentId := agentOrder.AgentId
// 查找上级代理ID
var ancestorAgentId int64 = 0
agentClosure, closureErr := l.AgentClosureModel.FindOneByDescendantIdDepth(ctx, promoterAgentId, 1)
if closureErr == nil && agentClosure != nil {
ancestorAgentId = agentClosure.AncestorId
}
// 第1步扣减推广代理佣金
promoterCommissions, _ := l.AgentCommissionModel.FindAll(ctx,
l.AgentCommissionModel.SelectBuilder().Where(squirrel.And{
squirrel.Eq{"order_id": order.Id},
squirrel.Eq{"agent_id": promoterAgentId},
squirrel.NotEq{"status": 2},
}), "")
for _, commission := range promoterCommissions {
if remainRefundAmount <= 0 {
break
}
available := roundRefundMoney(commission.Amount - commission.RefundedAmount)
if available <= 0 {
continue
}
currentRefund := available
if currentRefund > remainRefundAmount {
currentRefund = remainRefundAmount
}
currentRefund = roundRefundMoney(currentRefund)
commission.RefundedAmount = roundRefundMoney(commission.RefundedAmount + currentRefund)
if commission.RefundedAmount >= roundRefundMoney(commission.Amount) {
commission.Status = 2
}
if err := l.AgentCommissionModel.UpdateWithVersion(ctx, session, commission); err != nil {
logx.Errorf("退款扣款更新推广佣金失败佣金ID: %d, 错误: %v", commission.Id, err)
continue
}
deductFromAgentWallet(ctx, l, session, promoterAgentId, currentRefund,
fmt.Sprintf("订单退款,推广佣金扣除,订单号: %s", order.OrderNo))
remainRefundAmount = roundRefundMoney(remainRefundAmount - currentRefund)
}
// 第2步扣减上级抽佣
if ancestorAgentId > 0 && remainRefundAmount > 0 {
deductions, _ := l.AgentCommissionDeductionModel.FindAll(ctx,
l.AgentCommissionDeductionModel.SelectBuilder().Where(map[string]interface{}{
"order_id": order.Id,
"agent_id": ancestorAgentId,
}), "")
for _, deduction := range deductions {
if deduction.Status == 2 {
continue
}
if remainRefundAmount <= 0 {
break
}
available := roundRefundMoney(deduction.Amount - deduction.RefundedAmount)
if available <= 0 {
continue
}
currentRefund := available
if currentRefund > remainRefundAmount {
currentRefund = remainRefundAmount
}
currentRefund = roundRefundMoney(currentRefund)
deduction.RefundedAmount = roundRefundMoney(deduction.RefundedAmount + currentRefund)
if deduction.RefundedAmount >= roundRefundMoney(deduction.Amount) {
deduction.Status = 2
}
if err := l.AgentCommissionDeductionModel.UpdateWithVersion(ctx, session, deduction); err != nil {
logx.Errorf("退款扣款更新上级抽佣失败ID: %d, 错误: %v", deduction.Id, err)
continue
}
deductFromAgentWallet(ctx, l, session, ancestorAgentId, currentRefund,
fmt.Sprintf("订单退款,上级抽佣扣除,订单号: %s", order.OrderNo))
remainRefundAmount = roundRefundMoney(remainRefundAmount - currentRefund)
}
}
// 第3步取消上级推广奖励无论退多少都取消
if ancestorAgentId > 0 {
rewards, _ := l.AgentRewardsModel.FindAll(ctx,
l.AgentRewardsModel.SelectBuilder().Where(map[string]interface{}{
"agent_id": ancestorAgentId,
"relation_agent_id": promoterAgentId,
"type": model.AgentRewardsTypeDescendantPromotion,
"status": 0,
}), "id DESC")
if len(rewards) > 0 {
reward := rewards[0]
rewardAmount := roundRefundMoney(reward.Amount)
reward.Status = 1
reward.Remark = fmt.Sprintf("订单退款取消奖励,订单号: %s", order.OrderNo)
if err := l.AgentRewardsModel.UpdateWithVersion(ctx, session, reward); err != nil {
logx.Errorf("退款扣款取消推广奖励失败奖励ID: %d, 错误: %v", reward.Id, err)
} else {
deductFromAgentWallet(ctx, l, session, ancestorAgentId, rewardAmount,
fmt.Sprintf("订单退款,取消推广奖励,订单号: %s", order.OrderNo))
}
}
}
// 第4步不足部分从推广代理钱包扣
if remainRefundAmount > 0 {
deductFromAgentWallet(ctx, l, session, promoterAgentId, remainRefundAmount,
fmt.Sprintf("订单退款,不足部分从钱包扣除,订单号: %s", order.OrderNo))
}
}
// roundRefundMoney 四舍五入到分
func roundRefundMoney(v float64) float64 {
return math.Round(v*100) / 100
}
// deductFromAgentWallet 从代理钱包扣除金额(先冻结后余额)
func deductFromAgentWallet(ctx context.Context, l *AgentService, session sqlx.Session, agentId int64, amount float64, remark string) {
amount = roundRefundMoney(amount)
if amount <= 0 {
return
}
wallet, err := l.AgentWalletModel.FindOneByAgentId(ctx, agentId)
if err != nil {
logx.Errorf("退款扣款查询代理钱包失败代理ID: %d, 错误: %v", agentId, err)
return
}
balanceBefore := wallet.Balance
frozenBalanceBefore := wallet.FrozenBalance
if wallet.FrozenBalance >= amount {
wallet.FrozenBalance = roundRefundMoney(wallet.FrozenBalance - amount)
} else {
remaining := roundRefundMoney(amount - wallet.FrozenBalance)
wallet.FrozenBalance = 0
wallet.Balance = roundRefundMoney(wallet.Balance - remaining)
}
balanceAfter := roundRefundMoney(wallet.Balance)
frozenBalanceAfter := roundRefundMoney(wallet.FrozenBalance)
var updateErr error
if session != nil {
updateErr = l.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
} else {
updateErr = l.AgentWalletModel.UpdateWithVersion(ctx, nil, wallet)
}
if updateErr != nil {
logx.Errorf("退款扣款更新代理钱包失败代理ID: %d, 错误: %v", agentId, updateErr)
return
}
transErr := l.CreateWalletTransaction(
ctx,
session,
agentId,
model.WalletTransactionTypeRefund,
roundRefundMoney(-amount),
balanceBefore,
balanceAfter,
frozenBalanceBefore,
frozenBalanceAfter,
"",
0,
remark,
)
if transErr != nil {
logx.Errorf("退款扣款创建钱包流水失败代理ID: %d, 错误: %v", agentId, transErr)
}
}

View File

@@ -4,6 +4,7 @@ package service
import ( import (
"encoding/json" "encoding/json"
"fmt"
"time" "time"
"bdrp-server/app/main/api/internal/config" "bdrp-server/app/main/api/internal/config"
@@ -90,3 +91,32 @@ func (s *AsynqService) SendUnfreezeCommissionTask(commissionID int64) error {
logx.Infof("发送佣金解冻任务成功任务ID: %s, 队列: %s, 佣金ID: %d", info.ID, info.Queue, commissionID) logx.Infof("发送佣金解冻任务成功任务ID: %s, 队列: %s, 佣金ID: %d", info.ID, info.Queue, commissionID)
return nil return nil
} }
// SendAgentMembershipExpireHandleTask 发送代理会员到期处理任务
func (s *AsynqService) SendAgentMembershipExpireHandleTask(agentID int64, processAt time.Time) error {
payload := types.MsgAgentMembershipExpireHandlePayload{
AgentID: agentID,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
logx.Errorf("发送会员到期处理任务失败 (无法编码 payload): %v, 代理ID: %d", err, agentID)
return err
}
taskID := fmt.Sprintf("agent_membership_expire_handle_%d", agentID)
options := []asynq.Option{
asynq.ProcessAt(processAt),
asynq.MaxRetry(5),
asynq.TaskID(taskID),
}
task := asynq.NewTask(types.MsgAgentMembershipExpireHandle, payloadBytes, options...)
info, err := s.client.Enqueue(task)
if err != nil {
logx.Errorf("发送会员到期处理任务失败 (加入队列失败): %+v, 代理ID: %d, TaskID: %s", err, agentID, taskID)
return err
}
logx.Infof("发送会员到期处理任务成功任务ID: %s, 队列: %s, 代理ID: %d, 执行时间: %s", info.ID, info.Queue, agentID, processAt.Format("2006-01-02 15:04:05"))
return nil
}

View File

@@ -65,6 +65,7 @@ type ServiceContext struct {
AgentWithdrawalTaxModel model.AgentWithdrawalTaxModel AgentWithdrawalTaxModel model.AgentWithdrawalTaxModel
AgentWithdrawalTaxExemptionModel model.AgentWithdrawalTaxExemptionModel AgentWithdrawalTaxExemptionModel model.AgentWithdrawalTaxExemptionModel
AgentWalletTransactionModel model.AgentWalletTransactionModel AgentWalletTransactionModel model.AgentWalletTransactionModel
AgentConfigModel model.AgentConfigModel
// 管理后台相关模型 // 管理后台相关模型
AdminApiModel model.AdminApiModel AdminApiModel model.AdminApiModel
@@ -155,6 +156,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
agentWithdrawalTaxModel := model.NewAgentWithdrawalTaxModel(db, cacheConf) agentWithdrawalTaxModel := model.NewAgentWithdrawalTaxModel(db, cacheConf)
agentWithdrawalTaxExemptionModel := model.NewAgentWithdrawalTaxExemptionModel(db, cacheConf) agentWithdrawalTaxExemptionModel := model.NewAgentWithdrawalTaxExemptionModel(db, cacheConf)
agentWalletTransactionModel := model.NewAgentWalletTransactionModel(db, cacheConf) agentWalletTransactionModel := model.NewAgentWalletTransactionModel(db, cacheConf)
agentConfigModel := model.NewAgentConfigModel(db, cacheConf)
// ============================== 管理后台相关模型 ============================== // ============================== 管理后台相关模型 ==============================
adminApiModel := model.NewAdminApiModel(db, cacheConf) adminApiModel := model.NewAdminApiModel(db, cacheConf)
adminMenuModel := model.NewAdminMenuModel(db, cacheConf) adminMenuModel := model.NewAdminMenuModel(db, cacheConf)
@@ -196,7 +198,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel,
agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel,
agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel, agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel,
agentActiveStatModel, agentWithdrawalModel, agentWalletTransactionModel, asynqService) agentActiveStatModel, agentWithdrawalModel, agentWalletTransactionModel, agentConfigModel, asynqService)
userService := service.NewUserService(&c, userModel, userAuthModel, userTempModel, agentModel) userService := service.NewUserService(&c, userModel, userAuthModel, userTempModel, agentModel)
dictService := service.NewDictService(adminDictTypeModel, adminDictDataModel) dictService := service.NewDictService(adminDictTypeModel, adminDictDataModel)
adminPromotionLinkStatsService := service.NewAdminPromotionLinkStatsService(adminPromotionLinkModel, adminPromotionLinkStatsService := service.NewAdminPromotionLinkStatsService(adminPromotionLinkModel,
@@ -265,6 +267,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
AgentWithdrawalTaxModel: agentWithdrawalTaxModel, AgentWithdrawalTaxModel: agentWithdrawalTaxModel,
AgentWithdrawalTaxExemptionModel: agentWithdrawalTaxExemptionModel, AgentWithdrawalTaxExemptionModel: agentWithdrawalTaxExemptionModel,
AgentWalletTransactionModel: agentWalletTransactionModel, AgentWalletTransactionModel: agentWalletTransactionModel,
AgentConfigModel: agentConfigModel,
// 管理后台相关模型 // 管理后台相关模型
AdminApiModel: adminApiModel, AdminApiModel: adminApiModel,

View File

@@ -7,3 +7,7 @@ type MsgPaySuccessQueryPayload struct {
type MsgUnfreezeCommissionPayload struct { type MsgUnfreezeCommissionPayload struct {
CommissionID int64 `json:"commission_id"` CommissionID int64 `json:"commission_id"`
} }
type MsgAgentMembershipExpireHandlePayload struct {
AgentID int64 `json:"agent_id"`
}

View File

@@ -3,3 +3,5 @@ package types
const MsgPaySuccessQuery = "msg:pay_success:query" const MsgPaySuccessQuery = "msg:pay_success:query"
const MsgCleanQueryData = "msg:clean_query_data" const MsgCleanQueryData = "msg:clean_query_data"
const MsgUnfreezeCommission = "msg:unfreeze_commission" const MsgUnfreezeCommission = "msg:unfreeze_commission"
const MsgAgentMembershipExpireScan = "msg:agent_membership_expire_scan"
const MsgAgentMembershipExpireHandle = "msg:agent_membership_expire_handle"

View File

@@ -339,6 +339,7 @@ type AdminGetAgentRewardListReq struct {
AgentId *int64 `form:"agent_id,optional"` // 代理ID可选 AgentId *int64 `form:"agent_id,optional"` // 代理ID可选
RelationAgentId *int64 `form:"relation_agent_id,optional"` // 关联代理ID可选 RelationAgentId *int64 `form:"relation_agent_id,optional"` // 关联代理ID可选
Type *string `form:"type,optional"` // 奖励类型(可选) Type *string `form:"type,optional"` // 奖励类型(可选)
Status *int64 `form:"status,optional"` // 状态(可选)
} }
type AdminGetAgentRewardListResp struct { type AdminGetAgentRewardListResp struct {
@@ -1080,6 +1081,7 @@ type AgentCommissionDeductionListItem struct {
AgentId int64 `json:"agent_id"` // 代理ID AgentId int64 `json:"agent_id"` // 代理ID
DeductedAgentId int64 `json:"deducted_agent_id"` // 被扣代理ID DeductedAgentId int64 `json:"deducted_agent_id"` // 被扣代理ID
Amount float64 `json:"amount"` // 金额 Amount float64 `json:"amount"` // 金额
RefundedAmount float64 `json:"refunded_amount"` // 已退款金额
ProductName string `json:"product_name"` // 产品名 ProductName string `json:"product_name"` // 产品名
Type string `json:"type"` // 类型cost/pricing Type string `json:"type"` // 类型cost/pricing
Status int64 `json:"status"` // 状态 Status int64 `json:"status"` // 状态
@@ -1255,6 +1257,8 @@ type AgentRewardListItem struct {
RelationAgentId int64 `json:"relation_agent_id"` // 关联代理ID RelationAgentId int64 `json:"relation_agent_id"` // 关联代理ID
Amount float64 `json:"amount"` // 金额 Amount float64 `json:"amount"` // 金额
Type string `json:"type"` // 奖励类型 Type string `json:"type"` // 奖励类型
Status int64 `json:"status"` // 状态0=正常, 1=已取消
Remark string `json:"remark"` // 备注
CreateTime string `json:"create_time"` // 创建时间 CreateTime string `json:"create_time"` // 创建时间
} }

View File

@@ -1,16 +1,16 @@
package main package main
import ( import (
"context"
"flag"
"fmt"
"os"
"bdrp-server/app/main/api/internal/config" "bdrp-server/app/main/api/internal/config"
"bdrp-server/app/main/api/internal/handler" "bdrp-server/app/main/api/internal/handler"
"bdrp-server/app/main/api/internal/middleware" "bdrp-server/app/main/api/internal/middleware"
"bdrp-server/app/main/api/internal/queue" "bdrp-server/app/main/api/internal/queue"
"bdrp-server/app/main/api/internal/service" "bdrp-server/app/main/api/internal/service"
"bdrp-server/app/main/api/internal/svc" "bdrp-server/app/main/api/internal/svc"
"context"
"flag"
"fmt"
"os"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
@@ -58,6 +58,7 @@ func main() {
server := rest.MustNewServer(c.RestConf) server := rest.MustNewServer(c.RestConf)
server.Use(middleware.GlobalSourceInterceptor) server.Use(middleware.GlobalSourceInterceptor)
server.Use(middleware.NewMembershipExpiredInterceptor(svcContext.AgentModel).Handle)
defer server.Stop() defer server.Stop()
handler.RegisterHandlers(server, svcContext) handler.RegisterHandlers(server, svcContext)

View File

@@ -11,7 +11,6 @@ import (
"time" "time"
"bdrp-server/common/globalkey" "bdrp-server/common/globalkey"
"github.com/Masterminds/squirrel" "github.com/Masterminds/squirrel"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder" "github.com/zeromicro/go-zero/core/stores/builder"
@@ -59,8 +58,9 @@ type (
AgentId int64 `db:"agent_id"` AgentId int64 `db:"agent_id"`
DeductedAgentId int64 `db:"deducted_agent_id"` // 被抽佣代理ID DeductedAgentId int64 `db:"deducted_agent_id"` // 被抽佣代理ID
Amount float64 `db:"amount"` Amount float64 `db:"amount"`
ProductId int64 `db:"product_id"` // 产品ID RefundedAmount float64 `db:"refunded_amount"` // 已退款金额
OrderId sql.NullInt64 `db:"order_id"` // 关联订单ID ProductId int64 `db:"product_id"` // 产品ID
OrderId sql.NullInt64 `db:"order_id"` // 关联订单ID
Type string `db:"type"` Type string `db:"type"`
Status int64 `db:"status"` // 状态 Status int64 `db:"status"` // 状态
CreateTime time.Time `db:"create_time"` CreateTime time.Time `db:"create_time"`
@@ -82,11 +82,11 @@ func (m *defaultAgentCommissionDeductionModel) Insert(ctx context.Context, sessi
data.DelState = globalkey.DelStateNo data.DelState = globalkey.DelStateNo
bdrpAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentCommissionDeductionIdPrefix, data.Id) bdrpAgentCommissionDeductionIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentCommissionDeductionIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentCommissionDeductionRowsExpectAutoSet) query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentCommissionDeductionRowsExpectAutoSet)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version) return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.RefundedAmount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
} }
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version) return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.RefundedAmount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version)
}, bdrpAgentCommissionDeductionIdKey) }, bdrpAgentCommissionDeductionIdKey)
} }
@@ -112,9 +112,9 @@ func (m *defaultAgentCommissionDeductionModel) Update(ctx context.Context, sessi
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentCommissionDeductionRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentCommissionDeductionRowsWithPlaceHolder)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id) return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.RefundedAmount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
} }
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id) return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.RefundedAmount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id)
}, bdrpAgentCommissionDeductionIdKey) }, bdrpAgentCommissionDeductionIdKey)
} }
@@ -130,9 +130,9 @@ func (m *defaultAgentCommissionDeductionModel) UpdateWithVersion(ctx context.Con
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentCommissionDeductionRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentCommissionDeductionRowsWithPlaceHolder)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion) return session.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.RefundedAmount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
} }
return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion) return conn.ExecCtx(ctx, query, data.AgentId, data.DeductedAgentId, data.Amount, data.RefundedAmount, data.ProductId, data.OrderId, data.Type, data.Status, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
}, bdrpAgentCommissionDeductionIdKey) }, bdrpAgentCommissionDeductionIdKey)
if err != nil { if err != nil {
return err return err

View File

@@ -0,0 +1,57 @@
package model
import (
"context"
"strconv"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ AgentConfigModel = (*customAgentConfigModel)(nil)
type (
// AgentConfigModel is an interface to be customized, add more methods here,
// and implement the added methods in customAgentConfigModel.
AgentConfigModel interface {
agentConfigModel
IsCommissionSafeMode(ctx context.Context) bool
SetCommissionSafeMode(ctx context.Context, enabled bool) error
}
customAgentConfigModel struct {
*defaultAgentConfigModel
}
)
// 配置键常量
const (
AgentConfigKeyCommissionSafeMode = "commission_safe_mode"
)
// NewAgentConfigModel returns a model for the database table.
func NewAgentConfigModel(conn sqlx.SqlConn, c cache.CacheConf) AgentConfigModel {
return &customAgentConfigModel{
defaultAgentConfigModel: newAgentConfigModel(conn, c),
}
}
// IsCommissionSafeMode 从数据库查询佣金安全防御模式是否开启
func (m *customAgentConfigModel) IsCommissionSafeMode(ctx context.Context) bool {
config, err := m.FindOneByConfigKey(ctx, AgentConfigKeyCommissionSafeMode)
if err != nil {
return false
}
enabled, _ := strconv.ParseBool(config.ConfigValue)
return enabled
}
// SetCommissionSafeMode 更新佣金安全防御模式开关
func (m *customAgentConfigModel) SetCommissionSafeMode(ctx context.Context, enabled bool) error {
config, err := m.FindOneByConfigKey(ctx, AgentConfigKeyCommissionSafeMode)
if err != nil {
return err
}
config.ConfigValue = strconv.FormatBool(enabled)
return m.UpdateWithVersion(ctx, nil, config)
}

View File

@@ -0,0 +1,408 @@
// Code generated by goctl. DO NOT EDIT!
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"bdrp-server/common/globalkey"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
agentConfigFieldNames = builder.RawFieldNames(&AgentConfig{})
agentConfigRows = strings.Join(agentConfigFieldNames, ",")
agentConfigRowsExpectAutoSet = strings.Join(stringx.Remove(agentConfigFieldNames, "`create_time`", "`update_time`"), ",")
agentConfigRowsWithPlaceHolder = strings.Join(stringx.Remove(agentConfigFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
cacheBdrpAgentConfigIdPrefix = "cache:bdrp:agentConfig:id:"
cacheBdrpAgentConfigConfigKeyPrefix = "cache:bdrp:agentConfig:configKey:"
)
type (
agentConfigModel interface {
Insert(ctx context.Context, session sqlx.Session, data *AgentConfig) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*AgentConfig, error)
FindOneByConfigKey(ctx context.Context, configKey string) (*AgentConfig, error)
Update(ctx context.Context, session sqlx.Session, data *AgentConfig) (sql.Result, error)
UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentConfig) error
Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error
SelectBuilder() squirrel.SelectBuilder
DeleteSoft(ctx context.Context, session sqlx.Session, data *AgentConfig) error
FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error)
FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error)
FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*AgentConfig, error)
FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentConfig, error)
FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentConfig, int64, error)
FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*AgentConfig, error)
FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*AgentConfig, error)
Delete(ctx context.Context, session sqlx.Session, id int64) error
}
defaultAgentConfigModel struct {
sqlc.CachedConn
table string
}
AgentConfig struct {
Id int64 `db:"id"` // 主键ID
ConfigKey string `db:"config_key"` // 配置键名
ConfigValue string `db:"config_value"` // 配置值
Remark string `db:"remark"` // 备注说明
CreateTime time.Time `db:"create_time"` // 创建时间
UpdateTime time.Time `db:"update_time"` // 更新时间
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
DelState int64 `db:"del_state"` // 删除状态
Version int64 `db:"version"` // 版本号
}
)
func newAgentConfigModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultAgentConfigModel {
return &defaultAgentConfigModel{
CachedConn: sqlc.NewConn(conn, c),
table: "`agent_config`",
}
}
func (m *defaultAgentConfigModel) Insert(ctx context.Context, session sqlx.Session, data *AgentConfig) (sql.Result, error) {
data.DelState = globalkey.DelStateNo
bdrpAgentConfigConfigKeyKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigConfigKeyPrefix, data.ConfigKey)
bdrpAgentConfigIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, agentConfigRowsExpectAutoSet)
if session != nil {
return session.ExecCtx(ctx, query, data.Id, data.ConfigKey, data.ConfigValue, data.Remark, data.DeleteTime, data.DelState, data.Version)
}
return conn.ExecCtx(ctx, query, data.Id, data.ConfigKey, data.ConfigValue, data.Remark, data.DeleteTime, data.DelState, data.Version)
}, bdrpAgentConfigConfigKeyKey, bdrpAgentConfigIdKey)
}
func (m *defaultAgentConfigModel) FindOne(ctx context.Context, id int64) (*AgentConfig, error) {
bdrpAgentConfigIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigIdPrefix, id)
var resp AgentConfig
err := m.QueryRowCtx(ctx, &resp, bdrpAgentConfigIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentConfigRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultAgentConfigModel) FindOneByConfigKey(ctx context.Context, configKey string) (*AgentConfig, error) {
bdrpAgentConfigConfigKeyKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigConfigKeyPrefix, configKey)
var resp AgentConfig
err := m.QueryRowIndexCtx(ctx, &resp, bdrpAgentConfigConfigKeyKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where `config_key` = ? and del_state = ? limit 1", agentConfigRows, m.table)
if err := conn.QueryRowCtx(ctx, &resp, query, configKey, globalkey.DelStateNo); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultAgentConfigModel) Update(ctx context.Context, session sqlx.Session, newData *AgentConfig) (sql.Result, error) {
data, err := m.FindOne(ctx, newData.Id)
if err != nil {
return nil, err
}
bdrpAgentConfigConfigKeyKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigConfigKeyPrefix, data.ConfigKey)
bdrpAgentConfigIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentConfigRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.ConfigKey, newData.ConfigValue, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}
return conn.ExecCtx(ctx, query, newData.ConfigKey, newData.ConfigValue, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}, bdrpAgentConfigConfigKeyKey, bdrpAgentConfigIdKey)
}
func (m *defaultAgentConfigModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *AgentConfig) error {
oldVersion := newData.Version
newData.Version += 1
var sqlResult sql.Result
var err error
data, err := m.FindOne(ctx, newData.Id)
if err != nil {
return err
}
bdrpAgentConfigConfigKeyKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigConfigKeyPrefix, data.ConfigKey)
bdrpAgentConfigIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigIdPrefix, data.Id)
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentConfigRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.ConfigKey, newData.ConfigValue, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}
return conn.ExecCtx(ctx, query, newData.ConfigKey, newData.ConfigValue, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}, bdrpAgentConfigConfigKeyKey, bdrpAgentConfigIdKey)
if err != nil {
return err
}
updateCount, err := sqlResult.RowsAffected()
if err != nil {
return err
}
if updateCount == 0 {
return ErrNoRowsUpdate
}
return nil
}
func (m *defaultAgentConfigModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *AgentConfig) error {
data.DelState = globalkey.DelStateYes
data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := m.UpdateWithVersion(ctx, session, data); err != nil {
return errors.Wrapf(errors.New("delete soft failed "), "AgentConfigModel delete err : %+v", err)
}
return nil
}
func (m *defaultAgentConfigModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) {
if len(field) == 0 {
return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field")
}
builder = builder.Columns("IFNULL(SUM(" + field + "),0)")
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return 0, err
}
var resp float64
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return 0, err
}
}
func (m *defaultAgentConfigModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) {
if len(field) == 0 {
return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field")
}
builder = builder.Columns("COUNT(" + field + ")")
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return 0, err
}
var resp int64
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return 0, err
}
}
func (m *defaultAgentConfigModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*AgentConfig, error) {
builder = builder.Columns(agentConfigRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentConfig
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentConfigModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentConfig, error) {
builder = builder.Columns(agentConfigRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentConfig
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentConfigModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentConfig, int64, error) {
total, err := m.FindCount(ctx, builder, "id")
if err != nil {
return nil, 0, err
}
builder = builder.Columns(agentConfigRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, total, err
}
var resp []*AgentConfig
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, total, nil
default:
return nil, total, err
}
}
func (m *defaultAgentConfigModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*AgentConfig, error) {
builder = builder.Columns(agentConfigRows)
if preMinId > 0 {
builder = builder.Where(" id < ? ", preMinId)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentConfig
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentConfigModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*AgentConfig, error) {
builder = builder.Columns(agentConfigRows)
if preMaxId > 0 {
builder = builder.Where(" id > ? ", preMaxId)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentConfig
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentConfigModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {
return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
return fn(ctx, session)
})
}
func (m *defaultAgentConfigModel) SelectBuilder() squirrel.SelectBuilder {
return squirrel.Select().From(m.table)
}
func (m *defaultAgentConfigModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
data, err := m.FindOne(ctx, id)
if err != nil {
return err
}
bdrpAgentConfigConfigKeyKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigConfigKeyPrefix, data.ConfigKey)
bdrpAgentConfigIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentConfigIdPrefix, id)
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
if session != nil {
return session.ExecCtx(ctx, query, id)
}
return conn.ExecCtx(ctx, query, id)
}, bdrpAgentConfigConfigKeyKey, bdrpAgentConfigIdKey)
return err
}
func (m *defaultAgentConfigModel) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", cacheBdrpAgentConfigIdPrefix, primary)
}
func (m *defaultAgentConfigModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentConfigRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo)
}
func (m *defaultAgentConfigModel) tableName() string {
return m.table
}

View File

@@ -11,7 +11,6 @@ import (
"time" "time"
"bdrp-server/common/globalkey" "bdrp-server/common/globalkey"
"github.com/Masterminds/squirrel" "github.com/Masterminds/squirrel"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder" "github.com/zeromicro/go-zero/core/stores/builder"
@@ -27,7 +26,7 @@ var (
agentRewardsRowsExpectAutoSet = strings.Join(stringx.Remove(agentRewardsFieldNames, "`id`", "`create_time`", "`update_time`"), ",") agentRewardsRowsExpectAutoSet = strings.Join(stringx.Remove(agentRewardsFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
agentRewardsRowsWithPlaceHolder = strings.Join(stringx.Remove(agentRewardsFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" agentRewardsRowsWithPlaceHolder = strings.Join(stringx.Remove(agentRewardsFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
cacheHmAgentRewardsIdPrefix = "cache:bdrp:agentRewards:id:" cacheBdrpAgentRewardsIdPrefix = "cache:bdrp:agentRewards:id:"
) )
type ( type (
@@ -60,6 +59,8 @@ type (
RelationAgentId sql.NullInt64 `db:"relation_agent_id"` // 关联代理ID RelationAgentId sql.NullInt64 `db:"relation_agent_id"` // 关联代理ID
Amount float64 `db:"amount"` Amount float64 `db:"amount"`
Type string `db:"type"` Type string `db:"type"`
Status int64 `db:"status"` // 状态0=正常, 1=已取消
Remark string `db:"remark"` // 备注
CreateTime time.Time `db:"create_time"` CreateTime time.Time `db:"create_time"`
UpdateTime time.Time `db:"update_time"` // 更新时间 UpdateTime time.Time `db:"update_time"` // 更新时间
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
@@ -77,20 +78,20 @@ func newAgentRewardsModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultAgentRew
func (m *defaultAgentRewardsModel) Insert(ctx context.Context, session sqlx.Session, data *AgentRewards) (sql.Result, error) { func (m *defaultAgentRewardsModel) Insert(ctx context.Context, session sqlx.Session, data *AgentRewards) (sql.Result, error) {
data.DelState = globalkey.DelStateNo data.DelState = globalkey.DelStateNo
hmAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheHmAgentRewardsIdPrefix, data.Id) bdrpAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentRewardsIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, agentRewardsRowsExpectAutoSet) query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentRewardsRowsExpectAutoSet)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.DeleteTime, data.DelState, data.Version) return session.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.Status, data.Remark, data.DeleteTime, data.DelState, data.Version)
} }
return conn.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.DeleteTime, data.DelState, data.Version) return conn.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.Status, data.Remark, data.DeleteTime, data.DelState, data.Version)
}, hmAgentRewardsIdKey) }, bdrpAgentRewardsIdKey)
} }
func (m *defaultAgentRewardsModel) FindOne(ctx context.Context, id int64) (*AgentRewards, error) { func (m *defaultAgentRewardsModel) FindOne(ctx context.Context, id int64) (*AgentRewards, error) {
hmAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheHmAgentRewardsIdPrefix, id) bdrpAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentRewardsIdPrefix, id)
var resp AgentRewards var resp AgentRewards
err := m.QueryRowCtx(ctx, &resp, hmAgentRewardsIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { err := m.QueryRowCtx(ctx, &resp, bdrpAgentRewardsIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentRewardsRows, m.table) query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentRewardsRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
}) })
@@ -105,14 +106,14 @@ func (m *defaultAgentRewardsModel) FindOne(ctx context.Context, id int64) (*Agen
} }
func (m *defaultAgentRewardsModel) Update(ctx context.Context, session sqlx.Session, data *AgentRewards) (sql.Result, error) { func (m *defaultAgentRewardsModel) Update(ctx context.Context, session sqlx.Session, data *AgentRewards) (sql.Result, error) {
hmAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheHmAgentRewardsIdPrefix, data.Id) bdrpAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentRewardsIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentRewardsRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentRewardsRowsWithPlaceHolder)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.DeleteTime, data.DelState, data.Version, data.Id) return session.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.Status, data.Remark, data.DeleteTime, data.DelState, data.Version, data.Id)
} }
return conn.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.DeleteTime, data.DelState, data.Version, data.Id) return conn.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.Status, data.Remark, data.DeleteTime, data.DelState, data.Version, data.Id)
}, hmAgentRewardsIdKey) }, bdrpAgentRewardsIdKey)
} }
func (m *defaultAgentRewardsModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentRewards) error { func (m *defaultAgentRewardsModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentRewards) error {
@@ -123,14 +124,14 @@ func (m *defaultAgentRewardsModel) UpdateWithVersion(ctx context.Context, sessio
var sqlResult sql.Result var sqlResult sql.Result
var err error var err error
hmAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheHmAgentRewardsIdPrefix, data.Id) bdrpAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentRewardsIdPrefix, data.Id)
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentRewardsRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentRewardsRowsWithPlaceHolder)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion) return session.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.Status, data.Remark, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
} }
return conn.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion) return conn.ExecCtx(ctx, query, data.AgentId, data.RelationAgentId, data.Amount, data.Type, data.Status, data.Remark, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
}, hmAgentRewardsIdKey) }, bdrpAgentRewardsIdKey)
if err != nil { if err != nil {
return err return err
} }
@@ -348,18 +349,18 @@ func (m *defaultAgentRewardsModel) SelectBuilder() squirrel.SelectBuilder {
return squirrel.Select().From(m.table) return squirrel.Select().From(m.table)
} }
func (m *defaultAgentRewardsModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { func (m *defaultAgentRewardsModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
hmAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheHmAgentRewardsIdPrefix, id) bdrpAgentRewardsIdKey := fmt.Sprintf("%s%v", cacheBdrpAgentRewardsIdPrefix, id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { _, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table) query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, id) return session.ExecCtx(ctx, query, id)
} }
return conn.ExecCtx(ctx, query, id) return conn.ExecCtx(ctx, query, id)
}, hmAgentRewardsIdKey) }, bdrpAgentRewardsIdKey)
return err return err
} }
func (m *defaultAgentRewardsModel) formatPrimary(primary interface{}) string { func (m *defaultAgentRewardsModel) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", cacheHmAgentRewardsIdPrefix, primary) return fmt.Sprintf("%s%v", cacheBdrpAgentRewardsIdPrefix, primary)
} }
func (m *defaultAgentRewardsModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { func (m *defaultAgentRewardsModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentRewardsRows, m.table) query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentRewardsRows, m.table)

View File

@@ -13,7 +13,7 @@ $tables = @(
# "agent_closure", # "agent_closure",
# "agent_commission" # "agent_commission"
# "agent_wallet_transaction" # "agent_wallet_transaction"
# "agent_commission_deduction" # "agent_commission_deduction",
# "agent_link", # "agent_link",
# "agent_membership_config", # "agent_membership_config",
# "agent_membership_recharge_order" # "agent_membership_recharge_order"
@@ -21,7 +21,7 @@ $tables = @(
# "agent_order", # "agent_order",
# "agent_platform_deduction" # "agent_platform_deduction"
# "agent_product_config", # "agent_product_config",
# "agent_rewards", # "agent_rewards"
# "agent_wallet", # "agent_wallet",
# "agent_real_name" # "agent_real_name"
# "agent_withdrawal" # "agent_withdrawal"
@@ -38,7 +38,7 @@ $tables = @(
# "query_cleanup_log" # "query_cleanup_log"
# "query_cleanup_detail" # "query_cleanup_detail"
# "query_cleanup_config" # "query_cleanup_config"
"user" # "user"
# "user_auth" # "user_auth"
# "user_temp" # "user_temp"
# "example" # "example"
@@ -55,6 +55,7 @@ $tables = @(
# "admin_promotion_link_stats_total" # "admin_promotion_link_stats_total"
# "admin_promotion_link_stats_history" # "admin_promotion_link_stats_history"
# "admin_promotion_order" # "admin_promotion_order"
"agent_config"
) )