493 lines
18 KiB
Go
493 lines
18 KiB
Go
|
|
package agent
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"context"
|
|||
|
|
"time"
|
|||
|
|
"ycc-server/app/main/model"
|
|||
|
|
"ycc-server/common/ctxdata"
|
|||
|
|
"ycc-server/common/globalkey"
|
|||
|
|
"ycc-server/common/xerr"
|
|||
|
|
|
|||
|
|
"github.com/Masterminds/squirrel"
|
|||
|
|
"github.com/pkg/errors"
|
|||
|
|
|
|||
|
|
"ycc-server/app/main/api/internal/svc"
|
|||
|
|
"ycc-server/app/main/api/internal/types"
|
|||
|
|
|
|||
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type GetConversionRateLogic struct {
|
|||
|
|
logx.Logger
|
|||
|
|
ctx context.Context
|
|||
|
|
svcCtx *svc.ServiceContext
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewGetConversionRateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetConversionRateLogic {
|
|||
|
|
return &GetConversionRateLogic{
|
|||
|
|
Logger: logx.WithContext(ctx),
|
|||
|
|
ctx: ctx,
|
|||
|
|
svcCtx: svcCtx,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (l *GetConversionRateLogic) GetConversionRate() (resp *types.ConversionRateResp, err error) {
|
|||
|
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 获取代理信息
|
|||
|
|
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
|||
|
|
if err != nil {
|
|||
|
|
if errors.Is(err, model.ErrNotFound) {
|
|||
|
|
return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
|
|||
|
|
}
|
|||
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 统计我的转化率
|
|||
|
|
myConversionRate := l.calculateConversionRate(agent.Id, nil)
|
|||
|
|
|
|||
|
|
// 3. 统计下级转化率(按时间段动态查询历史下级关系)
|
|||
|
|
subordinateConversionRate := l.calculateSubordinateConversionRate(agent.Id)
|
|||
|
|
|
|||
|
|
return &types.ConversionRateResp{
|
|||
|
|
MyConversionRate: myConversionRate,
|
|||
|
|
SubordinateConversionRate: subordinateConversionRate,
|
|||
|
|
}, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// calculateSubordinateConversionRate 计算下级转化率(考虑历史关系)
|
|||
|
|
func (l *GetConversionRateLogic) calculateSubordinateConversionRate(parentAgentId int64) types.ConversionRateData {
|
|||
|
|
// 使用Asia/Shanghai时区,与数据库保持一致
|
|||
|
|
loc, _ := time.LoadLocation("Asia/Shanghai")
|
|||
|
|
now := time.Now().In(loc)
|
|||
|
|
|
|||
|
|
// 日统计:今日、昨日、前日
|
|||
|
|
todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
|
|||
|
|
todayEnd := todayStart.AddDate(0, 0, 1)
|
|||
|
|
yesterdayStart := todayStart.AddDate(0, 0, -1)
|
|||
|
|
yesterdayEnd := todayStart
|
|||
|
|
dayBeforeStart := todayStart.AddDate(0, 0, -2)
|
|||
|
|
dayBeforeEnd := yesterdayStart
|
|||
|
|
|
|||
|
|
daily := []types.PeriodConversionData{
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "今日", todayStart, todayEnd),
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "昨日", yesterdayStart, yesterdayEnd),
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "前日", dayBeforeStart, dayBeforeEnd),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 周统计:本周、上周、上上周
|
|||
|
|
weekdayOffset := int(now.Weekday())
|
|||
|
|
if weekdayOffset == 0 {
|
|||
|
|
weekdayOffset = 7 // 周日算作第7天
|
|||
|
|
}
|
|||
|
|
thisWeekStart := now.AddDate(0, 0, -(weekdayOffset - 1))
|
|||
|
|
thisWeekStart = time.Date(thisWeekStart.Year(), thisWeekStart.Month(), thisWeekStart.Day(), 0, 0, 0, 0, loc)
|
|||
|
|
thisWeekEnd := now
|
|||
|
|
lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
|
|||
|
|
lastWeekEnd := thisWeekStart
|
|||
|
|
lastTwoWeekStart := thisWeekStart.AddDate(0, 0, -14)
|
|||
|
|
lastTwoWeekEnd := lastWeekStart
|
|||
|
|
|
|||
|
|
weekly := []types.PeriodConversionData{
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "本周", thisWeekStart, thisWeekEnd),
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "上周", lastWeekStart, lastWeekEnd),
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "上上周", lastTwoWeekStart, lastTwoWeekEnd),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 月统计:本月、上月、前两月
|
|||
|
|
thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
|
|||
|
|
thisMonthEnd := now
|
|||
|
|
lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
|
|||
|
|
lastMonthEnd := thisMonthStart
|
|||
|
|
lastTwoMonthStart := thisMonthStart.AddDate(0, -2, 0)
|
|||
|
|
lastTwoMonthEnd := lastMonthStart
|
|||
|
|
|
|||
|
|
monthly := []types.PeriodConversionData{
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "本月", thisMonthStart, thisMonthEnd),
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "上月", lastMonthStart, lastMonthEnd),
|
|||
|
|
l.calculateSubordinatePeriodConversion(parentAgentId, "前两月", lastTwoMonthStart, lastTwoMonthEnd),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return types.ConversionRateData{
|
|||
|
|
Daily: daily,
|
|||
|
|
Weekly: weekly,
|
|||
|
|
Monthly: monthly,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// calculateConversionRate 计算转化率
|
|||
|
|
// agentId > 0 时统计该代理的转化率,否则统计 subordinateIds 列表的转化率
|
|||
|
|
func (l *GetConversionRateLogic) calculateConversionRate(agentId int64, subordinateIds []int64) types.ConversionRateData {
|
|||
|
|
// 使用Asia/Shanghai时区,与数据库保持一致
|
|||
|
|
loc, _ := time.LoadLocation("Asia/Shanghai")
|
|||
|
|
now := time.Now().In(loc)
|
|||
|
|
|
|||
|
|
// 日统计:今日、昨日、前日
|
|||
|
|
todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
|
|||
|
|
todayEnd := todayStart.AddDate(0, 0, 1)
|
|||
|
|
yesterdayStart := todayStart.AddDate(0, 0, -1)
|
|||
|
|
yesterdayEnd := todayStart
|
|||
|
|
dayBeforeStart := todayStart.AddDate(0, 0, -2)
|
|||
|
|
dayBeforeEnd := yesterdayStart
|
|||
|
|
|
|||
|
|
daily := []types.PeriodConversionData{
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "今日", todayStart, todayEnd),
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "昨日", yesterdayStart, yesterdayEnd),
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "前日", dayBeforeStart, dayBeforeEnd),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 周统计:本周、上周、上上周
|
|||
|
|
// 本周:本周一00:00:00 到现在
|
|||
|
|
weekdayOffset := int(now.Weekday())
|
|||
|
|
if weekdayOffset == 0 {
|
|||
|
|
weekdayOffset = 7 // 周日算作第7天
|
|||
|
|
}
|
|||
|
|
// 计算本周一:当前日期减去(weekdayOffset-1)天
|
|||
|
|
thisWeekStart := now.AddDate(0, 0, -(weekdayOffset - 1))
|
|||
|
|
thisWeekStart = time.Date(thisWeekStart.Year(), thisWeekStart.Month(), thisWeekStart.Day(), 0, 0, 0, 0, loc)
|
|||
|
|
thisWeekEnd := now
|
|||
|
|
lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
|
|||
|
|
lastWeekEnd := thisWeekStart
|
|||
|
|
lastTwoWeekStart := thisWeekStart.AddDate(0, 0, -14)
|
|||
|
|
lastTwoWeekEnd := lastWeekStart
|
|||
|
|
|
|||
|
|
weekly := []types.PeriodConversionData{
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "本周", thisWeekStart, thisWeekEnd),
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "上周", lastWeekStart, lastWeekEnd),
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "上上周", lastTwoWeekStart, lastTwoWeekEnd),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 月统计:本月、上月、前两月
|
|||
|
|
thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
|
|||
|
|
thisMonthEnd := now
|
|||
|
|
lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
|
|||
|
|
lastMonthEnd := thisMonthStart
|
|||
|
|
lastTwoMonthStart := thisMonthStart.AddDate(0, -2, 0)
|
|||
|
|
lastTwoMonthEnd := lastMonthStart
|
|||
|
|
|
|||
|
|
monthly := []types.PeriodConversionData{
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "本月", thisMonthStart, thisMonthEnd),
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "上月", lastMonthStart, lastMonthEnd),
|
|||
|
|
l.calculatePeriodConversion(agentId, subordinateIds, "前两月", lastTwoMonthStart, lastTwoMonthEnd),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return types.ConversionRateData{
|
|||
|
|
Daily: daily,
|
|||
|
|
Weekly: weekly,
|
|||
|
|
Monthly: monthly,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// calculatePeriodConversion 计算指定时间段的转化率数据
|
|||
|
|
func (l *GetConversionRateLogic) calculatePeriodConversion(agentId int64, subordinateIds []int64, periodLabel string, startTime, endTime time.Time) types.PeriodConversionData {
|
|||
|
|
// 构建 agent_order 查询条件
|
|||
|
|
agentOrderBuilder := l.svcCtx.AgentOrderModel.SelectBuilder().
|
|||
|
|
Where("del_state = ?", globalkey.DelStateNo).
|
|||
|
|
Where("create_time >= ? AND create_time < ?", startTime, endTime)
|
|||
|
|
|
|||
|
|
if agentId > 0 {
|
|||
|
|
// 统计我的转化率
|
|||
|
|
agentOrderBuilder = agentOrderBuilder.Where("agent_id = ?", agentId)
|
|||
|
|
} else if len(subordinateIds) > 0 {
|
|||
|
|
// 统计下级转化率
|
|||
|
|
agentOrderBuilder = agentOrderBuilder.Where(squirrel.Eq{"agent_id": subordinateIds})
|
|||
|
|
} else {
|
|||
|
|
// 没有数据
|
|||
|
|
l.Infof("calculatePeriodConversion: 没有代理ID或下级ID,periodLabel=%s", periodLabel)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加调试日志
|
|||
|
|
if agentId == 0 && len(subordinateIds) > 0 {
|
|||
|
|
l.Infof("calculatePeriodConversion: 统计下级转化率,periodLabel=%s, startTime=%v, endTime=%v, subordinateIds数量=%d",
|
|||
|
|
periodLabel, startTime, endTime, len(subordinateIds))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询所有代理订单
|
|||
|
|
agentOrders, err := l.svcCtx.AgentOrderModel.FindAll(l.ctx, agentOrderBuilder, "")
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
l.Errorf("查询代理订单失败: periodLabel=%s, err=%v", periodLabel, err)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if len(agentOrders) == 0 {
|
|||
|
|
if agentId == 0 && len(subordinateIds) > 0 {
|
|||
|
|
l.Infof("calculatePeriodConversion: 未找到代理订单,periodLabel=%s, startTime=%v, endTime=%v",
|
|||
|
|
periodLabel, startTime, endTime)
|
|||
|
|
}
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
l.Infof("calculatePeriodConversion: 找到代理订单数量=%d, periodLabel=%s", len(agentOrders), periodLabel)
|
|||
|
|
|
|||
|
|
// 收集订单ID
|
|||
|
|
orderIds := make([]int64, 0, len(agentOrders))
|
|||
|
|
for _, ao := range agentOrders {
|
|||
|
|
orderIds = append(orderIds, ao.OrderId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询订单信息
|
|||
|
|
orderBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
|||
|
|
Where(squirrel.Eq{"id": orderIds}).
|
|||
|
|
Where("del_state = ?", globalkey.DelStateNo)
|
|||
|
|
|
|||
|
|
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, orderBuilder, "")
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
l.Errorf("查询订单失败: %v", err)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 统计查询订单数、付费订单数、用户数和总金额
|
|||
|
|
var totalAmount float64
|
|||
|
|
paidOrderCount := 0
|
|||
|
|
queryUserSet := make(map[int64]bool)
|
|||
|
|
paidUserSet := make(map[int64]bool)
|
|||
|
|
|
|||
|
|
for _, order := range orders {
|
|||
|
|
// 查询用户数(所有订单的用户,去重)
|
|||
|
|
queryUserSet[order.UserId] = true
|
|||
|
|
|
|||
|
|
// 付费订单数和总金额(只统计已支付的订单)
|
|||
|
|
if order.Status == "paid" {
|
|||
|
|
paidOrderCount++
|
|||
|
|
paidUserSet[order.UserId] = true
|
|||
|
|
totalAmount += order.Amount
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询订单数 = 所有订单数量
|
|||
|
|
queryOrderCount := len(orders)
|
|||
|
|
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: int64(queryOrderCount), // 订单数量(保持向后兼容)
|
|||
|
|
PaidUsers: int64(paidOrderCount), // 订单数量(保持向后兼容)
|
|||
|
|
TotalAmount: totalAmount,
|
|||
|
|
QueryUserCount: int64(len(queryUserSet)), // 用户数量(新增)
|
|||
|
|
PaidUserCount: int64(len(paidUserSet)), // 用户数量(新增)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// calculateSubordinatePeriodConversion 计算指定时间段内下级转化率
|
|||
|
|
// 结合使用agent_rebate表和agent_order表:
|
|||
|
|
// 1. 查询量:通过agent_order表统计所有查询(包括未付费的)
|
|||
|
|
// 2. 付费量和金额:通过agent_rebate表统计(只有付费的订单才会产生返佣)
|
|||
|
|
func (l *GetConversionRateLogic) calculateSubordinatePeriodConversion(parentAgentId int64, periodLabel string, startTime, endTime time.Time) types.PeriodConversionData {
|
|||
|
|
// 1. 查询agent_rebate表:获取所有曾经给当前用户产生返佣的source_agent_id(这些代理在某个时间点是下级)
|
|||
|
|
// 不限制时间,获取所有历史返佣记录,用于确定哪些代理曾经是下级
|
|||
|
|
rebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder().
|
|||
|
|
Where("agent_id = ? AND del_state = ?", parentAgentId, globalkey.DelStateNo).
|
|||
|
|
Where("source_agent_id != ?", parentAgentId)
|
|||
|
|
|
|||
|
|
allRebates, err := l.svcCtx.AgentRebateModel.FindAll(l.ctx, rebateBuilder, "")
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
l.Errorf("查询返佣记录失败: periodLabel=%s, err=%v", periodLabel, err)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 收集所有曾经产生返佣的source_agent_id(这些代理在某个时间点是下级)
|
|||
|
|
sourceAgentIdSet := make(map[int64]bool)
|
|||
|
|
paidOrderIdSet := make(map[int64]bool) // 已付费的订单ID(有返佣的订单)
|
|||
|
|
paidOrderIdToAmount := make(map[int64]float64) // 已付费订单的金额
|
|||
|
|
|
|||
|
|
for _, rebate := range allRebates {
|
|||
|
|
sourceAgentIdSet[rebate.SourceAgentId] = true
|
|||
|
|
// 如果返佣记录的创建时间在时间段内,说明该订单在时间段内已付费
|
|||
|
|
if rebate.CreateTime.After(startTime) || rebate.CreateTime.Equal(startTime) {
|
|||
|
|
if rebate.CreateTime.Before(endTime) {
|
|||
|
|
paidOrderIdSet[rebate.OrderId] = true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if len(sourceAgentIdSet) == 0 {
|
|||
|
|
l.Infof("calculateSubordinatePeriodConversion: 未找到返佣记录,periodLabel=%s, startTime=%v, endTime=%v",
|
|||
|
|
periodLabel, startTime, endTime)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sourceAgentIds := make([]int64, 0, len(sourceAgentIdSet))
|
|||
|
|
for agentId := range sourceAgentIdSet {
|
|||
|
|
sourceAgentIds = append(sourceAgentIds, agentId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
l.Infof("calculateSubordinatePeriodConversion: periodLabel=%s, 曾经产生返佣的代理数量=%d", periodLabel, len(sourceAgentIds))
|
|||
|
|
|
|||
|
|
// 2. 查询agent_order表:统计这些代理在时间段内的所有订单(包括未付费的)
|
|||
|
|
agentOrderBuilder := l.svcCtx.AgentOrderModel.SelectBuilder().
|
|||
|
|
Where("del_state = ?", globalkey.DelStateNo).
|
|||
|
|
Where("create_time >= ? AND create_time < ?", startTime, endTime).
|
|||
|
|
Where(squirrel.Eq{"agent_id": sourceAgentIds})
|
|||
|
|
|
|||
|
|
agentOrders, err := l.svcCtx.AgentOrderModel.FindAll(l.ctx, agentOrderBuilder, "")
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
l.Errorf("查询代理订单失败: periodLabel=%s, err=%v", periodLabel, err)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
l.Infof("calculateSubordinatePeriodConversion: periodLabel=%s, 查询到代理订单数量=%d", periodLabel, len(agentOrders))
|
|||
|
|
|
|||
|
|
if len(agentOrders) == 0 {
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 通过order_id去重,获取所有订单ID(用于查询订单详情)
|
|||
|
|
orderIdSet := make(map[int64]bool)
|
|||
|
|
orderIdToAgentOrder := make(map[int64]*model.AgentOrder)
|
|||
|
|
|
|||
|
|
for _, ao := range agentOrders {
|
|||
|
|
orderIdSet[ao.OrderId] = true
|
|||
|
|
// 如果同一个订单有多个agent_order记录,保留金额更大的
|
|||
|
|
if existing, exists := orderIdToAgentOrder[ao.OrderId]; exists {
|
|||
|
|
if ao.OrderAmount > existing.OrderAmount {
|
|||
|
|
orderIdToAgentOrder[ao.OrderId] = ao
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
orderIdToAgentOrder[ao.OrderId] = ao
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
orderIds := make([]int64, 0, len(orderIdSet))
|
|||
|
|
for orderId := range orderIdSet {
|
|||
|
|
orderIds = append(orderIds, orderId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 查询订单信息
|
|||
|
|
orderBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
|||
|
|
Where(squirrel.Eq{"id": orderIds}).
|
|||
|
|
Where("del_state = ?", globalkey.DelStateNo)
|
|||
|
|
|
|||
|
|
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, orderBuilder, "")
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
l.Errorf("查询订单失败: %v", err)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 5. 查询时间段内的返佣记录,获取已付费订单的金额
|
|||
|
|
rebateBuilder = l.svcCtx.AgentRebateModel.SelectBuilder().
|
|||
|
|
Where("agent_id = ? AND del_state = ?", parentAgentId, globalkey.DelStateNo).
|
|||
|
|
Where("source_agent_id != ?", parentAgentId).
|
|||
|
|
Where("create_time >= ? AND create_time < ?", startTime, endTime).
|
|||
|
|
Where(squirrel.Eq{"order_id": orderIds})
|
|||
|
|
|
|||
|
|
rebates, err := l.svcCtx.AgentRebateModel.FindAll(l.ctx, rebateBuilder, "")
|
|||
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|||
|
|
l.Errorf("查询返佣记录失败: %v", err)
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: 0,
|
|||
|
|
PaidUsers: 0,
|
|||
|
|
TotalAmount: 0,
|
|||
|
|
QueryUserCount: 0,
|
|||
|
|
PaidUserCount: 0,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 记录已付费订单的金额(使用agent_order的order_amount)
|
|||
|
|
for _, rebate := range rebates {
|
|||
|
|
if ao, exists := orderIdToAgentOrder[rebate.OrderId]; exists {
|
|||
|
|
paidOrderIdToAmount[rebate.OrderId] = ao.OrderAmount
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 6. 统计查询订单数、付费订单数、用户数和总金额
|
|||
|
|
var totalAmount float64
|
|||
|
|
paidOrderCount := 0
|
|||
|
|
queryUserSet := make(map[int64]bool)
|
|||
|
|
paidUserSet := make(map[int64]bool)
|
|||
|
|
|
|||
|
|
for _, order := range orders {
|
|||
|
|
// 查询用户数(所有订单的用户,去重)
|
|||
|
|
queryUserSet[order.UserId] = true
|
|||
|
|
|
|||
|
|
// 付费订单数和总金额(只统计已付费的订单,即order_id在paidOrderIdToAmount中)
|
|||
|
|
if _, isPaid := paidOrderIdToAmount[order.Id]; isPaid {
|
|||
|
|
paidOrderCount++
|
|||
|
|
paidUserSet[order.UserId] = true
|
|||
|
|
// 使用agent_order的order_amount(用户实际支付金额)
|
|||
|
|
totalAmount += paidOrderIdToAmount[order.Id]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询订单数 = 所有订单数量
|
|||
|
|
queryOrderCount := len(orders)
|
|||
|
|
|
|||
|
|
l.Infof("calculateSubordinatePeriodConversion: periodLabel=%s, 查询订单数=%d, 付费订单数=%d, 查询用户数=%d, 付费用户数=%d, 总金额=%.2f",
|
|||
|
|
periodLabel, queryOrderCount, paidOrderCount, len(queryUserSet), len(paidUserSet), totalAmount)
|
|||
|
|
|
|||
|
|
return types.PeriodConversionData{
|
|||
|
|
PeriodLabel: periodLabel,
|
|||
|
|
QueryUsers: int64(queryOrderCount), // 订单数量(保持向后兼容)
|
|||
|
|
PaidUsers: int64(paidOrderCount), // 订单数量(保持向后兼容)
|
|||
|
|
TotalAmount: totalAmount,
|
|||
|
|
QueryUserCount: int64(len(queryUserSet)), // 用户数量(新增)
|
|||
|
|
PaidUserCount: int64(len(paidUserSet)), // 用户数量(新增)
|
|||
|
|
}
|
|||
|
|
}
|