gomod引用

This commit is contained in:
2025-12-12 16:20:47 +08:00
parent 0393931e91
commit a4ba4dd715
27 changed files with 2886 additions and 87 deletions

View File

@@ -0,0 +1,279 @@
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"
"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.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.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.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.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.Count(ctx, filter, consts.OrderDailyStatisticsCollection)
if err != nil {
return nil, 0, err
}
// 分页查询
skip := int64((pageNum - 1) * pageSize)
var results []*entity.OrderDailyStatistics
// 使用mongo.Find进行分页查询
err = mongo.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.Delete(ctx, filter, consts.OrderDailyStatisticsCollection)
return err
}

View File

@@ -45,7 +45,7 @@ func (d *order) CreatePendingOrder(ctx context.Context, order *entity.OrderPendi
return err
}
order.ID = bson.NewObjectID()
order.Id = bson.NewObjectID()
order.CreatedAt = time.Now()
order.UpdatedAt = time.Now()

View 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
}

View File

@@ -0,0 +1,332 @@
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"
)
// 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.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.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.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.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.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.FindOne(ctx, filter, &result, consts.OrderQuarterlyStatisticsCollection)
if err != nil {
return nil, err
}
return &result, nil
}

View File

@@ -0,0 +1,201 @@
package dao
import (
"context"
"fmt"
"time"
"gitee.com/red-future---jilin-g/common/mongo"
"order/consts"
"order/model/entity"
"go.mongodb.org/mongo-driver/v2/bson"
)
// OrderStatisticsBaseDAO 订单统计基础DAO
type OrderStatisticsBaseDAO struct{}
var OrderStatisticsBaseDAOInstance = &OrderStatisticsBaseDAO{}
// OrderStats 订单统计结果
type OrderStats struct {
TotalOrders int64
TotalAmount int64
TotalItems int64
UniqueUsers map[int64]bool
UniqueAssets map[string]bool
AssetCounts map[string]int64
}
// GetOrderStats 获取订单统计信息
func (dao *OrderStatisticsBaseDAO) GetOrderStats(ctx context.Context, tenantID int64, startDate, endDate time.Time) (*OrderStats, error) {
stats := &OrderStats{
UniqueUsers: make(map[int64]bool),
UniqueAssets: make(map[string]bool),
AssetCounts: make(map[string]int64),
}
// 查询所有状态的订单数据
filter := bson.M{
"tenantId": tenantID,
"createdAt": bson.M{
"$gte": startDate,
"$lt": endDate,
},
}
// 查询待支付订单
var pendingOrders []*entity.OrderPending
err := mongo.Find(ctx, filter, &pendingOrders, consts.OrderPendingCollection)
if err != nil {
return nil, fmt.Errorf("查询待支付订单数据失败: %v", err)
}
// 查询已支付订单
var paidOrders []*entity.OrderPaid
err = mongo.Find(ctx, filter, &paidOrders, 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 completedOrders []*entity.OrderCompleted
err = mongo.Find(ctx, filter, &completedOrders, consts.OrderCompletedCollection)
if err != nil {
return nil, fmt.Errorf("查询已完成订单数据失败: %v", err)
}
// 统计待支付订单
for _, order := range pendingOrders {
stats.TotalOrders++
stats.TotalAmount += order.TotalAmount
stats.UniqueUsers[order.UserID] = true
if order.OrderItems != nil {
stats.TotalItems += int64(len(order.OrderItems))
for _, item := range order.OrderItems {
stats.UniqueAssets[item.AssetID] = true
stats.AssetCounts[item.AssetID]++
}
}
}
// 统计已支付订单
for _, order := range paidOrders {
stats.TotalOrders++
stats.TotalAmount += order.TotalAmount
stats.UniqueUsers[order.UserID] = true
if order.OrderItems != nil {
stats.TotalItems += int64(len(order.OrderItems))
for _, item := range order.OrderItems {
stats.UniqueAssets[item.AssetID] = true
stats.AssetCounts[item.AssetID]++
}
}
}
// 统计已发货订单
for _, order := range shippedOrders {
stats.TotalOrders++
stats.TotalAmount += order.TotalAmount
stats.UniqueUsers[order.UserID] = true
if order.OrderItems != nil {
stats.TotalItems += int64(len(order.OrderItems))
for _, item := range order.OrderItems {
stats.UniqueAssets[item.AssetID] = true
stats.AssetCounts[item.AssetID]++
}
}
}
// 统计已完成订单
for _, order := range completedOrders {
stats.TotalOrders++
stats.TotalAmount += order.TotalAmount
stats.UniqueUsers[order.UserID] = true
if order.OrderItems != nil {
stats.TotalItems += int64(len(order.OrderItems))
for _, item := range order.OrderItems {
stats.UniqueAssets[item.AssetID] = true
stats.AssetCounts[item.AssetID]++
}
}
}
return stats, nil
}
// FindTopAsset 找出热门资产
func (dao *OrderStatisticsBaseDAO) FindTopAsset(assetCounts map[string]int64, orders []interface{}) (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 {
switch o := order.(type) {
case *entity.OrderPending:
if o.OrderItems != nil {
for _, item := range o.OrderItems {
if item.AssetID == topAssetID {
topAssetName = item.AssetName
break
}
}
}
case *entity.OrderPaid:
if o.OrderItems != nil {
for _, item := range o.OrderItems {
if item.AssetID == topAssetID {
topAssetName = item.AssetName
break
}
}
}
case *entity.OrderShipped:
if o.OrderItems != nil {
for _, item := range o.OrderItems {
if item.AssetID == topAssetID {
topAssetName = item.AssetName
break
}
}
}
case *entity.OrderCompleted:
if o.OrderItems != nil {
for _, item := range o.OrderItems {
if item.AssetID == topAssetID {
topAssetName = item.AssetName
break
}
}
}
}
if topAssetName != "" {
break
}
}
return topAssetID, topAssetName, maxCount
}

View File

@@ -0,0 +1,276 @@
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"
)
// OrderYearlyStatisticsDAO 订单年度统计DAO
type OrderYearlyStatisticsDAO struct{}
var OrderYearlyStatisticsDAOInstance = &OrderYearlyStatisticsDAO{}
// 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
err := mongo.Find(ctx, filter, &orders, consts.OrderCollection)
if err != nil {
return nil, fmt.Errorf("查询订单数据失败: %v", err)
}
// 如果没有数据,创建空统计
if len(orders) == 0 {
statistics := &entity.OrderYearlyStatistics{
MongoBaseDO: do.MongoBaseDO{
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{
MongoBaseDO: do.MongoBaseDO{
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
err := mongo.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 *OrderYearlyStatisticsDAO) Save(ctx context.Context, statistics *entity.OrderYearlyStatistics) error {
_, err := mongo.Insert(ctx, []interface{}{statistics}, consts.OrderYearlyStatisticsCollection)
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,
}
_, err := mongo.Update(ctx, filter, update, consts.OrderYearlyStatisticsCollection)
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,
}
err := mongo.FindOne(ctx, filter, &result, consts.OrderYearlyStatisticsCollection)
if err != nil {
return nil, err
}
return &result, nil
}

View File

@@ -41,10 +41,10 @@ func (d *paymentConfig) GetByTenantAndMethod(ctx context.Context, tenantID, payM
// Update 更新支付配置
func (d *paymentConfig) Update(ctx context.Context, config *entity.PaymentConfig) error {
filter := bson.M{"_id": config.ID}
filter := bson.M{"_id": config.Id}
update := bson.M{
"$set": bson.M{
"tenant_id": config.TenantID,
"tenant_id": config.TenantId,
"pay_method": config.PayMethod,
"config_name": config.ConfigName,
"description": config.Description,
@@ -120,8 +120,8 @@ var PaymentRecord = new(paymentRecord)
// Create 创建支付记录
func (d *paymentRecord) Create(ctx context.Context, record *entity.PaymentRecord) error {
record.CreatedAt = time.Now().Unix()
record.UpdatedAt = time.Now().Unix()
record.CreatedAt = time.Now()
record.UpdatedAt = time.Now()
_, err := mongo.Insert(ctx, []interface{}{record}, consts.PaymentRecordCollection)
return err
@@ -165,8 +165,8 @@ var RefundRecord = new(refundRecord)
// Create 创建退款记录
func (d *refundRecord) Create(ctx context.Context, record *entity.RefundRecord) error {
record.CreatedAt = time.Now().Unix()
record.UpdatedAt = time.Now().Unix()
record.CreatedAt = time.Now()
record.UpdatedAt = time.Now()
_, err := mongo.Insert(ctx, []interface{}{record}, consts.RefundRecordCollection)
return err