add agent stats

This commit is contained in:
2025-05-10 21:43:10 +08:00
parent c924a8afbb
commit d7f8e9c090
9 changed files with 645 additions and 4 deletions

View File

@@ -0,0 +1,200 @@
package agent
import (
"context"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentSubordinateContributionDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentSubordinateContributionDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentSubordinateContributionDetailLogic {
return &GetAgentSubordinateContributionDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentSubordinateContributionDetailLogic) GetAgentSubordinateContributionDetail(req *types.GetAgentSubordinateContributionDetailReq) (resp *types.GetAgentSubordinateContributionDetailResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 获取用户ID%v", err)
}
// 获取当前代理信息
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取代理信息%v", err)
}
// 获取下级代理信息
subordinateAgent, err := l.svcCtx.AgentModel.FindOne(l.ctx, req.SubordinateID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取下级代理信息%v", err)
}
// 验证是否是当前代理的下级
closureBuilder := l.svcCtx.AgentClosureModel.SelectBuilder().Where(squirrel.Eq{
"ancestor_id": agentModel.Id,
"descendant_id": req.SubordinateID,
})
closureList, err := l.svcCtx.AgentClosureModel.FindAll(l.ctx, closureBuilder, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 验证代理关系%v", err)
}
if len(closureList) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 非法的代理关系")
}
closure := closureList[0]
// 获取佣金扣除记录
deductionBuilder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder().Where(squirrel.Eq{
"agent_id": agentModel.Id,
"deducted_agent_id": req.SubordinateID,
})
deductionList, err := l.svcCtx.AgentCommissionDeductionModel.FindAll(l.ctx, deductionBuilder, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取佣金扣除记录%v", err)
}
// 获取奖励记录
rewardsBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where(squirrel.Eq{
"agent_id": agentModel.Id,
"relation_agent_id": req.SubordinateID,
})
rewards, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, rewardsBuilder, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取奖励记录%v", err)
}
// 计算总贡献
var totalContribution float64
for _, v := range deductionList {
totalContribution += v.Amount
}
// 加上奖励金额
for _, v := range rewards {
totalContribution += v.Amount
}
// 获取佣金记录
commissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{
"agent_id": req.SubordinateID,
})
commissionList, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, commissionBuilder, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取佣金记录%v", err)
}
// 计算总收益和总单量
var totalEarnings float64
for _, v := range commissionList {
totalEarnings += v.Amount
}
// 初始化统计数据
stats := types.AgentSubordinateContributionStats{
CostCount: 0,
CostAmount: 0,
PricingCount: 0,
PricingAmount: 0,
DescendantPromotionCount: 0,
DescendantPromotionAmount: 0,
DescendantUpgradeVipCount: 0,
DescendantUpgradeVipAmount: 0,
DescendantUpgradeSvipCount: 0,
DescendantUpgradeSvipAmount: 0,
DescendantStayActiveCount: 0,
DescendantStayActiveAmount: 0,
DescendantNewActiveCount: 0,
DescendantNewActiveAmount: 0,
DescendantWithdrawCount: 0,
DescendantWithdrawAmount: 0,
}
// 统计佣金扣除记录
for _, v := range deductionList {
switch v.Type {
case "cost":
stats.CostCount++
stats.CostAmount += v.Amount
case "pricing":
stats.PricingCount++
stats.PricingAmount += v.Amount
}
}
// 统计奖励记录
for _, v := range rewards {
switch v.Type {
case "descendant_promotion":
stats.DescendantPromotionCount++
stats.DescendantPromotionAmount += v.Amount
case "descendant_upgrade_vip":
stats.DescendantUpgradeVipCount++
stats.DescendantUpgradeVipAmount += v.Amount
case "descendant_upgrade_svip":
stats.DescendantUpgradeSvipCount++
stats.DescendantUpgradeSvipAmount += v.Amount
case "descendant_stay_active":
stats.DescendantStayActiveCount++
stats.DescendantStayActiveAmount += v.Amount
case "descendant_new_active":
stats.DescendantNewActiveCount++
stats.DescendantNewActiveAmount += v.Amount
case "descendant_withdraw":
stats.DescendantWithdrawCount++
stats.DescendantWithdrawAmount += v.Amount
}
}
// 解密手机号
secretKey := l.svcCtx.Config.Encrypt.SecretKey
mobile, err := crypto.DecryptMobile(subordinateAgent.Mobile, secretKey)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级贡献详情, 解密手机号失败: %v", err)
}
// 获取合并后的分页列表
unionDetails, total, err := l.svcCtx.AgentClosureModel.FindUnionPageListByPageWithTotal(l.ctx, agentModel.Id, req.SubordinateID, req.Page, req.PageSize)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级贡献详情, 获取分页列表%v", err)
}
// 转换为响应类型
detailList := make([]types.AgentSubordinateContributionDetail, 0, len(unionDetails))
for _, v := range unionDetails {
detail := types.AgentSubordinateContributionDetail{
ID: v.Id,
CreateTime: v.CreateTime,
Amount: v.Amount,
Type: v.Type,
}
detailList = append(detailList, detail)
}
return &types.GetAgentSubordinateContributionDetailResp{
Mobile: maskPhone(mobile),
Total: total,
CreateTime: closure.CreateTime.Format("2006-01-02 15:04:05"),
TotalEarnings: totalEarnings,
TotalContribution: totalContribution,
TotalOrders: int64(len(commissionList)),
LevelName: subordinateAgent.LevelName,
List: detailList,
Stats: stats,
}, nil
}

View File

@@ -0,0 +1,173 @@
package agent
import (
"context"
"strings"
"time"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mr"
)
type GetAgentSubordinateListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentSubordinateListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentSubordinateListLogic {
return &GetAgentSubordinateListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentSubordinateListLogic) GetAgentSubordinateList(req *types.GetAgentSubordinateListReq) (resp *types.GetAgentSubordinateListResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理下级列表, 获取用户ID%v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理信息%v", err)
}
agentID := agentModel.Id
builder := l.svcCtx.AgentClosureModel.SelectBuilder().Where(squirrel.Eq{
"ancestor_id": agentID,
})
agentClosureModelList, total, err := l.svcCtx.AgentClosureModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理关系%v", err)
}
// 构建ID到CreateTime的映射
createTimeMap := make(map[int64]time.Time)
descendantIDs := make([]int64, 0)
for _, v := range agentClosureModelList {
descendantIDs = append(descendantIDs, v.DescendantId)
createTimeMap[v.DescendantId] = v.CreateTime
}
// 并发查询代理信息
agentMap := make(map[int64]*model.Agent)
var descendantList []types.AgentSubordinateList
err = mr.Finish(func() error {
return mr.MapReduceVoid(func(source chan<- interface{}) {
for _, id := range descendantIDs {
source <- id
}
}, func(item interface{}, writer mr.Writer[interface{}], cancel func(error)) {
id := item.(int64)
agent, err := l.svcCtx.AgentModel.FindOne(l.ctx, id)
if err != nil {
cancel(err)
return
}
writer.Write(agent)
}, func(pipe <-chan interface{}, cancel func(error)) {
for item := range pipe {
agent := item.(*model.Agent)
agentMap[agent.Id] = agent
}
})
}, func() error {
// 并发查询佣金扣除信息
deductionBuilder := l.svcCtx.AgentCommissionDeductionModel.SelectBuilder().
Where(squirrel.Eq{"agent_id": agentID}).
Where(squirrel.Eq{"deducted_agent_id": descendantIDs})
deductionList, err := l.svcCtx.AgentCommissionDeductionModel.FindAll(l.ctx, deductionBuilder, "")
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理佣金扣除信息%v", err)
}
deductionMap := make(map[int64]float64)
for _, v := range deductionList {
deductionMap[v.DeductedAgentId] += v.Amount
}
// 并发查询奖励信息
rewardsBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().
Where(squirrel.Eq{"agent_id": agentID}).
Where(squirrel.Eq{"relation_agent_id": descendantIDs})
rewardsList, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, rewardsBuilder, "")
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理奖励信息%v", err)
}
rewardsMap := make(map[int64]float64)
for _, v := range rewardsList {
if v.RelationAgentId.Valid {
rewardsMap[v.RelationAgentId.Int64] += v.Amount
}
}
// 并发查询佣金信息
commissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder().
Where(squirrel.Eq{"agent_id": descendantIDs})
commissionList, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, commissionBuilder, "")
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理下级列表, 获取代理佣金信息%v", err)
}
commissionMap := make(map[int64]float64)
orderCountMap := make(map[int64]int64)
for _, v := range commissionList {
commissionMap[v.AgentId] += v.Amount
orderCountMap[v.AgentId]++
}
// 构建返回结果
secretKey := l.svcCtx.Config.Encrypt.SecretKey
descendantList = make([]types.AgentSubordinateList, 0, len(descendantIDs))
for _, id := range descendantIDs {
agent, exists := agentMap[id]
if !exists {
continue
}
mobile, err := crypto.DecryptMobile(agent.Mobile, secretKey)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, 解密手机号失败: %v", err)
}
subordinate := types.AgentSubordinateList{
ID: id,
Mobile: maskPhone(mobile),
LevelName: agent.LevelName,
CreateTime: createTimeMap[id].Format("2006-01-02 15:04:05"),
TotalContribution: deductionMap[id] + rewardsMap[id],
TotalEarnings: commissionMap[id],
TotalOrders: orderCountMap[id],
}
descendantList = append(descendantList, subordinate)
}
return nil
})
if err != nil {
return nil, err
}
return &types.GetAgentSubordinateListResp{
Total: total,
List: descendantList,
}, nil
}
// 手机号脱敏
func maskPhone(phone string) string {
length := len(phone)
if length < 8 {
return phone // 如果长度太短,可能不是手机号,不处理
}
// 保留前3位和后4位
return phone[:3] + strings.Repeat("*", length-7) + phone[length-4:]
}