// models/workout.go package models import ( "time" "gorm.io/gorm" ) type WorkoutType string const ( WorkoutTypeEasy WorkoutType = "easy" WorkoutTypeTempo WorkoutType = "tempo" WorkoutTypeInterval WorkoutType = "interval" WorkoutTypeLong WorkoutType = "long" WorkoutTypeRecovery WorkoutType = "recovery" ) type Workout struct { ID uint `json:"id" gorm:"primaryKey"` UserID uint `json:"user_id" gorm:"not null;index"` Type WorkoutType `json:"type" gorm:"type:varchar(20);not null"` Distance float64 `json:"distance_km" gorm:"type:decimal(5,2);not null"` // Дистанция в км Duration int `json:"duration_min" gorm:"not null"` // Продолжительность в минутах Pace string `json:"pace" gorm:"size:20"` // Темп (например, "5:30") Calories int `json:"calories" gorm:"default:0"` // Сожженные калории Notes string `json:"notes" gorm:"type:text"` // Заметки к тренировке Date time.Time `json:"date" gorm:"not null;index"` // Дата тренировки CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` // Связи User User `json:"user,omitempty" gorm:"foreignKey:UserID"` } // BeforeCreate hook func (w *Workout) BeforeCreate(tx *gorm.DB) error { if w.CreatedAt.IsZero() { w.CreatedAt = time.Now() } if w.UpdatedAt.IsZero() { w.UpdatedAt = time.Now() } return nil } // BeforeUpdate hook func (w *Workout) BeforeUpdate(tx *gorm.DB) error { w.UpdatedAt = time.Now() return nil } // DTO для создания тренировки type WorkoutCreateRequest struct { Type WorkoutType `json:"type" validate:"required,oneof=easy tempo interval long recovery"` Distance float64 `json:"distance_km" validate:"required,min=0.1,max=1000"` Duration int `json:"duration_min" validate:"required,min=1,max=1440"` Pace string `json:"pace" validate:"maxlen=20"` Calories int `json:"calories" validate:"minint=0,maxint=5000"` Notes string `json:"notes" validate:"maxlen=1000"` Date time.Time `json:"date" validate:"required"` } // DTO для обновления тренировки type WorkoutUpdateRequest struct { Type WorkoutType `json:"type" validate:"oneof=easy tempo interval long recovery"` Distance float64 `json:"distance_km" validate:"min=0.1,max=1000"` Duration int `json:"duration_min" validate:"min=1,max=1440"` Pace string `json:"pace" validate:"maxlen=20"` Calories int `json:"calories" validate:"minint=0,maxint=5000"` Notes string `json:"notes" validate:"maxlen=1000"` Date time.Time `json:"date"` } // DTO для статистики тренировок type WorkoutStatsResponse struct { TotalWorkouts int `json:"total_workouts"` TotalDistance float64 `json:"total_distance_km"` TotalTime int `json:"total_time_min"` AveragePace string `json:"average_pace"` MonthlyStats []MonthlyStat `json:"monthly_stats"` } type MonthlyStat struct { Month string `json:"month"` Distance float64 `json:"distance_km"` Workouts int `json:"workouts"` }