Files
plantillas-proyectos/backend/api/v1/modules/sitar/fracciones_usa/service.py

94 lines
3.0 KiB
Python

"""Fracciones USA Service"""
import logging
from typing import Optional, List, Tuple
from ..common import SitarAPIBaseService
from .schemas import FraccionesUSAResponse
logger = logging.getLogger(__name__)
class FraccionesUSAService(SitarAPIBaseService):
"""Service for USA Fracciones operations"""
_instance: Optional["FraccionesUSAService"] = None
@classmethod
def get_instance(cls) -> "FraccionesUSAService":
"""Get singleton instance"""
if cls._instance is None:
cls._instance = cls()
return cls._instance
async def search_with_total(
self,
fraccion: Optional[str] = None,
descripcion: Optional[str] = None,
skip: int = 0,
limit: int = 100,
) -> Tuple[List[FraccionesUSAResponse], int]:
"""Search USA tariff fractions; total matches SITAR PaginatedFraccionesUSAResponse.total."""
params = {"skip": skip, "limit": min(limit, 1000)}
if fraccion:
params["fraccion"] = fraccion
if descripcion:
params["descripcion"] = descripcion
raw = await self._make_request("GET", "api/v1/fracciones-usa/", params=params)
rows, total = self._parse_paginated_list_and_total(raw)
return [FraccionesUSAResponse(**item) for item in rows], total
async def search(
self,
fraccion: Optional[str] = None,
descripcion: Optional[str] = None,
skip: int = 0,
limit: int = 100,
) -> List[FraccionesUSAResponse]:
"""Search USA tariff fractions"""
items, _ = await self.search_with_total(
fraccion=fraccion,
descripcion=descripcion,
skip=skip,
limit=limit,
)
return items
async def get_by_id(self, consecutivo: int) -> FraccionesUSAResponse:
"""Get single USA Fraccion record by CONSECUTIVO"""
data = await self._make_request("GET", f"api/v1/fracciones-usa/{consecutivo}")
return FraccionesUSAResponse(**data)
@classmethod
def search_sync(
cls,
fraccion: Optional[str] = None,
descripcion: Optional[str] = None,
skip: int = 0,
limit: int = 100,
) -> List[FraccionesUSAResponse]:
"""
Synchronous SITAR search for use from sync validators (FastAPI async routes
run sync code on the event loop; asyncio.run must not be used there).
"""
try:
service = cls.get_instance()
except ValueError:
return []
params: dict = {"skip": skip, "limit": min(limit, 1000)}
if fraccion:
params["fraccion"] = fraccion
if descripcion:
params["descripcion"] = descripcion
try:
raw = service._make_request_sync("GET", "api/v1/fracciones-usa/", params=params)
rows, _ = service._parse_paginated_list_and_total(raw)
return [FraccionesUSAResponse(**item) for item in rows]
except Exception as exc:
logger.warning("SITAR fracciones-usa search_sync failed: %s", exc)
return []