mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 02:51:34 +00:00
This commit addresses the "Stabilize non-linguistics tests and interfaces" task from TODO.md.
The main changes are: - Refactored the `Copyright` and `Monetization` relationships to use explicit join tables for each owning model, as per the "Option A" strategy. This fixes the GORM migration issues related to polymorphic many-to-many relationships. - Created new join table structs (e.g., `WorkCopyright`, `AuthorCopyright`, `WorkMonetization`, etc.). - Updated the domain models to use standard `gorm:"many2many"` tags with the new join tables. - Refactored the `CopyrightRepository` and `MonetizationRepository` to use the new association-based logic. - Updated the application services (`CopyrightCommands`, `CopyrightQueries`, `MonetizationCommands`, `MonetizationQueries`) to use the new repository methods. - Consolidated all repository interfaces into a single `internal/domain/interfaces.go` file for better code organization. - Added extensive integration tests for the new repository and application layer logic for `Copyrights` and `Monetizations`. - Fixed the deletion logic for `WorkRepository` to correctly handle cascading deletes with SQLite. - Updated the `TODO.md` file to mark the "Stabilize non-linguistics tests and interfaces" task as complete.
This commit is contained in:
parent
042773c8f9
commit
5d6a6ef47b
@ -4,6 +4,7 @@ import (
|
||||
"tercul/internal/app/auth"
|
||||
"tercul/internal/app/copyright"
|
||||
"tercul/internal/app/localization"
|
||||
"tercul/internal/app/monetization"
|
||||
"tercul/internal/app/search"
|
||||
"tercul/internal/app/work"
|
||||
"tercul/internal/domain"
|
||||
@ -26,4 +27,8 @@ type Application struct {
|
||||
UserRepo domain.UserRepository
|
||||
TagRepo domain.TagRepository
|
||||
CategoryRepo domain.CategoryRepository
|
||||
BookRepo domain.BookRepository
|
||||
PublisherRepo domain.PublisherRepository
|
||||
SourceRepo domain.SourceRepository
|
||||
MonetizationQueries *monetization.MonetizationQueries
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"tercul/internal/app/auth"
|
||||
"tercul/internal/app/copyright"
|
||||
"tercul/internal/app/localization"
|
||||
"tercul/internal/app/monetization"
|
||||
"tercul/internal/app/search"
|
||||
"tercul/internal/app/work"
|
||||
"tercul/internal/data/sql"
|
||||
@ -122,7 +123,10 @@ func (b *ApplicationBuilder) BuildApplication() error {
|
||||
authQueries := auth.NewAuthQueries(userRepo, jwtManager)
|
||||
|
||||
copyrightCommands := copyright.NewCopyrightCommands(copyrightRepo)
|
||||
copyrightQueries := copyright.NewCopyrightQueries(copyrightRepo)
|
||||
bookRepo := sql.NewBookRepository(b.dbConn)
|
||||
publisherRepo := sql.NewPublisherRepository(b.dbConn)
|
||||
sourceRepo := sql.NewSourceRepository(b.dbConn)
|
||||
copyrightQueries := copyright.NewCopyrightQueries(copyrightRepo, workRepo, authorRepo, bookRepo, publisherRepo, sourceRepo)
|
||||
|
||||
localizationService := localization.NewService(translationRepo)
|
||||
|
||||
@ -141,6 +145,10 @@ func (b *ApplicationBuilder) BuildApplication() error {
|
||||
UserRepo: userRepo,
|
||||
TagRepo: tagRepo,
|
||||
CategoryRepo: categoryRepo,
|
||||
BookRepo: sql.NewBookRepository(b.dbConn),
|
||||
PublisherRepo: sql.NewPublisherRepository(b.dbConn),
|
||||
SourceRepo: sql.NewSourceRepository(b.dbConn),
|
||||
MonetizationQueries: monetization.NewMonetizationQueries(sql.NewMonetizationRepository(b.dbConn), workRepo, authorRepo, bookRepo, publisherRepo, sourceRepo),
|
||||
}
|
||||
|
||||
log.LogInfo("Application layer initialized successfully")
|
||||
|
||||
@ -55,26 +55,85 @@ func (c *CopyrightCommands) DeleteCopyright(ctx context.Context, id uint) error
|
||||
return c.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// AttachCopyrightToEntity attaches a copyright to any entity type.
|
||||
func (c *CopyrightCommands) AttachCopyrightToEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) error {
|
||||
if copyrightID == 0 || entityID == 0 {
|
||||
return errors.New("invalid copyright ID or entity ID")
|
||||
|
||||
// AddCopyrightToWork adds a copyright to a work.
|
||||
func (c *CopyrightCommands) AddCopyrightToWork(ctx context.Context, workID uint, copyrightID uint) error {
|
||||
if workID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid work ID or copyright ID")
|
||||
}
|
||||
if entityType == "" {
|
||||
return errors.New("entity type cannot be empty")
|
||||
}
|
||||
return c.repo.AttachToEntity(ctx, copyrightID, entityID, entityType)
|
||||
return c.repo.AddCopyrightToWork(ctx, workID, copyrightID)
|
||||
}
|
||||
|
||||
// DetachCopyrightFromEntity removes a copyright from an entity.
|
||||
func (c *CopyrightCommands) DetachCopyrightFromEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) error {
|
||||
if copyrightID == 0 || entityID == 0 {
|
||||
return errors.New("invalid copyright ID or entity ID")
|
||||
// RemoveCopyrightFromWork removes a copyright from a work.
|
||||
func (c *CopyrightCommands) RemoveCopyrightFromWork(ctx context.Context, workID uint, copyrightID uint) error {
|
||||
if workID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid work ID or copyright ID")
|
||||
}
|
||||
if entityType == "" {
|
||||
return errors.New("entity type cannot be empty")
|
||||
return c.repo.RemoveCopyrightFromWork(ctx, workID, copyrightID)
|
||||
}
|
||||
|
||||
// AddCopyrightToAuthor adds a copyright to an author.
|
||||
func (c *CopyrightCommands) AddCopyrightToAuthor(ctx context.Context, authorID uint, copyrightID uint) error {
|
||||
if authorID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid author ID or copyright ID")
|
||||
}
|
||||
return c.repo.DetachFromEntity(ctx, copyrightID, entityID, entityType)
|
||||
return c.repo.AddCopyrightToAuthor(ctx, authorID, copyrightID)
|
||||
}
|
||||
|
||||
// RemoveCopyrightFromAuthor removes a copyright from an author.
|
||||
func (c *CopyrightCommands) RemoveCopyrightFromAuthor(ctx context.Context, authorID uint, copyrightID uint) error {
|
||||
if authorID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid author ID or copyright ID")
|
||||
}
|
||||
return c.repo.RemoveCopyrightFromAuthor(ctx, authorID, copyrightID)
|
||||
}
|
||||
|
||||
// AddCopyrightToBook adds a copyright to a book.
|
||||
func (c *CopyrightCommands) AddCopyrightToBook(ctx context.Context, bookID uint, copyrightID uint) error {
|
||||
if bookID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid book ID or copyright ID")
|
||||
}
|
||||
return c.repo.AddCopyrightToBook(ctx, bookID, copyrightID)
|
||||
}
|
||||
|
||||
// RemoveCopyrightFromBook removes a copyright from a book.
|
||||
func (c *CopyrightCommands) RemoveCopyrightFromBook(ctx context.Context, bookID uint, copyrightID uint) error {
|
||||
if bookID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid book ID or copyright ID")
|
||||
}
|
||||
return c.repo.RemoveCopyrightFromBook(ctx, bookID, copyrightID)
|
||||
}
|
||||
|
||||
// AddCopyrightToPublisher adds a copyright to a publisher.
|
||||
func (c *CopyrightCommands) AddCopyrightToPublisher(ctx context.Context, publisherID uint, copyrightID uint) error {
|
||||
if publisherID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid publisher ID or copyright ID")
|
||||
}
|
||||
return c.repo.AddCopyrightToPublisher(ctx, publisherID, copyrightID)
|
||||
}
|
||||
|
||||
// RemoveCopyrightFromPublisher removes a copyright from a publisher.
|
||||
func (c *CopyrightCommands) RemoveCopyrightFromPublisher(ctx context.Context, publisherID uint, copyrightID uint) error {
|
||||
if publisherID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid publisher ID or copyright ID")
|
||||
}
|
||||
return c.repo.RemoveCopyrightFromPublisher(ctx, publisherID, copyrightID)
|
||||
}
|
||||
|
||||
// AddCopyrightToSource adds a copyright to a source.
|
||||
func (c *CopyrightCommands) AddCopyrightToSource(ctx context.Context, sourceID uint, copyrightID uint) error {
|
||||
if sourceID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid source ID or copyright ID")
|
||||
}
|
||||
return c.repo.AddCopyrightToSource(ctx, sourceID, copyrightID)
|
||||
}
|
||||
|
||||
// RemoveCopyrightFromSource removes a copyright from a source.
|
||||
func (c *CopyrightCommands) RemoveCopyrightFromSource(ctx context.Context, sourceID uint, copyrightID uint) error {
|
||||
if sourceID == 0 || copyrightID == 0 {
|
||||
return errors.New("invalid source ID or copyright ID")
|
||||
}
|
||||
return c.repo.RemoveCopyrightFromSource(ctx, sourceID, copyrightID)
|
||||
}
|
||||
|
||||
// AddTranslation adds a translation to a copyright.
|
||||
|
||||
237
internal/app/copyright/commands_test.go
Normal file
237
internal/app/copyright/commands_test.go
Normal file
@ -0,0 +1,237 @@
|
||||
package copyright_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/app/copyright"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type CopyrightCommandsTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
commands *copyright.CopyrightCommands
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
s.commands = copyright.NewCopyrightCommands(s.CopyrightRepo)
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToWork() {
|
||||
s.Run("should add a copyright to a work", func() {
|
||||
// Arrange
|
||||
work := s.CreateTestWork("Test Work", "en", "Test content")
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
|
||||
// Act
|
||||
err := s.commands.AddCopyrightToWork(context.Background(), work.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Verify that the association was created in the database
|
||||
var foundWork domain.Work
|
||||
err = s.DB.Preload("Copyrights").First(&foundWork, work.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundWork.Copyrights, 1)
|
||||
s.Equal(copyright.ID, foundWork.Copyrights[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromWork() {
|
||||
s.Run("should remove a copyright from a work", func() {
|
||||
// Arrange
|
||||
work := s.CreateTestWork("Test Work", "en", "Test content")
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
s.Require().NoError(s.commands.AddCopyrightToWork(context.Background(), work.ID, copyright.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveCopyrightFromWork(context.Background(), work.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Verify that the association was removed from the database
|
||||
var foundWork domain.Work
|
||||
err = s.DB.Preload("Copyrights").First(&foundWork, work.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundWork.Copyrights, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToAuthor() {
|
||||
s.Run("should add a copyright to an author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "Test Author"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
|
||||
// Act
|
||||
err := s.commands.AddCopyrightToAuthor(context.Background(), author.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.Preload("Copyrights").First(&foundAuthor, author.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundAuthor.Copyrights, 1)
|
||||
s.Equal(copyright.ID, foundAuthor.Copyrights[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromAuthor() {
|
||||
s.Run("should remove a copyright from an author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "Test Author"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
s.Require().NoError(s.commands.AddCopyrightToAuthor(context.Background(), author.ID, copyright.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveCopyrightFromAuthor(context.Background(), author.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.Preload("Copyrights").First(&foundAuthor, author.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundAuthor.Copyrights, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToBook() {
|
||||
s.Run("should add a copyright to a book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Test Book"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
|
||||
// Act
|
||||
err := s.commands.AddCopyrightToBook(context.Background(), book.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundBook domain.Book
|
||||
err = s.DB.Preload("Copyrights").First(&foundBook, book.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundBook.Copyrights, 1)
|
||||
s.Equal(copyright.ID, foundBook.Copyrights[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromBook() {
|
||||
s.Run("should remove a copyright from a book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Test Book"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
s.Require().NoError(s.commands.AddCopyrightToBook(context.Background(), book.ID, copyright.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveCopyrightFromBook(context.Background(), book.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundBook domain.Book
|
||||
err = s.DB.Preload("Copyrights").First(&foundBook, book.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundBook.Copyrights, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToPublisher() {
|
||||
s.Run("should add a copyright to a publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "Test Publisher"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
|
||||
// Act
|
||||
err := s.commands.AddCopyrightToPublisher(context.Background(), publisher.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.Preload("Copyrights").First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundPublisher.Copyrights, 1)
|
||||
s.Equal(copyright.ID, foundPublisher.Copyrights[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromPublisher() {
|
||||
s.Run("should remove a copyright from a publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "Test Publisher"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
s.Require().NoError(s.commands.AddCopyrightToPublisher(context.Background(), publisher.ID, copyright.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveCopyrightFromPublisher(context.Background(), publisher.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.Preload("Copyrights").First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundPublisher.Copyrights, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestAddCopyrightToSource() {
|
||||
s.Run("should add a copyright to a source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "Test Source"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
|
||||
// Act
|
||||
err := s.commands.AddCopyrightToSource(context.Background(), source.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundSource domain.Source
|
||||
err = s.DB.Preload("Copyrights").First(&foundSource, source.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundSource.Copyrights, 1)
|
||||
s.Equal(copyright.ID, foundSource.Copyrights[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CopyrightCommandsTestSuite) TestRemoveCopyrightFromSource() {
|
||||
s.Run("should remove a copyright from a source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "Test Source"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
copyright := &domain.Copyright{Name: "Test Copyright", Identificator: "TC-123"}
|
||||
s.Require().NoError(s.CopyrightRepo.Create(context.Background(), copyright))
|
||||
s.Require().NoError(s.commands.AddCopyrightToSource(context.Background(), source.ID, copyright.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveCopyrightFromSource(context.Background(), source.ID, copyright.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundSource domain.Source
|
||||
err = s.DB.Preload("Copyrights").First(&foundSource, source.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundSource.Copyrights, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopyrightCommands(t *testing.T) {
|
||||
suite.Run(t, new(CopyrightCommandsTestSuite))
|
||||
}
|
||||
@ -8,12 +8,17 @@ import (
|
||||
|
||||
// CopyrightQueries contains the query handlers for copyright.
|
||||
type CopyrightQueries struct {
|
||||
repo domain.CopyrightRepository
|
||||
repo domain.CopyrightRepository
|
||||
workRepo domain.WorkRepository
|
||||
authorRepo domain.AuthorRepository
|
||||
bookRepo domain.BookRepository
|
||||
publisherRepo domain.PublisherRepository
|
||||
sourceRepo domain.SourceRepository
|
||||
}
|
||||
|
||||
// NewCopyrightQueries creates a new CopyrightQueries handler.
|
||||
func NewCopyrightQueries(repo domain.CopyrightRepository) *CopyrightQueries {
|
||||
return &CopyrightQueries{repo: repo}
|
||||
func NewCopyrightQueries(repo domain.CopyrightRepository, workRepo domain.WorkRepository, authorRepo domain.AuthorRepository, bookRepo domain.BookRepository, publisherRepo domain.PublisherRepository, sourceRepo domain.SourceRepository) *CopyrightQueries {
|
||||
return &CopyrightQueries{repo: repo, workRepo: workRepo, authorRepo: authorRepo, bookRepo: bookRepo, publisherRepo: publisherRepo, sourceRepo: sourceRepo}
|
||||
}
|
||||
|
||||
// GetCopyrightByID retrieves a copyright by ID.
|
||||
@ -31,23 +36,51 @@ func (q *CopyrightQueries) ListCopyrights(ctx context.Context) ([]domain.Copyrig
|
||||
return q.repo.ListAll(ctx)
|
||||
}
|
||||
|
||||
// GetCopyrightsForEntity gets all copyrights for a specific entity.
|
||||
func (q *CopyrightQueries) GetCopyrightsForEntity(ctx context.Context, entityID uint, entityType string) ([]domain.Copyright, error) {
|
||||
if entityID == 0 {
|
||||
return nil, errors.New("invalid entity ID")
|
||||
|
||||
|
||||
// GetCopyrightsForWork gets all copyrights for a specific work.
|
||||
func (q *CopyrightQueries) GetCopyrightsForWork(ctx context.Context, workID uint) ([]*domain.Copyright, error) {
|
||||
work, err := q.workRepo.GetByIDWithOptions(ctx, workID, &domain.QueryOptions{Preloads: []string{"Copyrights"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entityType == "" {
|
||||
return nil, errors.New("entity type cannot be empty")
|
||||
}
|
||||
return q.repo.GetByEntity(ctx, entityID, entityType)
|
||||
return work.Copyrights, nil
|
||||
}
|
||||
|
||||
// GetEntitiesByCopyright gets all entities that have a specific copyright.
|
||||
func (q *CopyrightQueries) GetEntitiesByCopyright(ctx context.Context, copyrightID uint) ([]domain.Copyrightable, error) {
|
||||
if copyrightID == 0 {
|
||||
return nil, errors.New("invalid copyright ID")
|
||||
// GetCopyrightsForAuthor gets all copyrights for a specific author.
|
||||
func (q *CopyrightQueries) GetCopyrightsForAuthor(ctx context.Context, authorID uint) ([]*domain.Copyright, error) {
|
||||
author, err := q.authorRepo.GetByIDWithOptions(ctx, authorID, &domain.QueryOptions{Preloads: []string{"Copyrights"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.repo.GetEntitiesByCopyright(ctx, copyrightID)
|
||||
return author.Copyrights, nil
|
||||
}
|
||||
|
||||
// GetCopyrightsForBook gets all copyrights for a specific book.
|
||||
func (q *CopyrightQueries) GetCopyrightsForBook(ctx context.Context, bookID uint) ([]*domain.Copyright, error) {
|
||||
book, err := q.bookRepo.GetByIDWithOptions(ctx, bookID, &domain.QueryOptions{Preloads: []string{"Copyrights"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return book.Copyrights, nil
|
||||
}
|
||||
|
||||
// GetCopyrightsForPublisher gets all copyrights for a specific publisher.
|
||||
func (q *CopyrightQueries) GetCopyrightsForPublisher(ctx context.Context, publisherID uint) ([]*domain.Copyright, error) {
|
||||
publisher, err := q.publisherRepo.GetByIDWithOptions(ctx, publisherID, &domain.QueryOptions{Preloads: []string{"Copyrights"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return publisher.Copyrights, nil
|
||||
}
|
||||
|
||||
// GetCopyrightsForSource gets all copyrights for a specific source.
|
||||
func (q *CopyrightQueries) GetCopyrightsForSource(ctx context.Context, sourceID uint) ([]*domain.Copyright, error) {
|
||||
source, err := q.sourceRepo.GetByIDWithOptions(ctx, sourceID, &domain.QueryOptions{Preloads: []string{"Copyrights"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return source.Copyrights, nil
|
||||
}
|
||||
|
||||
// GetTranslations gets all translations for a copyright.
|
||||
|
||||
89
internal/app/monetization/commands.go
Normal file
89
internal/app/monetization/commands.go
Normal file
@ -0,0 +1,89 @@
|
||||
package monetization
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// MonetizationCommands contains the command handlers for monetization.
|
||||
type MonetizationCommands struct {
|
||||
repo domain.MonetizationRepository
|
||||
}
|
||||
|
||||
// NewMonetizationCommands creates a new MonetizationCommands handler.
|
||||
func NewMonetizationCommands(repo domain.MonetizationRepository) *MonetizationCommands {
|
||||
return &MonetizationCommands{repo: repo}
|
||||
}
|
||||
|
||||
// AddMonetizationToWork adds a monetization to a work.
|
||||
func (c *MonetizationCommands) AddMonetizationToWork(ctx context.Context, workID uint, monetizationID uint) error {
|
||||
if workID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid work ID or monetization ID")
|
||||
}
|
||||
return c.repo.AddMonetizationToWork(ctx, workID, monetizationID)
|
||||
}
|
||||
|
||||
// RemoveMonetizationFromWork removes a monetization from a work.
|
||||
func (c *MonetizationCommands) RemoveMonetizationFromWork(ctx context.Context, workID uint, monetizationID uint) error {
|
||||
if workID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid work ID or monetization ID")
|
||||
}
|
||||
return c.repo.RemoveMonetizationFromWork(ctx, workID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) AddMonetizationToAuthor(ctx context.Context, authorID uint, monetizationID uint) error {
|
||||
if authorID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid author ID or monetization ID")
|
||||
}
|
||||
return c.repo.AddMonetizationToAuthor(ctx, authorID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) RemoveMonetizationFromAuthor(ctx context.Context, authorID uint, monetizationID uint) error {
|
||||
if authorID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid author ID or monetization ID")
|
||||
}
|
||||
return c.repo.RemoveMonetizationFromAuthor(ctx, authorID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) AddMonetizationToBook(ctx context.Context, bookID uint, monetizationID uint) error {
|
||||
if bookID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid book ID or monetization ID")
|
||||
}
|
||||
return c.repo.AddMonetizationToBook(ctx, bookID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) RemoveMonetizationFromBook(ctx context.Context, bookID uint, monetizationID uint) error {
|
||||
if bookID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid book ID or monetization ID")
|
||||
}
|
||||
return c.repo.RemoveMonetizationFromBook(ctx, bookID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) AddMonetizationToPublisher(ctx context.Context, publisherID uint, monetizationID uint) error {
|
||||
if publisherID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid publisher ID or monetization ID")
|
||||
}
|
||||
return c.repo.AddMonetizationToPublisher(ctx, publisherID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) RemoveMonetizationFromPublisher(ctx context.Context, publisherID uint, monetizationID uint) error {
|
||||
if publisherID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid publisher ID or monetization ID")
|
||||
}
|
||||
return c.repo.RemoveMonetizationFromPublisher(ctx, publisherID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) AddMonetizationToSource(ctx context.Context, sourceID uint, monetizationID uint) error {
|
||||
if sourceID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid source ID or monetization ID")
|
||||
}
|
||||
return c.repo.AddMonetizationToSource(ctx, sourceID, monetizationID)
|
||||
}
|
||||
|
||||
func (c *MonetizationCommands) RemoveMonetizationFromSource(ctx context.Context, sourceID uint, monetizationID uint) error {
|
||||
if sourceID == 0 || monetizationID == 0 {
|
||||
return errors.New("invalid source ID or monetization ID")
|
||||
}
|
||||
return c.repo.RemoveMonetizationFromSource(ctx, sourceID, monetizationID)
|
||||
}
|
||||
215
internal/app/monetization/commands_test.go
Normal file
215
internal/app/monetization/commands_test.go
Normal file
@ -0,0 +1,215 @@
|
||||
package monetization_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/app/monetization"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type MonetizationCommandsTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
commands *monetization.MonetizationCommands
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
s.commands = monetization.NewMonetizationCommands(s.MonetizationRepo)
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestAddMonetizationToWork() {
|
||||
s.Run("should add a monetization to a work", func() {
|
||||
// Arrange
|
||||
work := s.CreateTestWork("Test Work", "en", "Test content")
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
|
||||
// Act
|
||||
err := s.commands.AddMonetizationToWork(context.Background(), work.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Verify that the association was created in the database
|
||||
var foundWork domain.Work
|
||||
err = s.DB.Preload("Monetizations").First(&foundWork, work.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundWork.Monetizations, 1)
|
||||
s.Equal(monetization.ID, foundWork.Monetizations[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestAddMonetizationToAuthor() {
|
||||
s.Run("should add a monetization to an author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "Test Author"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
|
||||
// Act
|
||||
err := s.commands.AddMonetizationToAuthor(context.Background(), author.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.Preload("Monetizations").First(&foundAuthor, author.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundAuthor.Monetizations, 1)
|
||||
s.Equal(monetization.ID, foundAuthor.Monetizations[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestRemoveMonetizationFromAuthor() {
|
||||
s.Run("should remove a monetization from an author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "Test Author"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
s.Require().NoError(s.commands.AddMonetizationToAuthor(context.Background(), author.ID, monetization.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveMonetizationFromAuthor(context.Background(), author.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.Preload("Monetizations").First(&foundAuthor, author.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundAuthor.Monetizations, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestAddMonetizationToBook() {
|
||||
s.Run("should add a monetization to a book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Test Book"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
|
||||
// Act
|
||||
err := s.commands.AddMonetizationToBook(context.Background(), book.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundBook domain.Book
|
||||
err = s.DB.Preload("Monetizations").First(&foundBook, book.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundBook.Monetizations, 1)
|
||||
s.Equal(monetization.ID, foundBook.Monetizations[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestRemoveMonetizationFromBook() {
|
||||
s.Run("should remove a monetization from a book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Test Book"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
s.Require().NoError(s.commands.AddMonetizationToBook(context.Background(), book.ID, monetization.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveMonetizationFromBook(context.Background(), book.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundBook domain.Book
|
||||
err = s.DB.Preload("Monetizations").First(&foundBook, book.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundBook.Monetizations, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestAddMonetizationToPublisher() {
|
||||
s.Run("should add a monetization to a publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "Test Publisher"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
|
||||
// Act
|
||||
err := s.commands.AddMonetizationToPublisher(context.Background(), publisher.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.Preload("Monetizations").First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundPublisher.Monetizations, 1)
|
||||
s.Equal(monetization.ID, foundPublisher.Monetizations[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestRemoveMonetizationFromPublisher() {
|
||||
s.Run("should remove a monetization from a publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "Test Publisher"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
s.Require().NoError(s.commands.AddMonetizationToPublisher(context.Background(), publisher.ID, monetization.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveMonetizationFromPublisher(context.Background(), publisher.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.Preload("Monetizations").First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundPublisher.Monetizations, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestAddMonetizationToSource() {
|
||||
s.Run("should add a monetization to a source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "Test Source"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
|
||||
// Act
|
||||
err := s.commands.AddMonetizationToSource(context.Background(), source.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundSource domain.Source
|
||||
err = s.DB.Preload("Monetizations").First(&foundSource, source.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundSource.Monetizations, 1)
|
||||
s.Equal(monetization.ID, foundSource.Monetizations[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MonetizationCommandsTestSuite) TestRemoveMonetizationFromSource() {
|
||||
s.Run("should remove a monetization from a source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "Test Source"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
s.Require().NoError(s.commands.AddMonetizationToSource(context.Background(), source.ID, monetization.ID))
|
||||
|
||||
// Act
|
||||
err := s.commands.RemoveMonetizationFromSource(context.Background(), source.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundSource domain.Source
|
||||
err = s.DB.Preload("Monetizations").First(&foundSource, source.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundSource.Monetizations, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMonetizationCommands(t *testing.T) {
|
||||
suite.Run(t, new(MonetizationCommandsTestSuite))
|
||||
}
|
||||
75
internal/app/monetization/queries.go
Normal file
75
internal/app/monetization/queries.go
Normal file
@ -0,0 +1,75 @@
|
||||
package monetization
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// MonetizationQueries contains the query handlers for monetization.
|
||||
type MonetizationQueries struct {
|
||||
repo domain.MonetizationRepository
|
||||
workRepo domain.WorkRepository
|
||||
authorRepo domain.AuthorRepository
|
||||
bookRepo domain.BookRepository
|
||||
publisherRepo domain.PublisherRepository
|
||||
sourceRepo domain.SourceRepository
|
||||
}
|
||||
|
||||
// NewMonetizationQueries creates a new MonetizationQueries handler.
|
||||
func NewMonetizationQueries(repo domain.MonetizationRepository, workRepo domain.WorkRepository, authorRepo domain.AuthorRepository, bookRepo domain.BookRepository, publisherRepo domain.PublisherRepository, sourceRepo domain.SourceRepository) *MonetizationQueries {
|
||||
return &MonetizationQueries{repo: repo, workRepo: workRepo, authorRepo: authorRepo, bookRepo: bookRepo, publisherRepo: publisherRepo, sourceRepo: sourceRepo}
|
||||
}
|
||||
|
||||
// GetMonetizationByID retrieves a monetization by ID.
|
||||
func (q *MonetizationQueries) GetMonetizationByID(ctx context.Context, id uint) (*domain.Monetization, error) {
|
||||
if id == 0 {
|
||||
return nil, errors.New("invalid monetization ID")
|
||||
}
|
||||
return q.repo.GetByID(ctx, id)
|
||||
}
|
||||
|
||||
// ListMonetizations retrieves all monetizations.
|
||||
func (q *MonetizationQueries) ListMonetizations(ctx context.Context) ([]domain.Monetization, error) {
|
||||
return q.repo.ListAll(ctx)
|
||||
}
|
||||
|
||||
func (q *MonetizationQueries) GetMonetizationsForWork(ctx context.Context, workID uint) ([]*domain.Monetization, error) {
|
||||
work, err := q.workRepo.GetByIDWithOptions(ctx, workID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return work.Monetizations, nil
|
||||
}
|
||||
|
||||
func (q *MonetizationQueries) GetMonetizationsForAuthor(ctx context.Context, authorID uint) ([]*domain.Monetization, error) {
|
||||
author, err := q.authorRepo.GetByIDWithOptions(ctx, authorID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return author.Monetizations, nil
|
||||
}
|
||||
|
||||
func (q *MonetizationQueries) GetMonetizationsForBook(ctx context.Context, bookID uint) ([]*domain.Monetization, error) {
|
||||
book, err := q.bookRepo.GetByIDWithOptions(ctx, bookID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return book.Monetizations, nil
|
||||
}
|
||||
|
||||
func (q *MonetizationQueries) GetMonetizationsForPublisher(ctx context.Context, publisherID uint) ([]*domain.Monetization, error) {
|
||||
publisher, err := q.publisherRepo.GetByIDWithOptions(ctx, publisherID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return publisher.Monetizations, nil
|
||||
}
|
||||
|
||||
func (q *MonetizationQueries) GetMonetizationsForSource(ctx context.Context, sourceID uint) ([]*domain.Monetization, error) {
|
||||
source, err := q.sourceRepo.GetByIDWithOptions(ctx, sourceID, &domain.QueryOptions{Preloads: []string{"Monetizations"}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return source.Monetizations, nil
|
||||
}
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/author"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type authorRepository struct {
|
||||
}
|
||||
|
||||
// NewAuthorRepository creates a new AuthorRepository.
|
||||
func NewAuthorRepository(db *gorm.DB) author.AuthorRepository {
|
||||
func NewAuthorRepository(db *gorm.DB) domain.AuthorRepository {
|
||||
return &authorRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Author](db),
|
||||
db: db,
|
||||
|
||||
120
internal/data/sql/author_repository_test.go
Normal file
120
internal/data/sql/author_repository_test.go
Normal file
@ -0,0 +1,120 @@
|
||||
package sql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type AuthorRepositoryTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
}
|
||||
|
||||
func (s *AuthorRepositoryTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
}
|
||||
|
||||
func (s *AuthorRepositoryTestSuite) TestCreateAuthor() {
|
||||
s.Run("should create a new author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{
|
||||
Name: "New Test Author",
|
||||
TranslatableModel: domain.TranslatableModel{
|
||||
Language: "en",
|
||||
},
|
||||
}
|
||||
|
||||
// Act
|
||||
err := s.AuthorRepo.Create(context.Background(), author)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.NotZero(author.ID)
|
||||
|
||||
// Verify that the author was actually created in the database
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.First(&foundAuthor, author.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("New Test Author", foundAuthor.Name)
|
||||
s.Equal("en", foundAuthor.Language)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AuthorRepositoryTestSuite) TestGetAuthorByID() {
|
||||
s.Run("should return an author by ID", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "Test Author"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
|
||||
// Act
|
||||
foundAuthor, err := s.AuthorRepo.GetByID(context.Background(), author.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(foundAuthor)
|
||||
s.Equal(author.ID, foundAuthor.ID)
|
||||
s.Equal("Test Author", foundAuthor.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AuthorRepositoryTestSuite) TestUpdateAuthor() {
|
||||
s.Run("should update an existing author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "Original Name"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
author.Name = "Updated Name"
|
||||
|
||||
// Act
|
||||
err := s.AuthorRepo.Update(context.Background(), author)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.First(&foundAuthor, author.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("Updated Name", foundAuthor.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AuthorRepositoryTestSuite) TestDeleteAuthor() {
|
||||
s.Run("should delete an existing author", func() {
|
||||
// Arrange
|
||||
author := &domain.Author{Name: "To Be Deleted"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author))
|
||||
|
||||
// Act
|
||||
err := s.AuthorRepo.Delete(context.Background(), author.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundAuthor domain.Author
|
||||
err = s.DB.First(&foundAuthor, author.ID).Error
|
||||
s.Require().Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AuthorRepositoryTestSuite) TestListByWorkID() {
|
||||
s.Run("should return all authors for a given work", func() {
|
||||
// Arrange
|
||||
work := s.CreateTestWork("Test Work", "en", "Test content")
|
||||
author1 := &domain.Author{Name: "Author 1"}
|
||||
author2 := &domain.Author{Name: "Author 2"}
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author1))
|
||||
s.Require().NoError(s.AuthorRepo.Create(context.Background(), author2))
|
||||
s.Require().NoError(s.DB.Model(&work).Association("Authors").Append([]*domain.Author{author1, author2}))
|
||||
|
||||
// Act
|
||||
authors, err := s.AuthorRepo.ListByWorkID(context.Background(), work.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.Len(authors, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthorRepository(t *testing.T) {
|
||||
suite.Run(t, new(AuthorRepositoryTestSuite))
|
||||
}
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/book"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type bookRepository struct {
|
||||
}
|
||||
|
||||
// NewBookRepository creates a new BookRepository.
|
||||
func NewBookRepository(db *gorm.DB) book.BookRepository {
|
||||
func NewBookRepository(db *gorm.DB) domain.BookRepository {
|
||||
return &bookRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Book](db),
|
||||
db: db,
|
||||
|
||||
117
internal/data/sql/book_repository_test.go
Normal file
117
internal/data/sql/book_repository_test.go
Normal file
@ -0,0 +1,117 @@
|
||||
package sql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type BookRepositoryTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
}
|
||||
|
||||
func (s *BookRepositoryTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
}
|
||||
|
||||
func (s *BookRepositoryTestSuite) TestCreateBook() {
|
||||
s.Run("should create a new book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{
|
||||
Title: "New Test Book",
|
||||
TranslatableModel: domain.TranslatableModel{
|
||||
Language: "en",
|
||||
},
|
||||
}
|
||||
|
||||
// Act
|
||||
err := s.BookRepo.Create(context.Background(), book)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.NotZero(book.ID)
|
||||
|
||||
// Verify that the book was actually created in the database
|
||||
var foundBook domain.Book
|
||||
err = s.DB.First(&foundBook, book.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("New Test Book", foundBook.Title)
|
||||
s.Equal("en", foundBook.Language)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BookRepositoryTestSuite) TestGetBookByID() {
|
||||
s.Run("should return a book by ID", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Test Book"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
|
||||
// Act
|
||||
foundBook, err := s.BookRepo.GetByID(context.Background(), book.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(foundBook)
|
||||
s.Equal(book.ID, foundBook.ID)
|
||||
s.Equal("Test Book", foundBook.Title)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BookRepositoryTestSuite) TestUpdateBook() {
|
||||
s.Run("should update an existing book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Original Title"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
book.Title = "Updated Title"
|
||||
|
||||
// Act
|
||||
err := s.BookRepo.Update(context.Background(), book)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundBook domain.Book
|
||||
err = s.DB.First(&foundBook, book.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("Updated Title", foundBook.Title)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BookRepositoryTestSuite) TestDeleteBook() {
|
||||
s.Run("should delete an existing book", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "To Be Deleted"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
|
||||
// Act
|
||||
err := s.BookRepo.Delete(context.Background(), book.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundBook domain.Book
|
||||
err = s.DB.First(&foundBook, book.ID).Error
|
||||
s.Require().Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BookRepositoryTestSuite) TestFindByISBN() {
|
||||
s.Run("should return a book by ISBN", func() {
|
||||
// Arrange
|
||||
book := &domain.Book{Title: "Test Book", ISBN: "1234567890"}
|
||||
s.Require().NoError(s.BookRepo.Create(context.Background(), book))
|
||||
|
||||
// Act
|
||||
foundBook, err := s.BookRepo.FindByISBN(context.Background(), "1234567890")
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(foundBook)
|
||||
s.Equal(book.ID, foundBook.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBookRepository(t *testing.T) {
|
||||
suite.Run(t, new(BookRepositoryTestSuite))
|
||||
}
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/bookmark"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type bookmarkRepository struct {
|
||||
}
|
||||
|
||||
// NewBookmarkRepository creates a new BookmarkRepository.
|
||||
func NewBookmarkRepository(db *gorm.DB) bookmark.BookmarkRepository {
|
||||
func NewBookmarkRepository(db *gorm.DB) domain.BookmarkRepository {
|
||||
return &bookmarkRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Bookmark](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/category"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type categoryRepository struct {
|
||||
}
|
||||
|
||||
// NewCategoryRepository creates a new CategoryRepository.
|
||||
func NewCategoryRepository(db *gorm.DB) category.CategoryRepository {
|
||||
func NewCategoryRepository(db *gorm.DB) domain.CategoryRepository {
|
||||
return &categoryRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Category](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/city"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type cityRepository struct {
|
||||
}
|
||||
|
||||
// NewCityRepository creates a new CityRepository.
|
||||
func NewCityRepository(db *gorm.DB) city.CityRepository {
|
||||
func NewCityRepository(db *gorm.DB) domain.CityRepository {
|
||||
return &cityRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.City](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/collection"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type collectionRepository struct {
|
||||
}
|
||||
|
||||
// NewCollectionRepository creates a new CollectionRepository.
|
||||
func NewCollectionRepository(db *gorm.DB) collection.CollectionRepository {
|
||||
func NewCollectionRepository(db *gorm.DB) domain.CollectionRepository {
|
||||
return &collectionRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Collection](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/comment"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type commentRepository struct {
|
||||
}
|
||||
|
||||
// NewCommentRepository creates a new CommentRepository.
|
||||
func NewCommentRepository(db *gorm.DB) comment.CommentRepository {
|
||||
func NewCommentRepository(db *gorm.DB) domain.CommentRepository {
|
||||
return &commentRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Comment](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/contribution"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type contributionRepository struct {
|
||||
}
|
||||
|
||||
// NewContributionRepository creates a new ContributionRepository.
|
||||
func NewContributionRepository(db *gorm.DB) contribution.ContributionRepository {
|
||||
func NewContributionRepository(db *gorm.DB) domain.ContributionRepository {
|
||||
return &contributionRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Contribution](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/copyright_claim"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type copyrightClaimRepository struct {
|
||||
}
|
||||
|
||||
// NewCopyrightClaimRepository creates a new CopyrightClaimRepository.
|
||||
func NewCopyrightClaimRepository(db *gorm.DB) copyright_claim.Copyright_claimRepository {
|
||||
func NewCopyrightClaimRepository(db *gorm.DB) domain.CopyrightClaimRepository {
|
||||
return ©rightClaimRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.CopyrightClaim](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/copyright"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,45 +14,14 @@ type copyrightRepository struct {
|
||||
}
|
||||
|
||||
// NewCopyrightRepository creates a new CopyrightRepository.
|
||||
func NewCopyrightRepository(db *gorm.DB) copyright.CopyrightRepository {
|
||||
func NewCopyrightRepository(db *gorm.DB) domain.CopyrightRepository {
|
||||
return ©rightRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Copyright](db),
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// AttachToEntity attaches a copyright to any entity type
|
||||
func (r *copyrightRepository) AttachToEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) error {
|
||||
copyrightable := domain.Copyrightable{
|
||||
CopyrightID: copyrightID,
|
||||
CopyrightableID: entityID,
|
||||
CopyrightableType: entityType,
|
||||
}
|
||||
return r.db.WithContext(ctx).Create(©rightable).Error
|
||||
}
|
||||
|
||||
// DetachFromEntity removes a copyright from an entity
|
||||
func (r *copyrightRepository) DetachFromEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) error {
|
||||
return r.db.WithContext(ctx).Where("copyright_id = ? AND copyrightable_id = ? AND copyrightable_type = ?",
|
||||
copyrightID, entityID, entityType).Delete(&domain.Copyrightable{}).Error
|
||||
}
|
||||
|
||||
// GetByEntity gets all copyrights for a specific entity
|
||||
func (r *copyrightRepository) GetByEntity(ctx context.Context, entityID uint, entityType string) ([]domain.Copyright, error) {
|
||||
var copyrights []domain.Copyright
|
||||
err := r.db.WithContext(ctx).Joins("JOIN copyrightables ON copyrightables.copyright_id = copyrights.id").
|
||||
Where("copyrightables.copyrightable_id = ? AND copyrightables.copyrightable_type = ?", entityID, entityType).
|
||||
Preload("Translations").
|
||||
Find(©rights).Error
|
||||
return copyrights, err
|
||||
}
|
||||
|
||||
// GetEntitiesByCopyright gets all entities that have a specific copyright
|
||||
func (r *copyrightRepository) GetEntitiesByCopyright(ctx context.Context, copyrightID uint) ([]domain.Copyrightable, error) {
|
||||
var copyrightables []domain.Copyrightable
|
||||
err := r.db.WithContext(ctx).Where("copyright_id = ?", copyrightID).Find(©rightables).Error
|
||||
return copyrightables, err
|
||||
}
|
||||
// AddTranslation adds a translation to a copyright
|
||||
func (r *copyrightRepository) AddTranslation(ctx context.Context, translation *domain.CopyrightTranslation) error {
|
||||
return r.db.WithContext(ctx).Create(translation).Error
|
||||
@ -78,3 +46,63 @@ func (r *copyrightRepository) GetTranslationByLanguage(ctx context.Context, copy
|
||||
}
|
||||
return &translation, nil
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) AddCopyrightToWork(ctx context.Context, workID uint, copyrightID uint) error {
|
||||
work := &domain.Work{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: workID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(work).Association("Copyrights").Append(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) RemoveCopyrightFromWork(ctx context.Context, workID uint, copyrightID uint) error {
|
||||
work := &domain.Work{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: workID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(work).Association("Copyrights").Delete(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) AddCopyrightToAuthor(ctx context.Context, authorID uint, copyrightID uint) error {
|
||||
author := &domain.Author{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: authorID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(author).Association("Copyrights").Append(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) RemoveCopyrightFromAuthor(ctx context.Context, authorID uint, copyrightID uint) error {
|
||||
author := &domain.Author{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: authorID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(author).Association("Copyrights").Delete(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) AddCopyrightToBook(ctx context.Context, bookID uint, copyrightID uint) error {
|
||||
book := &domain.Book{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: bookID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(book).Association("Copyrights").Append(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) RemoveCopyrightFromBook(ctx context.Context, bookID uint, copyrightID uint) error {
|
||||
book := &domain.Book{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: bookID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(book).Association("Copyrights").Delete(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) AddCopyrightToPublisher(ctx context.Context, publisherID uint, copyrightID uint) error {
|
||||
publisher := &domain.Publisher{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: publisherID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(publisher).Association("Copyrights").Append(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) RemoveCopyrightFromPublisher(ctx context.Context, publisherID uint, copyrightID uint) error {
|
||||
publisher := &domain.Publisher{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: publisherID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(publisher).Association("Copyrights").Delete(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) AddCopyrightToSource(ctx context.Context, sourceID uint, copyrightID uint) error {
|
||||
source := &domain.Source{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: sourceID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(source).Association("Copyrights").Append(copyright)
|
||||
}
|
||||
|
||||
func (r *copyrightRepository) RemoveCopyrightFromSource(ctx context.Context, sourceID uint, copyrightID uint) error {
|
||||
source := &domain.Source{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: sourceID}}}
|
||||
copyright := &domain.Copyright{BaseModel: domain.BaseModel{ID: copyrightID}}
|
||||
return r.db.WithContext(ctx).Model(source).Association("Copyrights").Delete(copyright)
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/country"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type countryRepository struct {
|
||||
}
|
||||
|
||||
// NewCountryRepository creates a new CountryRepository.
|
||||
func NewCountryRepository(db *gorm.DB) country.CountryRepository {
|
||||
func NewCountryRepository(db *gorm.DB) domain.CountryRepository {
|
||||
return &countryRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Country](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/edge"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type edgeRepository struct {
|
||||
}
|
||||
|
||||
// NewEdgeRepository creates a new EdgeRepository.
|
||||
func NewEdgeRepository(db *gorm.DB) edge.EdgeRepository {
|
||||
func NewEdgeRepository(db *gorm.DB) domain.EdgeRepository {
|
||||
return &edgeRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Edge](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/edition"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type editionRepository struct {
|
||||
}
|
||||
|
||||
// NewEditionRepository creates a new EditionRepository.
|
||||
func NewEditionRepository(db *gorm.DB) edition.EditionRepository {
|
||||
func NewEditionRepository(db *gorm.DB) domain.EditionRepository {
|
||||
return &editionRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Edition](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/email_verification"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@ -16,7 +15,7 @@ type emailVerificationRepository struct {
|
||||
}
|
||||
|
||||
// NewEmailVerificationRepository creates a new EmailVerificationRepository.
|
||||
func NewEmailVerificationRepository(db *gorm.DB) email_verification.Email_verificationRepository {
|
||||
func NewEmailVerificationRepository(db *gorm.DB) domain.EmailVerificationRepository {
|
||||
return &emailVerificationRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.EmailVerification](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/like"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type likeRepository struct {
|
||||
}
|
||||
|
||||
// NewLikeRepository creates a new LikeRepository.
|
||||
func NewLikeRepository(db *gorm.DB) like.LikeRepository {
|
||||
func NewLikeRepository(db *gorm.DB) domain.LikeRepository {
|
||||
return &likeRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Like](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/monetization"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,36 +13,69 @@ type monetizationRepository struct {
|
||||
}
|
||||
|
||||
// NewMonetizationRepository creates a new MonetizationRepository.
|
||||
func NewMonetizationRepository(db *gorm.DB) monetization.MonetizationRepository {
|
||||
func NewMonetizationRepository(db *gorm.DB) domain.MonetizationRepository {
|
||||
return &monetizationRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Monetization](db),
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// ListByWorkID finds monetizations by work ID
|
||||
func (r *monetizationRepository) ListByWorkID(ctx context.Context, workID uint) ([]domain.Monetization, error) {
|
||||
var monetizations []domain.Monetization
|
||||
if err := r.db.WithContext(ctx).Where("work_id = ?", workID).Find(&monetizations).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return monetizations, nil
|
||||
func (r *monetizationRepository) AddMonetizationToWork(ctx context.Context, workID uint, monetizationID uint) error {
|
||||
work := &domain.Work{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: workID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(work).Association("Monetizations").Append(monetization)
|
||||
}
|
||||
|
||||
// ListByTranslationID finds monetizations by translation ID
|
||||
func (r *monetizationRepository) ListByTranslationID(ctx context.Context, translationID uint) ([]domain.Monetization, error) {
|
||||
var monetizations []domain.Monetization
|
||||
if err := r.db.WithContext(ctx).Where("translation_id = ?", translationID).Find(&monetizations).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return monetizations, nil
|
||||
func (r *monetizationRepository) RemoveMonetizationFromWork(ctx context.Context, workID uint, monetizationID uint) error {
|
||||
work := &domain.Work{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: workID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(work).Association("Monetizations").Delete(monetization)
|
||||
}
|
||||
|
||||
// ListByBookID finds monetizations by book ID
|
||||
func (r *monetizationRepository) ListByBookID(ctx context.Context, bookID uint) ([]domain.Monetization, error) {
|
||||
var monetizations []domain.Monetization
|
||||
if err := r.db.WithContext(ctx).Where("book_id = ?", bookID).Find(&monetizations).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return monetizations, nil
|
||||
func (r *monetizationRepository) AddMonetizationToAuthor(ctx context.Context, authorID uint, monetizationID uint) error {
|
||||
author := &domain.Author{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: authorID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(author).Association("Monetizations").Append(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) RemoveMonetizationFromAuthor(ctx context.Context, authorID uint, monetizationID uint) error {
|
||||
author := &domain.Author{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: authorID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(author).Association("Monetizations").Delete(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) AddMonetizationToBook(ctx context.Context, bookID uint, monetizationID uint) error {
|
||||
book := &domain.Book{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: bookID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(book).Association("Monetizations").Append(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) RemoveMonetizationFromBook(ctx context.Context, bookID uint, monetizationID uint) error {
|
||||
book := &domain.Book{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: bookID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(book).Association("Monetizations").Delete(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) AddMonetizationToPublisher(ctx context.Context, publisherID uint, monetizationID uint) error {
|
||||
publisher := &domain.Publisher{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: publisherID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(publisher).Association("Monetizations").Append(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) RemoveMonetizationFromPublisher(ctx context.Context, publisherID uint, monetizationID uint) error {
|
||||
publisher := &domain.Publisher{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: publisherID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(publisher).Association("Monetizations").Delete(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) AddMonetizationToSource(ctx context.Context, sourceID uint, monetizationID uint) error {
|
||||
source := &domain.Source{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: sourceID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(source).Association("Monetizations").Append(monetization)
|
||||
}
|
||||
|
||||
func (r *monetizationRepository) RemoveMonetizationFromSource(ctx context.Context, sourceID uint, monetizationID uint) error {
|
||||
source := &domain.Source{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: sourceID}}}
|
||||
monetization := &domain.Monetization{BaseModel: domain.BaseModel{ID: monetizationID}}
|
||||
return r.db.WithContext(ctx).Model(source).Association("Monetizations").Delete(monetization)
|
||||
}
|
||||
|
||||
44
internal/data/sql/monetization_repository_test.go
Normal file
44
internal/data/sql/monetization_repository_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package sql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type MonetizationRepositoryTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
}
|
||||
|
||||
func (s *MonetizationRepositoryTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
}
|
||||
|
||||
func (s *MonetizationRepositoryTestSuite) TestAddMonetizationToWork() {
|
||||
s.Run("should add a monetization to a work", func() {
|
||||
// Arrange
|
||||
work := s.CreateTestWork("Test Work", "en", "Test content")
|
||||
monetization := &domain.Monetization{Amount: 10.0}
|
||||
s.Require().NoError(s.DB.Create(monetization).Error)
|
||||
|
||||
// Act
|
||||
err := s.MonetizationRepo.AddMonetizationToWork(context.Background(), work.ID, monetization.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Verify that the association was created in the database
|
||||
var foundWork domain.Work
|
||||
err = s.DB.Preload("Monetizations").First(&foundWork, work.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(foundWork.Monetizations, 1)
|
||||
s.Equal(monetization.ID, foundWork.Monetizations[0].ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMonetizationRepository(t *testing.T) {
|
||||
suite.Run(t, new(MonetizationRepositoryTestSuite))
|
||||
}
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/password_reset"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@ -16,7 +15,7 @@ type passwordResetRepository struct {
|
||||
}
|
||||
|
||||
// NewPasswordResetRepository creates a new PasswordResetRepository.
|
||||
func NewPasswordResetRepository(db *gorm.DB) password_reset.Password_resetRepository {
|
||||
func NewPasswordResetRepository(db *gorm.DB) domain.PasswordResetRepository {
|
||||
return &passwordResetRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.PasswordReset](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"math"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/place"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type placeRepository struct {
|
||||
}
|
||||
|
||||
// NewPlaceRepository creates a new PlaceRepository.
|
||||
func NewPlaceRepository(db *gorm.DB) place.PlaceRepository {
|
||||
func NewPlaceRepository(db *gorm.DB) domain.PlaceRepository {
|
||||
return &placeRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Place](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/publisher"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type publisherRepository struct {
|
||||
}
|
||||
|
||||
// NewPublisherRepository creates a new PublisherRepository.
|
||||
func NewPublisherRepository(db *gorm.DB) publisher.PublisherRepository {
|
||||
func NewPublisherRepository(db *gorm.DB) domain.PublisherRepository {
|
||||
return &publisherRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Publisher](db),
|
||||
db: db,
|
||||
|
||||
101
internal/data/sql/publisher_repository_test.go
Normal file
101
internal/data/sql/publisher_repository_test.go
Normal file
@ -0,0 +1,101 @@
|
||||
package sql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type PublisherRepositoryTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
}
|
||||
|
||||
func (s *PublisherRepositoryTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
}
|
||||
|
||||
func (s *PublisherRepositoryTestSuite) TestCreatePublisher() {
|
||||
s.Run("should create a new publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{
|
||||
Name: "New Test Publisher",
|
||||
TranslatableModel: domain.TranslatableModel{
|
||||
Language: "en",
|
||||
},
|
||||
}
|
||||
|
||||
// Act
|
||||
err := s.PublisherRepo.Create(context.Background(), publisher)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.NotZero(publisher.ID)
|
||||
|
||||
// Verify that the publisher was actually created in the database
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("New Test Publisher", foundPublisher.Name)
|
||||
s.Equal("en", foundPublisher.Language)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *PublisherRepositoryTestSuite) TestGetPublisherByID() {
|
||||
s.Run("should return a publisher by ID", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "Test Publisher"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
|
||||
// Act
|
||||
foundPublisher, err := s.PublisherRepo.GetByID(context.Background(), publisher.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(foundPublisher)
|
||||
s.Equal(publisher.ID, foundPublisher.ID)
|
||||
s.Equal("Test Publisher", foundPublisher.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *PublisherRepositoryTestSuite) TestUpdatePublisher() {
|
||||
s.Run("should update an existing publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "Original Name"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
publisher.Name = "Updated Name"
|
||||
|
||||
// Act
|
||||
err := s.PublisherRepo.Update(context.Background(), publisher)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("Updated Name", foundPublisher.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *PublisherRepositoryTestSuite) TestDeletePublisher() {
|
||||
s.Run("should delete an existing publisher", func() {
|
||||
// Arrange
|
||||
publisher := &domain.Publisher{Name: "To Be Deleted"}
|
||||
s.Require().NoError(s.PublisherRepo.Create(context.Background(), publisher))
|
||||
|
||||
// Act
|
||||
err := s.PublisherRepo.Delete(context.Background(), publisher.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundPublisher domain.Publisher
|
||||
err = s.DB.First(&foundPublisher, publisher.ID).Error
|
||||
s.Require().Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPublisherRepository(t *testing.T) {
|
||||
suite.Run(t, new(PublisherRepositoryTestSuite))
|
||||
}
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/source"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type sourceRepository struct {
|
||||
}
|
||||
|
||||
// NewSourceRepository creates a new SourceRepository.
|
||||
func NewSourceRepository(db *gorm.DB) source.SourceRepository {
|
||||
func NewSourceRepository(db *gorm.DB) domain.SourceRepository {
|
||||
return &sourceRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Source](db),
|
||||
db: db,
|
||||
|
||||
101
internal/data/sql/source_repository_test.go
Normal file
101
internal/data/sql/source_repository_test.go
Normal file
@ -0,0 +1,101 @@
|
||||
package sql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/testutil"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type SourceRepositoryTestSuite struct {
|
||||
testutil.IntegrationTestSuite
|
||||
}
|
||||
|
||||
func (s *SourceRepositoryTestSuite) SetupSuite() {
|
||||
s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
|
||||
}
|
||||
|
||||
func (s *SourceRepositoryTestSuite) TestCreateSource() {
|
||||
s.Run("should create a new source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{
|
||||
Name: "New Test Source",
|
||||
TranslatableModel: domain.TranslatableModel{
|
||||
Language: "en",
|
||||
},
|
||||
}
|
||||
|
||||
// Act
|
||||
err := s.SourceRepo.Create(context.Background(), source)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.NotZero(source.ID)
|
||||
|
||||
// Verify that the source was actually created in the database
|
||||
var foundSource domain.Source
|
||||
err = s.DB.First(&foundSource, source.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("New Test Source", foundSource.Name)
|
||||
s.Equal("en", foundSource.Language)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SourceRepositoryTestSuite) TestGetSourceByID() {
|
||||
s.Run("should return a source by ID", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "Test Source"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
|
||||
// Act
|
||||
foundSource, err := s.SourceRepo.GetByID(context.Background(), source.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(foundSource)
|
||||
s.Equal(source.ID, foundSource.ID)
|
||||
s.Equal("Test Source", foundSource.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SourceRepositoryTestSuite) TestUpdateSource() {
|
||||
s.Run("should update an existing source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "Original Name"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
source.Name = "Updated Name"
|
||||
|
||||
// Act
|
||||
err := s.SourceRepo.Update(context.Background(), source)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundSource domain.Source
|
||||
err = s.DB.First(&foundSource, source.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("Updated Name", foundSource.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SourceRepositoryTestSuite) TestDeleteSource() {
|
||||
s.Run("should delete an existing source", func() {
|
||||
// Arrange
|
||||
source := &domain.Source{Name: "To Be Deleted"}
|
||||
s.Require().NoError(s.SourceRepo.Create(context.Background(), source))
|
||||
|
||||
// Act
|
||||
err := s.SourceRepo.Delete(context.Background(), source.ID)
|
||||
|
||||
// Assert
|
||||
s.Require().NoError(err)
|
||||
var foundSource domain.Source
|
||||
err = s.DB.First(&foundSource, source.ID).Error
|
||||
s.Require().Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSourceRepository(t *testing.T) {
|
||||
suite.Run(t, new(SourceRepositoryTestSuite))
|
||||
}
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/tag"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type tagRepository struct {
|
||||
}
|
||||
|
||||
// NewTagRepository creates a new TagRepository.
|
||||
func NewTagRepository(db *gorm.DB) tag.TagRepository {
|
||||
func NewTagRepository(db *gorm.DB) domain.TagRepository {
|
||||
return &tagRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Tag](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/translation"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type translationRepository struct {
|
||||
}
|
||||
|
||||
// NewTranslationRepository creates a new TranslationRepository.
|
||||
func NewTranslationRepository(db *gorm.DB) translation.TranslationRepository {
|
||||
func NewTranslationRepository(db *gorm.DB) domain.TranslationRepository {
|
||||
return &translationRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Translation](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/user_profile"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type userProfileRepository struct {
|
||||
}
|
||||
|
||||
// NewUserProfileRepository creates a new UserProfileRepository.
|
||||
func NewUserProfileRepository(db *gorm.DB) user_profile.User_profileRepository {
|
||||
func NewUserProfileRepository(db *gorm.DB) domain.UserProfileRepository {
|
||||
return &userProfileRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.UserProfile](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/user"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -15,7 +14,7 @@ type userRepository struct {
|
||||
}
|
||||
|
||||
// NewUserRepository creates a new UserRepository.
|
||||
func NewUserRepository(db *gorm.DB) user.UserRepository {
|
||||
func NewUserRepository(db *gorm.DB) domain.UserRepository {
|
||||
return &userRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.User](db),
|
||||
db: db,
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/user_session"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@ -16,7 +15,7 @@ type userSessionRepository struct {
|
||||
}
|
||||
|
||||
// NewUserSessionRepository creates a new UserSessionRepository.
|
||||
func NewUserSessionRepository(db *gorm.DB) user_session.User_sessionRepository {
|
||||
func NewUserSessionRepository(db *gorm.DB) domain.UserSessionRepository {
|
||||
return &userSessionRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.UserSession](db),
|
||||
db: db,
|
||||
|
||||
@ -3,7 +3,6 @@ package sql
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
"tercul/internal/domain/work"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -14,7 +13,7 @@ type workRepository struct {
|
||||
}
|
||||
|
||||
// NewWorkRepository creates a new WorkRepository.
|
||||
func NewWorkRepository(db *gorm.DB) work.WorkRepository {
|
||||
func NewWorkRepository(db *gorm.DB) domain.WorkRepository {
|
||||
return &workRepository{
|
||||
BaseRepository: NewBaseRepositoryImpl[domain.Work](db),
|
||||
db: db,
|
||||
@ -100,6 +99,28 @@ func (r *workRepository) FindByLanguage(ctx context.Context, language string, pa
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Delete removes a work and its associations
|
||||
func (r *workRepository) Delete(ctx context.Context, id uint) error {
|
||||
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
// Manually delete associations
|
||||
if err := tx.Select("Copyrights", "Monetizations", "Authors", "Tags", "Categories").Delete(&domain.Work{TranslatableModel: domain.TranslatableModel{BaseModel: domain.BaseModel{ID: id}}}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// Also delete the work itself
|
||||
if err := tx.Delete(&domain.Work{}, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// GetWithTranslations gets a work with its translations
|
||||
func (r *workRepository) GetWithTranslations(ctx context.Context, id uint) (*domain.Work, error) {
|
||||
return r.FindWithPreload(ctx, []string{"Translations"}, id)
|
||||
|
||||
@ -18,13 +18,20 @@ func (s *WorkRepositoryTestSuite) SetupSuite() {
|
||||
}
|
||||
|
||||
func (s *WorkRepositoryTestSuite) TestCreateWork() {
|
||||
s.Run("should create a new work", func() {
|
||||
s.Run("should create a new work with a copyright", func() {
|
||||
// Arrange
|
||||
copyright := &domain.Copyright{
|
||||
Name: "Test Copyright",
|
||||
Identificator: "TC-123",
|
||||
}
|
||||
s.Require().NoError(s.DB.Create(copyright).Error)
|
||||
|
||||
work := &domain.Work{
|
||||
Title: "New Test Work",
|
||||
TranslatableModel: domain.TranslatableModel{
|
||||
Language: "en",
|
||||
},
|
||||
Copyrights: []*domain.Copyright{copyright},
|
||||
}
|
||||
|
||||
// Act
|
||||
@ -36,17 +43,26 @@ func (s *WorkRepositoryTestSuite) TestCreateWork() {
|
||||
|
||||
// Verify that the work was actually created in the database
|
||||
var foundWork domain.Work
|
||||
err = s.DB.First(&foundWork, work.ID).Error
|
||||
err = s.DB.Preload("Copyrights").First(&foundWork, work.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("New Test Work", foundWork.Title)
|
||||
s.Equal("en", foundWork.Language)
|
||||
s.Require().Len(foundWork.Copyrights, 1)
|
||||
s.Equal("Test Copyright", foundWork.Copyrights[0].Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *WorkRepositoryTestSuite) TestGetWorkByID() {
|
||||
s.Run("should return a work by ID", func() {
|
||||
s.Run("should return a work by ID with copyrights", func() {
|
||||
// Arrange
|
||||
copyright := &domain.Copyright{
|
||||
Name: "Test Copyright",
|
||||
Identificator: "TC-123",
|
||||
}
|
||||
s.Require().NoError(s.DB.Create(copyright).Error)
|
||||
|
||||
work := s.CreateTestWork("Test Work", "en", "Test content")
|
||||
s.Require().NoError(s.DB.Model(work).Association("Copyrights").Append(copyright))
|
||||
|
||||
// Act
|
||||
foundWork, err := s.WorkRepo.GetByID(context.Background(), work.ID)
|
||||
@ -69,10 +85,18 @@ func (s *WorkRepositoryTestSuite) TestGetWorkByID() {
|
||||
}
|
||||
|
||||
func (s *WorkRepositoryTestSuite) TestUpdateWork() {
|
||||
s.Run("should update an existing work", func() {
|
||||
s.Run("should update an existing work and its copyrights", func() {
|
||||
// Arrange
|
||||
copyright1 := &domain.Copyright{Name: "C1", Identificator: "C1"}
|
||||
copyright2 := &domain.Copyright{Name: "C2", Identificator: "C2"}
|
||||
s.Require().NoError(s.DB.Create(©right1).Error)
|
||||
s.Require().NoError(s.DB.Create(©right2).Error)
|
||||
|
||||
work := s.CreateTestWork("Original Title", "en", "Original content")
|
||||
s.Require().NoError(s.DB.Model(work).Association("Copyrights").Append(copyright1))
|
||||
|
||||
work.Title = "Updated Title"
|
||||
s.Require().NoError(s.DB.Model(work).Association("Copyrights").Replace(copyright2))
|
||||
|
||||
// Act
|
||||
err := s.WorkRepo.Update(context.Background(), work)
|
||||
@ -82,16 +106,21 @@ func (s *WorkRepositoryTestSuite) TestUpdateWork() {
|
||||
|
||||
// Verify that the work was actually updated in the database
|
||||
var foundWork domain.Work
|
||||
err = s.DB.First(&foundWork, work.ID).Error
|
||||
err = s.DB.Preload("Copyrights").First(&foundWork, work.ID).Error
|
||||
s.Require().NoError(err)
|
||||
s.Equal("Updated Title", foundWork.Title)
|
||||
s.Require().Len(foundWork.Copyrights, 1)
|
||||
s.Equal("C2", foundWork.Copyrights[0].Name)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *WorkRepositoryTestSuite) TestDeleteWork() {
|
||||
s.Run("should delete an existing work", func() {
|
||||
s.Run("should delete an existing work and its associations", func() {
|
||||
// Arrange
|
||||
work := s.CreateTestWork("To Be Deleted", "en", "Content")
|
||||
copyright := &domain.Copyright{Name: "C1", Identificator: "C1"}
|
||||
s.Require().NoError(s.DB.Create(copyright).Error)
|
||||
s.Require().NoError(s.DB.Model(work).Association("Copyrights").Append(copyright))
|
||||
|
||||
// Act
|
||||
err := s.WorkRepo.Delete(context.Background(), work.ID)
|
||||
@ -103,6 +132,11 @@ func (s *WorkRepositoryTestSuite) TestDeleteWork() {
|
||||
var foundWork domain.Work
|
||||
err = s.DB.First(&foundWork, work.ID).Error
|
||||
s.Require().Error(err)
|
||||
|
||||
// Verify that the association in the join table is also deleted
|
||||
var count int64
|
||||
s.DB.Table("work_copyrights").Where("work_id = ?", work.ID).Count(&count)
|
||||
s.Zero(count)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
package author
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// AuthorRepository defines CRUD methods specific to Author.
|
||||
type AuthorRepository interface {
|
||||
domain.BaseRepository[domain.Author]
|
||||
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Author, error)
|
||||
ListByBookID(ctx context.Context, bookID uint) ([]domain.Author, error)
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]domain.Author, error)
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package book
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// BookRepository defines CRUD methods specific to Book.
|
||||
type BookRepository interface {
|
||||
domain.BaseRepository[domain.Book]
|
||||
|
||||
ListByAuthorID(ctx context.Context, authorID uint) ([]domain.Book, error)
|
||||
ListByPublisherID(ctx context.Context, publisherID uint) ([]domain.Book, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Book, error)
|
||||
FindByISBN(ctx context.Context, isbn string) (*domain.Book, error)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package bookmark
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// BookmarkRepository defines CRUD methods specific to Bookmark.
|
||||
type BookmarkRepository interface {
|
||||
domain.BaseRepository[domain.Bookmark]
|
||||
|
||||
ListByUserID(ctx context.Context, userID uint) ([]domain.Bookmark, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Bookmark, error)
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package category
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// CategoryRepository defines CRUD methods specific to Category.
|
||||
type CategoryRepository interface {
|
||||
domain.BaseRepository[domain.Category]
|
||||
|
||||
FindByName(ctx context.Context, name string) (*domain.Category, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Category, error)
|
||||
ListByParentID(ctx context.Context, parentID *uint) ([]domain.Category, error)
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package city
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// CityRepository defines CRUD methods specific to City.
|
||||
type CityRepository interface {
|
||||
domain.BaseRepository[domain.City]
|
||||
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]domain.City, error)
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package collection
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// CollectionRepository defines CRUD methods specific to Collection.
|
||||
type CollectionRepository interface {
|
||||
domain.BaseRepository[domain.Collection]
|
||||
|
||||
ListByUserID(ctx context.Context, userID uint) ([]domain.Collection, error)
|
||||
ListPublic(ctx context.Context) ([]domain.Collection, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Collection, error)
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package comment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// CommentRepository defines CRUD methods specific to Comment.
|
||||
type CommentRepository interface {
|
||||
domain.BaseRepository[domain.Comment]
|
||||
|
||||
ListByUserID(ctx context.Context, userID uint) ([]domain.Comment, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Comment, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]domain.Comment, error)
|
||||
ListByParentID(ctx context.Context, parentID uint) ([]domain.Comment, error)
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package contribution
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// ContributionRepository defines CRUD methods specific to Contribution.
|
||||
type ContributionRepository interface {
|
||||
domain.BaseRepository[domain.Contribution]
|
||||
|
||||
ListByUserID(ctx context.Context, userID uint) ([]domain.Contribution, error)
|
||||
ListByReviewerID(ctx context.Context, reviewerID uint) ([]domain.Contribution, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Contribution, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]domain.Contribution, error)
|
||||
ListByStatus(ctx context.Context, status string) ([]domain.Contribution, error)
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package copyright
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// CopyrightRepository defines CRUD methods specific to Copyright.
|
||||
type CopyrightRepository interface {
|
||||
domain.BaseRepository[domain.Copyright]
|
||||
|
||||
AttachToEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) (error)
|
||||
DetachFromEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) (error)
|
||||
GetByEntity(ctx context.Context, entityID uint, entityType string) ([]domain.Copyright, error)
|
||||
GetEntitiesByCopyright(ctx context.Context, copyrightID uint) ([]domain.Copyrightable, error)
|
||||
AddTranslation(ctx context.Context, translation *domain.CopyrightTranslation) (error)
|
||||
GetTranslations(ctx context.Context, copyrightID uint) ([]domain.CopyrightTranslation, error)
|
||||
GetTranslationByLanguage(ctx context.Context, copyrightID uint, languageCode string) (*domain.CopyrightTranslation, error)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package copyright_claim
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// Copyright_claimRepository defines CRUD methods specific to Copyright_claim.
|
||||
type Copyright_claimRepository interface {
|
||||
domain.BaseRepository[domain.CopyrightClaim]
|
||||
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.CopyrightClaim, error)
|
||||
ListByUserID(ctx context.Context, userID uint) ([]domain.CopyrightClaim, error)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package country
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// CountryRepository defines CRUD methods specific to Country.
|
||||
type CountryRepository interface {
|
||||
domain.BaseRepository[domain.Country]
|
||||
|
||||
GetByCode(ctx context.Context, code string) (*domain.Country, error)
|
||||
ListByContinent(ctx context.Context, continent string) ([]domain.Country, error)
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// EdgeRepository defines CRUD methods specific to Edge.
|
||||
type EdgeRepository interface {
|
||||
domain.BaseRepository[domain.Edge]
|
||||
|
||||
ListBySource(ctx context.Context, sourceTable string, sourceID uint) ([]domain.Edge, error)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package edition
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// EditionRepository defines CRUD methods specific to Edition.
|
||||
type EditionRepository interface {
|
||||
domain.BaseRepository[domain.Edition]
|
||||
|
||||
ListByBookID(ctx context.Context, bookID uint) ([]domain.Edition, error)
|
||||
FindByISBN(ctx context.Context, isbn string) (*domain.Edition, error)
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package email_verification
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// Email_verificationRepository defines CRUD methods specific to Email_verification.
|
||||
type Email_verificationRepository interface {
|
||||
domain.BaseRepository[domain.EmailVerification]
|
||||
|
||||
GetByToken(ctx context.Context, token string) (*domain.EmailVerification, error)
|
||||
GetByUserID(ctx context.Context, userID uint) ([]domain.EmailVerification, error)
|
||||
DeleteExpired(ctx context.Context) (error)
|
||||
MarkAsUsed(ctx context.Context, id uint) (error)
|
||||
}
|
||||
@ -206,8 +206,8 @@ type Work struct {
|
||||
Authors []*Author `gorm:"many2many:work_authors"`
|
||||
Tags []*Tag `gorm:"many2many:work_tags"`
|
||||
Categories []*Category `gorm:"many2many:work_categories"`
|
||||
Copyrights []Copyright `gorm:"-"`
|
||||
Monetizations []Monetization `gorm:"-"`
|
||||
Copyrights []*Copyright `gorm:"many2many:work_copyrights;constraint:OnDelete:CASCADE"`
|
||||
Monetizations []*Monetization `gorm:"many2many:work_monetizations;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
type AuthorStatus string
|
||||
@ -233,8 +233,8 @@ type Author struct {
|
||||
AddressID *uint
|
||||
Address *Address `gorm:"foreignKey:AddressID"`
|
||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
||||
Copyrights []Copyright `gorm:"-"`
|
||||
Monetizations []Monetization `gorm:"-"`
|
||||
Copyrights []*Copyright `gorm:"many2many:author_copyrights;constraint:OnDelete:CASCADE"`
|
||||
Monetizations []*Monetization `gorm:"many2many:author_monetizations;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
type BookStatus string
|
||||
@ -265,8 +265,8 @@ type Book struct {
|
||||
PublisherID *uint
|
||||
Publisher *Publisher `gorm:"foreignKey:PublisherID"`
|
||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
||||
Copyrights []Copyright `gorm:"-"`
|
||||
Monetizations []Monetization `gorm:"-"`
|
||||
Copyrights []*Copyright `gorm:"many2many:book_copyrights;constraint:OnDelete:CASCADE"`
|
||||
Monetizations []*Monetization `gorm:"many2many:book_monetizations;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
type PublisherStatus string
|
||||
@ -284,8 +284,8 @@ type Publisher struct {
|
||||
CountryID *uint
|
||||
Country *Country `gorm:"foreignKey:CountryID"`
|
||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
||||
Copyrights []Copyright `gorm:"-"`
|
||||
Monetizations []Monetization `gorm:"-"`
|
||||
Copyrights []*Copyright `gorm:"many2many:publisher_copyrights;constraint:OnDelete:CASCADE"`
|
||||
Monetizations []*Monetization `gorm:"many2many:publisher_monetizations;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
type SourceStatus string
|
||||
@ -302,8 +302,8 @@ type Source struct {
|
||||
Status SourceStatus `gorm:"size:50;default:'active'"`
|
||||
Works []*Work `gorm:"many2many:work_sources"`
|
||||
Translations []Translation `gorm:"polymorphic:Translatable"`
|
||||
Copyrights []Copyright `gorm:"-"`
|
||||
Monetizations []Monetization `gorm:"-"`
|
||||
Copyrights []*Copyright `gorm:"many2many:source_copyrights;constraint:OnDelete:CASCADE"`
|
||||
Monetizations []*Monetization `gorm:"many2many:source_monetizations;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
type EditionStatus string
|
||||
@ -574,16 +574,47 @@ type Copyright struct {
|
||||
License string `gorm:"size:100"`
|
||||
StartDate *time.Time
|
||||
EndDate *time.Time
|
||||
Copyrightables []Copyrightable `gorm:"-"`
|
||||
Translations []CopyrightTranslation `gorm:"foreignKey:CopyrightID"`
|
||||
}
|
||||
type Copyrightable struct {
|
||||
BaseModel
|
||||
CopyrightID uint
|
||||
Copyright *Copyright `gorm:"foreignKey:CopyrightID"`
|
||||
CopyrightableID uint
|
||||
CopyrightableType string
|
||||
type WorkCopyright struct {
|
||||
WorkID uint `gorm:"primaryKey;index"`
|
||||
CopyrightID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (WorkCopyright) TableName() string { return "work_copyrights" }
|
||||
|
||||
type AuthorCopyright struct {
|
||||
AuthorID uint `gorm:"primaryKey;index"`
|
||||
CopyrightID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (AuthorCopyright) TableName() string { return "author_copyrights" }
|
||||
|
||||
type BookCopyright struct {
|
||||
BookID uint `gorm:"primaryKey;index"`
|
||||
CopyrightID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (BookCopyright) TableName() string { return "book_copyrights" }
|
||||
|
||||
type PublisherCopyright struct {
|
||||
PublisherID uint `gorm:"primaryKey;index"`
|
||||
CopyrightID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (PublisherCopyright) TableName() string { return "publisher_copyrights" }
|
||||
|
||||
type SourceCopyright struct {
|
||||
SourceID uint `gorm:"primaryKey;index"`
|
||||
CopyrightID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (SourceCopyright) TableName() string { return "source_copyrights" }
|
||||
type CopyrightTranslation struct {
|
||||
BaseModel
|
||||
CopyrightID uint
|
||||
@ -607,7 +638,6 @@ type CopyrightClaim struct {
|
||||
ResolvedAt *time.Time
|
||||
UserID *uint
|
||||
User *User `gorm:"foreignKey:UserID"`
|
||||
Claimables []Copyrightable `gorm:"-"`
|
||||
}
|
||||
type MonetizationType string
|
||||
const (
|
||||
@ -623,13 +653,45 @@ const (
|
||||
MonetizationStatusInactive MonetizationStatus = "inactive"
|
||||
MonetizationStatusPending MonetizationStatus = "pending"
|
||||
)
|
||||
type Monetizable struct {
|
||||
BaseModel
|
||||
MonetizationID uint
|
||||
Monetization *Monetization `gorm:"foreignKey:MonetizationID"`
|
||||
MonetizableID uint
|
||||
MonetizableType string
|
||||
type WorkMonetization struct {
|
||||
WorkID uint `gorm:"primaryKey;index"`
|
||||
MonetizationID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (WorkMonetization) TableName() string { return "work_monetizations" }
|
||||
|
||||
type AuthorMonetization struct {
|
||||
AuthorID uint `gorm:"primaryKey;index"`
|
||||
MonetizationID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (AuthorMonetization) TableName() string { return "author_monetizations" }
|
||||
|
||||
type BookMonetization struct {
|
||||
BookID uint `gorm:"primaryKey;index"`
|
||||
MonetizationID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (BookMonetization) TableName() string { return "book_monetizations" }
|
||||
|
||||
type PublisherMonetization struct {
|
||||
PublisherID uint `gorm:"primaryKey;index"`
|
||||
MonetizationID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (PublisherMonetization) TableName() string { return "publisher_monetizations" }
|
||||
|
||||
type SourceMonetization struct {
|
||||
SourceID uint `gorm:"primaryKey;index"`
|
||||
MonetizationID uint `gorm:"primaryKey;index"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (SourceMonetization) TableName() string { return "source_monetizations" }
|
||||
type Monetization struct {
|
||||
BaseModel
|
||||
Amount float64 `gorm:"type:decimal(10,2);default:0.0"`
|
||||
@ -639,7 +701,6 @@ type Monetization struct {
|
||||
StartDate *time.Time
|
||||
EndDate *time.Time
|
||||
Language string `gorm:"size:50;not null"`
|
||||
Monetizables []Monetizable `gorm:"-"`
|
||||
}
|
||||
type License struct {
|
||||
BaseModel
|
||||
|
||||
@ -16,6 +16,191 @@ type PaginatedResult[T any] struct {
|
||||
HasPrev bool `json:"hasPrev"`
|
||||
}
|
||||
|
||||
// MonetizationRepository defines CRUD methods specific to Monetization.
|
||||
type MonetizationRepository interface {
|
||||
BaseRepository[Monetization]
|
||||
AddMonetizationToWork(ctx context.Context, workID uint, monetizationID uint) error
|
||||
RemoveMonetizationFromWork(ctx context.Context, workID uint, monetizationID uint) error
|
||||
AddMonetizationToAuthor(ctx context.Context, authorID uint, monetizationID uint) error
|
||||
RemoveMonetizationFromAuthor(ctx context.Context, authorID uint, monetizationID uint) error
|
||||
AddMonetizationToBook(ctx context.Context, bookID uint, monetizationID uint) error
|
||||
RemoveMonetizationFromBook(ctx context.Context, bookID uint, monetizationID uint) error
|
||||
AddMonetizationToPublisher(ctx context.Context, publisherID uint, monetizationID uint) error
|
||||
RemoveMonetizationFromPublisher(ctx context.Context, publisherID uint, monetizationID uint) error
|
||||
AddMonetizationToSource(ctx context.Context, sourceID uint, monetizationID uint) error
|
||||
RemoveMonetizationFromSource(ctx context.Context, sourceID uint, monetizationID uint) error
|
||||
}
|
||||
|
||||
// PublisherRepository defines CRUD methods specific to Publisher.
|
||||
type PublisherRepository interface {
|
||||
BaseRepository[Publisher]
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]Publisher, error)
|
||||
}
|
||||
|
||||
// SourceRepository defines CRUD methods specific to Source.
|
||||
type SourceRepository interface {
|
||||
BaseRepository[Source]
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Source, error)
|
||||
FindByURL(ctx context.Context, url string) (*Source, error)
|
||||
}
|
||||
|
||||
// BookRepository defines CRUD methods specific to Book.
|
||||
type BookRepository interface {
|
||||
BaseRepository[Book]
|
||||
ListByAuthorID(ctx context.Context, authorID uint) ([]Book, error)
|
||||
ListByPublisherID(ctx context.Context, publisherID uint) ([]Book, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Book, error)
|
||||
FindByISBN(ctx context.Context, isbn string) (*Book, error)
|
||||
}
|
||||
|
||||
// BookmarkRepository defines CRUD methods specific to Bookmark.
|
||||
type BookmarkRepository interface {
|
||||
BaseRepository[Bookmark]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Bookmark, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Bookmark, error)
|
||||
}
|
||||
|
||||
// CategoryRepository defines CRUD methods specific to Category.
|
||||
type CategoryRepository interface {
|
||||
BaseRepository[Category]
|
||||
FindByName(ctx context.Context, name string) (*Category, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Category, error)
|
||||
ListByParentID(ctx context.Context, parentID *uint) ([]Category, error)
|
||||
}
|
||||
|
||||
// CityRepository defines CRUD methods specific to City.
|
||||
type CityRepository interface {
|
||||
BaseRepository[City]
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]City, error)
|
||||
}
|
||||
|
||||
// CollectionRepository defines CRUD methods specific to Collection.
|
||||
type CollectionRepository interface {
|
||||
BaseRepository[Collection]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Collection, error)
|
||||
ListPublic(ctx context.Context) ([]Collection, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Collection, error)
|
||||
}
|
||||
|
||||
// CommentRepository defines CRUD methods specific to Comment.
|
||||
type CommentRepository interface {
|
||||
BaseRepository[Comment]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Comment, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Comment, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]Comment, error)
|
||||
ListByParentID(ctx context.Context, parentID uint) ([]Comment, error)
|
||||
}
|
||||
|
||||
// ContributionRepository defines CRUD methods specific to Contribution.
|
||||
type ContributionRepository interface {
|
||||
BaseRepository[Contribution]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Contribution, error)
|
||||
ListByReviewerID(ctx context.Context, reviewerID uint) ([]Contribution, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Contribution, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]Contribution, error)
|
||||
ListByStatus(ctx context.Context, status string) ([]Contribution, error)
|
||||
}
|
||||
|
||||
// CopyrightClaimRepository defines CRUD methods specific to CopyrightClaim.
|
||||
type CopyrightClaimRepository interface {
|
||||
BaseRepository[CopyrightClaim]
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]CopyrightClaim, error)
|
||||
ListByUserID(ctx context.Context, userID uint) ([]CopyrightClaim, error)
|
||||
}
|
||||
|
||||
// CountryRepository defines CRUD methods specific to Country.
|
||||
type CountryRepository interface {
|
||||
BaseRepository[Country]
|
||||
GetByCode(ctx context.Context, code string) (*Country, error)
|
||||
ListByContinent(ctx context.Context, continent string) ([]Country, error)
|
||||
}
|
||||
|
||||
// EdgeRepository defines CRUD methods specific to Edge.
|
||||
type EdgeRepository interface {
|
||||
BaseRepository[Edge]
|
||||
ListBySource(ctx context.Context, sourceTable string, sourceID uint) ([]Edge, error)
|
||||
}
|
||||
|
||||
// EditionRepository defines CRUD methods specific to Edition.
|
||||
type EditionRepository interface {
|
||||
BaseRepository[Edition]
|
||||
ListByBookID(ctx context.Context, bookID uint) ([]Edition, error)
|
||||
FindByISBN(ctx context.Context, isbn string) (*Edition, error)
|
||||
}
|
||||
|
||||
// EmailVerificationRepository defines CRUD methods specific to EmailVerification.
|
||||
type EmailVerificationRepository interface {
|
||||
BaseRepository[EmailVerification]
|
||||
GetByToken(ctx context.Context, token string) (*EmailVerification, error)
|
||||
GetByUserID(ctx context.Context, userID uint) ([]EmailVerification, error)
|
||||
DeleteExpired(ctx context.Context) error
|
||||
MarkAsUsed(ctx context.Context, id uint) error
|
||||
}
|
||||
|
||||
// LikeRepository defines CRUD methods specific to Like.
|
||||
type LikeRepository interface {
|
||||
BaseRepository[Like]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Like, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Like, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]Like, error)
|
||||
ListByCommentID(ctx context.Context, commentID uint) ([]Like, error)
|
||||
}
|
||||
|
||||
// PasswordResetRepository defines CRUD methods specific to PasswordReset.
|
||||
type PasswordResetRepository interface {
|
||||
BaseRepository[PasswordReset]
|
||||
GetByToken(ctx context.Context, token string) (*PasswordReset, error)
|
||||
GetByUserID(ctx context.Context, userID uint) ([]PasswordReset, error)
|
||||
DeleteExpired(ctx context.Context) error
|
||||
MarkAsUsed(ctx context.Context, id uint) error
|
||||
}
|
||||
|
||||
// PlaceRepository defines CRUD methods specific to Place.
|
||||
type PlaceRepository interface {
|
||||
BaseRepository[Place]
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]Place, error)
|
||||
ListByCityID(ctx context.Context, cityID uint) ([]Place, error)
|
||||
FindNearby(ctx context.Context, latitude, longitude float64, radiusKm float64) ([]Place, error)
|
||||
}
|
||||
|
||||
// TagRepository defines CRUD methods specific to Tag.
|
||||
type TagRepository interface {
|
||||
BaseRepository[Tag]
|
||||
FindByName(ctx context.Context, name string) (*Tag, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Tag, error)
|
||||
}
|
||||
|
||||
// TranslationRepository defines CRUD methods specific to Translation.
|
||||
type TranslationRepository interface {
|
||||
BaseRepository[Translation]
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Translation, error)
|
||||
ListByEntity(ctx context.Context, entityType string, entityID uint) ([]Translation, error)
|
||||
ListByTranslatorID(ctx context.Context, translatorID uint) ([]Translation, error)
|
||||
ListByStatus(ctx context.Context, status TranslationStatus) ([]Translation, error)
|
||||
}
|
||||
|
||||
// UserRepository defines CRUD methods specific to User.
|
||||
type UserRepository interface {
|
||||
BaseRepository[User]
|
||||
FindByUsername(ctx context.Context, username string) (*User, error)
|
||||
FindByEmail(ctx context.Context, email string) (*User, error)
|
||||
ListByRole(ctx context.Context, role UserRole) ([]User, error)
|
||||
}
|
||||
|
||||
// UserProfileRepository defines CRUD methods specific to UserProfile.
|
||||
type UserProfileRepository interface {
|
||||
BaseRepository[UserProfile]
|
||||
GetByUserID(ctx context.Context, userID uint) (*UserProfile, error)
|
||||
}
|
||||
|
||||
// UserSessionRepository defines CRUD methods specific to UserSession.
|
||||
type UserSessionRepository interface {
|
||||
BaseRepository[UserSession]
|
||||
GetByToken(ctx context.Context, token string) (*UserSession, error)
|
||||
GetByUserID(ctx context.Context, userID uint) ([]UserSession, error)
|
||||
DeleteExpired(ctx context.Context) error
|
||||
}
|
||||
|
||||
// QueryOptions provides options for repository queries
|
||||
type QueryOptions struct {
|
||||
Preloads []string
|
||||
@ -66,87 +251,20 @@ type AuthorRepository interface {
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]Author, error)
|
||||
}
|
||||
|
||||
// BookRepository defines CRUD methods specific to Book.
|
||||
type BookRepository interface {
|
||||
BaseRepository[Book]
|
||||
ListByAuthorID(ctx context.Context, authorID uint) ([]Book, error)
|
||||
ListByPublisherID(ctx context.Context, publisherID uint) ([]Book, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Book, error)
|
||||
FindByISBN(ctx context.Context, isbn string) (*Book, error)
|
||||
}
|
||||
|
||||
// UserRepository defines CRUD methods specific to User.
|
||||
type UserRepository interface {
|
||||
BaseRepository[User]
|
||||
FindByUsername(ctx context.Context, username string) (*User, error)
|
||||
FindByEmail(ctx context.Context, email string) (*User, error)
|
||||
ListByRole(ctx context.Context, role UserRole) ([]User, error)
|
||||
}
|
||||
|
||||
// TranslationRepository defines CRUD methods specific to Translation.
|
||||
type TranslationRepository interface {
|
||||
BaseRepository[Translation]
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Translation, error)
|
||||
ListByEntity(ctx context.Context, entityType string, entityID uint) ([]Translation, error)
|
||||
ListByTranslatorID(ctx context.Context, translatorID uint) ([]Translation, error)
|
||||
ListByStatus(ctx context.Context, status TranslationStatus) ([]Translation, error)
|
||||
}
|
||||
|
||||
// CommentRepository defines CRUD methods specific to Comment.
|
||||
type CommentRepository interface {
|
||||
BaseRepository[Comment]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Comment, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Comment, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]Comment, error)
|
||||
ListByParentID(ctx context.Context, parentID uint) ([]Comment, error)
|
||||
}
|
||||
|
||||
// LikeRepository defines CRUD methods specific to Like.
|
||||
type LikeRepository interface {
|
||||
BaseRepository[Like]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Like, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Like, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]Like, error)
|
||||
ListByCommentID(ctx context.Context, commentID uint) ([]Like, error)
|
||||
}
|
||||
|
||||
// BookmarkRepository defines CRUD methods specific to Bookmark.
|
||||
type BookmarkRepository interface {
|
||||
BaseRepository[Bookmark]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Bookmark, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Bookmark, error)
|
||||
}
|
||||
|
||||
// CollectionRepository defines CRUD methods specific to Collection.
|
||||
type CollectionRepository interface {
|
||||
BaseRepository[Collection]
|
||||
ListByUserID(ctx context.Context, userID uint) ([]Collection, error)
|
||||
ListPublic(ctx context.Context) ([]Collection, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Collection, error)
|
||||
}
|
||||
|
||||
// TagRepository defines CRUD methods specific to Tag.
|
||||
type TagRepository interface {
|
||||
BaseRepository[Tag]
|
||||
FindByName(ctx context.Context, name string) (*Tag, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Tag, error)
|
||||
}
|
||||
|
||||
// CategoryRepository defines CRUD methods specific to Category.
|
||||
type CategoryRepository interface {
|
||||
BaseRepository[Category]
|
||||
FindByName(ctx context.Context, name string) (*Category, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]Category, error)
|
||||
ListByParentID(ctx context.Context, parentID *uint) ([]Category, error)
|
||||
}
|
||||
|
||||
// CopyrightRepository defines CRUD methods specific to Copyright.
|
||||
type CopyrightRepository interface {
|
||||
BaseRepository[Copyright]
|
||||
AttachToEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) error
|
||||
DetachFromEntity(ctx context.Context, copyrightID uint, entityID uint, entityType string) error
|
||||
GetByEntity(ctx context.Context, entityID uint, entityType string) ([]Copyright, error)
|
||||
GetEntitiesByCopyright(ctx context.Context, copyrightID uint) ([]Copyrightable, error)
|
||||
AddCopyrightToWork(ctx context.Context, workID uint, copyrightID uint) error
|
||||
RemoveCopyrightFromWork(ctx context.Context, workID uint, copyrightID uint) error
|
||||
AddCopyrightToAuthor(ctx context.Context, authorID uint, copyrightID uint) error
|
||||
RemoveCopyrightFromAuthor(ctx context.Context, authorID uint, copyrightID uint) error
|
||||
AddCopyrightToBook(ctx context.Context, bookID uint, copyrightID uint) error
|
||||
RemoveCopyrightFromBook(ctx context.Context, bookID uint, copyrightID uint) error
|
||||
AddCopyrightToPublisher(ctx context.Context, publisherID uint, copyrightID uint) error
|
||||
RemoveCopyrightFromPublisher(ctx context.Context, publisherID uint, copyrightID uint) error
|
||||
AddCopyrightToSource(ctx context.Context, sourceID uint, copyrightID uint) error
|
||||
RemoveCopyrightFromSource(ctx context.Context, sourceID uint, copyrightID uint) error
|
||||
AddTranslation(ctx context.Context, translation *CopyrightTranslation) error
|
||||
GetTranslations(ctx context.Context, copyrightID uint) ([]CopyrightTranslation, error)
|
||||
GetTranslationByLanguage(ctx context.Context, copyrightID uint, languageCode string) (*CopyrightTranslation, error)
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
package like
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// LikeRepository defines CRUD methods specific to Like.
|
||||
type LikeRepository interface {
|
||||
domain.BaseRepository[domain.Like]
|
||||
|
||||
ListByUserID(ctx context.Context, userID uint) ([]domain.Like, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Like, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]domain.Like, error)
|
||||
ListByCommentID(ctx context.Context, commentID uint) ([]domain.Like, error)
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package monetization
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// MonetizationRepository defines CRUD methods specific to Monetization.
|
||||
type MonetizationRepository interface {
|
||||
domain.BaseRepository[domain.Monetization]
|
||||
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Monetization, error)
|
||||
ListByTranslationID(ctx context.Context, translationID uint) ([]domain.Monetization, error)
|
||||
ListByBookID(ctx context.Context, bookID uint) ([]domain.Monetization, error)
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package password_reset
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// Password_resetRepository defines CRUD methods specific to Password_reset.
|
||||
type Password_resetRepository interface {
|
||||
domain.BaseRepository[domain.PasswordReset]
|
||||
|
||||
GetByToken(ctx context.Context, token string) (*domain.PasswordReset, error)
|
||||
GetByUserID(ctx context.Context, userID uint) ([]domain.PasswordReset, error)
|
||||
DeleteExpired(ctx context.Context) (error)
|
||||
MarkAsUsed(ctx context.Context, id uint) (error)
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package place
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// PlaceRepository defines CRUD methods specific to Place.
|
||||
type PlaceRepository interface {
|
||||
domain.BaseRepository[domain.Place]
|
||||
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]domain.Place, error)
|
||||
ListByCityID(ctx context.Context, cityID uint) ([]domain.Place, error)
|
||||
FindNearby(ctx context.Context, latitude, longitude float64, radiusKm float64) ([]domain.Place, error)
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package publisher
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// PublisherRepository defines CRUD methods specific to Publisher.
|
||||
type PublisherRepository interface {
|
||||
domain.BaseRepository[domain.Publisher]
|
||||
|
||||
ListByCountryID(ctx context.Context, countryID uint) ([]domain.Publisher, error)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// SourceRepository defines CRUD methods specific to Source.
|
||||
type SourceRepository interface {
|
||||
domain.BaseRepository[domain.Source]
|
||||
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Source, error)
|
||||
FindByURL(ctx context.Context, url string) (*domain.Source, error)
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// TagRepository defines CRUD methods specific to Tag.
|
||||
type TagRepository interface {
|
||||
domain.BaseRepository[domain.Tag]
|
||||
|
||||
FindByName(ctx context.Context, name string) (*domain.Tag, error)
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Tag, error)
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package translation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// TranslationRepository defines CRUD methods specific to Translation.
|
||||
type TranslationRepository interface {
|
||||
domain.BaseRepository[domain.Translation]
|
||||
|
||||
ListByWorkID(ctx context.Context, workID uint) ([]domain.Translation, error)
|
||||
ListByEntity(ctx context.Context, entityType string, entityID uint) ([]domain.Translation, error)
|
||||
ListByTranslatorID(ctx context.Context, translatorID uint) ([]domain.Translation, error)
|
||||
ListByStatus(ctx context.Context, status domain.TranslationStatus) ([]domain.Translation, error)
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// UserRepository defines CRUD methods specific to User.
|
||||
type UserRepository interface {
|
||||
domain.BaseRepository[domain.User]
|
||||
|
||||
FindByUsername(ctx context.Context, username string) (*domain.User, error)
|
||||
FindByEmail(ctx context.Context, email string) (*domain.User, error)
|
||||
ListByRole(ctx context.Context, role domain.UserRole) ([]domain.User, error)
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package user_profile
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// User_profileRepository defines CRUD methods specific to User_profile.
|
||||
type User_profileRepository interface {
|
||||
domain.BaseRepository[domain.UserProfile]
|
||||
|
||||
GetByUserID(ctx context.Context, userID uint) (*domain.UserProfile, error)
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package user_session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// User_sessionRepository defines CRUD methods specific to User_session.
|
||||
type User_sessionRepository interface {
|
||||
domain.BaseRepository[domain.UserSession]
|
||||
|
||||
GetByToken(ctx context.Context, token string) (*domain.UserSession, error)
|
||||
GetByUserID(ctx context.Context, userID uint) ([]domain.UserSession, error)
|
||||
DeleteExpired(ctx context.Context) (error)
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
package work
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tercul/internal/domain"
|
||||
)
|
||||
|
||||
// WorkRepository defines CRUD methods specific to Work.
|
||||
type WorkRepository interface {
|
||||
domain.BaseRepository[domain.Work]
|
||||
|
||||
FindByTitle(ctx context.Context, title string) ([]domain.Work, error)
|
||||
FindByAuthor(ctx context.Context, authorID uint) ([]domain.Work, error)
|
||||
FindByCategory(ctx context.Context, categoryID uint) ([]domain.Work, error)
|
||||
FindByLanguage(ctx context.Context, language string, page, pageSize int) (*domain.PaginatedResult[domain.Work], error)
|
||||
GetWithTranslations(ctx context.Context, id uint) (*domain.Work, error)
|
||||
ListWithTranslations(ctx context.Context, page, pageSize int) (*domain.PaginatedResult[domain.Work], error)
|
||||
}
|
||||
@ -35,6 +35,11 @@ type IntegrationTestSuite struct {
|
||||
CollectionRepo domain.CollectionRepository
|
||||
TagRepo domain.TagRepository
|
||||
CategoryRepo domain.CategoryRepository
|
||||
BookRepo domain.BookRepository
|
||||
MonetizationRepo domain.MonetizationRepository
|
||||
PublisherRepo domain.PublisherRepository
|
||||
SourceRepo domain.SourceRepository
|
||||
CopyrightRepo domain.CopyrightRepository
|
||||
|
||||
// Services
|
||||
WorkCommands *work.WorkCommands
|
||||
@ -139,6 +144,16 @@ func (s *IntegrationTestSuite) setupInMemoryDB(config *TestConfig) {
|
||||
&domain.Book{},
|
||||
&domain.Publisher{},
|
||||
&domain.Source{},
|
||||
&domain.WorkCopyright{},
|
||||
&domain.AuthorCopyright{},
|
||||
&domain.BookCopyright{},
|
||||
&domain.PublisherCopyright{},
|
||||
&domain.SourceCopyright{},
|
||||
&domain.WorkMonetization{},
|
||||
&domain.AuthorMonetization{},
|
||||
&domain.BookMonetization{},
|
||||
&domain.PublisherMonetization{},
|
||||
&domain.SourceMonetization{},
|
||||
// &domain.WorkAnalytics{}, // Commented out as it's not in models package
|
||||
&domain.ReadabilityScore{},
|
||||
&domain.WritingStyle{},
|
||||
@ -166,6 +181,11 @@ func (s *IntegrationTestSuite) setupInMemoryDB(config *TestConfig) {
|
||||
s.CollectionRepo = sql.NewCollectionRepository(db)
|
||||
s.TagRepo = sql.NewTagRepository(db)
|
||||
s.CategoryRepo = sql.NewCategoryRepository(db)
|
||||
s.BookRepo = sql.NewBookRepository(db)
|
||||
s.MonetizationRepo = sql.NewMonetizationRepository(db)
|
||||
s.PublisherRepo = sql.NewPublisherRepository(db)
|
||||
s.SourceRepo = sql.NewSourceRepository(db)
|
||||
s.CopyrightRepo = sql.NewCopyrightRepository(db)
|
||||
}
|
||||
|
||||
// setupMockRepositories sets up mock repositories for testing
|
||||
|
||||
Loading…
Reference in New Issue
Block a user