package service import ( "context" "database/sql" "fmt" "tydata-server/app/main/api/internal/config" "tydata-server/app/main/model" "tydata-server/common/globalkey" "tydata-server/pkg/lzkit/lzUtils" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/sqlx" ) type AgentService struct { config config.Config OrderModel model.OrderModel AgentModel model.AgentModel AgentAuditModel model.AgentAuditModel AgentClosureModel model.AgentClosureModel AgentCommissionModel model.AgentCommissionModel AgentCommissionDeductionModel model.AgentCommissionDeductionModel AgentWalletModel model.AgentWalletModel AgentLinkModel model.AgentLinkModel AgentOrderModel model.AgentOrderModel AgentRewardsModel model.AgentRewardsModel AgentMembershipConfigModel model.AgentMembershipConfigModel AgentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel AgentMembershipUserConfigModel model.AgentMembershipUserConfigModel AgentProductConfigModel model.AgentProductConfigModel AgentPlatformDeductionModel model.AgentPlatformDeductionModel AgentActiveStatModel model.AgentActiveStatModel AgentWithdrawalModel model.AgentWithdrawalModel AgentWalletTransactionModel model.AgentWalletTransactionModel AsynqService *AsynqService } func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel model.AgentModel, agentAuditModel model.AgentAuditModel, agentClosureModel model.AgentClosureModel, agentCommissionModel model.AgentCommissionModel, agentCommissionDeductionModel model.AgentCommissionDeductionModel, agentWalletModel model.AgentWalletModel, agentLinkModel model.AgentLinkModel, agentOrderModel model.AgentOrderModel, agentRewardsModel model.AgentRewardsModel, agentMembershipConfigModel model.AgentMembershipConfigModel, agentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel, agentMembershipUserConfigModel model.AgentMembershipUserConfigModel, agentProductConfigModel model.AgentProductConfigModel, agentPlatformDeductionModel model.AgentPlatformDeductionModel, agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel, agentWalletTransactionModel model.AgentWalletTransactionModel, asynqService *AsynqService) *AgentService { return &AgentService{ config: c, OrderModel: orderModel, AgentModel: agentModel, AgentAuditModel: agentAuditModel, AgentClosureModel: agentClosureModel, AgentCommissionModel: agentCommissionModel, AgentCommissionDeductionModel: agentCommissionDeductionModel, AgentWalletModel: agentWalletModel, AgentLinkModel: agentLinkModel, AgentOrderModel: agentOrderModel, AgentRewardsModel: agentRewardsModel, AgentMembershipConfigModel: agentMembershipConfigModel, AgentMembershipRechargeOrderModel: agentMembershipRechargeOrderModel, AgentMembershipUserConfigModel: agentMembershipUserConfigModel, AgentProductConfigModel: agentProductConfigModel, AgentPlatformDeductionModel: agentPlatformDeductionModel, AgentActiveStatModel: agentActiveStatModel, AgentWithdrawalModel: agentWithdrawalModel, AgentWalletTransactionModel: agentWalletTransactionModel, AsynqService: asynqService, } } // AgentProcess 推广单成功 func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) error { // 获取是否该订单是代理推广订单 agentOrderModel, err := l.AgentOrderModel.FindOneByOrderId(ctx, order.Id) if err != nil && !errors.Is(err, model.ErrNotFound) { return err } if errors.Is(err, model.ErrNotFound) || agentOrderModel == nil { return nil } // 事务 transErr := l.AgentWalletModel.Trans(ctx, func(transCtx context.Context, session sqlx.Session) error { agentID := agentOrderModel.AgentId agentProductConfigModel, findAgentProductConfigModelErr := l.AgentProductConfigModel.FindOneByProductId(transCtx, order.ProductId) if findAgentProductConfigModelErr != nil { return findAgentProductConfigModelErr } // 平台底价成本 PlatformCostAmount, platformCostErr := l.PlatformCost(transCtx, agentID, order.Id, agentProductConfigModel, session) if platformCostErr != nil { return platformCostErr } // 平台提价成本 PlatformPricingAmount, platformPricingErr := l.PlatformPricing(transCtx, agentID, order.Id, order.Amount, agentProductConfigModel, session) if platformPricingErr != nil { return platformPricingErr } // 查找上级 AgentClosureModel, findAgentClosureModelErr := l.AgentClosureModel.FindOneByDescendantIdDepth(transCtx, agentID, 1) if findAgentClosureModelErr != nil && !errors.Is(findAgentClosureModelErr, model.ErrNotFound) { return findAgentClosureModelErr } var descendantDeductedAmount = 0.00 if AgentClosureModel != nil { AncestorId := AgentClosureModel.AncestorId AncestorModel, findAgentModelErr := l.AgentModel.FindOne(transCtx, AncestorId) if findAgentModelErr != nil && !errors.Is(findAgentModelErr, model.ErrNotFound) { return findAgentModelErr } if AncestorModel != nil { if AncestorModel.LevelName == "" { AncestorModel.LevelName = model.AgentLeveNameNormal } AgentMembershipConfigModel, findAgentMembersipConfigModelErr := l.AgentMembershipConfigModel.FindOneByLevelName(ctx, AncestorModel.LevelName) if findAgentMembersipConfigModelErr != nil { return findAgentMembersipConfigModelErr } // 定价 commissionCost, commissionCostErr := l.CommissionCost(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, order.Id, session) if commissionCostErr != nil { return commissionCostErr } // 提价 commissionPricing, commissionPricingErr := l.CommissionPricing(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, order.Amount, order.Id, session) if commissionPricingErr != nil { return commissionPricingErr } // 上级克扣的成本 descendantDeductedAmount = commissionCost + commissionPricing // 奖励 ancestorCommissionReward, ancestorCommissionErr := l.AncestorCommission(transCtx, agentID, AncestorId, session) if ancestorCommissionErr != nil { return ancestorCommissionErr } // 给上级成本以及佣金 ancestorCommissionAmount := commissionCost + commissionPricing ancestorWallet, findAgentWalletModelErr := l.AgentWalletModel.FindOneByAgentId(transCtx, AncestorId) if findAgentWalletModelErr != nil { return findAgentWalletModelErr } // 记录变动前的余额 balanceBefore := ancestorWallet.Balance frozenBalanceBefore := ancestorWallet.FrozenBalance // 奖励不冻结,直接进入balance ancestorWallet.Balance += ancestorCommissionReward // 根据安全防御模式配置决定佣金处理方式 var commissionStatus int64 if l.config.SystemConfig.CommissionSafeMode { // 安全防御模式:佣金冻结在frozen_balance中 ancestorWallet.FrozenBalance += ancestorCommissionAmount commissionStatus = 1 // 冻结状态 } else { // 非安全防御模式:佣金直接进入balance ancestorWallet.Balance += ancestorCommissionAmount commissionStatus = 0 // 已结算状态 } // 为上级创建佣金记录 ancestorCommissionRecord := model.AgentCommission{ AgentId: AncestorId, OrderId: order.Id, Amount: ancestorCommissionAmount, ProductId: order.ProductId, Status: commissionStatus, } insertResult, insertAncestorCommissionErr := l.AgentCommissionModel.Insert(transCtx, session, &ancestorCommissionRecord) if insertAncestorCommissionErr != nil { return insertAncestorCommissionErr } ancestorWallet.TotalEarnings += ancestorCommissionAmount + ancestorCommissionReward updateErr := l.AgentWalletModel.UpdateWithVersion(transCtx, session, ancestorWallet) if updateErr != nil { return updateErr } // 获取新插入的佣金记录ID commissionID, err := insertResult.LastInsertId() if err != nil { return err } commissionIDStr := fmt.Sprintf("%d", commissionID) // 转换为字符串 // 记录交易流水(佣金收入) transErr := l.CreateWalletTransaction( transCtx, session, AncestorId, model.WalletTransactionTypeCommission, ancestorCommissionAmount, // 变动金额(正数表示增加) balanceBefore, // 变动前余额 ancestorWallet.Balance, // 变动后余额 frozenBalanceBefore, // 变动前冻结余额 ancestorWallet.FrozenBalance, // 变动后冻结余额 order.OrderNo, // 关联交易ID(订单号) commissionID, // 关联佣金记录ID fmt.Sprintf("订单佣金收入,佣金记录ID: %s", commissionIDStr), // 备注(包含佣金记录ID) ) if transErr != nil { return transErr } } } // 推广人扣除金额 = 平台成本价 + 平台提价成本 + 上级佣金 deductedAmount := PlatformCostAmount + PlatformPricingAmount + descendantDeductedAmount agentCommissionErr := l.AgentCommission(transCtx, agentID, order, deductedAmount, session) if agentCommissionErr != nil { return agentCommissionErr } return nil }) if transErr != nil { return transErr } // 在事务提交后,仅在安全防御模式下触发解冻任务 // 注意:这里发送的是任务,实际解冻将在指定时间后由队列处理 if l.AsynqService != nil && l.config.SystemConfig.CommissionSafeMode { // 仅在安全防御模式下,才需要发送解冻任务 // 获取刚创建的佣金记录ID // 由于我们需要佣金记录ID来触发解冻任务,但事务中无法获取,我们可以在事务后查询 builder := l.AgentCommissionModel.SelectBuilder(). Where("order_id = ?", order.Id). Where("status = ?", 1). // 只查询状态为冻结的佣金 Where("del_state = ?", globalkey.DelStateNo) commissions, findErr := l.AgentCommissionModel.FindAll(ctx, builder, "") if findErr != nil { logx.Errorf("查询刚创建的佣金记录失败,订单ID: %d, 错误: %v", order.Id, findErr) return findErr } if len(commissions) > 0 { // 为所有新创建的冻结佣金记录触发解冻任务 for _, commission := range commissions { // 发送解冻任务,将在10小时后执行 sendTaskErr := l.AsynqService.SendUnfreezeCommissionTask(commission.Id) if sendTaskErr != nil { logx.Errorf("发送佣金解冻任务失败,佣金ID: %d, 错误: %v", commission.Id, sendTaskErr) // 不返回错误,因为佣金记录已创建成功,只是解冻任务失败 } else { logx.Infof("已发送佣金解冻任务,佣金ID: %d, 代理ID: %d, 金额: %.2f", commission.Id, commission.AgentId, commission.Amount) } } } } return nil } // AgentCommission 直推报告推广人佣金 func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order *model.Order, deductedAmount float64, session sqlx.Session) error { agentWalletModel, findAgentWalletModelErr := l.AgentWalletModel.FindOneByAgentId(ctx, agentID) if findAgentWalletModelErr != nil { return findAgentWalletModelErr } // 推广人最终获得代理佣金 finalCommission := order.Amount - deductedAmount // 记录变动前的余额 balanceBefore := agentWalletModel.Balance frozenBalanceBefore := agentWalletModel.FrozenBalance // 根据安全防御模式配置决定佣金状态和钱包操作 if l.config.SystemConfig.CommissionSafeMode { // 安全防御模式:佣金冻结在frozen_balance中 agentWalletModel.FrozenBalance += finalCommission } else { // 非安全防御模式:佣金直接进入balance agentWalletModel.Balance += finalCommission } agentWalletModel.TotalEarnings += finalCommission // 根据安全防御模式配置决定佣金状态 commissionStatus := int64(1) // 默认为冻结状态 if !l.config.SystemConfig.CommissionSafeMode { commissionStatus = 0 // 非安全模式直接设置为已结算 } agentCommission := model.AgentCommission{ AgentId: agentID, OrderId: order.Id, Amount: finalCommission, ProductId: order.ProductId, Status: commissionStatus, } insertResult, insertAgentCommissionErr := l.AgentCommissionModel.Insert(ctx, session, &agentCommission) if insertAgentCommissionErr != nil { return insertAgentCommissionErr } // 获取新插入的佣金记录ID(用于日志记录) commissionID, err := insertResult.LastInsertId() if err != nil { return err } _ = commissionID // 暂时忽略该变量,因为我们使用其他方式获取佣金记录 // 更新钱包 updateAgentWalletErr := l.AgentWalletModel.UpdateWithVersion(ctx, session, agentWalletModel) if updateAgentWalletErr != nil { return updateAgentWalletErr } // 记录交易流水(佣金收入) transErr := l.CreateWalletTransaction( ctx, session, agentID, model.WalletTransactionTypeCommission, finalCommission, // 变动金额(正数表示增加) balanceBefore, // 变动前余额 agentWalletModel.Balance, // 变动后余额 frozenBalanceBefore, // 变动前冻结余额 agentWalletModel.FrozenBalance, // 变动后冻结余额 order.OrderNo, // 关联交易ID(订单号) 0, // 关联用户ID "订单佣金收入", // 备注 ) if transErr != nil { return transErr } return nil } // AncestorCommission 直推报告上级佣金(奖励型) func (l *AgentService) AncestorCommission(ctx context.Context, descendantId int64, ancestorId int64, session sqlx.Session) (float64, error) { agentModel, err := l.AgentModel.FindOne(ctx, ancestorId) if err != nil { return 0, err } if agentModel.LevelName == "" { agentModel.LevelName = model.AgentLeveNameNormal } agentMembershipConfigModel, err := l.AgentMembershipConfigModel.FindOneByLevelName(ctx, agentModel.LevelName) if err != nil { return 0, err } if agentMembershipConfigModel.ReportCommission.Valid { reportCommissionAmount := agentMembershipConfigModel.ReportCommission.Float64 agentRewards := model.AgentRewards{ AgentId: ancestorId, Amount: reportCommissionAmount, RelationAgentId: lzUtils.Int64ToNullInt64(descendantId), Type: model.AgentRewardsTypeDescendantPromotion, } _, agentRewardsModelInsetErr := l.AgentRewardsModel.Insert(ctx, session, &agentRewards) if agentRewardsModelInsetErr != nil { return 0, agentRewardsModelInsetErr } return reportCommissionAmount, nil } return 0, nil } // PlatformCost 平台底价成本 func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, orderID int64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) { costAgentPlatformDeductionModel := model.AgentPlatformDeduction{ AgentId: agentID, OrderId: orderID, Amount: agentProductConfigModel.CostPrice, Type: model.AgentDeductionTypeCost, } _, err := l.AgentPlatformDeductionModel.Insert(ctx, session, &costAgentPlatformDeductionModel) if err != nil { return 0, err } return agentProductConfigModel.CostPrice, nil } // PlatformPricing 平台提价成本 func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, orderID int64, pricing float64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) { // 2. 计算平台提价成本 if pricing > agentProductConfigModel.PricingStandard { // 超出部分 overpricing := pricing - agentProductConfigModel.PricingStandard // 收取成本 overpricingCost := overpricing * agentProductConfigModel.OverpricingRatio pricingAgentPlatformDeductionModel := model.AgentPlatformDeduction{ AgentId: agentID, OrderId: orderID, Amount: overpricingCost, Type: model.AgentDeductionTypePricing, } _, err := l.AgentPlatformDeductionModel.Insert(ctx, session, &pricingAgentPlatformDeductionModel) if err != nil { return 0, err } return overpricingCost, nil } return 0, nil } // CommissionCost 上级底价成本 func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, orderId int64, session sqlx.Session) (float64, error) { if agentMembershipConfigModel.PriceIncreaseAmount.Valid { // 拥有则查看该上级设定的成本 agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) if findAgentMembershipUserConfigModelErr != nil { // 如果上级没有配置该产品的定价规则,则跳过成本计算 if errors.Is(findAgentMembershipUserConfigModelErr, model.ErrNotFound) { return 0, nil } return 0, findAgentMembershipUserConfigModelErr } deductCostAmount := agentMembershipUserConfigModel.PriceIncreaseAmount agentCommissionDeductionModel := model.AgentCommissionDeduction{ AgentId: AncestorId, DeductedAgentId: descendantId, Amount: deductCostAmount, Type: model.AgentDeductionTypeCost, ProductId: productID, OrderId: sql.NullInt64{Int64: orderId, Valid: true}, } _, insertAgentCommissionDeductionModelErr := l.AgentCommissionDeductionModel.Insert(ctx, session, &agentCommissionDeductionModel) if insertAgentCommissionDeductionModelErr != nil { return 0, insertAgentCommissionDeductionModelErr } return deductCostAmount, nil } return 0, nil } // 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) { //看上级代理等级否有拥有定价标准收益功能 if agentMembershipConfigModel.PriceIncreaseMax.Valid && agentMembershipConfigModel.PriceRatio.Valid { // 拥有则查看该上级设定的成本 agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) if findAgentMembershipUserConfigModelErr != nil { // 如果上级没有配置该产品的定价规则,则跳过成本计算 if errors.Is(findAgentMembershipUserConfigModelErr, model.ErrNotFound) { return 0, nil } return 0, findAgentMembershipUserConfigModelErr } // 计算是否在范围内 var pricingRange float64 if pricing > agentMembershipUserConfigModel.PriceRangeFrom { if pricing > agentMembershipUserConfigModel.PriceRangeTo { pricingRange = agentMembershipUserConfigModel.PriceRangeTo - agentMembershipUserConfigModel.PriceRangeFrom } else { pricingRange = pricing - agentMembershipUserConfigModel.PriceRangeFrom } } deductCostAmount := pricingRange * agentMembershipUserConfigModel.PriceRatio agentCommissionDeductionModel := model.AgentCommissionDeduction{ AgentId: AncestorId, DeductedAgentId: descendantId, Amount: deductCostAmount, Type: model.AgentDeductionTypePricing, ProductId: productID, OrderId: sql.NullInt64{Int64: orderId, Valid: true}, } _, insertAgentCommissionDeductionModelErr := l.AgentCommissionDeductionModel.Insert(ctx, session, &agentCommissionDeductionModel) if insertAgentCommissionDeductionModelErr != nil { return 0, insertAgentCommissionDeductionModelErr } return deductCostAmount, nil } return 0, nil } // GiveUpgradeReward 给上级代理发放下级升级奖励 func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, oldLevel, newLevel string, session sqlx.Session) error { // 查找上级代理 agentClosureModel, err := l.AgentClosureModel.FindOneByDescendantIdDepth(ctx, agentID, 1) if err != nil { if errors.Is(err, model.ErrNotFound) { // 没有上级代理,直接返回 return nil } return err } ancestorID := agentClosureModel.AncestorId ancestorModel, err := l.AgentModel.FindOne(ctx, ancestorID) if err != nil { if errors.Is(err, model.ErrNotFound) { // 上级代理不存在,直接返回 return nil } return err } if ancestorModel == nil { // 上级代理不存在,直接返回 return nil } // 获取上级代理的等级配置 if ancestorModel.LevelName == "" { ancestorModel.LevelName = model.AgentLeveNameNormal } agentMembershipConfigModel, err := l.AgentMembershipConfigModel.FindOneByLevelName(ctx, ancestorModel.LevelName) if err != nil { return err } // 根据升级路径计算奖励金额差额 var rewardAmount float64 var rewardType string // 获取各等级的奖励金额 var vipRewardAmount float64 var svipRewardAmount float64 if agentMembershipConfigModel.LowerConvertVipReward.Valid { vipRewardAmount = agentMembershipConfigModel.LowerConvertVipReward.Float64 } if agentMembershipConfigModel.LowerConvertSvipReward.Valid { svipRewardAmount = agentMembershipConfigModel.LowerConvertSvipReward.Float64 } // 根据升级路径计算实际奖励金额 switch { case oldLevel == "" || oldLevel == model.AgentLeveNameNormal: // 普通代理升级 switch newLevel { case model.AgentLeveNameVIP: rewardAmount = vipRewardAmount rewardType = model.AgentRewardsTypeDescendantUpgradeVip case model.AgentLeveNameSVIP: rewardAmount = svipRewardAmount rewardType = model.AgentRewardsTypeDescendantUpgradeSvip default: // 无效的升级路径,直接返回 return nil } case oldLevel == model.AgentLeveNameVIP && newLevel == model.AgentLeveNameSVIP: // VIP升级到SVIP,发放差额奖励 rewardAmount = svipRewardAmount - vipRewardAmount rewardType = model.AgentRewardsTypeDescendantUpgradeSvip // 如果差额为负数或零,不发放奖励 if rewardAmount <= 0 { return nil } default: // 其他无效的升级路径(如SVIP降级等),直接返回 return nil } // 如果有奖励金额,则发放奖励 if rewardAmount > 0 { // 创建奖励记录 agentRewards := model.AgentRewards{ AgentId: ancestorID, Amount: rewardAmount, RelationAgentId: lzUtils.Int64ToNullInt64(agentID), Type: rewardType, } insertResult, err := l.AgentRewardsModel.Insert(ctx, session, &agentRewards) if err != nil { return err } // 更新上级代理钱包 ancestorWallet, err := l.AgentWalletModel.FindOneByAgentId(ctx, ancestorID) if err != nil { return err } // 记录变动前的余额 balanceBefore := ancestorWallet.Balance frozenBalanceBefore := ancestorWallet.FrozenBalance ancestorWallet.Balance += rewardAmount ancestorWallet.TotalEarnings += rewardAmount err = l.AgentWalletModel.UpdateWithVersion(ctx, session, ancestorWallet) if err != nil { return err } // 获取新插入的奖励记录ID rewardID, err := insertResult.LastInsertId() if err != nil { return err } rewardIDStr := fmt.Sprintf("%d", rewardID) // 转换为字符串 // 记录交易流水(奖励收入) transErr := l.CreateWalletTransaction( ctx, session, ancestorID, model.WalletTransactionTypeReward, rewardAmount, // 变动金额(正数表示增加) balanceBefore, // 变动前余额 ancestorWallet.Balance, // 变动后余额 frozenBalanceBefore, // 变动前冻结余额 ancestorWallet.FrozenBalance, // 变动后冻结余额 rewardIDStr, // 关联交易ID(奖励记录ID) agentID, // 关联用户ID(下级代理ID) "下级升级奖励", // 备注 ) if transErr != nil { return transErr } } return nil } // GiveWithdrawReward 给上级代理发放下级提现奖励 func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, withdrawAmount float64, session sqlx.Session) error { // 验证提现金额 if withdrawAmount <= 0 { return nil } // 查找上级代理 agentClosureModel, err := l.AgentClosureModel.FindOneByDescendantIdDepth(ctx, agentID, 1) if err != nil { if errors.Is(err, model.ErrNotFound) { // 没有上级代理,直接返回 return nil } return err } ancestorID := agentClosureModel.AncestorId ancestorModel, err := l.AgentModel.FindOne(ctx, ancestorID) if err != nil { if errors.Is(err, model.ErrNotFound) { // 上级代理不存在,直接返回 return nil } return err } if ancestorModel == nil { // 上级代理不存在,直接返回 return nil } // 获取上级代理的等级配置 if ancestorModel.LevelName == "" { ancestorModel.LevelName = model.AgentLeveNameNormal } agentMembershipConfigModel, err := l.AgentMembershipConfigModel.FindOneByLevelName(ctx, ancestorModel.LevelName) if err != nil { return err } // 计算提现奖励金额 if agentMembershipConfigModel.LowerWithdrawRewardRatio.Valid { rewardRatio := agentMembershipConfigModel.LowerWithdrawRewardRatio.Float64 // 验证奖励比例的有效性(0-1之间) if rewardRatio < 0 || rewardRatio > 1 { // 无效的奖励比例,直接返回 return nil } rewardAmount := withdrawAmount * rewardRatio if rewardAmount > 0 { // 创建奖励记录 agentRewards := model.AgentRewards{ AgentId: ancestorID, Amount: rewardAmount, RelationAgentId: lzUtils.Int64ToNullInt64(agentID), Type: model.AgentRewardsTypeDescendantWithdraw, } insertResult, err := l.AgentRewardsModel.Insert(ctx, session, &agentRewards) if err != nil { return err } // 更新上级代理钱包 ancestorWallet, err := l.AgentWalletModel.FindOneByAgentId(ctx, ancestorID) if err != nil { return err } // 记录变动前的余额 balanceBefore := ancestorWallet.Balance frozenBalanceBefore := ancestorWallet.FrozenBalance ancestorWallet.Balance += rewardAmount ancestorWallet.TotalEarnings += rewardAmount err = l.AgentWalletModel.UpdateWithVersion(ctx, session, ancestorWallet) if err != nil { return err } // 获取新插入的奖励记录ID rewardID, err := insertResult.LastInsertId() if err != nil { return err } rewardIDStr := fmt.Sprintf("%d", rewardID) // 转换为字符串 // 记录交易流水(奖励收入) transErr := l.CreateWalletTransaction( ctx, session, ancestorID, model.WalletTransactionTypeReward, rewardAmount, // 变动金额(正数表示增加) balanceBefore, // 变动前余额 ancestorWallet.Balance, // 变动后余额 frozenBalanceBefore, // 变动前冻结余额 ancestorWallet.FrozenBalance, // 变动后冻结余额 rewardIDStr, // 关联交易ID(奖励记录ID) agentID, // 关联用户ID(下级代理ID) "下级提现奖励", // 备注 ) if transErr != nil { return transErr } } } return nil } // CheckAgentProcessStatus 检查代理处理事务是否已成功 func (l *AgentService) CheckAgentProcessStatus(ctx context.Context, orderID int64) (bool, error) { // 检查是否存在代理订单记录 _, err := l.AgentOrderModel.FindOneByOrderId(ctx, orderID) if err != nil { if errors.Is(err, model.ErrNotFound) { // 没有代理订单记录,说明不是代理推广订单 return true, nil } return false, err } // 检查是否存在代理佣金记录 // 使用SelectBuilder查询该订单的佣金记录 selectBuilder := l.AgentCommissionModel.SelectBuilder() selectBuilder = selectBuilder.Where("order_id = ?", orderID) selectBuilder = selectBuilder.Where("del_state = ?", 0) // 未删除 commissions, err := l.AgentCommissionModel.FindAll(ctx, selectBuilder, "") if err != nil { return false, err } // 如果存在佣金记录,说明代理处理已成功 return len(commissions) > 0, nil } // RetryAgentProcess 重新执行代理处理事务 func (l *AgentService) RetryAgentProcess(ctx context.Context, orderID int64) error { // 首先检查订单是否存在 order, err := l.OrderModel.FindOne(ctx, orderID) if err != nil { return err } // 检查订单状态是否为已支付 if order.Status != "paid" { return errors.New("订单状态不是已支付,无法执行代理处理") } // 检查代理处理是否已经成功 alreadyProcessed, err := l.CheckAgentProcessStatus(ctx, orderID) if err != nil { return err } if alreadyProcessed { return errors.New("代理处理已经成功,无需重新执行") } // 执行代理处理 return l.AgentProcess(ctx, order) } // CreateWalletTransaction 创建代理钱包流水记录 // ctx: 上下文 // session: 数据库会话(事务) // agentID: 代理ID // transactionType: 交易类型 (commission/withdraw/freeze/unfreeze/reward/refund/adjust) // amount: 变动金额(正数为增加,负数为减少) // balanceBefore: 变动前余额 // balanceAfter: 变动后余额 // frozenBalanceBefore: 变动前冻结余额 // frozenBalanceAfter: 变动后冻结余额 // transactionID: 关联交易ID(订单号、提现申请号等) // relatedUserID: 关联用户ID(如佣金来源用户) // remark: 备注说明 func (l *AgentService) CreateWalletTransaction(ctx context.Context, session sqlx.Session, agentID int64, transactionType string, amount float64, balanceBefore, balanceAfter, frozenBalanceBefore, frozenBalanceAfter float64, transactionID string, relatedUserID int64, remark string) error { // 处理可空字段 var transactionIDField sql.NullString if transactionID != "" { transactionIDField = sql.NullString{String: transactionID, Valid: true} } var relatedUserIDField sql.NullInt64 if relatedUserID > 0 { relatedUserIDField = sql.NullInt64{Int64: relatedUserID, Valid: true} } var remarkField sql.NullString if remark != "" { remarkField = sql.NullString{String: remark, Valid: true} } transaction := &model.AgentWalletTransaction{ AgentId: agentID, TransactionType: transactionType, Amount: amount, BalanceBefore: balanceBefore, BalanceAfter: balanceAfter, FrozenBalanceBefore: frozenBalanceBefore, FrozenBalanceAfter: frozenBalanceAfter, TransactionId: transactionIDField, RelatedUserId: relatedUserIDField, Remark: remarkField, } _, err := l.AgentWalletTransactionModel.Insert(ctx, session, transaction) if err != nil { return errors.Wrapf(err, "创建代理钱包流水记录失败,agentID: %d, type: %s, amount: %.2f", agentID, transactionType, amount) } return nil }