MIF_E31222379_BE/internal/article/article_repository.go

149 lines
3.9 KiB
Go

package article
import (
"context"
"errors"
"fmt"
"rijig/model"
"gorm.io/gorm"
)
type ArticleRepository interface {
CreateArticle(ctx context.Context, article *model.Article) error
FindArticleByID(ctx context.Context, id string) (*model.Article, error)
FindAllArticles(ctx context.Context, page, limit int) ([]model.Article, int64, error)
UpdateArticle(ctx context.Context, id string, article *model.Article) error
DeleteArticle(ctx context.Context, id string) error
ArticleExists(ctx context.Context, id string) (bool, error)
}
type articleRepository struct {
db *gorm.DB
}
func NewArticleRepository(db *gorm.DB) ArticleRepository {
return &articleRepository{db: db}
}
func (r *articleRepository) CreateArticle(ctx context.Context, article *model.Article) error {
if article == nil {
return errors.New("article cannot be nil")
}
if err := r.db.WithContext(ctx).Create(article).Error; err != nil {
return fmt.Errorf("failed to create article: %w", err)
}
return nil
}
func (r *articleRepository) FindArticleByID(ctx context.Context, id string) (*model.Article, error) {
if id == "" {
return nil, errors.New("article ID cannot be empty")
}
var article model.Article
err := r.db.WithContext(ctx).Where("id = ?", id).First(&article).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("article with ID %s not found", id)
}
return nil, fmt.Errorf("failed to fetch article: %w", err)
}
return &article, nil
}
func (r *articleRepository) FindAllArticles(ctx context.Context, page, limit int) ([]model.Article, int64, error) {
var articles []model.Article
var total int64
if page < 0 || limit < 0 {
return nil, 0, errors.New("page and limit must be non-negative")
}
if err := r.db.WithContext(ctx).Model(&model.Article{}).Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("failed to count articles: %w", err)
}
query := r.db.WithContext(ctx).Model(&model.Article{})
if page > 0 && limit > 0 {
offset := (page - 1) * limit
query = query.Offset(offset).Limit(limit)
}
if err := query.Find(&articles).Error; err != nil {
return nil, 0, fmt.Errorf("failed to fetch articles: %w", err)
}
return articles, total, nil
}
func (r *articleRepository) UpdateArticle(ctx context.Context, id string, article *model.Article) error {
if id == "" {
return errors.New("article ID cannot be empty")
}
if article == nil {
return errors.New("article cannot be nil")
}
exists, err := r.ArticleExists(ctx, id)
if err != nil {
return fmt.Errorf("failed to check article existence: %w", err)
}
if !exists {
return fmt.Errorf("article with ID %s not found", id)
}
result := r.db.WithContext(ctx).Model(&model.Article{}).Where("id = ?", id).Updates(article)
if result.Error != nil {
return fmt.Errorf("failed to update article: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("no rows affected when updating article with ID %s", id)
}
return nil
}
func (r *articleRepository) DeleteArticle(ctx context.Context, id string) error {
if id == "" {
return errors.New("article ID cannot be empty")
}
exists, err := r.ArticleExists(ctx, id)
if err != nil {
return fmt.Errorf("failed to check article existence: %w", err)
}
if !exists {
return fmt.Errorf("article with ID %s not found", id)
}
result := r.db.WithContext(ctx).Where("id = ?", id).Delete(&model.Article{})
if result.Error != nil {
return fmt.Errorf("failed to delete article: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("no rows affected when deleting article with ID %s", id)
}
return nil
}
func (r *articleRepository) ArticleExists(ctx context.Context, id string) (bool, error) {
if id == "" {
return false, errors.New("article ID cannot be empty")
}
var count int64
err := r.db.WithContext(ctx).Model(&model.Article{}).Where("id = ?", id).Count(&count).Error
if err != nil {
return false, fmt.Errorf("failed to check article existence: %w", err)
}
return count > 0, nil
}