This commit is contained in:
2025-09-12 01:15:09 +08:00
parent c563b2266b
commit e05ad9e223
103 changed files with 20034 additions and 1041 deletions

View File

@@ -0,0 +1,461 @@
package statistics
import (
"context"
"fmt"
"gorm.io/gorm"
"tyapi-server/internal/domains/statistics/entities"
"tyapi-server/internal/domains/statistics/repositories"
)
// GormStatisticsDashboardRepository GORM统计仪表板仓储实现
type GormStatisticsDashboardRepository struct {
db *gorm.DB
}
// NewGormStatisticsDashboardRepository 创建GORM统计仪表板仓储
func NewGormStatisticsDashboardRepository(db *gorm.DB) repositories.StatisticsDashboardRepository {
return &GormStatisticsDashboardRepository{
db: db,
}
}
// Save 保存统计仪表板
func (r *GormStatisticsDashboardRepository) Save(ctx context.Context, dashboard *entities.StatisticsDashboard) error {
if dashboard == nil {
return fmt.Errorf("统计仪表板不能为空")
}
// 验证仪表板
if err := dashboard.Validate(); err != nil {
return fmt.Errorf("统计仪表板验证失败: %w", err)
}
// 保存到数据库
result := r.db.WithContext(ctx).Save(dashboard)
if result.Error != nil {
return fmt.Errorf("保存统计仪表板失败: %w", result.Error)
}
return nil
}
// FindByID 根据ID查找统计仪表板
func (r *GormStatisticsDashboardRepository) FindByID(ctx context.Context, id string) (*entities.StatisticsDashboard, error) {
if id == "" {
return nil, fmt.Errorf("仪表板ID不能为空")
}
var dashboard entities.StatisticsDashboard
result := r.db.WithContext(ctx).Where("id = ?", id).First(&dashboard)
if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("统计仪表板不存在")
}
return nil, fmt.Errorf("查询统计仪表板失败: %w", result.Error)
}
return &dashboard, nil
}
// FindByUser 根据用户查找统计仪表板
func (r *GormStatisticsDashboardRepository) FindByUser(ctx context.Context, userID string, limit, offset int) ([]*entities.StatisticsDashboard, error) {
if userID == "" {
return nil, fmt.Errorf("用户ID不能为空")
}
var dashboards []*entities.StatisticsDashboard
query := r.db.WithContext(ctx).Where("created_by = ?", userID)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&dashboards)
if result.Error != nil {
return nil, fmt.Errorf("查询统计仪表板失败: %w", result.Error)
}
return dashboards, nil
}
// FindByUserRole 根据用户角色查找统计仪表板
func (r *GormStatisticsDashboardRepository) FindByUserRole(ctx context.Context, userRole string, limit, offset int) ([]*entities.StatisticsDashboard, error) {
if userRole == "" {
return nil, fmt.Errorf("用户角色不能为空")
}
var dashboards []*entities.StatisticsDashboard
query := r.db.WithContext(ctx).Where("user_role = ?", userRole)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&dashboards)
if result.Error != nil {
return nil, fmt.Errorf("查询统计仪表板失败: %w", result.Error)
}
return dashboards, nil
}
// Update 更新统计仪表板
func (r *GormStatisticsDashboardRepository) Update(ctx context.Context, dashboard *entities.StatisticsDashboard) error {
if dashboard == nil {
return fmt.Errorf("统计仪表板不能为空")
}
if dashboard.ID == "" {
return fmt.Errorf("仪表板ID不能为空")
}
// 验证仪表板
if err := dashboard.Validate(); err != nil {
return fmt.Errorf("统计仪表板验证失败: %w", err)
}
// 更新数据库
result := r.db.WithContext(ctx).Save(dashboard)
if result.Error != nil {
return fmt.Errorf("更新统计仪表板失败: %w", result.Error)
}
return nil
}
// Delete 删除统计仪表板
func (r *GormStatisticsDashboardRepository) Delete(ctx context.Context, id string) error {
if id == "" {
return fmt.Errorf("仪表板ID不能为空")
}
result := r.db.WithContext(ctx).Delete(&entities.StatisticsDashboard{}, "id = ?", id)
if result.Error != nil {
return fmt.Errorf("删除统计仪表板失败: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("统计仪表板不存在")
}
return nil
}
// FindByRole 根据角色查找统计仪表板
func (r *GormStatisticsDashboardRepository) FindByRole(ctx context.Context, userRole string, limit, offset int) ([]*entities.StatisticsDashboard, error) {
if userRole == "" {
return nil, fmt.Errorf("用户角色不能为空")
}
var dashboards []*entities.StatisticsDashboard
query := r.db.WithContext(ctx).Where("user_role = ?", userRole)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&dashboards)
if result.Error != nil {
return nil, fmt.Errorf("查询统计仪表板失败: %w", result.Error)
}
return dashboards, nil
}
// FindDefaultByRole 根据角色查找默认统计仪表板
func (r *GormStatisticsDashboardRepository) FindDefaultByRole(ctx context.Context, userRole string) (*entities.StatisticsDashboard, error) {
if userRole == "" {
return nil, fmt.Errorf("用户角色不能为空")
}
var dashboard entities.StatisticsDashboard
result := r.db.WithContext(ctx).
Where("user_role = ? AND is_default = ? AND is_active = ?", userRole, true, true).
First(&dashboard)
if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("默认统计仪表板不存在")
}
return nil, fmt.Errorf("查询默认统计仪表板失败: %w", result.Error)
}
return &dashboard, nil
}
// FindActiveByRole 根据角色查找激活的统计仪表板
func (r *GormStatisticsDashboardRepository) FindActiveByRole(ctx context.Context, userRole string, limit, offset int) ([]*entities.StatisticsDashboard, error) {
if userRole == "" {
return nil, fmt.Errorf("用户角色不能为空")
}
var dashboards []*entities.StatisticsDashboard
query := r.db.WithContext(ctx).
Where("user_role = ? AND is_active = ?", userRole, true)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&dashboards)
if result.Error != nil {
return nil, fmt.Errorf("查询激活统计仪表板失败: %w", result.Error)
}
return dashboards, nil
}
// FindByStatus 根据状态查找统计仪表板
func (r *GormStatisticsDashboardRepository) FindByStatus(ctx context.Context, isActive bool, limit, offset int) ([]*entities.StatisticsDashboard, error) {
var dashboards []*entities.StatisticsDashboard
query := r.db.WithContext(ctx).Where("is_active = ?", isActive)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&dashboards)
if result.Error != nil {
return nil, fmt.Errorf("查询统计仪表板失败: %w", result.Error)
}
return dashboards, nil
}
// FindByAccessLevel 根据访问级别查找统计仪表板
func (r *GormStatisticsDashboardRepository) FindByAccessLevel(ctx context.Context, accessLevel string, limit, offset int) ([]*entities.StatisticsDashboard, error) {
if accessLevel == "" {
return nil, fmt.Errorf("访问级别不能为空")
}
var dashboards []*entities.StatisticsDashboard
query := r.db.WithContext(ctx).Where("access_level = ?", accessLevel)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&dashboards)
if result.Error != nil {
return nil, fmt.Errorf("查询统计仪表板失败: %w", result.Error)
}
return dashboards, nil
}
// CountByUser 根据用户统计数量
func (r *GormStatisticsDashboardRepository) CountByUser(ctx context.Context, userID string) (int64, error) {
if userID == "" {
return 0, fmt.Errorf("用户ID不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsDashboard{}).
Where("created_by = ?", userID).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计仪表板数量失败: %w", result.Error)
}
return count, nil
}
// CountByRole 根据角色统计数量
func (r *GormStatisticsDashboardRepository) CountByRole(ctx context.Context, userRole string) (int64, error) {
if userRole == "" {
return 0, fmt.Errorf("用户角色不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsDashboard{}).
Where("user_role = ?", userRole).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计仪表板数量失败: %w", result.Error)
}
return count, nil
}
// CountByStatus 根据状态统计数量
func (r *GormStatisticsDashboardRepository) CountByStatus(ctx context.Context, isActive bool) (int64, error) {
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsDashboard{}).
Where("is_active = ?", isActive).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计仪表板数量失败: %w", result.Error)
}
return count, nil
}
// BatchSave 批量保存统计仪表板
func (r *GormStatisticsDashboardRepository) BatchSave(ctx context.Context, dashboards []*entities.StatisticsDashboard) error {
if len(dashboards) == 0 {
return fmt.Errorf("统计仪表板列表不能为空")
}
// 验证所有仪表板
for _, dashboard := range dashboards {
if err := dashboard.Validate(); err != nil {
return fmt.Errorf("统计仪表板验证失败: %w", err)
}
}
// 批量保存
result := r.db.WithContext(ctx).CreateInBatches(dashboards, 100)
if result.Error != nil {
return fmt.Errorf("批量保存统计仪表板失败: %w", result.Error)
}
return nil
}
// BatchDelete 批量删除统计仪表板
func (r *GormStatisticsDashboardRepository) BatchDelete(ctx context.Context, ids []string) error {
if len(ids) == 0 {
return fmt.Errorf("仪表板ID列表不能为空")
}
result := r.db.WithContext(ctx).Delete(&entities.StatisticsDashboard{}, "id IN ?", ids)
if result.Error != nil {
return fmt.Errorf("批量删除统计仪表板失败: %w", result.Error)
}
return nil
}
// SetDefaultDashboard 设置默认仪表板
func (r *GormStatisticsDashboardRepository) SetDefaultDashboard(ctx context.Context, dashboardID string) error {
if dashboardID == "" {
return fmt.Errorf("仪表板ID不能为空")
}
// 开始事务
tx := r.db.WithContext(ctx).Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 先取消同角色的所有默认状态
var dashboard entities.StatisticsDashboard
if err := tx.Where("id = ?", dashboardID).First(&dashboard).Error; err != nil {
tx.Rollback()
return fmt.Errorf("查询仪表板失败: %w", err)
}
// 取消同角色的所有默认状态
if err := tx.Model(&entities.StatisticsDashboard{}).
Where("user_role = ? AND is_default = ?", dashboard.UserRole, true).
Update("is_default", false).Error; err != nil {
tx.Rollback()
return fmt.Errorf("取消默认状态失败: %w", err)
}
// 设置新的默认状态
if err := tx.Model(&entities.StatisticsDashboard{}).
Where("id = ?", dashboardID).
Update("is_default", true).Error; err != nil {
tx.Rollback()
return fmt.Errorf("设置默认状态失败: %w", err)
}
// 提交事务
if err := tx.Commit().Error; err != nil {
return fmt.Errorf("提交事务失败: %w", err)
}
return nil
}
// RemoveDefaultDashboard 移除默认仪表板
func (r *GormStatisticsDashboardRepository) RemoveDefaultDashboard(ctx context.Context, userRole string) error {
if userRole == "" {
return fmt.Errorf("用户角色不能为空")
}
result := r.db.WithContext(ctx).
Model(&entities.StatisticsDashboard{}).
Where("user_role = ? AND is_default = ?", userRole, true).
Update("is_default", false)
if result.Error != nil {
return fmt.Errorf("移除默认仪表板失败: %w", result.Error)
}
return nil
}
// ActivateDashboard 激活仪表板
func (r *GormStatisticsDashboardRepository) ActivateDashboard(ctx context.Context, dashboardID string) error {
if dashboardID == "" {
return fmt.Errorf("仪表板ID不能为空")
}
result := r.db.WithContext(ctx).
Model(&entities.StatisticsDashboard{}).
Where("id = ?", dashboardID).
Update("is_active", true)
if result.Error != nil {
return fmt.Errorf("激活仪表板失败: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("仪表板不存在")
}
return nil
}
// DeactivateDashboard 停用仪表板
func (r *GormStatisticsDashboardRepository) DeactivateDashboard(ctx context.Context, dashboardID string) error {
if dashboardID == "" {
return fmt.Errorf("仪表板ID不能为空")
}
result := r.db.WithContext(ctx).
Model(&entities.StatisticsDashboard{}).
Where("id = ?", dashboardID).
Update("is_active", false)
if result.Error != nil {
return fmt.Errorf("停用仪表板失败: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("仪表板不存在")
}
return nil
}

View File

@@ -0,0 +1,377 @@
package statistics
import (
"context"
"fmt"
"time"
"gorm.io/gorm"
"tyapi-server/internal/domains/statistics/entities"
"tyapi-server/internal/domains/statistics/repositories"
)
// GormStatisticsReportRepository GORM统计报告仓储实现
type GormStatisticsReportRepository struct {
db *gorm.DB
}
// NewGormStatisticsReportRepository 创建GORM统计报告仓储
func NewGormStatisticsReportRepository(db *gorm.DB) repositories.StatisticsReportRepository {
return &GormStatisticsReportRepository{
db: db,
}
}
// Save 保存统计报告
func (r *GormStatisticsReportRepository) Save(ctx context.Context, report *entities.StatisticsReport) error {
if report == nil {
return fmt.Errorf("统计报告不能为空")
}
// 验证报告
if err := report.Validate(); err != nil {
return fmt.Errorf("统计报告验证失败: %w", err)
}
// 保存到数据库
result := r.db.WithContext(ctx).Save(report)
if result.Error != nil {
return fmt.Errorf("保存统计报告失败: %w", result.Error)
}
return nil
}
// FindByID 根据ID查找统计报告
func (r *GormStatisticsReportRepository) FindByID(ctx context.Context, id string) (*entities.StatisticsReport, error) {
if id == "" {
return nil, fmt.Errorf("报告ID不能为空")
}
var report entities.StatisticsReport
result := r.db.WithContext(ctx).Where("id = ?", id).First(&report)
if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("统计报告不存在")
}
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return &report, nil
}
// FindByUser 根据用户查找统计报告
func (r *GormStatisticsReportRepository) FindByUser(ctx context.Context, userID string, limit, offset int) ([]*entities.StatisticsReport, error) {
if userID == "" {
return nil, fmt.Errorf("用户ID不能为空")
}
var reports []*entities.StatisticsReport
query := r.db.WithContext(ctx).Where("generated_by = ?", userID)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&reports)
if result.Error != nil {
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return reports, nil
}
// FindByStatus 根据状态查找统计报告
func (r *GormStatisticsReportRepository) FindByStatus(ctx context.Context, status string) ([]*entities.StatisticsReport, error) {
if status == "" {
return nil, fmt.Errorf("报告状态不能为空")
}
var reports []*entities.StatisticsReport
result := r.db.WithContext(ctx).
Where("status = ?", status).
Order("created_at DESC").
Find(&reports)
if result.Error != nil {
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return reports, nil
}
// Update 更新统计报告
func (r *GormStatisticsReportRepository) Update(ctx context.Context, report *entities.StatisticsReport) error {
if report == nil {
return fmt.Errorf("统计报告不能为空")
}
if report.ID == "" {
return fmt.Errorf("报告ID不能为空")
}
// 验证报告
if err := report.Validate(); err != nil {
return fmt.Errorf("统计报告验证失败: %w", err)
}
// 更新数据库
result := r.db.WithContext(ctx).Save(report)
if result.Error != nil {
return fmt.Errorf("更新统计报告失败: %w", result.Error)
}
return nil
}
// Delete 删除统计报告
func (r *GormStatisticsReportRepository) Delete(ctx context.Context, id string) error {
if id == "" {
return fmt.Errorf("报告ID不能为空")
}
result := r.db.WithContext(ctx).Delete(&entities.StatisticsReport{}, "id = ?", id)
if result.Error != nil {
return fmt.Errorf("删除统计报告失败: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("统计报告不存在")
}
return nil
}
// FindByType 根据类型查找统计报告
func (r *GormStatisticsReportRepository) FindByType(ctx context.Context, reportType string, limit, offset int) ([]*entities.StatisticsReport, error) {
if reportType == "" {
return nil, fmt.Errorf("报告类型不能为空")
}
var reports []*entities.StatisticsReport
query := r.db.WithContext(ctx).Where("report_type = ?", reportType)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&reports)
if result.Error != nil {
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return reports, nil
}
// FindByTypeAndPeriod 根据类型和周期查找统计报告
func (r *GormStatisticsReportRepository) FindByTypeAndPeriod(ctx context.Context, reportType, period string, limit, offset int) ([]*entities.StatisticsReport, error) {
if reportType == "" {
return nil, fmt.Errorf("报告类型不能为空")
}
if period == "" {
return nil, fmt.Errorf("统计周期不能为空")
}
var reports []*entities.StatisticsReport
query := r.db.WithContext(ctx).
Where("report_type = ? AND period = ?", reportType, period)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&reports)
if result.Error != nil {
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return reports, nil
}
// FindByDateRange 根据日期范围查找统计报告
func (r *GormStatisticsReportRepository) FindByDateRange(ctx context.Context, startDate, endDate time.Time, limit, offset int) ([]*entities.StatisticsReport, error) {
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
var reports []*entities.StatisticsReport
query := r.db.WithContext(ctx).
Where("created_at >= ? AND created_at < ?", startDate, endDate)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&reports)
if result.Error != nil {
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return reports, nil
}
// FindByUserAndDateRange 根据用户和日期范围查找统计报告
func (r *GormStatisticsReportRepository) FindByUserAndDateRange(ctx context.Context, userID string, startDate, endDate time.Time, limit, offset int) ([]*entities.StatisticsReport, error) {
if userID == "" {
return nil, fmt.Errorf("用户ID不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
var reports []*entities.StatisticsReport
query := r.db.WithContext(ctx).
Where("generated_by = ? AND created_at >= ? AND created_at < ?", userID, startDate, endDate)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&reports)
if result.Error != nil {
return nil, fmt.Errorf("查询统计报告失败: %w", result.Error)
}
return reports, nil
}
// CountByUser 根据用户统计数量
func (r *GormStatisticsReportRepository) CountByUser(ctx context.Context, userID string) (int64, error) {
if userID == "" {
return 0, fmt.Errorf("用户ID不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsReport{}).
Where("generated_by = ?", userID).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计报告数量失败: %w", result.Error)
}
return count, nil
}
// CountByType 根据类型统计数量
func (r *GormStatisticsReportRepository) CountByType(ctx context.Context, reportType string) (int64, error) {
if reportType == "" {
return 0, fmt.Errorf("报告类型不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsReport{}).
Where("report_type = ?", reportType).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计报告数量失败: %w", result.Error)
}
return count, nil
}
// CountByStatus 根据状态统计数量
func (r *GormStatisticsReportRepository) CountByStatus(ctx context.Context, status string) (int64, error) {
if status == "" {
return 0, fmt.Errorf("报告状态不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsReport{}).
Where("status = ?", status).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计报告数量失败: %w", result.Error)
}
return count, nil
}
// BatchSave 批量保存统计报告
func (r *GormStatisticsReportRepository) BatchSave(ctx context.Context, reports []*entities.StatisticsReport) error {
if len(reports) == 0 {
return fmt.Errorf("统计报告列表不能为空")
}
// 验证所有报告
for _, report := range reports {
if err := report.Validate(); err != nil {
return fmt.Errorf("统计报告验证失败: %w", err)
}
}
// 批量保存
result := r.db.WithContext(ctx).CreateInBatches(reports, 100)
if result.Error != nil {
return fmt.Errorf("批量保存统计报告失败: %w", result.Error)
}
return nil
}
// BatchDelete 批量删除统计报告
func (r *GormStatisticsReportRepository) BatchDelete(ctx context.Context, ids []string) error {
if len(ids) == 0 {
return fmt.Errorf("报告ID列表不能为空")
}
result := r.db.WithContext(ctx).Delete(&entities.StatisticsReport{}, "id IN ?", ids)
if result.Error != nil {
return fmt.Errorf("批量删除统计报告失败: %w", result.Error)
}
return nil
}
// DeleteExpiredReports 删除过期报告
func (r *GormStatisticsReportRepository) DeleteExpiredReports(ctx context.Context, expiredBefore time.Time) error {
if expiredBefore.IsZero() {
return fmt.Errorf("过期时间不能为空")
}
result := r.db.WithContext(ctx).
Delete(&entities.StatisticsReport{}, "expires_at IS NOT NULL AND expires_at < ?", expiredBefore)
if result.Error != nil {
return fmt.Errorf("删除过期报告失败: %w", result.Error)
}
return nil
}
// DeleteByStatus 根据状态删除统计报告
func (r *GormStatisticsReportRepository) DeleteByStatus(ctx context.Context, status string) error {
if status == "" {
return fmt.Errorf("报告状态不能为空")
}
result := r.db.WithContext(ctx).
Delete(&entities.StatisticsReport{}, "status = ?", status)
if result.Error != nil {
return fmt.Errorf("根据状态删除统计报告失败: %w", result.Error)
}
return nil
}

View File

@@ -0,0 +1,381 @@
package statistics
import (
"context"
"fmt"
"time"
"gorm.io/gorm"
"tyapi-server/internal/domains/statistics/entities"
"tyapi-server/internal/domains/statistics/repositories"
)
// GormStatisticsRepository GORM统计指标仓储实现
type GormStatisticsRepository struct {
db *gorm.DB
}
// NewGormStatisticsRepository 创建GORM统计指标仓储
func NewGormStatisticsRepository(db *gorm.DB) repositories.StatisticsRepository {
return &GormStatisticsRepository{
db: db,
}
}
// Save 保存统计指标
func (r *GormStatisticsRepository) Save(ctx context.Context, metric *entities.StatisticsMetric) error {
if metric == nil {
return fmt.Errorf("统计指标不能为空")
}
// 验证指标
if err := metric.Validate(); err != nil {
return fmt.Errorf("统计指标验证失败: %w", err)
}
// 保存到数据库
result := r.db.WithContext(ctx).Create(metric)
if result.Error != nil {
return fmt.Errorf("保存统计指标失败: %w", result.Error)
}
return nil
}
// FindByID 根据ID查找统计指标
func (r *GormStatisticsRepository) FindByID(ctx context.Context, id string) (*entities.StatisticsMetric, error) {
if id == "" {
return nil, fmt.Errorf("指标ID不能为空")
}
var metric entities.StatisticsMetric
result := r.db.WithContext(ctx).Where("id = ?", id).First(&metric)
if result.Error != nil {
if result.Error == gorm.ErrRecordNotFound {
return nil, fmt.Errorf("统计指标不存在")
}
return nil, fmt.Errorf("查询统计指标失败: %w", result.Error)
}
return &metric, nil
}
// FindByType 根据类型查找统计指标
func (r *GormStatisticsRepository) FindByType(ctx context.Context, metricType string, limit, offset int) ([]*entities.StatisticsMetric, error) {
if metricType == "" {
return nil, fmt.Errorf("指标类型不能为空")
}
var metrics []*entities.StatisticsMetric
query := r.db.WithContext(ctx).Where("metric_type = ?", metricType)
if limit > 0 {
query = query.Limit(limit)
}
if offset > 0 {
query = query.Offset(offset)
}
result := query.Order("created_at DESC").Find(&metrics)
if result.Error != nil {
return nil, fmt.Errorf("查询统计指标失败: %w", result.Error)
}
return metrics, nil
}
// Update 更新统计指标
func (r *GormStatisticsRepository) Update(ctx context.Context, metric *entities.StatisticsMetric) error {
if metric == nil {
return fmt.Errorf("统计指标不能为空")
}
if metric.ID == "" {
return fmt.Errorf("指标ID不能为空")
}
// 验证指标
if err := metric.Validate(); err != nil {
return fmt.Errorf("统计指标验证失败: %w", err)
}
// 更新数据库
result := r.db.WithContext(ctx).Save(metric)
if result.Error != nil {
return fmt.Errorf("更新统计指标失败: %w", result.Error)
}
return nil
}
// Delete 删除统计指标
func (r *GormStatisticsRepository) Delete(ctx context.Context, id string) error {
if id == "" {
return fmt.Errorf("指标ID不能为空")
}
result := r.db.WithContext(ctx).Delete(&entities.StatisticsMetric{}, "id = ?", id)
if result.Error != nil {
return fmt.Errorf("删除统计指标失败: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("统计指标不存在")
}
return nil
}
// FindByTypeAndDateRange 根据类型和日期范围查找统计指标
func (r *GormStatisticsRepository) FindByTypeAndDateRange(ctx context.Context, metricType string, startDate, endDate time.Time) ([]*entities.StatisticsMetric, error) {
if metricType == "" {
return nil, fmt.Errorf("指标类型不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
var metrics []*entities.StatisticsMetric
result := r.db.WithContext(ctx).
Where("metric_type = ? AND date >= ? AND date < ?", metricType, startDate, endDate).
Order("date ASC").
Find(&metrics)
if result.Error != nil {
return nil, fmt.Errorf("查询统计指标失败: %w", result.Error)
}
return metrics, nil
}
// FindByTypeDimensionAndDateRange 根据类型、维度和日期范围查找统计指标
func (r *GormStatisticsRepository) FindByTypeDimensionAndDateRange(ctx context.Context, metricType, dimension string, startDate, endDate time.Time) ([]*entities.StatisticsMetric, error) {
if metricType == "" {
return nil, fmt.Errorf("指标类型不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
var metrics []*entities.StatisticsMetric
query := r.db.WithContext(ctx).
Where("metric_type = ? AND date >= ? AND date < ?", metricType, startDate, endDate)
if dimension != "" {
query = query.Where("dimension = ?", dimension)
}
result := query.Order("date ASC").Find(&metrics)
if result.Error != nil {
return nil, fmt.Errorf("查询统计指标失败: %w", result.Error)
}
return metrics, nil
}
// FindByTypeNameAndDateRange 根据类型、名称和日期范围查找统计指标
func (r *GormStatisticsRepository) FindByTypeNameAndDateRange(ctx context.Context, metricType, metricName string, startDate, endDate time.Time) ([]*entities.StatisticsMetric, error) {
if metricType == "" {
return nil, fmt.Errorf("指标类型不能为空")
}
if metricName == "" {
return nil, fmt.Errorf("指标名称不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
var metrics []*entities.StatisticsMetric
result := r.db.WithContext(ctx).
Where("metric_type = ? AND metric_name = ? AND date >= ? AND date < ?",
metricType, metricName, startDate, endDate).
Order("date ASC").
Find(&metrics)
if result.Error != nil {
return nil, fmt.Errorf("查询统计指标失败: %w", result.Error)
}
return metrics, nil
}
// GetAggregatedMetrics 获取聚合指标
func (r *GormStatisticsRepository) GetAggregatedMetrics(ctx context.Context, metricType, dimension string, startDate, endDate time.Time) (map[string]float64, error) {
if metricType == "" {
return nil, fmt.Errorf("指标类型不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
type AggregatedResult struct {
MetricName string `json:"metric_name"`
TotalValue float64 `json:"total_value"`
}
var results []AggregatedResult
query := r.db.WithContext(ctx).
Model(&entities.StatisticsMetric{}).
Select("metric_name, SUM(value) as total_value").
Where("metric_type = ? AND date >= ? AND date < ?", metricType, startDate, endDate).
Group("metric_name")
if dimension != "" {
query = query.Where("dimension = ?", dimension)
}
result := query.Find(&results)
if result.Error != nil {
return nil, fmt.Errorf("查询聚合指标失败: %w", result.Error)
}
// 转换为map
aggregated := make(map[string]float64)
for _, res := range results {
aggregated[res.MetricName] = res.TotalValue
}
return aggregated, nil
}
// GetMetricsByDimension 根据维度获取指标
func (r *GormStatisticsRepository) GetMetricsByDimension(ctx context.Context, dimension string, startDate, endDate time.Time) ([]*entities.StatisticsMetric, error) {
if dimension == "" {
return nil, fmt.Errorf("统计维度不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return nil, fmt.Errorf("开始日期和结束日期不能为空")
}
var metrics []*entities.StatisticsMetric
result := r.db.WithContext(ctx).
Where("dimension = ? AND date >= ? AND date < ?", dimension, startDate, endDate).
Order("date ASC").
Find(&metrics)
if result.Error != nil {
return nil, fmt.Errorf("查询统计指标失败: %w", result.Error)
}
return metrics, nil
}
// CountByType 根据类型统计数量
func (r *GormStatisticsRepository) CountByType(ctx context.Context, metricType string) (int64, error) {
if metricType == "" {
return 0, fmt.Errorf("指标类型不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsMetric{}).
Where("metric_type = ?", metricType).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计指标数量失败: %w", result.Error)
}
return count, nil
}
// CountByTypeAndDateRange 根据类型和日期范围统计数量
func (r *GormStatisticsRepository) CountByTypeAndDateRange(ctx context.Context, metricType string, startDate, endDate time.Time) (int64, error) {
if metricType == "" {
return 0, fmt.Errorf("指标类型不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return 0, fmt.Errorf("开始日期和结束日期不能为空")
}
var count int64
result := r.db.WithContext(ctx).
Model(&entities.StatisticsMetric{}).
Where("metric_type = ? AND date >= ? AND date < ?", metricType, startDate, endDate).
Count(&count)
if result.Error != nil {
return 0, fmt.Errorf("统计指标数量失败: %w", result.Error)
}
return count, nil
}
// BatchSave 批量保存统计指标
func (r *GormStatisticsRepository) BatchSave(ctx context.Context, metrics []*entities.StatisticsMetric) error {
if len(metrics) == 0 {
return fmt.Errorf("统计指标列表不能为空")
}
// 验证所有指标
for _, metric := range metrics {
if err := metric.Validate(); err != nil {
return fmt.Errorf("统计指标验证失败: %w", err)
}
}
// 批量保存
result := r.db.WithContext(ctx).CreateInBatches(metrics, 100)
if result.Error != nil {
return fmt.Errorf("批量保存统计指标失败: %w", result.Error)
}
return nil
}
// BatchDelete 批量删除统计指标
func (r *GormStatisticsRepository) BatchDelete(ctx context.Context, ids []string) error {
if len(ids) == 0 {
return fmt.Errorf("指标ID列表不能为空")
}
result := r.db.WithContext(ctx).Delete(&entities.StatisticsMetric{}, "id IN ?", ids)
if result.Error != nil {
return fmt.Errorf("批量删除统计指标失败: %w", result.Error)
}
return nil
}
// DeleteByDateRange 根据日期范围删除统计指标
func (r *GormStatisticsRepository) DeleteByDateRange(ctx context.Context, startDate, endDate time.Time) error {
if startDate.IsZero() || endDate.IsZero() {
return fmt.Errorf("开始日期和结束日期不能为空")
}
result := r.db.WithContext(ctx).
Delete(&entities.StatisticsMetric{}, "date >= ? AND date < ?", startDate, endDate)
if result.Error != nil {
return fmt.Errorf("根据日期范围删除统计指标失败: %w", result.Error)
}
return nil
}
// DeleteByTypeAndDateRange 根据类型和日期范围删除统计指标
func (r *GormStatisticsRepository) DeleteByTypeAndDateRange(ctx context.Context, metricType string, startDate, endDate time.Time) error {
if metricType == "" {
return fmt.Errorf("指标类型不能为空")
}
if startDate.IsZero() || endDate.IsZero() {
return fmt.Errorf("开始日期和结束日期不能为空")
}
result := r.db.WithContext(ctx).
Delete(&entities.StatisticsMetric{}, "metric_type = ? AND date >= ? AND date < ?",
metricType, startDate, endDate)
if result.Error != nil {
return fmt.Errorf("根据类型和日期范围删除统计指标失败: %w", result.Error)
}
return nil
}