257 lines
13 KiB
Go
257 lines
13 KiB
Go
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
|
|
}
|