package book import ( "context" "tercul/internal/app/authz" "tercul/internal/domain" "github.com/google/uuid" ) // BookCommands contains the command handlers for the book aggregate. type BookCommands struct { repo domain.BookRepository authzSvc *authz.Service } // NewBookCommands creates a new BookCommands handler. func NewBookCommands(repo domain.BookRepository, authzSvc *authz.Service) *BookCommands { return &BookCommands{ repo: repo, authzSvc: authzSvc, } } // CreateBookInput represents the input for creating a new book. type CreateBookInput struct { Title string Description string Language string ISBN *string AuthorIDs []uuid.UUID } // CreateBook creates a new book. func (c *BookCommands) CreateBook(ctx context.Context, input CreateBookInput) (*domain.Book, error) { can, err := c.authzSvc.CanCreateBook(ctx) if err != nil { return nil, err } if !can { return nil, domain.ErrForbidden } book := &domain.Book{ Title: input.Title, Description: input.Description, TranslatableModel: domain.TranslatableModel{ Language: input.Language, }, } if input.ISBN != nil { book.ISBN = *input.ISBN } // In a real implementation, we would associate the authors here. // for _, authorID := range input.AuthorIDs { ... } err = c.repo.Create(ctx, book) if err != nil { return nil, err } return book, nil } // UpdateBookInput represents the input for updating an existing book. type UpdateBookInput struct { ID uuid.UUID Title *string Description *string Language *string ISBN *string AuthorIDs []uuid.UUID } // UpdateBook updates an existing book. func (c *BookCommands) UpdateBook(ctx context.Context, input UpdateBookInput) (*domain.Book, error) { can, err := c.authzSvc.CanUpdateBook(ctx) if err != nil { return nil, err } if !can { return nil, domain.ErrForbidden } book, err := c.repo.GetByID(ctx, input.ID) if err != nil { return nil, err } if input.Title != nil { book.Title = *input.Title } if input.Description != nil { book.Description = *input.Description } if input.Language != nil { book.Language = *input.Language } if input.ISBN != nil { book.ISBN = *input.ISBN } err = c.repo.Update(ctx, book) if err != nil { return nil, err } return book, nil } // DeleteBook deletes a book by ID. func (c *BookCommands) DeleteBook(ctx context.Context, id uuid.UUID) error { can, err := c.authzSvc.CanDeleteBook(ctx) if err != nil { return err } if !can { return domain.ErrForbidden } return c.repo.Delete(ctx, id) }