Files
order/dao/order_daily_statistics_dao.go
2025-12-30 11:03:11 +08:00

282 lines
7.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dao
import (
"context"
"fmt"
"time"
"order/consts"
"order/model/entity"
"gitee.com/red-future---jilin-g/common/do"
"gitee.com/red-future---jilin-g/common/mongo"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
// OrderDailyStatisticsDAO 订单日统计DAO
type OrderDailyStatisticsDAO struct {
}
var OrderDailyStatisticsDAOInstance = &OrderDailyStatisticsDAO{}
// GenerateStatistics 使用Go代码生成日统计数据
func (dao *OrderDailyStatisticsDAO) GenerateStatistics(ctx context.Context, tenantID int64, date time.Time) (*entity.OrderDailyStatistics, error) {
// 设置时间范围
startDate := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
endDate := startDate.Add(24 * time.Hour)
// 查询订单数据
filter := bson.M{
"tenantId": tenantID,
"createdAt": bson.M{
"$gte": startDate,
"$lt": endDate,
},
}
var orders []*entity.OrderBase
err := mongo.DB().Find(ctx, filter, &orders, consts.OrderCollection)
if err != nil {
return nil, fmt.Errorf("查询订单数据失败: %v", err)
}
// 如果没有数据,创建空统计
if len(orders) == 0 {
statistics := &entity.OrderDailyStatistics{
MongoBaseDO: do.MongoBaseDO{
TenantId: tenantID,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
ReportDate: startDate,
Period: startDate.Format("2006-01-02"),
}
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)
hourlyOrders := make([]int64, 24)
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]++
}
}
// 统计小时分布
hour := order.CreatedAt.Hour()
if hour >= 0 && hour < 24 {
hourlyOrders[hour]++
}
}
// 计算业务指标
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.OrderDailyStatistics{
MongoBaseDO: do.MongoBaseDO{
TenantId: tenantID,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
ReportDate: startDate,
Period: startDate.Format("2006-01-02"),
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,
HourlyOrders: hourlyOrders,
PeakHour: dao.findPeakHour(hourlyOrders),
}
return statistics, nil
}
// findTopAsset 找出热门资产
func (dao *OrderDailyStatisticsDAO) 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
}
// findPeakHour 找出高峰时段
func (dao *OrderDailyStatisticsDAO) findPeakHour(hourlyOrders []int64) int {
maxHour := 0
maxCount := int64(0)
for hour, count := range hourlyOrders {
if count > maxCount {
maxCount = count
maxHour = hour
}
}
return maxHour
}
// Save 保存日统计数据
func (dao *OrderDailyStatisticsDAO) Save(ctx context.Context, statistics *entity.OrderDailyStatistics) error {
_, err := mongo.DB().Insert(ctx, []interface{}{statistics}, consts.OrderDailyStatisticsCollection)
return err
}
// Update 更新日统计数据
func (dao *OrderDailyStatisticsDAO) Update(ctx context.Context, statistics *entity.OrderDailyStatistics) error {
filter := bson.M{
"tenantId": statistics.TenantId,
"reportDate": statistics.ReportDate,
}
update := bson.M{
"$set": statistics,
}
_, err := mongo.DB().Update(ctx, filter, update, consts.OrderDailyStatisticsCollection)
return err
}
// GetByTenantAndDate 获取指定租户和日期的日统计数据
func (dao *OrderDailyStatisticsDAO) GetByTenantAndDate(ctx context.Context, tenantID int64, reportDate time.Time) (*entity.OrderDailyStatistics, error) {
var result entity.OrderDailyStatistics
filter := bson.M{
"tenantId": tenantID,
"reportDate": reportDate,
}
err := mongo.DB().FindOne(ctx, filter, &result, consts.OrderDailyStatisticsCollection)
if err != nil {
return nil, err
}
return &result, nil
}
// GetListByTenant 获取指定租户的日统计列表
func (dao *OrderDailyStatisticsDAO) GetListByTenant(ctx context.Context, tenantID int64, startDate, endDate time.Time, pageNum, pageSize int) ([]*entity.OrderDailyStatistics, int64, error) {
filter := bson.M{
"tenantId": tenantID,
}
// 添加日期范围过滤
if !startDate.IsZero() || !endDate.IsZero() {
dateFilter := bson.M{}
if !startDate.IsZero() {
dateFilter["$gte"] = startDate
}
if !endDate.IsZero() {
dateFilter["$lte"] = endDate
}
filter["reportDate"] = dateFilter
}
// 获取总数
totalCount, err := mongo.DB().Count(ctx, filter, consts.OrderDailyStatisticsCollection)
if err != nil {
return nil, 0, err
}
// 分页查询
skip := int64((pageNum - 1) * pageSize)
var results []*entity.OrderDailyStatistics
// 使用mongo.DB().Find进行分页查询
err = mongo.DB().Find(ctx, filter, &results, consts.OrderDailyStatisticsCollection,
options.Find().SetSkip(skip).SetLimit(int64(pageSize)).SetSort(bson.D{{Key: "reportDate", Value: -1}}))
if err != nil {
return nil, 0, err
}
return results, totalCount, nil
}
// DeleteByTenantAndDate 删除指定日统计数据
func (dao *OrderDailyStatisticsDAO) DeleteByTenantAndDate(ctx context.Context, tenantID int64, reportDate time.Time) error {
filter := bson.M{
"tenantId": tenantID,
"reportDate": reportDate,
}
_, err := mongo.DB().Delete(ctx, filter, consts.OrderDailyStatisticsCollection)
return err
}