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 }