15357fd3c0
yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarba
246 lines
6.4 KiB
Go
246 lines
6.4 KiB
Go
package service
|
|
|
|
import (
|
|
"api_bb/internal/models"
|
|
"api_bb/internal/repository"
|
|
"api_bb/pkg/logger"
|
|
"errors"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type NewsService interface {
|
|
CreateNews(req models.CreateNewsRequest, authorID uint) (*models.NewsResponse, error)
|
|
GetNewsByID(id uint) (*models.NewsResponse, error)
|
|
GetAllNews(limit, offset int, category string) ([]models.NewsResponse, int64, error)
|
|
UpdateNews(id uint, req models.UpdateNewsRequest, userID uint) (*models.NewsResponse, error)
|
|
DeleteNews(id uint, userID uint) error
|
|
IncrementViews(id uint) error
|
|
CreateComment(newsID uint, req models.CreateCommentRequest, authorID uint) (*models.CommentResponse, error)
|
|
GetCommentsByNewsID(newsID uint) ([]models.CommentResponse, error)
|
|
DeleteComment(commentID, userID uint) error
|
|
GetUserNews(userID uint, limit, offset int) ([]models.NewsResponse, int64, error)
|
|
}
|
|
|
|
type newsService struct {
|
|
newsRepo repository.NewsRepository
|
|
commentRepo repository.CommentRepository
|
|
logger logger.LoggerInterface
|
|
}
|
|
|
|
func NewNewsService(newsRepo repository.NewsRepository, commentRepo repository.CommentRepository, log logger.LoggerInterface) NewsService {
|
|
|
|
serviceLogger := log.With(zap.String("service", "news"))
|
|
|
|
return &newsService{
|
|
newsRepo: newsRepo,
|
|
commentRepo: commentRepo,
|
|
logger: serviceLogger,
|
|
}
|
|
}
|
|
|
|
func (s *newsService) CreateNews(req models.CreateNewsRequest, authorID uint) (*models.NewsResponse, error) {
|
|
news := &models.News{
|
|
Title: req.Title,
|
|
Excerpt: req.Excerpt,
|
|
Content: req.Content,
|
|
Image: req.Image,
|
|
Category: req.Category,
|
|
AuthorID: authorID,
|
|
}
|
|
|
|
if err := s.newsRepo.Create(news); err != nil {
|
|
s.logger.Error("Failed to create news", zap.Error(err))
|
|
return nil, errors.New("failed to create news")
|
|
}
|
|
|
|
// Получаем созданную новость с автором
|
|
createdNews, err := s.newsRepo.GetByID(news.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.toNewsResponse(createdNews), nil
|
|
}
|
|
|
|
func (s *newsService) GetNewsByID(id uint) (*models.NewsResponse, error) {
|
|
news, err := s.newsRepo.GetByID(id)
|
|
if err != nil {
|
|
return nil, errors.New("news not found")
|
|
}
|
|
|
|
// Увеличиваем счетчик просмотров
|
|
go s.newsRepo.IncrementViews(id)
|
|
|
|
return s.toNewsResponse(news), nil
|
|
}
|
|
|
|
func (s *newsService) GetAllNews(limit, offset int, category string) ([]models.NewsResponse, int64, error) {
|
|
news, total, err := s.newsRepo.GetAll(limit, offset, category)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
responses := make([]models.NewsResponse, len(news))
|
|
for i, n := range news {
|
|
responses[i] = *s.toNewsResponse(&n)
|
|
}
|
|
|
|
return responses, total, nil
|
|
}
|
|
|
|
func (s *newsService) UpdateNews(id uint, req models.UpdateNewsRequest, userID uint) (*models.NewsResponse, error) {
|
|
news, err := s.newsRepo.GetByID(id)
|
|
if err != nil {
|
|
return nil, errors.New("news not found")
|
|
}
|
|
|
|
// Проверяем права доступа
|
|
if news.AuthorID != userID {
|
|
return nil, errors.New("access denied")
|
|
}
|
|
|
|
// Обновляем поля
|
|
if req.Title != "" {
|
|
news.Title = req.Title
|
|
}
|
|
if req.Excerpt != "" {
|
|
news.Excerpt = req.Excerpt
|
|
}
|
|
if req.Content != "" {
|
|
news.Content = req.Content
|
|
}
|
|
if req.Image != "" {
|
|
news.Image = req.Image
|
|
}
|
|
if req.Category != "" {
|
|
news.Category = req.Category
|
|
}
|
|
|
|
if err := s.newsRepo.Update(news); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.toNewsResponse(news), nil
|
|
}
|
|
|
|
func (s *newsService) DeleteNews(id uint, userID uint) error {
|
|
news, err := s.newsRepo.GetByID(id)
|
|
if err != nil {
|
|
return errors.New("news not found")
|
|
}
|
|
|
|
// Проверяем права доступа
|
|
if news.AuthorID != userID {
|
|
return errors.New("access denied")
|
|
}
|
|
|
|
return s.newsRepo.Delete(id)
|
|
}
|
|
|
|
func (s *newsService) IncrementViews(id uint) error {
|
|
return s.newsRepo.IncrementViews(id)
|
|
}
|
|
|
|
func (s *newsService) CreateComment(newsID uint, req models.CreateCommentRequest, authorID uint) (*models.CommentResponse, error) {
|
|
// Проверяем существование новости
|
|
_, err := s.newsRepo.GetByID(newsID)
|
|
if err != nil {
|
|
return nil, errors.New("news not found")
|
|
}
|
|
|
|
comment := &models.Comment{
|
|
Content: req.Content,
|
|
NewsID: newsID,
|
|
AuthorID: authorID,
|
|
}
|
|
|
|
if err := s.commentRepo.Create(comment); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Получаем созданный комментарий с автором
|
|
createdComment, err := s.commentRepo.GetByID(comment.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.toCommentResponse(createdComment), nil
|
|
}
|
|
|
|
func (s *newsService) GetCommentsByNewsID(newsID uint) ([]models.CommentResponse, error) {
|
|
comments, err := s.commentRepo.GetByNewsID(newsID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responses := make([]models.CommentResponse, len(comments))
|
|
for i, c := range comments {
|
|
responses[i] = *s.toCommentResponse(&c)
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
func (s *newsService) DeleteComment(commentID, userID uint) error {
|
|
comment, err := s.commentRepo.GetByID(commentID)
|
|
if err != nil {
|
|
return errors.New("comment not found")
|
|
}
|
|
|
|
// Проверяем права доступа
|
|
if comment.AuthorID != userID {
|
|
return errors.New("access denied")
|
|
}
|
|
|
|
return s.commentRepo.Delete(commentID)
|
|
}
|
|
|
|
func (s *newsService) GetUserNews(userID uint, limit, offset int) ([]models.NewsResponse, int64, error) {
|
|
news, total, err := s.newsRepo.GetByAuthor(userID, limit, offset)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
responses := make([]models.NewsResponse, len(news))
|
|
for i, n := range news {
|
|
responses[i] = *s.toNewsResponse(&n)
|
|
}
|
|
|
|
return responses, total, nil
|
|
}
|
|
|
|
// Вспомогательные методы для преобразования
|
|
func (s *newsService) toNewsResponse(news *models.News) *models.NewsResponse {
|
|
return &models.NewsResponse{
|
|
ID: news.ID,
|
|
CreatedAt: news.CreatedAt,
|
|
UpdatedAt: news.UpdatedAt,
|
|
Title: news.Title,
|
|
Excerpt: news.Excerpt,
|
|
Content: news.Content,
|
|
Image: news.Image,
|
|
Category: news.Category,
|
|
Views: news.Views,
|
|
Author: models.AuthorInfo{
|
|
ID: news.Author.ID,
|
|
FirstName: news.Author.FirstName,
|
|
LastName: news.Author.LastName,
|
|
},
|
|
Comments: len(news.Comments),
|
|
}
|
|
}
|
|
|
|
func (s *newsService) toCommentResponse(comment *models.Comment) *models.CommentResponse {
|
|
return &models.CommentResponse{
|
|
ID: comment.ID,
|
|
CreatedAt: comment.CreatedAt,
|
|
Content: comment.Content,
|
|
Author: models.AuthorInfo{
|
|
ID: comment.Author.ID,
|
|
FirstName: comment.Author.FirstName,
|
|
LastName: comment.Author.LastName,
|
|
},
|
|
}
|
|
}
|