package admin_dashboard import ( "context" "time" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" "qnc-server/app/main/api/internal/service" "qnc-server/app/main/api/internal/svc" "qnc-server/app/main/api/internal/types" "qnc-server/common/globalkey" "qnc-server/common/xerr" ) 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) { 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) orderStats, err := l.calculateOrderStatistics(todayStart, todayEnd, yesterdayStart, yesterdayEnd, monthStart, monthEnd) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算订单统计失败, %v", err) } revenueStats, err := l.calculateRevenueStatistics(todayStart, todayEnd, yesterdayStart, yesterdayEnd, monthStart, monthEnd) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算营收统计失败, %v", err) } agentStats, err := l.calculateAgentStatistics(todayStart, monthStart) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算代理统计失败, %v", err) } profitStats, err := l.calculateProfitStatistics(todayStart, todayEnd, monthStart, monthEnd, revenueStats) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算利润统计失败, %v", err) } orderTrend, err := l.calculateOrderTrend(now, loc) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "计算订单趋势失败, %v", err) } 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 } 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, _ := l.svcCtx.OrderModel.FindCount(l.ctx, yesterdayBuilder, "id") stats.YesterdayCount = yesterdayCount monthBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", monthStart, monthEnd) monthCount, _ := l.svcCtx.OrderModel.FindCount(l.ctx, monthBuilder, "id") stats.MonthCount = monthCount totalBuilder := l.svcCtx.OrderModel.SelectBuilder().Where("status = ?", "paid") totalCount, _ := l.svcCtx.OrderModel.FindCount(l.ctx, totalBuilder, "id") 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 } return stats, nil } 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, _ := l.svcCtx.OrderModel.FindSum(l.ctx, todayBuilder, "amount") stats.TodayAmount = todayAmount yesterdayBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", yesterdayStart, yesterdayEnd) yesterdayAmount, _ := l.svcCtx.OrderModel.FindSum(l.ctx, yesterdayBuilder, "amount") stats.YesterdayAmount = yesterdayAmount monthBuilder := l.svcCtx.OrderModel.SelectBuilder(). Where("status = ? AND create_time >= ? AND create_time < ?", "paid", monthStart, monthEnd) monthAmount, _ := l.svcCtx.OrderModel.FindSum(l.ctx, monthBuilder, "amount") stats.MonthAmount = monthAmount totalBuilder := l.svcCtx.OrderModel.SelectBuilder().Where("status = ?", "paid") totalAmount, _ := l.svcCtx.OrderModel.FindSum(l.ctx, totalBuilder, "amount") stats.TotalAmount = totalAmount if stats.YesterdayAmount > 0 { stats.ChangeRate = (stats.TodayAmount - stats.YesterdayAmount) / stats.YesterdayAmount * 100 } else if stats.TodayAmount > 0 { stats.ChangeRate = 100 } return stats, nil } func (l *AdminGetDashboardStatisticsLogic) calculateAgentStatistics(todayStart, monthStart time.Time) (types.AdminAgentStatistics, error) { var stats types.AdminAgentStatistics totalCount, _ := l.svcCtx.AgentModel.FindCount(l.ctx, l.svcCtx.AgentModel.SelectBuilder(), "id") stats.TotalCount = totalCount todayBuilder := l.svcCtx.AgentModel.SelectBuilder().Where("create_time >= ?", todayStart) todayNew, _ := l.svcCtx.AgentModel.FindCount(l.ctx, todayBuilder, "id") stats.TodayNew = todayNew monthBuilder := l.svcCtx.AgentModel.SelectBuilder().Where("create_time >= ?", monthStart) monthNew, _ := l.svcCtx.AgentModel.FindCount(l.ctx, monthBuilder, "id") stats.MonthNew = monthNew return stats, nil } func (l *AdminGetDashboardStatisticsLogic) calculateProfitStatistics(todayStart, todayEnd, monthStart, monthEnd time.Time, revenueStats types.AdminRevenueStatistics) (types.AdminProfitStatistics, error) { var stats types.AdminProfitStatistics 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, _ := l.svcCtx.AgentCommissionModel.FindSum(l.ctx, todayCommissionBuilder, "amount") todayRebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder(). Where("del_state = ? AND status != ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 3, todayStart, todayEnd) todayRebate, _ := l.svcCtx.AgentRebateModel.FindSum(l.ctx, todayRebateBuilder, "rebate_amount") todayCompanyTax := todayRevenue * companyTaxRate todayTaxIncomeBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder(). Where("del_state = ? AND tax_status = ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 2, todayStart, todayEnd) todayTaxIncome, _ := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, todayTaxIncomeBuilder, "tax_amount") todayApiCost := 0.0 if l.svcCtx.TianyuanapiCallLogService != nil { todayApiStats, e := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{StartDate: todayStart, EndDate: todayEnd}) if e == nil { todayApiCost = todayApiStats.TotalCost } } 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, _ := l.svcCtx.AgentCommissionModel.FindSum(l.ctx, monthCommissionBuilder, "amount") monthRebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder(). Where("del_state = ? AND status != ? AND create_time >= ? AND create_time < ?", globalkey.DelStateNo, 3, monthStart, monthEnd) monthRebate, _ := l.svcCtx.AgentRebateModel.FindSum(l.ctx, monthRebateBuilder, "rebate_amount") 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, _ := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, monthTaxIncomeBuilder, "tax_amount") monthApiCost := 0.0 if l.svcCtx.TianyuanapiCallLogService != nil { monthApiStats, e := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{StartDate: monthStart, EndDate: monthEnd}) if e == nil { monthApiCost = monthApiStats.TotalCost } } 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, _ := l.svcCtx.AgentCommissionModel.FindSum(l.ctx, totalCommissionBuilder, "amount") totalRebateBuilder := l.svcCtx.AgentRebateModel.SelectBuilder().Where("status != ?", 3) totalRebate, _ := l.svcCtx.AgentRebateModel.FindSum(l.ctx, totalRebateBuilder, "rebate_amount") totalCompanyTax := totalRevenue * companyTaxRate totalTaxIncomeBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder().Where("tax_status = ?", 2) totalTaxIncome, _ := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, totalTaxIncomeBuilder, "tax_amount") totalApiCost := 0.0 if l.svcCtx.TianyuanapiCallLogService != nil { totalApiStats, e := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{}) if e == nil { totalApiCost = totalApiStats.TotalCost } } 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 } func (l *AdminGetDashboardStatisticsLogic) calculateOrderTrend(now time.Time, loc *time.Location) ([]types.AdminTrendData, error) { var trend []types.AdminTrendData 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 } func (l *AdminGetDashboardStatisticsLogic) calculateRevenueTrend(now time.Time, loc *time.Location) ([]types.AdminTrendData, error) { var trend []types.AdminTrendData 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 }