package admin_dashboard import ( "context" "time" "ycc-server/common/globalkey" "ycc-server/common/xerr" "github.com/pkg/errors" "ycc-server/app/main/api/internal/service" "ycc-server/app/main/api/internal/svc" "ycc-server/app/main/api/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type AdminGetDashboardStatisticsLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewAdminGetDashboardStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetDashboardStatisticsLogic { return &AdminGetDashboardStatisticsLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *AdminGetDashboardStatisticsLogic) AdminGetDashboardStatistics() (resp *types.AdminGetDashboardStatisticsResp, err error) { // 使用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 monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc) monthEnd := monthStart.AddDate(0, 1, 0) // 1. 订单统计 orderStats, err := l.calculateOrderStatistics(todayStart, todayEnd, yesterdayStart, yesterdayEnd, monthStart, monthEnd) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算订单统计失败, %v", err) } // 2. 营收统计 revenueStats, err := l.calculateRevenueStatistics(todayStart, todayEnd, yesterdayStart, yesterdayEnd, monthStart, monthEnd) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算营收统计失败, %v", err) } // 3. 代理统计 agentStats, err := l.calculateAgentStatistics(todayStart, monthStart) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算代理统计失败, %v", err) } // 4. 利润统计 profitStats, err := l.calculateProfitStatistics(todayStart, todayEnd, monthStart, monthEnd, revenueStats) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算利润统计失败, %v", err) } // 5. 订单趋势(最近7天) orderTrend, err := l.calculateOrderTrend(now, loc) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算订单趋势失败, %v", err) } // 6. 营收趋势(最近7天) revenueTrend, err := l.calculateRevenueTrend(now, loc) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算营收趋势失败, %v", err) } return &types.AdminGetDashboardStatisticsResp{ OrderStats: orderStats, RevenueStats: revenueStats, AgentStats: agentStats, ProfitStats: profitStats, OrderTrend: orderTrend, RevenueTrend: revenueTrend, }, nil } // calculateOrderStatistics 计算订单统计 func (l *AdminGetDashboardStatisticsLogic) calculateOrderStatistics(todayStart, todayEnd, yesterdayStart, yesterdayEnd, monthStart, monthEnd time.Time) (types.AdminOrderStatistics, error) { var stats types.AdminOrderStatistics // 今日订单数 todayBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", todayStart, todayEnd) todayCount, err := l.svcCtx.OrderModel.FindCount(l.ctx, todayBuilder, "id") if err != nil { return stats, err } stats.TodayCount = todayCount // 昨日订单数 yesterdayBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", yesterdayStart, yesterdayEnd) yesterdayCount, err := l.svcCtx.OrderModel.FindCount(l.ctx, yesterdayBuilder, "id") if err != nil { return stats, err } stats.YesterdayCount = yesterdayCount // 当月订单数 monthBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", monthStart, monthEnd) monthCount, err := l.svcCtx.OrderModel.FindCount(l.ctx, monthBuilder, "id") if err != nil { return stats, err } stats.MonthCount = monthCount // 总订单数 totalBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ?", "paid") totalCount, err := l.svcCtx.OrderModel.FindCount(l.ctx, totalBuilder, "id") if err != nil { return stats, err } stats.TotalCount = totalCount // 计算变化率 if stats.YesterdayCount > 0 { stats.ChangeRate = float64(stats.TodayCount-stats.YesterdayCount) / float64(stats.YesterdayCount) * 100 } else if stats.TodayCount > 0 { stats.ChangeRate = 100 // 从0增长到有值,算100%增长 } return stats, nil } // calculateRevenueStatistics 计算营收统计 func (l *AdminGetDashboardStatisticsLogic) calculateRevenueStatistics(todayStart, todayEnd, yesterdayStart, yesterdayEnd, monthStart, monthEnd time.Time) (types.AdminRevenueStatistics, error) { var stats types.AdminRevenueStatistics // 今日营收 todayBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", todayStart, todayEnd) todayAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, todayBuilder, "amount") if err != nil { return stats, err } stats.TodayAmount = todayAmount // 昨日营收 yesterdayBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", yesterdayStart, yesterdayEnd) yesterdayAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, yesterdayBuilder, "amount") if err != nil { return stats, err } stats.YesterdayAmount = yesterdayAmount // 当月营收 monthBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", monthStart, monthEnd) monthAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, monthBuilder, "amount") if err != nil { return stats, err } stats.MonthAmount = monthAmount // 总营收 totalBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ?", "paid") totalAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, totalBuilder, "amount") if err != nil { return stats, err } stats.TotalAmount = totalAmount // 计算变化率 if stats.YesterdayAmount > 0 { stats.ChangeRate = (stats.TodayAmount - stats.YesterdayAmount) / stats.YesterdayAmount * 100 } else if stats.TodayAmount > 0 { stats.ChangeRate = 100 // 从0增长到有值,算100%增长 } return stats, nil } // calculateAgentStatistics 计算代理统计 func (l *AdminGetDashboardStatisticsLogic) calculateAgentStatistics(todayStart, monthStart time.Time) (types.AdminAgentStatistics, error) { var stats types.AdminAgentStatistics // 代理总数 totalBuilder := l.svcCtx.AgentModel.SelectBuilder() totalCount, err := l.svcCtx.AgentModel.FindCount(l.ctx, totalBuilder, "id") if err != nil { return stats, err } stats.TotalCount = totalCount // 今日新增 todayBuilder := l.svcCtx.AgentModel.SelectBuilder(). Where("create_time >= ?", todayStart) todayNew, err := l.svcCtx.AgentModel.FindCount(l.ctx, todayBuilder, "id") if err != nil { return stats, err } stats.TodayNew = todayNew // 当月新增 monthBuilder := l.svcCtx.AgentModel.SelectBuilder(). Where("create_time >= ?", monthStart) monthNew, err := l.svcCtx.AgentModel.FindCount(l.ctx, monthBuilder, "id") if err != nil { return stats, err } stats.MonthNew = monthNew return stats, nil } // calculateProfitStatistics 计算利润统计 func (l *AdminGetDashboardStatisticsLogic) calculateProfitStatistics(todayStart, todayEnd, monthStart, monthEnd time.Time, revenueStats types.AdminRevenueStatistics) (types.AdminProfitStatistics, error) { var stats types.AdminProfitStatistics // 税务成本比例(6%) const companyTaxRate = 0.06 // 今日利润计算 // 今日营收 todayRevenue := revenueStats.TodayAmount // 今日佣金 todayCommissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder(). Where("del_state = ? AND status != ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 3, todayStart, todayEnd) todayCommission, err := l.svcCtx.AgentCommissionModel.FindSum(l.ctx, todayCommissionBuilder, "amount") if err != nil { return stats, err } // 今日返利 todayRebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder(). Where("del_state = ? AND status != ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 3, todayStart, todayEnd) todayRebate, err := l.svcCtx.AgentRebateModel.FindSum(l.ctx, todayRebateBuilder, "rebate_amount") if err != nil { return stats, err } // 今日税务成本(订单金额的6%) todayCompanyTax := todayRevenue * companyTaxRate // 今日提现收税(agent_withdrawal_tax表中tax_status=2的tax_amount总和) todayTaxIncomeBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder(). Where("del_state = ? AND tax_status = ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 2, todayStart, todayEnd) todayTaxIncome, err := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, todayTaxIncomeBuilder, "tax_amount") if err != nil { return stats, err } // 今日API调用成本 todayApiCost := 0.0 if l.svcCtx.TianyuanapiCallLogService != nil { logx.Infof("开始获取今日API调用成本,时间范围: %v 到 %v", todayStart, todayEnd) todayApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{ StartDate: todayStart, EndDate: todayEnd, }) if err != nil { logx.Errorf("获取今日API调用成本失败: %v", err) } else { todayApiCost = todayApiStats.TotalCost logx.Infof("今日API调用成本统计完成,总成本: %f", todayApiCost) } } else { logx.Errorf("TianyuanapiCallLogService 未初始化,无法获取API调用成本") } // 今日利润 = 营收 - 佣金 - 返利 - 税务成本 - API调用成本 + 提现收税 stats.TodayProfit = todayRevenue - todayCommission - todayRebate - todayCompanyTax - todayApiCost + todayTaxIncome if todayRevenue > 0 { stats.TodayProfitRate = stats.TodayProfit / todayRevenue * 100 } // 今日明细 stats.TodayDetail = types.AdminProfitDetail{ Revenue: todayRevenue, Commission: todayCommission, Rebate: todayRebate, CompanyTax: todayCompanyTax, ApiCost: todayApiCost, TaxIncome: todayTaxIncome, Profit: stats.TodayProfit, ProfitRate: stats.TodayProfitRate, } // 当月利润计算 // 当月营收 monthRevenue := revenueStats.MonthAmount // 当月佣金 monthCommissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder(). Where("del_state = ? AND status != ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 3, monthStart, monthEnd) monthCommission, err := l.svcCtx.AgentCommissionModel.FindSum(l.ctx, monthCommissionBuilder, "amount") if err != nil { return stats, err } // 当月返利 monthRebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder(). Where("del_state = ? AND status != ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 3, monthStart, monthEnd) monthRebate, err := l.svcCtx.AgentRebateModel.FindSum(l.ctx, monthRebateBuilder, "rebate_amount") if err != nil { return stats, err } // 当月税务成本 monthCompanyTax := monthRevenue * companyTaxRate // 当月提现收税 monthTaxIncomeBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder(). Where("del_state = ? AND tax_status = ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 2, monthStart, monthEnd) monthTaxIncome, err := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, monthTaxIncomeBuilder, "tax_amount") if err != nil { return stats, err } // 当月API调用成本 monthApiCost := 0.0 if l.svcCtx.TianyuanapiCallLogService != nil { logx.Infof("开始获取当月API调用成本,时间范围: %v 到 %v", monthStart, monthEnd) monthApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{ StartDate: monthStart, EndDate: monthEnd, }) if err != nil { logx.Errorf("获取当月API调用成本失败: %v", err) } else { monthApiCost = monthApiStats.TotalCost logx.Infof("当月API调用成本统计完成,总成本: %f", monthApiCost) } } else { logx.Errorf("TianyuanapiCallLogService 未初始化,无法获取API调用成本") } // 当月利润 stats.MonthProfit = monthRevenue - monthCommission - monthRebate - monthCompanyTax - monthApiCost + monthTaxIncome if monthRevenue > 0 { stats.MonthProfitRate = stats.MonthProfit / monthRevenue * 100 } // 当月明细 stats.MonthDetail = types.AdminProfitDetail{ Revenue: monthRevenue, Commission: monthCommission, Rebate: monthRebate, CompanyTax: monthCompanyTax, ApiCost: monthApiCost, TaxIncome: monthTaxIncome, Profit: stats.MonthProfit, ProfitRate: stats.MonthProfitRate, } // 总利润计算 // 总营收 totalRevenue := revenueStats.TotalAmount // 总佣金 totalCommissionBuilder := l.svcCtx.AgentCommissionModel.SelectBuilder(). Where("del_state = ? AND status != ?", globalkey.DelStateNo, 3) totalCommission, err := l.svcCtx.AgentCommissionModel.FindSum(l.ctx, totalCommissionBuilder, "amount") if err != nil { return stats, err } // 总返利 totalRebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder(). Where("status != ?", 3) totalRebate, err := l.svcCtx.AgentRebateModel.FindSum(l.ctx, totalRebateBuilder, "rebate_amount") if err != nil { return stats, err } // 总税务成本 totalCompanyTax := totalRevenue * companyTaxRate // 总提现收税 totalTaxIncomeBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder(). Where("tax_status = ?", 2) totalTaxIncome, err := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, totalTaxIncomeBuilder, "tax_amount") if err != nil { return stats, err } // 总API调用成本 totalApiCost := 0.0 if l.svcCtx.TianyuanapiCallLogService != nil { logx.Infof("开始获取总API调用成本(无时间限制)") totalApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{}) if err != nil { logx.Errorf("获取总API调用成本失败: %v", err) } else { totalApiCost = totalApiStats.TotalCost logx.Infof("总API调用成本统计完成,总成本: %f", totalApiCost) } } else { logx.Errorf("TianyuanapiCallLogService 未初始化,无法获取API调用成本") } // 总利润 stats.TotalProfit = totalRevenue - totalCommission - totalRebate - totalCompanyTax - totalApiCost + totalTaxIncome if totalRevenue > 0 { stats.TotalProfitRate = stats.TotalProfit / totalRevenue * 100 } // 总计明细 stats.TotalDetail = types.AdminProfitDetail{ Revenue: totalRevenue, Commission: totalCommission, Rebate: totalRebate, CompanyTax: totalCompanyTax, ApiCost: totalApiCost, TaxIncome: totalTaxIncome, Profit: stats.TotalProfit, ProfitRate: stats.TotalProfitRate, } return stats, nil } // calculateOrderTrend 计算订单趋势(最近7天) func (l *AdminGetDashboardStatisticsLogic) calculateOrderTrend(now time.Time, loc *time.Location) ([]types.AdminTrendData, error) { var trend []types.AdminTrendData // 计算最近7天的日期 for i := 6; i >= 0; i-- { date := now.AddDate(0, 0, -i) dateStart := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, loc) dateEnd := dateStart.AddDate(0, 0, 1) // 查询当天的订单数 builder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", dateStart, dateEnd) count, err := l.svcCtx.OrderModel.FindCount(l.ctx, builder, "id") if err != nil { return nil, err } trend = append(trend, types.AdminTrendData{ Date: date.Format("01-02"), Value: float64(count), }) } return trend, nil } // calculateRevenueTrend 计算营收趋势(最近7天) func (l *AdminGetDashboardStatisticsLogic) calculateRevenueTrend(now time.Time, loc *time.Location) ([]types.AdminTrendData, error) { var trend []types.AdminTrendData // 计算最近7天的日期 for i := 6; i >= 0; i-- { date := now.AddDate(0, 0, -i) dateStart := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, loc) dateEnd := dateStart.AddDate(0, 0, 1) // 查询当天的营收 builder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", dateStart, dateEnd) amount, err := l.svcCtx.OrderModel.FindSum(l.ctx, builder, "amount") if err != nil { return nil, err } trend = append(trend, types.AdminTrendData{ Date: date.Format("01-02"), Value: amount, }) } return trend, nil }