Files
order/dao/order_yearly_statistics_dao.go

279 lines
7.3 KiB
Go
Raw Permalink Normal View History

2025-12-12 16:20:47 +08:00
package dao
import (
"context"
"fmt"
"time"
"order/consts"
"order/model/entity"
2026-02-24 16:49:31 +08:00
"gitea.com/red-future/common/beans"
2026-02-24 17:17:10 +08:00
"gitea.com/red-future/common/db/mongo"
2025-12-30 11:03:11 +08:00
2025-12-12 16:20:47 +08:00
"go.mongodb.org/mongo-driver/v2/bson"
)
// OrderYearlyStatisticsDAO 订单年度统计DAO
type OrderYearlyStatisticsDAO struct {
}
2025-12-12 16:20:47 +08:00
2025-12-30 11:03:11 +08:00
var OrderYearlyStatisticsDAOInstance = &OrderYearlyStatisticsDAO{}
2025-12-12 16:20:47 +08:00
// GenerateStatistics 使用Go代码生成年度统计数据
func (dao *OrderYearlyStatisticsDAO) GenerateStatistics(ctx context.Context, tenantID int64, year int) (*entity.OrderYearlyStatistics, error) {
// 设置时间范围
startDate := time.Date(year, 1, 1, 0, 0, 0, 0, time.Local)
endDate := startDate.AddDate(1, 0, 0)
// 查询订单数据
filter := bson.M{
"tenantId": tenantID,
"createdAt": bson.M{
"$gte": startDate,
"$lt": endDate,
},
}
var orders []*entity.OrderBase
2025-12-30 11:03:11 +08:00
err := mongo.DB().Find(ctx, filter, &orders, consts.OrderCollection)
2025-12-12 16:20:47 +08:00
if err != nil {
return nil, fmt.Errorf("查询订单数据失败: %v", err)
}
// 如果没有数据,创建空统计
if len(orders) == 0 {
statistics := &entity.OrderYearlyStatistics{
2025-12-31 11:18:52 +08:00
MongoBaseDO: beans.MongoBaseDO{
2025-12-12 16:20:47 +08:00
TenantId: tenantID,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
ReportDate: startDate,
Period: startDate.Format("2006"),
Year: year,
}
return statistics, nil
}
// 使用Go代码计算统计指标
totalOrders := int64(len(orders))
totalAmount := int64(0)
completedOrders := int64(0)
cancelledOrders := int64(0)
paidOrders := int64(0)
totalItems := int64(0)
uniqueUsers := make(map[int64]bool)
uniqueAssets := make(map[string]bool)
assetCounts := make(map[string]int64)
quarterlyOrders := make([]int64, 4)
quarterlyAmounts := make([]int64, 4)
monthlyOrders := make([]int64, 12)
monthlyAmounts := make([]int64, 12)
for _, order := range orders {
// 计算总金额
totalAmount += order.TotalAmount
// 注意OrderBase结构体没有Status字段状态统计需要通过其他方式获取
// 统计唯一用户
uniqueUsers[order.UserID] = true
// 统计商品信息
if order.OrderItems != nil {
totalItems += int64(len(order.OrderItems))
for _, item := range order.OrderItems {
uniqueAssets[item.AssetID] = true
assetCounts[item.AssetID]++
}
}
// 统计季度分布
quarter := (int(order.CreatedAt.Month())-1)/3 + 1
if quarter >= 1 && quarter <= 4 {
quarterlyOrders[quarter-1]++
quarterlyAmounts[quarter-1] += order.TotalAmount
}
// 统计月度分布
month := int(order.CreatedAt.Month())
if month >= 1 && month <= 12 {
monthlyOrders[month-1]++
monthlyAmounts[month-1] += order.TotalAmount
}
}
// 计算业务指标
var averageOrderValue int64
if totalOrders > 0 {
averageOrderValue = totalAmount / totalOrders
}
var paymentRate, completionRate float64
if totalOrders > 0 {
paymentRate = float64(paidOrders) / float64(totalOrders) * 100
completionRate = float64(completedOrders) / float64(totalOrders) * 100
}
// 获取热门资产
topAssetID, topAssetName, topAssetCount := dao.findTopAsset(assetCounts, orders)
statistics := &entity.OrderYearlyStatistics{
2025-12-31 11:18:52 +08:00
MongoBaseDO: beans.MongoBaseDO{
2025-12-12 16:20:47 +08:00
TenantId: tenantID,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
ReportDate: startDate,
Period: startDate.Format("2006"),
Year: year,
TotalOrders: totalOrders,
CompletedOrders: completedOrders,
CancelledOrders: cancelledOrders,
PaidOrders: paidOrders,
TotalAmount: totalAmount,
PaidAmount: totalAmount,
NetAmount: totalAmount,
AverageOrderValue: averageOrderValue,
PaymentRate: paymentRate,
CompletionRate: completionRate,
UniqueUsers: int64(len(uniqueUsers)),
NewUsers: 0,
ReturningUsers: 0,
TotalItems: totalItems,
UniqueAssets: int64(len(uniqueAssets)),
TopAssetID: topAssetID,
TopAssetName: topAssetName,
TopAssetCount: topAssetCount,
QuarterlyOrders: quarterlyOrders,
QuarterlyAmounts: quarterlyAmounts,
PeakQuarter: dao.findPeakQuarter(quarterlyOrders),
MonthlyOrders: monthlyOrders,
MonthlyAmounts: monthlyAmounts,
YearOverYearGrowth: dao.calculateYearOverYearGrowth(ctx, tenantID, year, totalOrders),
}
return statistics, nil
}
// findTopAsset 找出热门资产
func (dao *OrderYearlyStatisticsDAO) findTopAsset(assetCounts map[string]int64, orders []*entity.OrderBase) (string, string, int64) {
if len(assetCounts) == 0 {
return "", "", 0
}
var topAssetID string
var maxCount int64
for assetID, count := range assetCounts {
if count > maxCount {
maxCount = count
topAssetID = assetID
}
}
// 查找资产名称
var topAssetName string
for _, order := range orders {
if order.OrderItems != nil {
for _, item := range order.OrderItems {
if item.AssetID == topAssetID {
topAssetName = item.AssetName
break
}
}
}
if topAssetName != "" {
break
}
}
return topAssetID, topAssetName, maxCount
}
// findPeakQuarter 找出高峰季度
func (dao *OrderYearlyStatisticsDAO) findPeakQuarter(quarterlyOrders []int64) int {
maxQuarter := 1
maxCount := int64(0)
for i, count := range quarterlyOrders {
if count > maxCount {
maxCount = count
maxQuarter = i + 1
}
}
return maxQuarter
}
// calculateYearOverYearGrowth 计算同比增长率
func (dao *OrderYearlyStatisticsDAO) calculateYearOverYearGrowth(ctx context.Context, tenantID int64, year int, currentOrders int64) float64 {
// 查询去年同期的订单数据
lastYear := year - 1
lastYearStartDate := time.Date(lastYear, 1, 1, 0, 0, 0, 0, time.Local)
lastYearEndDate := lastYearStartDate.AddDate(1, 0, 0)
filter := bson.M{
"tenantId": tenantID,
"createdAt": bson.M{
"$gte": lastYearStartDate,
"$lt": lastYearEndDate,
},
}
var lastYearOrders []*entity.OrderBase
2025-12-30 11:03:11 +08:00
err := mongo.DB().Find(ctx, filter, &lastYearOrders, consts.OrderCollection)
2025-12-12 16:20:47 +08:00
if err != nil || len(lastYearOrders) == 0 {
return 0.0
}
lastYearOrderCount := int64(len(lastYearOrders))
if lastYearOrderCount == 0 {
return 0.0
}
// 计算同比增长率
growth := (float64(currentOrders) - float64(lastYearOrderCount)) / float64(lastYearOrderCount) * 100
return growth
}
// Save 保存年度统计数据
func (dao *OrderYearlyStatisticsDAO) Save(ctx context.Context, statistics *entity.OrderYearlyStatistics) error {
2025-12-30 11:03:11 +08:00
_, err := mongo.DB().Insert(ctx, []interface{}{statistics}, consts.OrderYearlyStatisticsCollection)
2025-12-12 16:20:47 +08:00
return err
}
// Update 更新年度统计数据
func (dao *OrderYearlyStatisticsDAO) Update(ctx context.Context, statistics *entity.OrderYearlyStatistics) error {
filter := bson.M{
"tenantId": statistics.TenantId,
"reportDate": statistics.ReportDate,
}
update := bson.M{
"$set": statistics,
}
2025-12-30 11:03:11 +08:00
_, err := mongo.DB().Update(ctx, filter, update, consts.OrderYearlyStatisticsCollection)
2025-12-12 16:20:47 +08:00
return err
}
// GetByTenantAndDate 获取指定租户和日期的年度统计数据
func (dao *OrderYearlyStatisticsDAO) GetByTenantAndDate(ctx context.Context, tenantID int64, reportDate time.Time) (*entity.OrderYearlyStatistics, error) {
var result entity.OrderYearlyStatistics
filter := bson.M{
"tenantId": tenantID,
"reportDate": reportDate,
}
2025-12-30 11:03:11 +08:00
err := mongo.DB().FindOne(ctx, filter, &result, consts.OrderYearlyStatisticsCollection)
2025-12-12 16:20:47 +08:00
if err != nil {
return nil, err
}
return &result, nil
}