Add daily_track_stats, geographic_play_stats, track_discovery_sources tables. Add source and country_code columns to track_plays. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84 lines
3.1 KiB
Go
84 lines
3.1 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// DailyTrackStats represents daily aggregated playback statistics for a track
|
|
type DailyTrackStats struct {
|
|
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
|
|
TrackID uuid.UUID `gorm:"type:uuid;not null;uniqueIndex:uq_daily_track_stats_track_date" json:"track_id"`
|
|
Date time.Time `gorm:"type:date;not null;uniqueIndex:uq_daily_track_stats_track_date" json:"date"`
|
|
TotalPlays int64 `gorm:"not null;default:0" json:"total_plays"`
|
|
UniqueListeners int64 `gorm:"not null;default:0" json:"unique_listeners"`
|
|
CompleteListens int64 `gorm:"not null;default:0" json:"complete_listens"`
|
|
TotalPlayTime int64 `gorm:"not null;default:0" json:"total_play_time"`
|
|
AvgCompletionRate float64 `gorm:"type:decimal(5,2);not null;default:0" json:"avg_completion_rate"`
|
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
|
|
|
Track Track `gorm:"foreignKey:TrackID;constraint:OnDelete:CASCADE" json:"-"`
|
|
}
|
|
|
|
func (DailyTrackStats) TableName() string {
|
|
return "daily_track_stats"
|
|
}
|
|
|
|
func (m *DailyTrackStats) BeforeCreate(tx *gorm.DB) error {
|
|
if m.ID == uuid.Nil {
|
|
m.ID = uuid.New()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GeographicPlayStats represents aggregated geographic play data (anonymized)
|
|
type GeographicPlayStats struct {
|
|
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
|
|
TrackID uuid.UUID `gorm:"type:uuid;not null" json:"track_id"`
|
|
CountryCode string `gorm:"size:2;not null" json:"country_code"`
|
|
Region string `gorm:"size:100;not null;default:''" json:"region"`
|
|
Date time.Time `gorm:"type:date;not null" json:"date"`
|
|
PlayCount int64 `gorm:"not null;default:0" json:"play_count"`
|
|
UniqueListeners int64 `gorm:"not null;default:0" json:"unique_listeners"`
|
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
|
|
|
Track Track `gorm:"foreignKey:TrackID;constraint:OnDelete:CASCADE" json:"-"`
|
|
}
|
|
|
|
func (GeographicPlayStats) TableName() string {
|
|
return "geographic_play_stats"
|
|
}
|
|
|
|
func (m *GeographicPlayStats) BeforeCreate(tx *gorm.DB) error {
|
|
if m.ID == uuid.Nil {
|
|
m.ID = uuid.New()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TrackDiscoverySource records how a user discovered a track
|
|
type TrackDiscoverySource struct {
|
|
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
|
|
TrackID uuid.UUID `gorm:"type:uuid;not null" json:"track_id"`
|
|
UserID uuid.UUID `gorm:"type:uuid;not null" json:"user_id"`
|
|
Source string `gorm:"size:50;not null" json:"source"` // search, feed, share, profile, playlist, direct
|
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
|
|
|
Track Track `gorm:"foreignKey:TrackID;constraint:OnDelete:CASCADE" json:"-"`
|
|
User User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"-"`
|
|
}
|
|
|
|
func (TrackDiscoverySource) TableName() string {
|
|
return "track_discovery_sources"
|
|
}
|
|
|
|
func (m *TrackDiscoverySource) BeforeCreate(tx *gorm.DB) error {
|
|
if m.ID == uuid.Nil {
|
|
m.ID = uuid.New()
|
|
}
|
|
return nil
|
|
}
|