- Inmovilizar Lotes: selección múltiple de almacén origen con cantidad editable, genera Solicitud de Transferencia hacia un almacén de inmovilizados. - Liberar Lotes: inversa de la anterior, con almacenes/campos de usuario propios (U_SIS_MOVINV, U_EXX_TIPOOPER, U_SIS_TIPDESP, U_SIS_MOTALM). - Confirmar Liberación Lote: lista las Solicitudes abiertas pendientes (U_SIS_MOTALM=108) y, por cada lote, resuelve contra el historial de transferencias en HANA a qué almacén(es) debe volver, repartiendo la cantidad entre orígenes; permite editar cantidad, almacén destino, y agregar/quitar líneas antes de actualizar la Solicitud en SAP. - Backend: nuevo endpoint /api/batch/lot-source-warehouse (HANA) para resolver el origen histórico de un lote; endpoint genérico /api/Catalogs/UdfValidValues (Service Layer) para valores válidos de un UDF; PATCH genérico ahora reenvía cualquier header B1S-* que mande el frontend en vez de decidirlos en el backend. - Registro de rutas, menú y permisos para las tres pantallas nuevas. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
42 lines
1.6 KiB
Python
42 lines
1.6 KiB
Python
from typing import Dict
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
|
|
from core.sap import forward_to_sapb1
|
|
|
|
router = APIRouter(tags=["Tablas de Usuario"])
|
|
|
|
# Mapea un nombre amigable de tabla de usuario (@...) a su nombre real de
|
|
# entidad en Service Layer. La convención de nombre no es uniforme entre
|
|
# tablas (confirmado contra el SAP real de tagumedica: @SIS_MOVINV se expone
|
|
# como "U_SIS_MOVINV", pero @EXX_TIPOOPER se expone como "EXX_TIPOOPER", sin
|
|
# prefijo "U_"), así que se centraliza acá en vez de que cada módulo tenga
|
|
# que adivinar o repetir el nombre de endpoint real.
|
|
USER_TABLES: Dict[str, str] = {
|
|
"MovimientoInventario": "U_SIS_MOVINV",
|
|
"TipoOperacion": "EXX_TIPOOPER",
|
|
}
|
|
|
|
|
|
@router.get("/api/UserTables/{name}")
|
|
async def get_user_table(name: str):
|
|
"""
|
|
Catálogo Code/Name de una tabla de usuario de SAP B1, identificada por un
|
|
nombre amigable (ver USER_TABLES) en vez del nombre real de tabla/entidad.
|
|
Pensado para reutilizarse en cualquier formulario que necesite un select
|
|
cargado desde una tabla de usuario de este tipo.
|
|
"""
|
|
entity = USER_TABLES.get(name)
|
|
if not entity:
|
|
raise HTTPException(status_code=404, detail=f"Tabla de usuario '{name}' no está registrada")
|
|
|
|
# Service Layer limita el tamaño de página por defecto (server-side, no
|
|
# depende solo de "$top") salvo que se indique explícitamente el header
|
|
# B1S-PageSize; sin él, catálogos con más de ~20 filas quedaban truncados.
|
|
return forward_to_sapb1(
|
|
method="GET",
|
|
endpoint_path=entity,
|
|
params={"$select": "Code,Name", "$top": 200},
|
|
extra_headers={"B1S-PageSize": "200"},
|
|
).json()
|