gomod引用
This commit is contained in:
348
dao/order_monthly_statistics_dao.go
Normal file
348
dao/order_monthly_statistics_dao.go
Normal file
@@ -0,0 +1,348 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitee.com/red-future---jilin-g/common/do"
|
||||
"gitee.com/red-future---jilin-g/common/mongo"
|
||||
"order/consts"
|
||||
"order/model/entity"
|
||||
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
// OrderMonthlyStatisticsDAO 订单月统计DAO
|
||||
type OrderMonthlyStatisticsDAO struct{}
|
||||
|
||||
var OrderMonthlyStatisticsDAOInstance = &OrderMonthlyStatisticsDAO{}
|
||||
|
||||
// GenerateStatistics 使用Go代码生成月统计数据
|
||||
func (dao *OrderMonthlyStatisticsDAO) GenerateStatistics(ctx context.Context, tenantID int64, year int, month int) (*entity.OrderMonthlyStatistics, error) {
|
||||
// 设置时间范围
|
||||
startDate := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
|
||||
endDate := startDate.AddDate(0, 1, 0)
|
||||
|
||||
// 查询所有状态的订单数据
|
||||
var orders []*entity.OrderBase
|
||||
|
||||
// 查询待支付订单
|
||||
var pendingOrders []*entity.OrderPending
|
||||
filter := bson.M{
|
||||
"tenantId": tenantID,
|
||||
"createdAt": bson.M{
|
||||
"$gte": startDate,
|
||||
"$lt": endDate,
|
||||
},
|
||||
}
|
||||
err := mongo.Find(ctx, filter, &pendingOrders, consts.OrderPendingCollection)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询待支付订单数据失败: %v", err)
|
||||
}
|
||||
|
||||
// 查询已支付订单
|
||||
var paidOrderEntities []*entity.OrderPaid
|
||||
err = mongo.Find(ctx, filter, &paidOrderEntities, consts.OrderPaidCollection)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询已支付订单数据失败: %v", err)
|
||||
}
|
||||
|
||||
// 查询已发货订单
|
||||
var shippedOrders []*entity.OrderShipped
|
||||
err = mongo.Find(ctx, filter, &shippedOrders, consts.OrderShippedCollection)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询已发货订单数据失败: %v", err)
|
||||
}
|
||||
|
||||
// 查询已完成订单
|
||||
var completedOrderEntities []*entity.OrderCompleted
|
||||
err = mongo.Find(ctx, filter, &completedOrderEntities, consts.OrderCompletedCollection)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询已完成订单数据失败: %v", err)
|
||||
}
|
||||
|
||||
// 合并所有订单到基础订单结构
|
||||
for _, order := range pendingOrders {
|
||||
orders = append(orders, &entity.OrderBase{
|
||||
MongoBaseDO: order.MongoBaseDO,
|
||||
OrderNo: order.OrderNo,
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: order.OrderItems,
|
||||
ExpiredAt: order.ExpiredAt,
|
||||
})
|
||||
}
|
||||
|
||||
for _, order := range paidOrderEntities {
|
||||
orders = append(orders, &entity.OrderBase{
|
||||
MongoBaseDO: order.MongoBaseDO,
|
||||
OrderNo: order.OrderNo,
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: order.OrderItems,
|
||||
ExpiredAt: order.ExpiredAt,
|
||||
})
|
||||
}
|
||||
|
||||
for _, order := range shippedOrders {
|
||||
orders = append(orders, &entity.OrderBase{
|
||||
MongoBaseDO: order.MongoBaseDO,
|
||||
OrderNo: order.OrderNo,
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: order.OrderItems,
|
||||
ExpiredAt: order.ExpiredAt,
|
||||
})
|
||||
}
|
||||
|
||||
for _, order := range completedOrderEntities {
|
||||
orders = append(orders, &entity.OrderBase{
|
||||
MongoBaseDO: order.MongoBaseDO,
|
||||
OrderNo: order.OrderNo,
|
||||
UserID: order.UserID,
|
||||
TotalAmount: order.TotalAmount,
|
||||
PayAmount: order.PayAmount,
|
||||
OrderType: order.OrderType,
|
||||
Subject: order.Subject,
|
||||
Description: order.Description,
|
||||
OrderItems: order.OrderItems,
|
||||
ExpiredAt: order.ExpiredAt,
|
||||
})
|
||||
}
|
||||
|
||||
// 如果没有数据,创建空统计
|
||||
if len(orders) == 0 {
|
||||
statistics := &entity.OrderMonthlyStatistics{
|
||||
MongoBaseDO: do.MongoBaseDO{
|
||||
TenantId: tenantID,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
ReportDate: startDate,
|
||||
Period: startDate.Format("2006-01"),
|
||||
}
|
||||
return statistics, nil
|
||||
}
|
||||
|
||||
// 使用Go代码计算统计指标
|
||||
totalOrders := int64(0)
|
||||
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)
|
||||
dailyOrders := make([]int64, 31)
|
||||
dailyAmounts := make([]int64, 31)
|
||||
|
||||
for _, order := range orders {
|
||||
// 计算总金额
|
||||
totalAmount += order.TotalAmount
|
||||
|
||||
// 统计订单状态(基于订单来源集合推断)
|
||||
// 由于订单已按状态拆分,这里可以统计总订单数
|
||||
totalOrders++
|
||||
|
||||
// 统计唯一用户
|
||||
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]++
|
||||
}
|
||||
}
|
||||
|
||||
// 统计每日分布
|
||||
day := order.CreatedAt.Day()
|
||||
if day >= 1 && day <= 31 {
|
||||
dailyOrders[day-1]++
|
||||
dailyAmounts[day-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.OrderMonthlyStatistics{
|
||||
MongoBaseDO: do.MongoBaseDO{
|
||||
TenantId: tenantID,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
ReportDate: startDate,
|
||||
Period: startDate.Format("2006-01"),
|
||||
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,
|
||||
DailyOrders: dailyOrders,
|
||||
DailyAmounts: dailyAmounts,
|
||||
PeakDay: dao.findPeakDay(dailyOrders),
|
||||
MonthOverMonthGrowth: dao.calculateMonthOverMonthGrowth(ctx, tenantID, startDate, totalOrders),
|
||||
}
|
||||
|
||||
return statistics, nil
|
||||
}
|
||||
|
||||
// findTopAsset 找出热门资产
|
||||
func (dao *OrderMonthlyStatisticsDAO) 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
|
||||
}
|
||||
|
||||
// findPeakDay 找出高峰日
|
||||
func (dao *OrderMonthlyStatisticsDAO) findPeakDay(dailyOrders []int64) int {
|
||||
maxDay := 1
|
||||
maxCount := int64(0)
|
||||
|
||||
for day, count := range dailyOrders {
|
||||
if count > maxCount {
|
||||
maxCount = count
|
||||
maxDay = day + 1
|
||||
}
|
||||
}
|
||||
|
||||
return maxDay
|
||||
}
|
||||
|
||||
// calculateMonthOverMonthGrowth 计算环比增长率
|
||||
func (dao *OrderMonthlyStatisticsDAO) calculateMonthOverMonthGrowth(ctx context.Context, tenantID int64, currentMonth time.Time, currentOrders int64) float64 {
|
||||
lastMonth := currentMonth.AddDate(0, -1, 0)
|
||||
lastMonthEnd := lastMonth.AddDate(0, 1, -1)
|
||||
|
||||
// 查询上个月的订单数据
|
||||
filter := bson.M{
|
||||
"tenantId": tenantID,
|
||||
"createdAt": bson.M{
|
||||
"$gte": lastMonth,
|
||||
"$lt": lastMonthEnd,
|
||||
},
|
||||
}
|
||||
|
||||
var lastMonthOrders []*entity.OrderBase
|
||||
err := mongo.Find(ctx, filter, &lastMonthOrders, consts.OrderCollection)
|
||||
if err != nil || len(lastMonthOrders) == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
lastMonthOrderCount := int64(len(lastMonthOrders))
|
||||
if lastMonthOrderCount == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
// 计算环比增长率
|
||||
growth := (float64(currentOrders) - float64(lastMonthOrderCount)) / float64(lastMonthOrderCount) * 100
|
||||
return growth
|
||||
}
|
||||
|
||||
// Save 保存月统计数据
|
||||
func (dao *OrderMonthlyStatisticsDAO) Save(ctx context.Context, statistics *entity.OrderMonthlyStatistics) error {
|
||||
_, err := mongo.Insert(ctx, []interface{}{statistics}, consts.OrderMonthlyStatisticsCollection)
|
||||
return err
|
||||
}
|
||||
|
||||
// Update 更新月统计数据
|
||||
func (dao *OrderMonthlyStatisticsDAO) Update(ctx context.Context, statistics *entity.OrderMonthlyStatistics) error {
|
||||
filter := bson.M{
|
||||
"tenantId": statistics.TenantId,
|
||||
"reportDate": statistics.ReportDate,
|
||||
}
|
||||
|
||||
update := bson.M{
|
||||
"$set": statistics,
|
||||
}
|
||||
|
||||
_, err := mongo.Update(ctx, filter, update, consts.OrderMonthlyStatisticsCollection)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetByTenantAndDate 获取指定租户和日期的月统计数据
|
||||
func (dao *OrderMonthlyStatisticsDAO) GetByTenantAndDate(ctx context.Context, tenantID int64, reportDate time.Time) (*entity.OrderMonthlyStatistics, error) {
|
||||
var result entity.OrderMonthlyStatistics
|
||||
|
||||
filter := bson.M{
|
||||
"tenantId": tenantID,
|
||||
"reportDate": reportDate,
|
||||
}
|
||||
|
||||
err := mongo.FindOne(ctx, filter, &result, consts.OrderMonthlyStatisticsCollection)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user