2026-01-12 16:43:08 +08:00
|
|
|
|
package admin_dashboard
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
"ycc-server/common/globalkey"
|
|
|
|
|
|
"ycc-server/common/xerr"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
|
|
2026-01-13 18:30:10 +08:00
|
|
|
|
"ycc-server/app/main/api/internal/service"
|
2026-01-12 16:43:08 +08:00
|
|
|
|
"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
|
|
|
|
|
|
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 税务成本比例(6%)
|
2026-01-12 16:43:08 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 今日税务成本(订单金额的6%)
|
2026-01-12 16:43:08 +08:00
|
|
|
|
todayCompanyTax := todayRevenue * companyTaxRate
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 今日提现收税(agent_withdrawal_tax表中tax_status=2的tax_amount总和)
|
2026-01-12 16:43:08 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 今日API调用成本
|
|
|
|
|
|
todayApiCost := 0.0
|
|
|
|
|
|
if l.svcCtx.TianyuanapiCallLogService != nil {
|
2026-01-19 17:01:10 +08:00
|
|
|
|
logx.Infof("开始获取今日API调用成本,时间范围: %v 到 %v", todayStart, todayEnd)
|
2026-01-13 18:30:10 +08:00
|
|
|
|
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
|
2026-01-19 17:01:10 +08:00
|
|
|
|
logx.Infof("今日API调用成本统计完成,总成本: %f", todayApiCost)
|
2026-01-13 18:30:10 +08:00
|
|
|
|
}
|
2026-01-19 17:01:10 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
logx.Errorf("TianyuanapiCallLogService 未初始化,无法获取API调用成本")
|
2026-01-13 18:30:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 今日利润 = 营收 - 佣金 - 返利 - 税务成本 - API调用成本 + 提现收税
|
|
|
|
|
|
stats.TodayProfit = todayRevenue - todayCommission - todayRebate - todayCompanyTax - todayApiCost + todayTaxIncome
|
2026-01-12 16:43:08 +08:00
|
|
|
|
if todayRevenue > 0 {
|
|
|
|
|
|
stats.TodayProfitRate = stats.TodayProfit / todayRevenue * 100
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 今日明细
|
|
|
|
|
|
stats.TodayDetail = types.AdminProfitDetail{
|
|
|
|
|
|
Revenue: todayRevenue,
|
|
|
|
|
|
Commission: todayCommission,
|
|
|
|
|
|
Rebate: todayRebate,
|
|
|
|
|
|
CompanyTax: todayCompanyTax,
|
|
|
|
|
|
ApiCost: todayApiCost,
|
|
|
|
|
|
TaxIncome: todayTaxIncome,
|
|
|
|
|
|
Profit: stats.TodayProfit,
|
|
|
|
|
|
ProfitRate: stats.TodayProfitRate,
|
|
|
|
|
|
}
|
2026-01-12 16:43:08 +08:00
|
|
|
|
|
|
|
|
|
|
// 当月利润计算
|
|
|
|
|
|
// 当月营收
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 当月税务成本
|
2026-01-12 16:43:08 +08:00
|
|
|
|
monthCompanyTax := monthRevenue * companyTaxRate
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 当月提现收税
|
2026-01-12 16:43:08 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 当月API调用成本
|
|
|
|
|
|
monthApiCost := 0.0
|
|
|
|
|
|
if l.svcCtx.TianyuanapiCallLogService != nil {
|
2026-01-19 17:01:10 +08:00
|
|
|
|
logx.Infof("开始获取当月API调用成本,时间范围: %v 到 %v", monthStart, monthEnd)
|
2026-01-13 18:30:10 +08:00
|
|
|
|
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
|
2026-01-19 17:01:10 +08:00
|
|
|
|
logx.Infof("当月API调用成本统计完成,总成本: %f", monthApiCost)
|
2026-01-13 18:30:10 +08:00
|
|
|
|
}
|
2026-01-19 17:01:10 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
logx.Errorf("TianyuanapiCallLogService 未初始化,无法获取API调用成本")
|
2026-01-13 18:30:10 +08:00
|
|
|
|
}
|
2026-01-12 16:43:08 +08:00
|
|
|
|
// 当月利润
|
2026-01-13 18:30:10 +08:00
|
|
|
|
stats.MonthProfit = monthRevenue - monthCommission - monthRebate - monthCompanyTax - monthApiCost + monthTaxIncome
|
2026-01-12 16:43:08 +08:00
|
|
|
|
if monthRevenue > 0 {
|
|
|
|
|
|
stats.MonthProfitRate = stats.MonthProfit / monthRevenue * 100
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 当月明细
|
|
|
|
|
|
stats.MonthDetail = types.AdminProfitDetail{
|
|
|
|
|
|
Revenue: monthRevenue,
|
|
|
|
|
|
Commission: monthCommission,
|
|
|
|
|
|
Rebate: monthRebate,
|
|
|
|
|
|
CompanyTax: monthCompanyTax,
|
|
|
|
|
|
ApiCost: monthApiCost,
|
|
|
|
|
|
TaxIncome: monthTaxIncome,
|
|
|
|
|
|
Profit: stats.MonthProfit,
|
|
|
|
|
|
ProfitRate: stats.MonthProfitRate,
|
|
|
|
|
|
}
|
2026-01-12 16:43:08 +08:00
|
|
|
|
|
|
|
|
|
|
// 总利润计算
|
|
|
|
|
|
// 总营收
|
|
|
|
|
|
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().
|
2026-01-13 18:30:10 +08:00
|
|
|
|
Where("status != ?", 3)
|
2026-01-12 16:43:08 +08:00
|
|
|
|
totalRebate, err := l.svcCtx.AgentRebateModel.FindSum(l.ctx, totalRebateBuilder, "rebate_amount")
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return stats, err
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 总税务成本
|
2026-01-12 16:43:08 +08:00
|
|
|
|
totalCompanyTax := totalRevenue * companyTaxRate
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 总提现收税
|
2026-01-12 16:43:08 +08:00
|
|
|
|
totalTaxIncomeBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder().
|
2026-01-13 18:30:10 +08:00
|
|
|
|
Where("tax_status = ?", 2)
|
2026-01-12 16:43:08 +08:00
|
|
|
|
totalTaxIncome, err := l.svcCtx.AgentWithdrawalTaxModel.FindSum(l.ctx, totalTaxIncomeBuilder, "tax_amount")
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return stats, err
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 总API调用成本
|
|
|
|
|
|
totalApiCost := 0.0
|
|
|
|
|
|
if l.svcCtx.TianyuanapiCallLogService != nil {
|
2026-01-19 17:01:10 +08:00
|
|
|
|
logx.Infof("开始获取总API调用成本(无时间限制)")
|
2026-01-13 18:30:10 +08:00
|
|
|
|
totalApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{})
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
logx.Errorf("获取总API调用成本失败: %v", err)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
totalApiCost = totalApiStats.TotalCost
|
2026-01-19 17:01:10 +08:00
|
|
|
|
logx.Infof("总API调用成本统计完成,总成本: %f", totalApiCost)
|
2026-01-13 18:30:10 +08:00
|
|
|
|
}
|
2026-01-19 17:01:10 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
logx.Errorf("TianyuanapiCallLogService 未初始化,无法获取API调用成本")
|
2026-01-13 18:30:10 +08:00
|
|
|
|
}
|
2026-01-12 16:43:08 +08:00
|
|
|
|
// 总利润
|
2026-01-13 18:30:10 +08:00
|
|
|
|
stats.TotalProfit = totalRevenue - totalCommission - totalRebate - totalCompanyTax - totalApiCost + totalTaxIncome
|
2026-01-12 16:43:08 +08:00
|
|
|
|
if totalRevenue > 0 {
|
|
|
|
|
|
stats.TotalProfitRate = stats.TotalProfit / totalRevenue * 100
|
|
|
|
|
|
}
|
2026-01-13 18:30:10 +08:00
|
|
|
|
// 总计明细
|
|
|
|
|
|
stats.TotalDetail = types.AdminProfitDetail{
|
|
|
|
|
|
Revenue: totalRevenue,
|
|
|
|
|
|
Commission: totalCommission,
|
|
|
|
|
|
Rebate: totalRebate,
|
|
|
|
|
|
CompanyTax: totalCompanyTax,
|
|
|
|
|
|
ApiCost: totalApiCost,
|
|
|
|
|
|
TaxIncome: totalTaxIncome,
|
|
|
|
|
|
Profit: stats.TotalProfit,
|
|
|
|
|
|
ProfitRate: stats.TotalProfitRate,
|
|
|
|
|
|
}
|
2026-01-12 16:43:08 +08:00
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|