63d486f48d
modified: main_dc/yalarba/api_yal/internal/domain/appeal/router.go modified: main_dc/yalarba/api_yal/internal/domain/feetback/dto.go modified: main_dc/yalarba/api_yal/internal/domain/feetback/handler.go modified: main_dc/yalarba/api_yal/internal/domain/feetback/router.go modified: main_dc/yalarba/api_yal/internal/domain/feetback/service.go modified: main_dc/yalarba/api_yal/internal/models/feedback.go modified: main_dc/yalarba/api_yal/internal/repository/comment_repository.go modified: main_dc/yalarba/api_yal/internal/repository/feedback_repository.go modified: main_dc/yalarba/api_yal/internal/repository/feedback_repository_impl.go modified: main_dc/yalarba/api_yal/internal/router/router.go craete routerRegister, service, hander, dto for feedback
317 lines
9.4 KiB
Go
317 lines
9.4 KiB
Go
package feetback
|
||
|
||
import (
|
||
"api_yal/internal/models"
|
||
"api_yal/internal/repository"
|
||
"errors"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// FeedbackService интерфейс сервиса отзывов
|
||
type FeedbackService interface {
|
||
Create(feedback *models.Feedback, AuthorID uint) error
|
||
GetByID(id uint) (*models.Feedback, error)
|
||
Update(id uint, AuthorID uint, updates map[string]interface{}) error
|
||
Delete(id uint, AuthorID uint, isAdmin bool) error
|
||
List(offset, limit int) ([]models.Feedback, int64, error)
|
||
ListByOwner(ownerID uint, offset, limit int) ([]models.Feedback, int64, error)
|
||
ListByObject(objectID uint, offset, limit int) ([]models.Feedback, int64, error)
|
||
ListByPlatform(platform models.PlatformType, offset, limit int) ([]models.Feedback, int64, error)
|
||
Search(query string, offset, limit int) ([]models.Feedback, int64, error)
|
||
GetComments(feedbackID uint, offset, limit int) ([]models.Comment, int, error)
|
||
AddComment(feedbackID uint, AuthorID uint, text string) (*models.Comment, error)
|
||
UpdateComment(commentID uint, AuthorID uint, text string, isAdmin bool) error
|
||
DeleteComment(commentID uint, AuthorID uint, isAdmin bool) error
|
||
GetStats() (*FeedbackStatsResponse, error)
|
||
}
|
||
|
||
// FeedbackServiceImpl реализация сервиса отзывов
|
||
type FeedbackServiceImpl struct {
|
||
feedbackRepo repository.FeedbackRepository
|
||
db *gorm.DB
|
||
}
|
||
|
||
// NewFeedbackServiceImpl создает новый экземпляр сервиса
|
||
func NewFeedbackServiceImpl(feedbackRepo repository.FeedbackRepository, db *gorm.DB) FeedbackService {
|
||
return &FeedbackServiceImpl{
|
||
feedbackRepo: feedbackRepo,
|
||
db: db,
|
||
}
|
||
}
|
||
|
||
// Create создает новый отзыв
|
||
func (s *FeedbackServiceImpl) Create(feedback *models.Feedback, AuthorID uint) error {
|
||
feedback.OwnerID = AuthorID
|
||
feedback.CommentCount = 0
|
||
|
||
return s.feedbackRepo.Create(feedback)
|
||
}
|
||
|
||
// GetByID возвращает отзыв по ID
|
||
func (s *FeedbackServiceImpl) GetByID(id uint) (*models.Feedback, error) {
|
||
return s.feedbackRepo.GetByID(id)
|
||
}
|
||
|
||
// Update обновляет отзыв
|
||
func (s *FeedbackServiceImpl) Update(id uint, AuthorID uint, updates map[string]interface{}) error {
|
||
// Получаем существующий отзыв
|
||
feedback, err := s.feedbackRepo.GetByID(id)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Проверяем права (только владелец может редактировать)
|
||
if feedback.OwnerID != AuthorID {
|
||
return errors.New("you can only update your own feedback")
|
||
}
|
||
|
||
// Применяем обновления
|
||
return s.db.Model(&models.Feedback{}).Where("id = ?", id).Updates(updates).Error
|
||
}
|
||
|
||
// Delete удаляет отзыв
|
||
func (s *FeedbackServiceImpl) Delete(id uint, AuthorID uint, isAdmin bool) error {
|
||
// Получаем существующий отзыв
|
||
feedback, err := s.feedbackRepo.GetByID(id)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Проверяем права (владелец или админ)
|
||
if feedback.OwnerID != AuthorID && !isAdmin {
|
||
return errors.New("you can only delete your own feedback")
|
||
}
|
||
|
||
return s.feedbackRepo.Delete(id)
|
||
}
|
||
|
||
// List возвращает список отзывов с пагинацией
|
||
func (s *FeedbackServiceImpl) List(offset, limit int) ([]models.Feedback, int64, error) {
|
||
if limit <= 0 || limit > 100 {
|
||
limit = 20
|
||
}
|
||
if offset < 0 {
|
||
offset = 0
|
||
}
|
||
|
||
feedbacks, err := s.feedbackRepo.List(offset, limit)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
total, err := s.feedbackRepo.Count()
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
return feedbacks, total, nil
|
||
}
|
||
|
||
// ListByOwner возвращает отзывы по владельцу
|
||
func (s *FeedbackServiceImpl) ListByOwner(ownerID uint, offset, limit int) ([]models.Feedback, int64, error) {
|
||
if limit <= 0 || limit > 100 {
|
||
limit = 20
|
||
}
|
||
if offset < 0 {
|
||
offset = 0
|
||
}
|
||
|
||
feedbacks, err := s.feedbackRepo.ListByOwner(ownerID, offset, limit)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
// Считаем общее количество отзывов пользователя
|
||
var total int64
|
||
err = s.db.Model(&models.Feedback{}).Where("owner_id = ?", ownerID).Count(&total).Error
|
||
|
||
return feedbacks, total, err
|
||
}
|
||
|
||
// ListByObject возвращает отзывы по объекту
|
||
func (s *FeedbackServiceImpl) ListByObject(objectID uint, offset, limit int) ([]models.Feedback, int64, error) {
|
||
if limit <= 0 || limit > 100 {
|
||
limit = 20
|
||
}
|
||
if offset < 0 {
|
||
offset = 0
|
||
}
|
||
|
||
feedbacks, err := s.feedbackRepo.ListByObject(objectID, offset, limit)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
var total int64
|
||
err = s.db.Model(&models.Feedback{}).Where("object_id = ?", objectID).Count(&total).Error
|
||
|
||
return feedbacks, total, err
|
||
}
|
||
|
||
// ListByPlatform возвращает отзывы по платформе
|
||
func (s *FeedbackServiceImpl) ListByPlatform(platform models.PlatformType, offset, limit int) ([]models.Feedback, int64, error) {
|
||
if limit <= 0 || limit > 100 {
|
||
limit = 20
|
||
}
|
||
if offset < 0 {
|
||
offset = 0
|
||
}
|
||
|
||
feedbacks, err := s.feedbackRepo.ListByPlatform(platform, offset, limit)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
var total int64
|
||
err = s.db.Model(&models.Feedback{}).Where("platform = ?", platform).Count(&total).Error
|
||
|
||
return feedbacks, total, err
|
||
}
|
||
|
||
// Search ищет отзывы по тексту
|
||
func (s *FeedbackServiceImpl) Search(query string, offset, limit int) ([]models.Feedback, int64, error) {
|
||
if limit <= 0 || limit > 100 {
|
||
limit = 20
|
||
}
|
||
if offset < 0 {
|
||
offset = 0
|
||
}
|
||
|
||
feedbacks, err := s.feedbackRepo.Search(query, offset, limit)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
var total int64
|
||
err = s.db.Model(&models.Feedback{}).Where("text LIKE ?", "%"+query+"%").Count(&total).Error
|
||
|
||
return feedbacks, total, err
|
||
}
|
||
|
||
// GetComments возвращает комментарии к отзыву
|
||
func (s *FeedbackServiceImpl) GetComments(feedbackID uint, offset, limit int) ([]models.Comment, int, error) {
|
||
if limit <= 0 || limit > 50 {
|
||
limit = 20
|
||
}
|
||
if offset < 0 {
|
||
offset = 0
|
||
}
|
||
|
||
comments, err := s.feedbackRepo.GetComments(feedbackID, offset, limit)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
total, err := s.feedbackRepo.GetCommentCount(feedbackID)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
return comments, total, err
|
||
}
|
||
|
||
// AddComment добавляет комментарий к отзыву
|
||
func (s *FeedbackServiceImpl) AddComment(feedbackID uint, AuthorID uint, text string) (*models.Comment, error) {
|
||
// Проверяем существование отзыва
|
||
_, err := s.feedbackRepo.GetByID(feedbackID)
|
||
if err != nil {
|
||
return nil, errors.New("feedback not found")
|
||
}
|
||
|
||
// Создаем комментарий
|
||
comment := &models.Comment{
|
||
FeedbackID: feedbackID,
|
||
AuthorID: AuthorID, // Используем AuthorID, а не OwnerID
|
||
Text: text,
|
||
}
|
||
|
||
err = s.db.Create(comment).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// Загружаем аккаунт для комментария
|
||
s.db.Preload("Account").First(comment, comment.ID)
|
||
|
||
// Обновляем счетчик комментариев
|
||
newCount, _ := s.feedbackRepo.GetCommentCount(feedbackID)
|
||
s.feedbackRepo.UpdateCommentCount(feedbackID, newCount)
|
||
|
||
return comment, nil
|
||
}
|
||
|
||
// UpdateComment обновляет комментарий
|
||
func (s *FeedbackServiceImpl) UpdateComment(commentID uint, AuthorID uint, text string, isAdmin bool) error {
|
||
var comment models.Comment
|
||
err := s.db.First(&comment, commentID).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Проверяем права (владелец или админ)
|
||
if comment.AuthorID != AuthorID && !isAdmin {
|
||
return errors.New("you can only update your own comments")
|
||
}
|
||
|
||
return s.db.Model(&comment).Update("text", text).Error
|
||
}
|
||
|
||
// DeleteComment удаляет комментарий
|
||
func (s *FeedbackServiceImpl) DeleteComment(commentID uint, AuthorID uint, isAdmin bool) error {
|
||
var comment models.Comment
|
||
err := s.db.First(&comment, commentID).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Проверяем права (владелец или админ)
|
||
if comment.AuthorID != AuthorID && !isAdmin {
|
||
return errors.New("you can only delete your own comments")
|
||
}
|
||
|
||
feedbackID := comment.FeedbackID
|
||
|
||
err = s.db.Delete(&comment).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Обновляем счетчик комментариев у отзыва
|
||
newCount, _ := s.feedbackRepo.GetCommentCount(feedbackID)
|
||
s.feedbackRepo.UpdateCommentCount(feedbackID, newCount)
|
||
|
||
return nil
|
||
}
|
||
|
||
// GetStats возвращает статистику по отзывам
|
||
func (s *FeedbackServiceImpl) GetStats() (*FeedbackStatsResponse, error) {
|
||
stats := &FeedbackStatsResponse{
|
||
RatingDistribution: make(map[int]int64),
|
||
PlatformStats: make(map[models.PlatformType]int64),
|
||
}
|
||
|
||
// Общее количество
|
||
s.db.Model(&models.Feedback{}).Count(&stats.TotalFeedbacks)
|
||
|
||
// Средний рейтинг
|
||
var avgRating float64
|
||
s.db.Model(&models.Feedback{}).Select("COALESCE(AVG(rating), 0)").Row().Scan(&avgRating)
|
||
stats.AverageRating = avgRating
|
||
|
||
// Распределение рейтингов
|
||
for i := 1; i <= 5; i++ {
|
||
var count int64
|
||
s.db.Model(&models.Feedback{}).Where("rating = ?", i).Count(&count)
|
||
stats.RatingDistribution[i] = count
|
||
}
|
||
|
||
// Статистика по платформам
|
||
platforms := []models.PlatformType{"google", "yandex", "2gis", "whatsapp", "telegram", "vk"}
|
||
for _, platform := range platforms {
|
||
var count int64
|
||
s.db.Model(&models.Feedback{}).Where("platform = ?", platform).Count(&count)
|
||
stats.PlatformStats[platform] = count
|
||
}
|
||
|
||
return stats, nil
|
||
} |