tercul-backend/services/work_service.go
Damir Mukimov 4957117cb6 Initial commit: Tercul Go project with comprehensive architecture
- Core Go application with GraphQL API using gqlgen
- Comprehensive data models for literary works, authors, translations
- Repository pattern with caching layer
- Authentication and authorization system
- Linguistics analysis capabilities with multiple adapters
- Vector search integration with Weaviate
- Docker containerization support
- Python data migration and analysis scripts
- Clean architecture with proper separation of concerns
- Production-ready configuration and middleware
- Proper .gitignore excluding vendor/, database files, and build artifacts
2025-08-13 07:42:32 +02:00

186 lines
5.2 KiB
Go

package services
import (
"context"
"errors"
"tercul/models"
"tercul/repositories"
)
// WorkService defines the interface for work-related business logic
type WorkService interface {
// Basic CRUD operations
CreateWork(ctx context.Context, work *models.Work) error
GetWorkByID(ctx context.Context, id uint) (*models.Work, error)
UpdateWork(ctx context.Context, work *models.Work) error
DeleteWork(ctx context.Context, id uint) error
ListWorks(ctx context.Context, page, pageSize int) (*repositories.PaginatedResult[models.Work], error)
// Domain-specific operations
GetWorkWithTranslations(ctx context.Context, id uint) (*models.Work, error)
FindWorksByTitle(ctx context.Context, title string) ([]models.Work, error)
FindWorksByAuthor(ctx context.Context, authorID uint) ([]models.Work, error)
FindWorksByCategory(ctx context.Context, categoryID uint) ([]models.Work, error)
FindWorksByLanguage(ctx context.Context, language string, page, pageSize int) (*repositories.PaginatedResult[models.Work], error)
// Analysis operations
AnalyzeWork(ctx context.Context, workID uint) error
}
// WorkAnalytics contains analytics data for a work
type WorkAnalytics struct {
WorkID uint
ViewCount int64
LikeCount int64
CommentCount int64
BookmarkCount int64
TranslationCount int64
ReadabilityScore float64
SentimentScore float64
TopKeywords []string
PopularTranslations []TranslationAnalytics
}
// TranslationAnalytics contains analytics data for a translation
type TranslationAnalytics struct {
TranslationID uint
Language string
ViewCount int64
LikeCount int64
}
// workService implements WorkService
type workService struct {
workRepo repositories.WorkRepository
analyzer interface {
AnalyzeWork(ctx context.Context, workID uint) error
}
}
// NewWorkService creates a new WorkService
func NewWorkService(workRepo repositories.WorkRepository, analyzer interface {
AnalyzeWork(ctx context.Context, workID uint) error
}) WorkService {
return &workService{
workRepo: workRepo,
analyzer: analyzer,
}
}
// CreateWork creates a new work
func (s *workService) CreateWork(ctx context.Context, work *models.Work) error {
if work == nil {
return errors.New("work cannot be nil")
}
// Validate work
if work.Title == "" {
return errors.New("work title cannot be empty")
}
if work.Language == "" {
return errors.New("work language cannot be empty")
}
return s.workRepo.Create(ctx, work)
}
// GetWorkByID retrieves a work by ID
func (s *workService) GetWorkByID(ctx context.Context, id uint) (*models.Work, error) {
if id == 0 {
return nil, errors.New("invalid work ID")
}
return s.workRepo.GetByID(ctx, id)
}
// UpdateWork updates an existing work
func (s *workService) UpdateWork(ctx context.Context, work *models.Work) error {
if work == nil {
return errors.New("work cannot be nil")
}
if work.ID == 0 {
return errors.New("work ID cannot be zero")
}
// Validate work
if work.Title == "" {
return errors.New("work title cannot be empty")
}
if work.Language == "" {
return errors.New("work language cannot be empty")
}
return s.workRepo.Update(ctx, work)
}
// DeleteWork deletes a work by ID
func (s *workService) DeleteWork(ctx context.Context, id uint) error {
if id == 0 {
return errors.New("invalid work ID")
}
return s.workRepo.Delete(ctx, id)
}
// ListWorks returns a paginated list of works
func (s *workService) ListWorks(ctx context.Context, page, pageSize int) (*repositories.PaginatedResult[models.Work], error) {
return s.workRepo.List(ctx, page, pageSize)
}
// GetWorkWithTranslations retrieves a work with its translations
func (s *workService) GetWorkWithTranslations(ctx context.Context, id uint) (*models.Work, error) {
if id == 0 {
return nil, errors.New("invalid work ID")
}
return s.workRepo.GetWithTranslations(ctx, id)
}
// FindWorksByTitle finds works by title
func (s *workService) FindWorksByTitle(ctx context.Context, title string) ([]models.Work, error) {
if title == "" {
return nil, errors.New("title cannot be empty")
}
return s.workRepo.FindByTitle(ctx, title)
}
// FindWorksByAuthor finds works by author ID
func (s *workService) FindWorksByAuthor(ctx context.Context, authorID uint) ([]models.Work, error) {
if authorID == 0 {
return nil, errors.New("invalid author ID")
}
return s.workRepo.FindByAuthor(ctx, authorID)
}
// FindWorksByCategory finds works by category ID
func (s *workService) FindWorksByCategory(ctx context.Context, categoryID uint) ([]models.Work, error) {
if categoryID == 0 {
return nil, errors.New("invalid category ID")
}
return s.workRepo.FindByCategory(ctx, categoryID)
}
// FindWorksByLanguage finds works by language
func (s *workService) FindWorksByLanguage(ctx context.Context, language string, page, pageSize int) (*repositories.PaginatedResult[models.Work], error) {
if language == "" {
return nil, errors.New("language cannot be empty")
}
return s.workRepo.FindByLanguage(ctx, language, page, pageSize)
}
// AnalyzeWork performs linguistic analysis on a work
func (s *workService) AnalyzeWork(ctx context.Context, workID uint) error {
if workID == 0 {
return errors.New("invalid work ID")
}
return s.analyzer.AnalyzeWork(ctx, workID)
}