a342da193e
- Updated feedback repository and service methods to use a consistent naming convention, changing `NewTenderRepository` and similar methods to `NewRepository`. - Refactored feedback handler methods to improve clarity by renaming methods such as `ListFeedback` to `Search` and `GetFeedback` to `Get`. - Enhanced feedback response structures to include detailed company and tender information, improving the clarity of feedback data returned to API consumers. - Updated Swagger documentation to reflect changes in feedback response structures and endpoint paths, ensuring accurate representation of the API for consumers.
265 lines
6.8 KiB
Go
265 lines
6.8 KiB
Go
package company_category
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
"tm/pkg/logger"
|
|
orm "tm/pkg/mongo"
|
|
"tm/pkg/response"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
// Repository defines the interface for category data operations
|
|
type Repository interface {
|
|
Create(ctx context.Context, category *Category) error
|
|
Update(ctx context.Context, category *Category) error
|
|
GetByID(ctx context.Context, id string) (*Category, error)
|
|
GetByIDs(ctx context.Context, ids []string) ([]Category, error)
|
|
GetByName(ctx context.Context, name string) (*Category, error)
|
|
Search(ctx context.Context, form *SearchForm, pagination *response.Pagination) ([]Category, int64, error)
|
|
Delete(ctx context.Context, id string) error
|
|
TogglePublish(ctx context.Context, id string) (bool, error)
|
|
}
|
|
|
|
// categoryRepository implements the Repository interface using the MongoDB ORM
|
|
type categoryRepository struct {
|
|
ormRepo orm.Repository[Category]
|
|
logger logger.Logger
|
|
}
|
|
|
|
// NewCategoryRepository creates a new category repository
|
|
func NewRepository(mongoManager *orm.ConnectionManager, logger logger.Logger) Repository {
|
|
// Create indexes using the ORM's index management
|
|
indexes := []orm.Index{
|
|
*orm.NewIndex("name_idx", bson.D{{Key: "name", Value: 1}}),
|
|
*orm.NewIndex("published_idx", bson.D{{Key: "published", Value: 1}}),
|
|
}
|
|
|
|
// Create indexes
|
|
err := mongoManager.CreateIndexes("company_categories", indexes)
|
|
if err != nil {
|
|
logger.Warn("Failed to create category indexes", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
}
|
|
|
|
// Create ORM repository
|
|
ormRepo := orm.NewRepository[Category](mongoManager.GetCollection("company_categories"), logger)
|
|
|
|
return &categoryRepository{
|
|
ormRepo: ormRepo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// Create creates a new category
|
|
func (r *categoryRepository) Create(ctx context.Context, category *Category) error {
|
|
// Set created/updated timestamps using Unix timestamps
|
|
now := time.Now().Unix()
|
|
category.SetCreatedAt(now)
|
|
|
|
// Use ORM to create category
|
|
err := r.ormRepo.Create(ctx, category)
|
|
if err != nil {
|
|
r.logger.Error("Failed to create category", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"name": category.Name,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Category created successfully", map[string]interface{}{
|
|
"category_id": category.ID,
|
|
"name": category.Name,
|
|
"published": category.Published,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetByID retrieves a category by ID
|
|
func (r *categoryRepository) GetByID(ctx context.Context, id string) (*Category, error) {
|
|
category, err := r.ormRepo.FindByID(ctx, id)
|
|
if err != nil {
|
|
if errors.Is(err, orm.ErrDocumentNotFound) {
|
|
return nil, errors.New("category not found")
|
|
}
|
|
r.logger.Error("Failed to get category by ID", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"category_id": id,
|
|
})
|
|
return nil, err
|
|
}
|
|
|
|
return category, nil
|
|
}
|
|
|
|
// GetByIDs retrieves categories by IDs
|
|
func (r *categoryRepository) GetByIDs(ctx context.Context, ids []string) ([]Category, error) {
|
|
objectIDs := make([]bson.ObjectID, len(ids))
|
|
for i, id := range ids {
|
|
objectID, err := bson.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
objectIDs[i] = objectID
|
|
}
|
|
|
|
filter := bson.M{"_id": bson.M{"$in": objectIDs}}
|
|
|
|
paginationBuilder := orm.NewPaginationBuilder().
|
|
Build()
|
|
|
|
result, err := r.ormRepo.FindAll(ctx, filter, paginationBuilder)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result.Items, nil
|
|
}
|
|
|
|
// GetByName retrieves a category by name
|
|
func (r *categoryRepository) GetByName(ctx context.Context, name string) (*Category, error) {
|
|
category, err := r.ormRepo.FindOne(ctx, bson.M{"name": name})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return category, nil
|
|
}
|
|
|
|
// Update updates a category
|
|
func (r *categoryRepository) Update(ctx context.Context, category *Category) error {
|
|
// Set updated timestamp using Unix timestamp
|
|
category.SetUpdatedAt(time.Now().Unix())
|
|
|
|
// Use ORM to update category
|
|
err := r.ormRepo.Update(ctx, category)
|
|
if err != nil {
|
|
r.logger.Error("Failed to update category", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"category_id": category.ID,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Category updated successfully", map[string]interface{}{
|
|
"category_id": category.ID,
|
|
"name": category.Name,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Delete deletes a category
|
|
func (r *categoryRepository) Delete(ctx context.Context, id string) error {
|
|
// Get category first
|
|
_, err := r.GetByID(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Delete from database
|
|
err = r.ormRepo.Delete(ctx, id)
|
|
if err != nil {
|
|
r.logger.Error("Failed to delete category", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"category_id": id,
|
|
})
|
|
return err
|
|
}
|
|
|
|
r.logger.Info("Category deleted successfully", map[string]interface{}{
|
|
"category_id": id,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Search retrieves categories with search and filters
|
|
func (r *categoryRepository) Search(ctx context.Context, form *SearchForm, pagination *response.Pagination) ([]Category, int64, error) {
|
|
// Build filter
|
|
filter := bson.M{}
|
|
|
|
if form.Search != nil && *form.Search != "" {
|
|
// Use regex search for case-insensitive partial matching
|
|
searchRegex := bson.M{
|
|
"$regex": *form.Search,
|
|
"$options": "i", // case-insensitive
|
|
}
|
|
filter["$or"] = []bson.M{
|
|
{"name": searchRegex},
|
|
{"description": searchRegex},
|
|
}
|
|
}
|
|
|
|
if form.Published != nil {
|
|
filter["published"] = *form.Published
|
|
}
|
|
|
|
// Build sort
|
|
sort := "created_at"
|
|
if pagination.SortBy != "" {
|
|
sort = pagination.SortBy
|
|
}
|
|
|
|
sortOrder := "desc"
|
|
if pagination.SortOrder != "" {
|
|
sortOrder = pagination.SortOrder
|
|
}
|
|
|
|
// Build pagination
|
|
paginationBuilder := orm.NewPaginationBuilder().
|
|
Limit(pagination.Limit).
|
|
Skip(pagination.Offset).
|
|
SortBy(sort, sortOrder).
|
|
Build()
|
|
|
|
// Use ORM to find categories
|
|
result, err := r.ormRepo.FindAll(ctx, filter, paginationBuilder)
|
|
if err != nil {
|
|
r.logger.Error("Failed to search categories", map[string]interface{}{
|
|
"error": err.Error(),
|
|
})
|
|
return nil, 0, err
|
|
}
|
|
|
|
return result.Items, result.TotalCount, nil
|
|
}
|
|
|
|
// TogglePublish toggles category publish status
|
|
func (r *categoryRepository) TogglePublish(ctx context.Context, id string) (bool, error) {
|
|
// Get category first
|
|
category, err := r.GetByID(ctx, id)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// Update publish status
|
|
category.Published = !category.Published
|
|
now := time.Now().Unix()
|
|
category.SetUpdatedAt(now)
|
|
|
|
// Set published_at timestamp if publishing
|
|
category.PublishedAt = &now
|
|
|
|
// Update in database
|
|
err = r.ormRepo.Update(ctx, category)
|
|
if err != nil {
|
|
r.logger.Error("Failed to toggle category publish status", map[string]interface{}{
|
|
"error": err.Error(),
|
|
"category_id": id,
|
|
"published": category.Published,
|
|
})
|
|
return false, err
|
|
}
|
|
|
|
r.logger.Info("Category publish status updated successfully", map[string]interface{}{
|
|
"category_id": id,
|
|
"published": category.Published,
|
|
})
|
|
|
|
return category.Published, nil
|
|
}
|