package entities import ( "errors" "time" "github.com/google/uuid" "gorm.io/gorm" ) // StatisticsReport 统计报告实体 // 用于存储生成的统计报告数据 type StatisticsReport struct { // 基础标识 ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"报告唯一标识"` ReportType string `gorm:"type:varchar(50);not null;index" json:"report_type" comment:"报告类型"` Title string `gorm:"type:varchar(200);not null" json:"title" comment:"报告标题"` Content string `gorm:"type:json" json:"content" comment:"报告内容"` Period string `gorm:"type:varchar(20)" json:"period" comment:"统计周期"` UserRole string `gorm:"type:varchar(20)" json:"user_role" comment:"用户角色"` Status string `gorm:"type:varchar(20);default:'draft'" json:"status" comment:"报告状态"` // 报告元数据 GeneratedBy string `gorm:"type:varchar(36)" json:"generated_by" comment:"生成者ID"` GeneratedAt *time.Time `json:"generated_at" comment:"生成时间"` ExpiresAt *time.Time `json:"expires_at" comment:"过期时间"` // 时间戳字段 CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-" comment:"软删除时间"` // 领域事件 (不持久化) domainEvents []interface{} `gorm:"-" json:"-"` } // TableName 指定数据库表名 func (StatisticsReport) TableName() string { return "statistics_reports" } // BeforeCreate GORM钩子:创建前自动生成UUID func (s *StatisticsReport) BeforeCreate(tx *gorm.DB) error { if s.ID == "" { s.ID = uuid.New().String() } return nil } // 实现 Entity 接口 - 提供统一的实体管理接口 // GetID 获取实体唯一标识 func (s *StatisticsReport) GetID() string { return s.ID } // GetCreatedAt 获取创建时间 func (s *StatisticsReport) GetCreatedAt() time.Time { return s.CreatedAt } // GetUpdatedAt 获取更新时间 func (s *StatisticsReport) GetUpdatedAt() time.Time { return s.UpdatedAt } // Validate 验证统计报告信息 // 检查统计报告必填字段是否完整,确保数据的有效性 func (s *StatisticsReport) Validate() error { if s.ReportType == "" { return NewValidationError("报告类型不能为空") } if s.Title == "" { return NewValidationError("报告标题不能为空") } if s.Period == "" { return NewValidationError("统计周期不能为空") } // 验证报告类型 if !s.IsValidReportType() { return NewValidationError("无效的报告类型") } // 验证报告状态 if !s.IsValidStatus() { return NewValidationError("无效的报告状态") } return nil } // IsValidReportType 检查报告类型是否有效 func (s *StatisticsReport) IsValidReportType() bool { validTypes := []string{ "dashboard", // 仪表板报告 "summary", // 汇总报告 "detailed", // 详细报告 "custom", // 自定义报告 } for _, validType := range validTypes { if s.ReportType == validType { return true } } return false } // IsValidStatus 检查报告状态是否有效 func (s *StatisticsReport) IsValidStatus() bool { validStatuses := []string{ "draft", // 草稿 "generating", // 生成中 "completed", // 已完成 "failed", // 生成失败 "expired", // 已过期 } for _, validStatus := range validStatuses { if s.Status == validStatus { return true } } return false } // GetReportTypeName 获取报告类型的中文名称 func (s *StatisticsReport) GetReportTypeName() string { typeNames := map[string]string{ "dashboard": "仪表板报告", "summary": "汇总报告", "detailed": "详细报告", "custom": "自定义报告", } if name, exists := typeNames[s.ReportType]; exists { return name } return s.ReportType } // GetStatusName 获取报告状态的中文名称 func (s *StatisticsReport) GetStatusName() string { statusNames := map[string]string{ "draft": "草稿", "generating": "生成中", "completed": "已完成", "failed": "生成失败", "expired": "已过期", } if name, exists := statusNames[s.Status]; exists { return name } return s.Status } // NewStatisticsReport 工厂方法 - 创建统计报告 func NewStatisticsReport(reportType, title, period, userRole string) (*StatisticsReport, error) { if reportType == "" { return nil, errors.New("报告类型不能为空") } if title == "" { return nil, errors.New("报告标题不能为空") } if period == "" { return nil, errors.New("统计周期不能为空") } report := &StatisticsReport{ ReportType: reportType, Title: title, Period: period, UserRole: userRole, Status: "draft", domainEvents: make([]interface{}, 0), } // 验证报告 if err := report.Validate(); err != nil { return nil, err } // 添加领域事件 report.addDomainEvent(&StatisticsReportCreatedEvent{ ReportID: report.ID, ReportType: reportType, Title: title, Period: period, CreatedAt: time.Now(), }) return report, nil } // StartGeneration 开始生成报告 func (s *StatisticsReport) StartGeneration(generatedBy string) error { if s.Status != "draft" { return NewValidationError("只有草稿状态的报告才能开始生成") } s.Status = "generating" s.GeneratedBy = generatedBy now := time.Now() s.GeneratedAt = &now // 添加领域事件 s.addDomainEvent(&StatisticsReportGenerationStartedEvent{ ReportID: s.ID, GeneratedBy: generatedBy, StartedAt: now, }) return nil } // CompleteGeneration 完成报告生成 func (s *StatisticsReport) CompleteGeneration(content string) error { if s.Status != "generating" { return NewValidationError("只有生成中状态的报告才能完成生成") } s.Status = "completed" s.Content = content // 设置过期时间(默认7天) expiresAt := time.Now().Add(7 * 24 * time.Hour) s.ExpiresAt = &expiresAt // 添加领域事件 s.addDomainEvent(&StatisticsReportCompletedEvent{ ReportID: s.ID, CompletedAt: time.Now(), }) return nil } // FailGeneration 报告生成失败 func (s *StatisticsReport) FailGeneration(reason string) error { if s.Status != "generating" { return NewValidationError("只有生成中状态的报告才能标记为失败") } s.Status = "failed" // 添加领域事件 s.addDomainEvent(&StatisticsReportFailedEvent{ ReportID: s.ID, Reason: reason, FailedAt: time.Now(), }) return nil } // IsExpired 检查报告是否已过期 func (s *StatisticsReport) IsExpired() bool { if s.ExpiresAt == nil { return false } return time.Now().After(*s.ExpiresAt) } // MarkAsExpired 标记报告为过期 func (s *StatisticsReport) MarkAsExpired() error { if s.Status != "completed" { return NewValidationError("只有已完成状态的报告才能标记为过期") } s.Status = "expired" // 添加领域事件 s.addDomainEvent(&StatisticsReportExpiredEvent{ ReportID: s.ID, ExpiredAt: time.Now(), }) return nil } // CanBeRegenerated 检查报告是否可以重新生成 func (s *StatisticsReport) CanBeRegenerated() bool { return s.Status == "failed" || s.Status == "expired" } // ================ 领域事件管理 ================ // addDomainEvent 添加领域事件 func (s *StatisticsReport) addDomainEvent(event interface{}) { if s.domainEvents == nil { s.domainEvents = make([]interface{}, 0) } s.domainEvents = append(s.domainEvents, event) } // GetDomainEvents 获取领域事件 func (s *StatisticsReport) GetDomainEvents() []interface{} { return s.domainEvents } // ClearDomainEvents 清除领域事件 func (s *StatisticsReport) ClearDomainEvents() { s.domainEvents = make([]interface{}, 0) } // ================ 领域事件定义 ================ // StatisticsReportCreatedEvent 统计报告创建事件 type StatisticsReportCreatedEvent struct { ReportID string `json:"report_id"` ReportType string `json:"report_type"` Title string `json:"title"` Period string `json:"period"` CreatedAt time.Time `json:"created_at"` } // StatisticsReportGenerationStartedEvent 统计报告生成开始事件 type StatisticsReportGenerationStartedEvent struct { ReportID string `json:"report_id"` GeneratedBy string `json:"generated_by"` StartedAt time.Time `json:"started_at"` } // StatisticsReportCompletedEvent 统计报告完成事件 type StatisticsReportCompletedEvent struct { ReportID string `json:"report_id"` CompletedAt time.Time `json:"completed_at"` } // StatisticsReportFailedEvent 统计报告失败事件 type StatisticsReportFailedEvent struct { ReportID string `json:"report_id"` Reason string `json:"reason"` FailedAt time.Time `json:"failed_at"` } // StatisticsReportExpiredEvent 统计报告过期事件 type StatisticsReportExpiredEvent struct { ReportID string `json:"report_id"` ExpiredAt time.Time `json:"expired_at"` }