245 lines
6.4 KiB
Go
245 lines
6.4 KiB
Go
|
|
package entities
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"errors"
|
|||
|
|
"fmt"
|
|||
|
|
"time"
|
|||
|
|
|
|||
|
|
"github.com/google/uuid"
|
|||
|
|
"gorm.io/gorm"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// StatisticsMetric 统计指标实体
|
|||
|
|
// 用于存储各种统计指标数据,支持多维度统计
|
|||
|
|
type StatisticsMetric struct {
|
|||
|
|
// 基础标识
|
|||
|
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"统计指标唯一标识"`
|
|||
|
|
MetricType string `gorm:"type:varchar(50);not null;index" json:"metric_type" comment:"指标类型"`
|
|||
|
|
MetricName string `gorm:"type:varchar(100);not null" json:"metric_name" comment:"指标名称"`
|
|||
|
|
Dimension string `gorm:"type:varchar(50)" json:"dimension" comment:"统计维度"`
|
|||
|
|
Value float64 `gorm:"type:decimal(20,4);not null" json:"value" comment:"指标值"`
|
|||
|
|
Metadata string `gorm:"type:json" json:"metadata" comment:"额外维度信息"`
|
|||
|
|
Date time.Time `gorm:"type:date;index" json:"date" 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 (StatisticsMetric) TableName() string {
|
|||
|
|
return "statistics_metrics"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BeforeCreate GORM钩子:创建前自动生成UUID
|
|||
|
|
func (s *StatisticsMetric) BeforeCreate(tx *gorm.DB) error {
|
|||
|
|
if s.ID == "" {
|
|||
|
|
s.ID = uuid.New().String()
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 实现 Entity 接口 - 提供统一的实体管理接口
|
|||
|
|
// GetID 获取实体唯一标识
|
|||
|
|
func (s *StatisticsMetric) GetID() string {
|
|||
|
|
return s.ID
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetCreatedAt 获取创建时间
|
|||
|
|
func (s *StatisticsMetric) GetCreatedAt() time.Time {
|
|||
|
|
return s.CreatedAt
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetUpdatedAt 获取更新时间
|
|||
|
|
func (s *StatisticsMetric) GetUpdatedAt() time.Time {
|
|||
|
|
return s.UpdatedAt
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Validate 验证统计指标信息
|
|||
|
|
// 检查统计指标必填字段是否完整,确保数据的有效性
|
|||
|
|
func (s *StatisticsMetric) Validate() error {
|
|||
|
|
if s.MetricType == "" {
|
|||
|
|
return NewValidationError("指标类型不能为空")
|
|||
|
|
}
|
|||
|
|
if s.MetricName == "" {
|
|||
|
|
return NewValidationError("指标名称不能为空")
|
|||
|
|
}
|
|||
|
|
if s.Value < 0 {
|
|||
|
|
return NewValidationError("指标值不能为负数")
|
|||
|
|
}
|
|||
|
|
if s.Date.IsZero() {
|
|||
|
|
return NewValidationError("统计日期不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证指标类型
|
|||
|
|
if !s.IsValidMetricType() {
|
|||
|
|
return NewValidationError("无效的指标类型")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// IsValidMetricType 检查指标类型是否有效
|
|||
|
|
func (s *StatisticsMetric) IsValidMetricType() bool {
|
|||
|
|
validTypes := []string{
|
|||
|
|
"api_calls", // API调用统计
|
|||
|
|
"users", // 用户统计
|
|||
|
|
"finance", // 财务统计
|
|||
|
|
"products", // 产品统计
|
|||
|
|
"certification", // 认证统计
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for _, validType := range validTypes {
|
|||
|
|
if s.MetricType == validType {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetMetricTypeName 获取指标类型的中文名称
|
|||
|
|
func (s *StatisticsMetric) GetMetricTypeName() string {
|
|||
|
|
typeNames := map[string]string{
|
|||
|
|
"api_calls": "API调用统计",
|
|||
|
|
"users": "用户统计",
|
|||
|
|
"finance": "财务统计",
|
|||
|
|
"products": "产品统计",
|
|||
|
|
"certification": "认证统计",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if name, exists := typeNames[s.MetricType]; exists {
|
|||
|
|
return name
|
|||
|
|
}
|
|||
|
|
return s.MetricType
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetFormattedValue 获取格式化的指标值
|
|||
|
|
func (s *StatisticsMetric) GetFormattedValue() string {
|
|||
|
|
// 根据指标类型格式化数值
|
|||
|
|
switch s.MetricType {
|
|||
|
|
case "api_calls", "users":
|
|||
|
|
return fmt.Sprintf("%.0f", s.Value)
|
|||
|
|
case "finance":
|
|||
|
|
return fmt.Sprintf("%.2f", s.Value)
|
|||
|
|
default:
|
|||
|
|
return fmt.Sprintf("%.4f", s.Value)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewStatisticsMetric 工厂方法 - 创建统计指标
|
|||
|
|
func NewStatisticsMetric(metricType, metricName, dimension string, value float64, date time.Time) (*StatisticsMetric, error) {
|
|||
|
|
if metricType == "" {
|
|||
|
|
return nil, errors.New("指标类型不能为空")
|
|||
|
|
}
|
|||
|
|
if metricName == "" {
|
|||
|
|
return nil, errors.New("指标名称不能为空")
|
|||
|
|
}
|
|||
|
|
if value < 0 {
|
|||
|
|
return nil, errors.New("指标值不能为负数")
|
|||
|
|
}
|
|||
|
|
if date.IsZero() {
|
|||
|
|
return nil, errors.New("统计日期不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
metric := &StatisticsMetric{
|
|||
|
|
MetricType: metricType,
|
|||
|
|
MetricName: metricName,
|
|||
|
|
Dimension: dimension,
|
|||
|
|
Value: value,
|
|||
|
|
Date: date,
|
|||
|
|
domainEvents: make([]interface{}, 0),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证指标
|
|||
|
|
if err := metric.Validate(); err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加领域事件
|
|||
|
|
metric.addDomainEvent(&StatisticsMetricCreatedEvent{
|
|||
|
|
MetricID: metric.ID,
|
|||
|
|
MetricType: metricType,
|
|||
|
|
MetricName: metricName,
|
|||
|
|
Value: value,
|
|||
|
|
CreatedAt: time.Now(),
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return metric, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateValue 更新指标值
|
|||
|
|
func (s *StatisticsMetric) UpdateValue(newValue float64) error {
|
|||
|
|
if newValue < 0 {
|
|||
|
|
return NewValidationError("指标值不能为负数")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
oldValue := s.Value
|
|||
|
|
s.Value = newValue
|
|||
|
|
|
|||
|
|
// 添加领域事件
|
|||
|
|
s.addDomainEvent(&StatisticsMetricUpdatedEvent{
|
|||
|
|
MetricID: s.ID,
|
|||
|
|
OldValue: oldValue,
|
|||
|
|
NewValue: newValue,
|
|||
|
|
UpdatedAt: time.Now(),
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ================ 领域事件管理 ================
|
|||
|
|
|
|||
|
|
// addDomainEvent 添加领域事件
|
|||
|
|
func (s *StatisticsMetric) addDomainEvent(event interface{}) {
|
|||
|
|
if s.domainEvents == nil {
|
|||
|
|
s.domainEvents = make([]interface{}, 0)
|
|||
|
|
}
|
|||
|
|
s.domainEvents = append(s.domainEvents, event)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetDomainEvents 获取领域事件
|
|||
|
|
func (s *StatisticsMetric) GetDomainEvents() []interface{} {
|
|||
|
|
return s.domainEvents
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ClearDomainEvents 清除领域事件
|
|||
|
|
func (s *StatisticsMetric) ClearDomainEvents() {
|
|||
|
|
s.domainEvents = make([]interface{}, 0)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ================ 领域事件定义 ================
|
|||
|
|
|
|||
|
|
// StatisticsMetricCreatedEvent 统计指标创建事件
|
|||
|
|
type StatisticsMetricCreatedEvent struct {
|
|||
|
|
MetricID string `json:"metric_id"`
|
|||
|
|
MetricType string `json:"metric_type"`
|
|||
|
|
MetricName string `json:"metric_name"`
|
|||
|
|
Value float64 `json:"value"`
|
|||
|
|
CreatedAt time.Time `json:"created_at"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// StatisticsMetricUpdatedEvent 统计指标更新事件
|
|||
|
|
type StatisticsMetricUpdatedEvent struct {
|
|||
|
|
MetricID string `json:"metric_id"`
|
|||
|
|
OldValue float64 `json:"old_value"`
|
|||
|
|
NewValue float64 `json:"new_value"`
|
|||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ValidationError 验证错误
|
|||
|
|
type ValidationError struct {
|
|||
|
|
Message string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (e *ValidationError) Error() string {
|
|||
|
|
return e.Message
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewValidationError(message string) *ValidationError {
|
|||
|
|
return &ValidationError{Message: message}
|
|||
|
|
}
|