f add
This commit is contained in:
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"tydata-server/app/main/api/internal/config"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/globalkey"
|
||||
@@ -32,6 +33,7 @@ type AgentService struct {
|
||||
AgentPlatformDeductionModel model.AgentPlatformDeductionModel
|
||||
AgentActiveStatModel model.AgentActiveStatModel
|
||||
AgentWithdrawalModel model.AgentWithdrawalModel
|
||||
AgentWalletTransactionModel model.AgentWalletTransactionModel
|
||||
AsynqService *AsynqService
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@ func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel mo
|
||||
agentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel,
|
||||
agentMembershipUserConfigModel model.AgentMembershipUserConfigModel,
|
||||
agentProductConfigModel model.AgentProductConfigModel, agentPlatformDeductionModel model.AgentPlatformDeductionModel,
|
||||
agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel, asynqService *AsynqService) *AgentService {
|
||||
agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel, agentWalletTransactionModel model.AgentWalletTransactionModel, asynqService *AsynqService) *AgentService {
|
||||
|
||||
return &AgentService{
|
||||
config: c,
|
||||
@@ -63,6 +65,7 @@ func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel mo
|
||||
AgentPlatformDeductionModel: agentPlatformDeductionModel,
|
||||
AgentActiveStatModel: agentActiveStatModel,
|
||||
AgentWithdrawalModel: agentWithdrawalModel,
|
||||
AgentWalletTransactionModel: agentWalletTransactionModel,
|
||||
AsynqService: asynqService,
|
||||
}
|
||||
}
|
||||
@@ -142,6 +145,11 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
|
||||
if findAgentWalletModelErr != nil {
|
||||
return findAgentWalletModelErr
|
||||
}
|
||||
|
||||
// 记录变动前的余额
|
||||
balanceBefore := ancestorWallet.Balance
|
||||
frozenBalanceBefore := ancestorWallet.FrozenBalance
|
||||
|
||||
// 奖励不冻结,直接进入balance
|
||||
ancestorWallet.Balance += ancestorCommissionReward
|
||||
|
||||
@@ -165,7 +173,7 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
|
||||
ProductId: order.ProductId,
|
||||
Status: commissionStatus,
|
||||
}
|
||||
_, insertAncestorCommissionErr := l.AgentCommissionModel.Insert(transCtx, session, &ancestorCommissionRecord)
|
||||
insertResult, insertAncestorCommissionErr := l.AgentCommissionModel.Insert(transCtx, session, &ancestorCommissionRecord)
|
||||
if insertAncestorCommissionErr != nil {
|
||||
return insertAncestorCommissionErr
|
||||
}
|
||||
@@ -175,6 +183,32 @@ func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) err
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +270,10 @@ func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order
|
||||
// 推广人最终获得代理佣金
|
||||
finalCommission := order.Amount - deductedAmount
|
||||
|
||||
// 记录变动前的余额
|
||||
balanceBefore := agentWalletModel.Balance
|
||||
frozenBalanceBefore := agentWalletModel.FrozenBalance
|
||||
|
||||
// 根据安全防御模式配置决定佣金状态和钱包操作
|
||||
if l.config.SystemConfig.CommissionSafeMode {
|
||||
// 安全防御模式:佣金冻结在frozen_balance中
|
||||
@@ -271,10 +309,31 @@ func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order
|
||||
}
|
||||
_ = 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
|
||||
}
|
||||
|
||||
@@ -519,7 +578,7 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
|
||||
Type: rewardType,
|
||||
}
|
||||
|
||||
_, err = l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
insertResult, err := l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -530,12 +589,42 @@ func (l *AgentService) GiveUpgradeReward(ctx context.Context, agentID int64, old
|
||||
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
|
||||
@@ -599,7 +688,7 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
|
||||
Type: model.AgentRewardsTypeDescendantWithdraw,
|
||||
}
|
||||
|
||||
_, err = l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
insertResult, err := l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -610,12 +699,42 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,3 +794,57 @@ func (l *AgentService) RetryAgentProcess(ctx context.Context, orderID int64) err
|
||||
// 执行代理处理
|
||||
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
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ func TestGenerateAuthorizationDocument(t *testing.T) {
|
||||
assert.False(t, authDoc.ExpireTime.Valid) // 永久保留,不设置过期时间
|
||||
|
||||
// 验证文件路径格式(兼容Windows和Unix路径分隔符)
|
||||
assert.True(t, strings.Contains(authDoc.FilePath, "data/authorization_docs") ||
|
||||
assert.True(t, strings.Contains(authDoc.FilePath, "data/authorization_docs") ||
|
||||
strings.Contains(authDoc.FilePath, "data\\authorization_docs"))
|
||||
assert.Contains(t, authDoc.FileName, "auth_")
|
||||
assert.Contains(t, authDoc.FileName, ".pdf")
|
||||
@@ -372,7 +372,7 @@ func TestGeneratePDFContent(t *testing.T) {
|
||||
t.Logf("📁 文件路径: %s", filePath)
|
||||
t.Logf("🔗 相对路径: %s", relativePath)
|
||||
t.Logf("📊 文件大小: %d 字节", len(pdfBytes))
|
||||
|
||||
|
||||
// 获取绝对路径
|
||||
absPath, _ := filepath.Abs(filePath)
|
||||
t.Logf("📍 绝对路径: %s", absPath)
|
||||
@@ -430,16 +430,16 @@ func TestSavePDFToLocal(t *testing.T) {
|
||||
t.Logf("📁 文件路径: %s", filePath)
|
||||
t.Logf("🔗 相对路径: %s", relativePath)
|
||||
t.Logf("📊 文件大小: %d 字节", len(pdfBytes))
|
||||
|
||||
|
||||
// 获取绝对路径
|
||||
absPath, _ := filepath.Abs(filePath)
|
||||
t.Logf("📍 绝对路径: %s", absPath)
|
||||
|
||||
|
||||
// 验证文件内容
|
||||
fileInfo, err := os.Stat(filePath)
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, fileInfo.Size(), int64(1000)) // 文件应该大于1KB
|
||||
|
||||
|
||||
t.Logf("🎉 文件保存验证通过!")
|
||||
} else {
|
||||
t.Errorf("❌ PDF文件保存失败: %v", err)
|
||||
@@ -648,18 +648,18 @@ func TestGeneratePDFFile(t *testing.T) {
|
||||
t.Logf("📁 文件路径: %s", authDoc.FilePath)
|
||||
t.Logf("🔗 相对路径: %s", authDoc.FileUrl)
|
||||
t.Logf("📊 文件大小: %d 字节", authDoc.FileSize)
|
||||
|
||||
|
||||
// 验证文件内容
|
||||
fileInfo, err := os.Stat(authDoc.FilePath)
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, fileInfo.Size(), int64(1000)) // 文件应该大于1KB
|
||||
|
||||
|
||||
// 验证文件名格式
|
||||
assert.Regexp(t, `^auth_999_888_\d{8}_\d{6}\.pdf$`, authDoc.FileName)
|
||||
|
||||
|
||||
// 验证路径格式
|
||||
assert.Regexp(t, `^\d{4}/\d{2}/auth_999_888_\d{8}_\d{6}\.pdf$`, authDoc.FileUrl)
|
||||
|
||||
|
||||
t.Logf("🎉 所有验证通过!")
|
||||
} else {
|
||||
t.Errorf("❌ PDF文件未创建: %s", authDoc.FilePath)
|
||||
|
||||
Reference in New Issue
Block a user