Files
History_Api/internal/services/entityService.go
T
2026-06-05 14:18:55 +07:00

153 lines
4.5 KiB
Go

package services
import (
"context"
"database/sql"
"errors"
"history-api/internal/dtos/request"
"history-api/internal/dtos/response"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/internal/repositories"
"history-api/pkg/convert"
"github.com/gofiber/fiber/v3"
)
type EntityService interface {
GetEntityByID(ctx context.Context, id string) (*response.EntityResponse, *fiber.Error)
GetEntityBySlug(ctx context.Context, slug string) (*response.EntityResponse, *fiber.Error)
IsExistEntitySlug(ctx context.Context, slug string) (bool, *fiber.Error)
SearchEntities(ctx context.Context, req *request.SearchEntityDto) ([]*response.EntityResponse, *fiber.Error)
GetEntitiesByGeometryIDs(ctx context.Context, req *request.GetEntitiesByGeometryIDsDto) (map[string][]*response.EntityResponse, *fiber.Error)
}
type entityService struct {
entityRepo repositories.EntityRepository
}
func NewEntityService(entityRepo repositories.EntityRepository) EntityService {
return &entityService{
entityRepo: entityRepo,
}
}
func (s *entityService) GetEntityByID(ctx context.Context, id string) (*response.EntityResponse, *fiber.Error) {
entityId, err := convert.StringToUUID(id)
if err != nil {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid entity ID format")
}
entity, err := s.entityRepo.GetByID(ctx, entityId)
if err != nil {
return nil, fiber.NewError(fiber.StatusNotFound, "Entity not found")
}
return entity.ToResponse(), nil
}
func (s *entityService) GetEntityBySlug(ctx context.Context, slug string) (*response.EntityResponse, *fiber.Error) {
if slug == "" {
return nil, fiber.NewError(fiber.StatusBadRequest, "Slug is required")
}
entity, err := s.entityRepo.GetBySlug(ctx, slug)
if err != nil {
return nil, fiber.NewError(fiber.StatusNotFound, "Entity not found")
}
return entity.ToResponse(), nil
}
func (s *entityService) IsExistEntitySlug(ctx context.Context, slug string) (bool, *fiber.Error) {
if slug == "" {
return false, fiber.NewError(fiber.StatusBadRequest, "Slug is required")
}
entity, err := s.entityRepo.GetBySlug(ctx, slug)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return false, fiber.NewError(fiber.StatusInternalServerError, "Failed to check slug existence")
}
return entity != nil, nil
}
func (s *entityService) SearchEntities(ctx context.Context, req *request.SearchEntityDto) ([]*response.EntityResponse, *fiber.Error) {
limit := int32(25)
if req.Limit > 0 {
limit = int32(req.Limit)
}
params := sqlc.SearchEntitiesParams{
LimitCount: limit,
}
if req.Cursor != "" {
cursor, err := convert.StringToUUID(req.Cursor)
if err == nil {
params.CursorID = cursor
}
}
if req.Name != "" {
params.Name = convert.PtrToText(&req.Name)
}
if req.ProjectID != nil {
projectID, err := convert.StringToUUID(*req.ProjectID)
if err == nil {
params.ProjectID = projectID
}
}
entities, err := s.entityRepo.Search(ctx, params)
if err != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to search entities")
}
return models.EntitiesEntityToResponse(entities), nil
}
func (s *entityService) GetEntitiesByGeometryIDs(ctx context.Context, req *request.GetEntitiesByGeometryIDsDto) (map[string][]*response.EntityResponse, *fiber.Error) {
mapping, err := s.entityRepo.GetEntityIDsByGeometryIDs(ctx, req.GeometryIDs)
if err != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch entity IDs by geometry IDs")
}
totalEntityIDs := 0
for _, eIDs := range mapping {
totalEntityIDs += len(eIDs)
}
entityIDMap := make(map[string]struct{}, totalEntityIDs)
allEntityIDs := make([]string, 0, totalEntityIDs)
for _, eIDs := range mapping {
for _, eID := range eIDs {
if _, ok := entityIDMap[eID]; !ok {
entityIDMap[eID] = struct{}{}
allEntityIDs = append(allEntityIDs, eID)
}
}
}
entities, err := s.entityRepo.GetByIDs(ctx, allEntityIDs)
if err != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch entities")
}
entitiesByID := make(map[string]*models.EntityEntity, len(entities))
for _, e := range entities {
entitiesByID[e.ID] = e
}
result := make(map[string][]*response.EntityResponse, len(req.GeometryIDs))
for _, idStr := range req.GeometryIDs {
eIDs, exists := mapping[idStr]
result[idStr] = make([]*response.EntityResponse, 0, len(eIDs))
if exists {
for _, eID := range eIDs {
if e, found := entitiesByID[eID]; found {
result[idStr] = append(result[idStr], e.ToResponse())
}
}
}
}
return result, nil
}