Backport de mejoras genéricas de backend (desde cliente/tagumedica) + limpieza de datos de cliente en main

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>
This commit is contained in:
GeorgeandClaude Sonnet 5 committed 2026-09-28 14:18:42 -05:00
1 parent b2fb4e2d0a
commit fef21898f9
30 files changed
+462 -112

No files matched your search

+11 -1
View File
@@ -113,11 +113,21 @@ def make_crud_router(
@router.patch(f"/api/{resource}/{{key}}", status_code=204, name=f"update_{resource}")
async def update_resource(key: str, request: Request):
data = await request.json()
# Las cabeceras de Service Layer (B1S-*) las decide quien llama
# (el frontend), no el backend: cualquier header "B1S-*" que
# venga en el request se reenvía tal cual a SAP. Ej.:
# B1S-ReplaceCollectionsOnPatch para reemplazar una colección
# hija (StockTransferLines) en vez de mergearla por LineNum,
# necesario solo cuando ese PATCH agrega o quita líneas.
headers = dict(patch_headers or {})
headers.update(
{k: v for k, v in request.headers.items() if k.lower().startswith("b1s-")}
)
forward_to_sapb1(
method="PATCH",
endpoint_path=key_expr(key),
json_data=data,
extra_headers=patch_headers,
extra_headers=headers or None,
)
return router