Files
2025-07-28 14:58:08 +03:00

135 lines
3.4 KiB
Go

package service
import (
"context"
"fmt"
"sort"
"time"
"route256/comments/internal/domain/entity"
"route256/comments/internal/domain/model"
)
type CommentRepository interface {
GetCommentByID(ctx context.Context, id int64) (*entity.Comment, error)
InsertComment(ctx context.Context, comment *entity.Comment) (*entity.Comment, error)
ListCommentsBySku(ctx context.Context, sku int64) ([]*entity.Comment, error)
ListCommentsByUser(ctx context.Context, userID int64) ([]*entity.Comment, error)
UpdateComment(ctx context.Context, comment *entity.Comment) (*entity.Comment, error)
}
type CommentsService struct {
comments CommentRepository
timeout time.Duration
}
func NewCommentsService(commRepo CommentRepository, timeout time.Duration) *CommentsService {
return &CommentsService{
comments: commRepo,
timeout: timeout,
}
}
func (s *CommentsService) checkTimeout(newTime, oldTime time.Time) error {
if newTime.Sub(oldTime) >= s.timeout {
return model.ErrCommentEditTimeout
}
return nil
}
func (s *CommentsService) CommentCreate(ctx context.Context, comment *entity.Comment) (int64, error) {
comm, err := s.comments.InsertComment(ctx, &entity.Comment{
UserID: comment.UserID,
SKU: comment.SKU,
CreatedAt: time.Now(),
Text: comment.Text,
})
if err != nil {
return 0, fmt.Errorf("repository.InsertComment: %w", err)
}
return comm.ID, nil
}
func (s *CommentsService) CommentGetByID(ctx context.Context, id int64) (*entity.Comment, error) {
if id <= 0 {
return nil, fmt.Errorf("comment id must be greater than 0")
}
comm, err := s.comments.GetCommentByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("repository.InsertComment: %w", err)
}
return comm, nil
}
func (s *CommentsService) CommentEdit(ctx context.Context, newComment *entity.Comment) error {
if newComment.ID <= 0 {
return fmt.Errorf("comment id must be greater than 0")
}
oldComment, err := s.comments.GetCommentByID(ctx, newComment.ID)
if err != nil {
return fmt.Errorf("repository.GetCommentByID: %w", err)
}
if oldComment.UserID != newComment.UserID {
return model.ErrCommentEditUserMismatch
}
comment := &entity.Comment{
ID: newComment.ID,
UserID: newComment.UserID,
SKU: newComment.SKU,
CreatedAt: time.Now(),
Text: newComment.Text,
}
if err := s.checkTimeout(comment.CreatedAt, oldComment.CreatedAt); err != nil {
return err
}
if _, err := s.comments.UpdateComment(ctx, comment); err != nil {
return fmt.Errorf("repository.UpdateComment: %w", err)
}
return nil
}
func (s *CommentsService) CommentListBySKU(ctx context.Context, sku int64) ([]*entity.Comment, error) {
if sku <= 0 {
return nil, fmt.Errorf("sku must be greater than 0")
}
comms, err := s.comments.ListCommentsBySku(ctx, sku)
if err != nil {
return nil, fmt.Errorf("repository.ListCommentsBySku: %w", err)
}
return comms, nil
}
func (s *CommentsService) CommentListByUser(ctx context.Context, userID int64) ([]*entity.Comment, error) {
if userID <= 0 {
return nil, fmt.Errorf("userID must be greater than 0")
}
comms, err := s.comments.ListCommentsByUser(ctx, userID)
if err != nil {
return nil, fmt.Errorf("repository.ListCommentsByUser: %w", err)
}
sort.Slice(comms, func(i, j int) bool {
if comms[i].CreatedAt.Equal(comms[j].CreatedAt) {
return comms[i].UserID < comms[j].UserID
}
return comms[i].CreatedAt.After(comms[j].CreatedAt)
})
return comms, nil
}