From 17dac03dac75bda26d73b93d43f0f792a88eb93b Mon Sep 17 00:00:00 2001 From: valitovgaziz Date: Fri, 17 Oct 2025 09:23:23 +0500 Subject: [PATCH] new file: serv_nginx/api_bb/internal/repository/workout_repository.go add workout repository --- .../internal/repository/workout_repository.go | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 serv_nginx/api_bb/internal/repository/workout_repository.go diff --git a/serv_nginx/api_bb/internal/repository/workout_repository.go b/serv_nginx/api_bb/internal/repository/workout_repository.go new file mode 100644 index 0000000..e58a336 --- /dev/null +++ b/serv_nginx/api_bb/internal/repository/workout_repository.go @@ -0,0 +1,164 @@ +// repositories/workout_repository.go +package repository + +import ( + "api_bb/internal/models" + "fmt" + "time" + + "gorm.io/gorm" +) + +type WorkoutRepository interface { + Create(workout *models.Workout) error + FindByID(id uint) (*models.Workout, error) + FindByUserID(userID uint) ([]models.Workout, error) + Update(workout *models.Workout) error + Delete(id uint) error + GetWorkoutStats(userID uint) (*models.WorkoutStatsResponse, error) + FindByDateRange(userID uint, startDate, endDate time.Time) ([]models.Workout, error) + GetMonthlyStats(userID uint, year int) ([]models.MonthlyStat, error) + GetLatestWorkouts(userID uint, limit int) ([]models.Workout, error) + GetByType(userID uint, workoutType models.WorkoutType) ([]models.Workout, error) +} + +type workoutRepository struct { + db *gorm.DB +} + +func NewWorkoutRepository(db *gorm.DB) WorkoutRepository { + return &workoutRepository{db: db} +} + +func (r *workoutRepository) Create(workout *models.Workout) error { + return r.db.Create(workout).Error +} + +func (r *workoutRepository) FindByID(id uint) (*models.Workout, error) { + var workout models.Workout + err := r.db.Preload("User").First(&workout, id).Error + if err != nil { + return nil, err + } + return &workout, nil +} + +func (r *workoutRepository) FindByUserID(userID uint) ([]models.Workout, error) { + var workouts []models.Workout + err := r.db.Preload("User").Where("user_id = ?", userID).Order("date DESC").Find(&workouts).Error + if err != nil { + return nil, err + } + return workouts, nil +} + +func (r *workoutRepository) Update(workout *models.Workout) error { + return r.db.Save(workout).Error +} + +func (r *workoutRepository) Delete(id uint) error { + return r.db.Delete(&models.Workout{}, id).Error +} + +func (r *workoutRepository) GetWorkoutStats(userID uint) (*models.WorkoutStatsResponse, error) { + var stats models.WorkoutStatsResponse + + // Получаем общее количество тренировок + var totalWorkouts int64 + if err := r.db.Model(&models.Workout{}).Where("user_id = ?", userID).Count(&totalWorkouts).Error; err != nil { + return nil, err + } + stats.TotalWorkouts = int(totalWorkouts) + + // Получаем общую дистанцию + var totalDistance struct{ Total float64 } + if err := r.db.Model(&models.Workout{}).Where("user_id = ?", userID).Select("COALESCE(SUM(distance_km), 0) as total").Scan(&totalDistance).Error; err != nil { + return nil, err + } + stats.TotalDistance = totalDistance.Total + + // Получаем общее время + var totalTime struct{ Total int } + if err := r.db.Model(&models.Workout{}).Where("user_id = ?", userID).Select("COALESCE(SUM(duration_min), 0) as total").Scan(&totalTime).Error; err != nil { + return nil, err + } + stats.TotalTime = totalTime.Total + + // Получаем месячную статистику + monthlyStats, err := r.GetMonthlyStats(userID, time.Now().Year()) + if err != nil { + return nil, err + } + stats.MonthlyStats = monthlyStats + + // Рассчитываем средний темп (упрощенная версия) + if totalDistance.Total > 0 && totalTime.Total > 0 { + avgPaceMinPerKm := float64(totalTime.Total) / totalDistance.Total + minutes := int(avgPaceMinPerKm) + seconds := int((avgPaceMinPerKm - float64(minutes)) * 60) + stats.AveragePace = fmt.Sprintf("%d:%02d", minutes, seconds) + } else { + stats.AveragePace = "0:00" + } + + return &stats, nil +} + +func (r *workoutRepository) FindByDateRange(userID uint, startDate, endDate time.Time) ([]models.Workout, error) { + var workouts []models.Workout + err := r.db.Preload("User"). + Where("user_id = ? AND date BETWEEN ? AND ?", userID, startDate, endDate). + Order("date DESC"). + Find(&workouts).Error + if err != nil { + return nil, err + } + return workouts, nil +} + +func (r *workoutRepository) GetMonthlyStats(userID uint, year int) ([]models.MonthlyStat, error) { + var monthlyStats []models.MonthlyStat + + query := ` + SELECT + TO_CHAR(date, 'YYYY-MM') as month, + COALESCE(SUM(distance_km), 0) as distance, + COUNT(*) as workouts + FROM workouts + WHERE user_id = ? AND EXTRACT(YEAR FROM date) = ? + GROUP BY TO_CHAR(date, 'YYYY-MM') + ORDER BY month DESC + ` + + err := r.db.Raw(query, userID, year).Scan(&monthlyStats).Error + if err != nil { + return nil, err + } + + return monthlyStats, nil +} + +func (r *workoutRepository) GetLatestWorkouts(userID uint, limit int) ([]models.Workout, error) { + var workouts []models.Workout + err := r.db.Preload("User"). + Where("user_id = ?", userID). + Order("date DESC"). + Limit(limit). + Find(&workouts).Error + if err != nil { + return nil, err + } + return workouts, nil +} + +func (r *workoutRepository) GetByType(userID uint, workoutType models.WorkoutType) ([]models.Workout, error) { + var workouts []models.Workout + err := r.db.Preload("User"). + Where("user_id = ? AND type = ?", userID, workoutType). + Order("date DESC"). + Find(&workouts).Error + if err != nil { + return nil, err + } + return workouts, nil +}