package company_category import ( "context" "errors" "tm/pkg/logger" "tm/pkg/response" ) // Service defines business logic for category operations type Service interface { // Core category operations Create(ctx context.Context, form *CategoryForm) (*CategoryResponse, error) Update(ctx context.Context, id string, form *CategoryForm) (*CategoryResponse, error) GetByID(ctx context.Context, id string) (*CategoryResponse, error) GetByIDs(ctx context.Context, ids []string) ([]*CategoryResponse, error) Delete(ctx context.Context, id string) error // Category listing and search SearchCategories(ctx context.Context, form *SearchForm, pagination *response.Pagination) (*CategoryListResponse, error) // Category management TogglePublish(ctx context.Context, id string) (bool, error) } // categoryService implements the Service interface type categoryService struct { repository Repository logger logger.Logger } // NewService creates a new category service func NewService(repository Repository, logger logger.Logger) Service { return &categoryService{ repository: repository, logger: logger, } } // Create creates a new category func (s *categoryService) Create(ctx context.Context, form *CategoryForm) (*CategoryResponse, error) { // Check if category name already exists existingCategory, _ := s.repository.GetByName(ctx, form.Name) if existingCategory != nil { return nil, errors.New("category with this name already exists") } // Create category category := &Category{ Name: form.Name, Description: form.Description, Thumbnail: form.Thumbnail, Published: false, // Default to unpublished } // Save to database err := s.repository.Create(ctx, category) if err != nil { s.logger.Error("Failed to create category", map[string]interface{}{ "error": err.Error(), "name": form.Name, }) return nil, err } s.logger.Info("Category created successfully", map[string]interface{}{ "category_id": category.ID, "name": category.Name, "published": category.Published, }) return category.ToResponse(), nil } // GetByIDs retrieves categories by IDs func (s *categoryService) GetByIDs(ctx context.Context, ids []string) ([]*CategoryResponse, error) { categories, err := s.repository.GetByIDs(ctx, ids) if err != nil { return nil, err } var categoryResponses []*CategoryResponse for _, category := range categories { categoryResponses = append(categoryResponses, category.ToResponse()) } return categoryResponses, nil } // GetByID retrieves a category by ID func (s *categoryService) GetByID(ctx context.Context, id string) (*CategoryResponse, error) { category, err := s.repository.GetByID(ctx, id) if err != nil { s.logger.Error("Failed to get category by ID", map[string]interface{}{ "error": err.Error(), "category_id": id, }) return nil, err } s.logger.Info("Category retrieved successfully", map[string]interface{}{ "category_id": category.ID, "name": category.Name, }) return category.ToResponse(), nil } // Update updates a category func (s *categoryService) Update(ctx context.Context, id string, form *CategoryForm) (*CategoryResponse, error) { // Get existing category category, err := s.repository.GetByID(ctx, id) if err != nil { s.logger.Error("Failed to get category for update", map[string]interface{}{ "error": err.Error(), "category_id": id, }) return nil, errors.New("category not found") } // Check if name already exists (if changing name) if form.Name != "" && form.Name != category.Name { existingCategory, _ := s.repository.GetByName(ctx, form.Name) if existingCategory != nil { return nil, errors.New("category with this name already exists") } category.Name = form.Name } // Update fields if provided if form.Description != nil { category.Description = form.Description } if form.Thumbnail != nil { category.Thumbnail = form.Thumbnail } // Update in database err = s.repository.Update(ctx, category) if err != nil { s.logger.Error("Failed to update category", map[string]interface{}{ "error": err.Error(), "category_id": id, }) return nil, errors.New("failed to update category") } s.logger.Info("Category updated successfully", map[string]interface{}{ "category_id": category.ID, "name": category.Name, }) return category.ToResponse(), nil } // Delete deletes a category func (s *categoryService) Delete(ctx context.Context, id string) error { // Delete category err := s.repository.Delete(ctx, id) if err != nil { s.logger.Error("Failed to delete category", map[string]interface{}{ "error": err.Error(), "category_id": id, }) return errors.New("failed to delete category") } s.logger.Info("Category deleted successfully", map[string]interface{}{ "category_id": id, }) return nil } // SearchCategories searches categories with filters func (s *categoryService) SearchCategories(ctx context.Context, form *SearchForm, pagination *response.Pagination) (*CategoryListResponse, error) { // Get categories using search page, err := s.repository.Search(ctx, form, pagination) if err != nil { s.logger.Error("Failed to search categories", map[string]interface{}{ "error": err.Error(), }) return nil, err } var categoryResponses []*CategoryResponse for _, category := range page.Items { categoryResponses = append(categoryResponses, category.ToResponse()) } return &CategoryListResponse{ Categories: categoryResponses, Meta: pagination.ListMeta(page.TotalCount, page.NextCursor, page.HasMore, page.PageOffset), }, nil } // TogglePublish toggles category publish status func (s *categoryService) TogglePublish(ctx context.Context, id string) (bool, error) { // Get category to check if exists _, err := s.repository.GetByID(ctx, id) if err != nil { return false, errors.New("category not found") } // Toggle publish status published, err := s.repository.TogglePublish(ctx, id) if err != nil { s.logger.Error("Failed to toggle category publish status", map[string]interface{}{ "error": err.Error(), "category_id": id, }) return false, errors.New("failed to toggle category publish status") } s.logger.Info("Category publish status updated successfully", map[string]interface{}{ "category_id": id, "published": published, }) return published, nil }