new file: serv_nginx/api_bb/internal/repository/achievement_repository.go
modified: serv_nginx/api_bb/internal/repository/personal_best_repository.go new file: serv_nginx/api_bb/internal/service/achievement_service.go new file: serv_nginx/api_bb/internal/service/personal_best_service.go new file: serv_nginx/api_bb/internal/service/user_stats_service.go add some services
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
// service/achievement_service.go
|
||||
package service
|
||||
|
||||
import (
|
||||
"api_bb/internal/models"
|
||||
"api_bb/internal/repository"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type AchievementService struct {
|
||||
achievementRepo repository.AchievementRepository
|
||||
}
|
||||
|
||||
func NewAchievementService(achievementRepo repository.AchievementRepository) *AchievementService {
|
||||
return &AchievementService{
|
||||
achievementRepo: achievementRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateAchievement создает новое достижение
|
||||
func (s *AchievementService) CreateAchievement(userID uint, req models.AchievementCreateRequest) (*models.Achievement, error) {
|
||||
// Проверяем, нет ли уже достижения с таким названием у пользователя
|
||||
exists, err := s.achievementRepo.ExistsByTitleAndUser(userID, req.Title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
return nil, ErrAchievementAlreadyExists
|
||||
}
|
||||
|
||||
achievement := &models.Achievement{
|
||||
UserID: userID,
|
||||
Type: req.Type,
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
Result: req.Result,
|
||||
Distance: req.Distance,
|
||||
Date: req.Date,
|
||||
BadgeImage: req.BadgeImage,
|
||||
Verified: false, // По умолчанию не подтверждено
|
||||
}
|
||||
|
||||
if err := s.achievementRepo.Create(achievement); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return achievement, nil
|
||||
}
|
||||
|
||||
// GetUserAchievements возвращает все достижения пользователя
|
||||
func (s *AchievementService) GetUserAchievements(userID uint) ([]models.Achievement, error) {
|
||||
return s.achievementRepo.GetByUserID(userID)
|
||||
}
|
||||
|
||||
// GetUserAchievementsSummary возвращает сводку по достижениям пользователя
|
||||
func (s *AchievementService) GetUserAchievementsSummary(userID uint) (*models.UserAchievementsResponse, error) {
|
||||
return s.achievementRepo.GetUserAchievementsSummary(userID)
|
||||
}
|
||||
|
||||
// VerifyAchievement подтверждает достижение
|
||||
func (s *AchievementService) VerifyAchievement(achievementID uint, userID uint) error {
|
||||
// Проверяем, что достижение принадлежит пользователю
|
||||
achievement, err := s.achievementRepo.GetByID(achievementID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if achievement.UserID != userID {
|
||||
return ErrAchievementNotFound
|
||||
}
|
||||
|
||||
return s.achievementRepo.VerifyAchievement(achievementID)
|
||||
}
|
||||
|
||||
// GetRecentAchievements возвращает последние достижения
|
||||
func (s *AchievementService) GetRecentAchievements(userID uint, limit int) ([]models.Achievement, error) {
|
||||
return s.achievementRepo.GetRecentAchievements(userID, limit)
|
||||
}
|
||||
|
||||
// GetAchievementsByType возвращает достижения по типу
|
||||
func (s *AchievementService) GetAchievementsByType(userID uint, achievementType models.AchievementType) ([]models.Achievement, error) {
|
||||
return s.achievementRepo.GetByUserAndType(userID, achievementType)
|
||||
}
|
||||
|
||||
// DeleteAchievement удаляет достижение
|
||||
func (s *AchievementService) DeleteAchievement(achievementID uint, userID uint) error {
|
||||
// Проверяем, что достижение принадлежит пользователю
|
||||
achievement, err := s.achievementRepo.GetByID(achievementID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if achievement.UserID != userID {
|
||||
return ErrAchievementNotFound
|
||||
}
|
||||
|
||||
return s.achievementRepo.Delete(achievementID)
|
||||
}
|
||||
|
||||
// Ошибки
|
||||
var (
|
||||
ErrAchievementAlreadyExists = errors.New("achievement with this title already exists")
|
||||
ErrAchievementNotFound = errors.New("achievement not found")
|
||||
)
|
||||
@@ -0,0 +1,86 @@
|
||||
// services/personal_best_service.go
|
||||
package service
|
||||
|
||||
import (
|
||||
"api_bb/internal/models"
|
||||
"api_bb/internal/repository"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PersonalBestService struct {
|
||||
pbRepo repository.PersonalBestRepository
|
||||
}
|
||||
|
||||
func NewPersonalBestService(pbRepo repository.PersonalBestRepository) *PersonalBestService {
|
||||
return &PersonalBestService{
|
||||
pbRepo: pbRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePersonalBest создает новый личный рекорд
|
||||
func (s *PersonalBestService) CreatePersonalBest(userID uint, req models.PersonalBestCreateRequest) (*models.PersonalBest, error) {
|
||||
// Вычисляем темп, если не предоставлен
|
||||
pace := req.Pace
|
||||
if pace == "" {
|
||||
calculatedPace, err := s.pbRepo.CalculatePace(req.Time, req.DistanceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pace = calculatedPace
|
||||
}
|
||||
|
||||
// Проверяем, является ли это личным рекордом
|
||||
isBest, err := s.pbRepo.ExistsBetterTime(userID, req.DistanceType, req.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
personalBest := &models.PersonalBest{
|
||||
UserID: userID,
|
||||
DistanceType: req.DistanceType,
|
||||
Time: req.Time,
|
||||
Pace: pace,
|
||||
Date: req.Date,
|
||||
EventName: req.EventName,
|
||||
Location: req.Location,
|
||||
Verified: false, // По умолчанию не подтвержден
|
||||
}
|
||||
|
||||
if err := s.pbRepo.Create(personalBest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Если это лучший результат, можно обновить статистику пользователя
|
||||
if !isBest {
|
||||
// Здесь можно вызвать метод для обновления UserStats
|
||||
}
|
||||
|
||||
return personalBest, nil
|
||||
}
|
||||
|
||||
// GetUserPersonalBests возвращает все личные рекорды пользователя
|
||||
func (s *PersonalBestService) GetUserPersonalBests(userID uint) ([]models.PersonalBest, error) {
|
||||
return s.pbRepo.GetByUserID(userID)
|
||||
}
|
||||
|
||||
// GetPersonalBestsSummary возвращает сводку лучших результатов
|
||||
func (s *PersonalBestService) GetPersonalBestsSummary(userID uint) (*models.PersonalBestsSummary, error) {
|
||||
return s.pbRepo.GetPersonalBestsSummary(userID)
|
||||
}
|
||||
|
||||
// VerifyPersonalBest подтверждает личный рекорд
|
||||
func (s *PersonalBestService) VerifyPersonalBest(id uint, userID uint) error {
|
||||
pb, err := s.pbRepo.GetByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Проверяем, что рекорд принадлежит пользователю
|
||||
if pb.UserID != userID {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
pb.Verified = true
|
||||
return s.pbRepo.Update(pb)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// services/user_stats_service.go
|
||||
package service
|
||||
|
||||
import (
|
||||
"time"
|
||||
"api_bb/internal/models"
|
||||
"api_bb/internal/repository"
|
||||
)
|
||||
|
||||
type UserStatsService struct {
|
||||
userStatsRepo repository.UserStatsRepository
|
||||
}
|
||||
|
||||
func NewUserStatsService(userStatsRepo repository.UserStatsRepository) *UserStatsService {
|
||||
return &UserStatsService{
|
||||
userStatsRepo: userStatsRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *UserStatsService) AddWorkout(userID uint, distance float64, duration int, workoutTime time.Time) error {
|
||||
// Обновляем общую статистику
|
||||
if err := s.userStatsRepo.IncrementWorkouts(userID, distance, duration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Обновляем серии
|
||||
if err := s.userStatsRepo.UpdateStreaks(userID, workoutTime); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Обновляем недельный и месячный пробег
|
||||
if err := s.userStatsRepo.UpdateWeeklyDistance(userID, distance); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.userStatsRepo.UpdateMonthlyDistance(userID, distance)
|
||||
}
|
||||
|
||||
func (s *UserStatsService) GetUserStats(userID uint) (*models.UserStatsResponse, error) {
|
||||
return s.userStatsRepo.GetUserStatsResponse(userID)
|
||||
}
|
||||
|
||||
func (s *UserStatsService) UpdatePersonalBest(userID uint, distanceType string, time string) error {
|
||||
return s.userStatsRepo.UpdatePersonalBest(userID, distanceType, time)
|
||||
}
|
||||
Reference in New Issue
Block a user