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" ) // OrderQuarterlyStatisticsDAO 订单季度统计DAO type OrderQuarterlyStatisticsDAO struct { } var OrderQuarterlyStatisticsDAOInstance = &OrderQuarterlyStatisticsDAO{} // GenerateStatistics 使用Go代码生成季度统计数据 func (dao *OrderQuarterlyStatisticsDAO) GenerateStatistics(ctx context.Context, tenantID int64, year int, quarter int) (*entity.OrderQuarterlyStatistics, error) { // 设置时间范围 var startDate time.Time switch quarter { case 1: startDate = time.Date(year, 1, 1, 0, 0, 0, 0, time.Local) case 2: startDate = time.Date(year, 4, 1, 0, 0, 0, 0, time.Local) case 3: startDate = time.Date(year, 7, 1, 0, 0, 0, 0, time.Local) case 4: startDate = time.Date(year, 10, 1, 0, 0, 0, 0, time.Local) default: return nil, fmt.Errorf("无效的季度: %d", quarter) } endDate := startDate.AddDate(0, 3, 0) // 查询订单数据 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.OrderQuarterlyStatistics{ MongoBaseDO: do.MongoBaseDO{ TenantId: tenantID, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, ReportDate: startDate, Period: fmt.Sprintf("%d-Q%d", year, quarter), Quarter: quarter, } 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) monthlyOrders := make([]int64, 3) monthlyAmounts := make([]int64, 3) 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]++ } } // 统计月度分布 month := int(order.CreatedAt.Month()) quarterStartMonth := int(startDate.Month()) if month >= quarterStartMonth && month < quarterStartMonth+3 { index := month - quarterStartMonth if index >= 0 && index < 3 { monthlyOrders[index]++ monthlyAmounts[index] += 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.OrderQuarterlyStatistics{ MongoBaseDO: do.MongoBaseDO{ TenantId: tenantID, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, ReportDate: startDate, Period: fmt.Sprintf("%d-Q%d", year, quarter), Quarter: quarter, 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, MonthlyOrders: monthlyOrders, MonthlyAmounts: monthlyAmounts, PeakMonth: dao.findPeakMonth(monthlyOrders), QuarterOverQuarterGrowth: dao.calculateQuarterOverQuarterGrowth(ctx, tenantID, year, quarter, totalOrders), YearOverYearGrowth: dao.calculateYearOverYearGrowth(ctx, tenantID, year, totalOrders), } return statistics, nil } // findTopAsset 找出热门资产 func (dao *OrderQuarterlyStatisticsDAO) 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 } // findPeakMonth 找出高峰月份 func (dao *OrderQuarterlyStatisticsDAO) findPeakMonth(monthlyOrders []int64) int { maxMonth := 1 maxCount := int64(0) for i, count := range monthlyOrders { if count > maxCount { maxCount = count maxMonth = i + 1 } } return maxMonth } // calculateQuarterOverQuarterGrowth 计算环比增长率 func (dao *OrderQuarterlyStatisticsDAO) calculateQuarterOverQuarterGrowth(ctx context.Context, tenantID int64, year, quarter int, currentOrders int64) float64 { // 计算上个季度 lastYear := year lastQuarter := quarter - 1 if lastQuarter == 0 { lastYear = year - 1 lastQuarter = 4 } // 查询上个季度的订单数据 var lastQuarterStartDate time.Time switch lastQuarter { case 1: lastQuarterStartDate = time.Date(lastYear, 1, 1, 0, 0, 0, 0, time.Local) case 2: lastQuarterStartDate = time.Date(lastYear, 4, 1, 0, 0, 0, 0, time.Local) case 3: lastQuarterStartDate = time.Date(lastYear, 7, 1, 0, 0, 0, 0, time.Local) case 4: lastQuarterStartDate = time.Date(lastYear, 10, 1, 0, 0, 0, 0, time.Local) default: return 0.0 } lastQuarterEndDate := lastQuarterStartDate.AddDate(0, 3, 0) filter := bson.M{ "tenantId": tenantID, "createdAt": bson.M{ "$gte": lastQuarterStartDate, "$lt": lastQuarterEndDate, }, } var lastQuarterOrders []*entity.OrderBase err := mongo.DB().Find(ctx, filter, &lastQuarterOrders, consts.OrderCollection) if err != nil || len(lastQuarterOrders) == 0 { return 0.0 } lastQuarterOrderCount := int64(len(lastQuarterOrders)) if lastQuarterOrderCount == 0 { return 0.0 } // 计算环比增长率 growth := (float64(currentOrders) - float64(lastQuarterOrderCount)) / float64(lastQuarterOrderCount) * 100 return growth } // calculateYearOverYearGrowth 计算同比增长率 func (dao *OrderQuarterlyStatisticsDAO) 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 err := mongo.DB().Find(ctx, filter, &lastYearOrders, consts.OrderCollection) 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 *OrderQuarterlyStatisticsDAO) Save(ctx context.Context, statistics *entity.OrderQuarterlyStatistics) error { _, err := mongo.DB().Insert(ctx, []interface{}{statistics}, consts.OrderQuarterlyStatisticsCollection) return err } // Update 更新季度统计数据 func (dao *OrderQuarterlyStatisticsDAO) Update(ctx context.Context, statistics *entity.OrderQuarterlyStatistics) error { filter := bson.M{ "tenantId": statistics.TenantId, "reportDate": statistics.ReportDate, } update := bson.M{ "$set": statistics, } _, err := mongo.DB().Update(ctx, filter, update, consts.OrderQuarterlyStatisticsCollection) return err } // GetByTenantAndDate 获取指定租户和日期的季度统计数据 func (dao *OrderQuarterlyStatisticsDAO) GetByTenantAndDate(ctx context.Context, tenantID int64, reportDate time.Time) (*entity.OrderQuarterlyStatistics, error) { var result entity.OrderQuarterlyStatistics filter := bson.M{ "tenantId": tenantID, "reportDate": reportDate, } err := mongo.DB().FindOne(ctx, filter, &result, consts.OrderQuarterlyStatisticsCollection) if err != nil { return nil, err } return &result, nil }