Files
tm_back/internal/company_category/service.go
T
2026-05-17 17:21:36 +03:30

224 lines
6.2 KiB
Go

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
}