Mejoras genéricas traídas: - core/crud_router.py: el PATCH genérico reenvía cualquier header B1S-* recibido del caller en vez de decidirlo el backend. - routers/catalogs.py: nuevo endpoint /api/Catalogs/UdfValidValues (valores válidos de cualquier UDF vía Service Layer). - routers/batch.py: /api/batch/stock (stock de un lote por almacén) y /api/batch/lot-source-warehouse (resuelve contra HANA de qué almacén salió un lote, repartiendo por origen). - routers/inventory_transfer_requests.py + core/inventory_transfer_requests.py: CRUD genérico de Solicitudes de Transferencia de Inventario. - routers/series.py + core/series.py: series activas de un tipo de documento. - routers/user_tables.py: catálogo Code/Name genérico de tablas de usuario (mapeo USER_TABLES vacío, cada cliente completa el suyo). - routers/reports.py / templates/reports/stickers.html: fix de márgenes/alto de página del reporte de etiquetas. - mini-backend/test/ -> mini-backend/tools/ (rename organizativo). Limpieza de datos de Tagumedica que ya estaban en el commit base de main (anteriores a la branch cliente/tagumedica, no relacionados con el backport): - tools/sap-tagumedica/sl.http: eliminado (tenía CompanyDB y password reales). - tools/ApiGateway/Login.yml: CompanyDB/host/password reemplazados por placeholders. - templates/reports/stickers.html: título hardcodeado "TAGUMEDICA" reemplazado por "EMPRESA". - menu_permissions.json: reemplazado por un ejemplo demo (usuarios/módulos ficticios) en vez de emails reales. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
import logging
|
|
from typing import List, Optional
|
|
|
|
from core.sap import forward_to_sapb1
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def get_default_series(document_type: str) -> Optional[int]:
|
|
"""
|
|
Consulta a Service Layer (SeriesService_GetDefaultSeries) la serie activa
|
|
por defecto para un tipo de documento de SAP B1 (código BoObjectTypes,
|
|
ej. "1250000001" para Solicitud de Transferencia). Si la llamada falla o
|
|
la respuesta no trae el campo esperado, se registra en el log y se
|
|
devuelve None; quien llama decide cómo seguir sin una serie por defecto.
|
|
"""
|
|
try:
|
|
response = forward_to_sapb1(
|
|
method="POST",
|
|
endpoint_path="SeriesService_GetDefaultSeries",
|
|
json_data={"DocumentTypeParams": {"Document": document_type}},
|
|
)
|
|
except Exception as exc:
|
|
logger.warning(
|
|
f"No se pudo obtener la serie por defecto de SAP (documento {document_type}): {exc}"
|
|
)
|
|
return None
|
|
|
|
data = response.json()
|
|
series = data.get("Series")
|
|
if series is None:
|
|
logger.warning(
|
|
f"SeriesService_GetDefaultSeries no devolvió 'Series' (documento {document_type}): {data}"
|
|
)
|
|
return series
|
|
|
|
|
|
def get_active_series(document_type: str) -> List[dict]:
|
|
"""
|
|
Lista las series no bloqueadas de un tipo de documento de SAP B1, vía
|
|
SeriesService_GetDocumentSeries. Confirmado contra Service Layer real:
|
|
la respuesta viene en "value", cada item con "Series" (código) y
|
|
"Name"; "Locked" en "tYES"/"tNO".
|
|
"""
|
|
response = forward_to_sapb1(
|
|
method="POST",
|
|
endpoint_path="SeriesService_GetDocumentSeries",
|
|
json_data={"DocumentTypeParams": {"Document": document_type}},
|
|
)
|
|
series_list = response.json().get("value", [])
|
|
return [s for s in series_list if str(s.get("Locked", "")).lower() != "tyes"]
|