Confirmado por el usuario contra el Service Layer de HANA (DP_Stock y DP_EntradasAbiertas). Quedan por confirmar el paginado y los tipos de metadatos. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7.6 KiB
API — Devolución a Proveedores
Backend en NestJS 12 (ESM) de la aplicación Devolución a Proveedores para SAP Business One.
No tiene base de datos propia: habla con el Service Layer de SAP B1 en nombre del usuario que
inició sesión, y guarda cada ejecución en el UDO LIB_ODEV.
La documentación general del proyecto (decisiones, flujo, estado) está en
../../CLAUDE.md. Este archivo cubre solo cómo ejecutar y mantener la API.
Requisitos
- Node 22 LTS o superior.
- Acceso de red al Service Layer de SAP B1 (por defecto
https://servidor:50000/b1s/v1). - Red con Fortinet (inspección SSL): exportar
NODE_OPTIONS=--use-system-ca(oNODE_EXTRA_CA_CERTS) antes de usarnpm.
Puesta en marcha
Desde la raíz del monorepo (devolucion-proveedores-web/):
npm install
cp apps/api/.env.example apps/api/.env # y completar los valores
npm run dev:api # compila @dp/shared y levanta la API en :3000
Variables de .env
| Variable | Descripción |
|---|---|
PORT |
Puerto de la API (3000). |
WEB_ORIGIN |
Origen del frontend para CORS. En desarrollo ng serve usa proxy y no hace falta. |
SL_URL |
URL del Service Layer, con /b1s/v1 al final. |
SL_COMPANY_DB |
Base de la sociedad (CompanyDB del Login). |
SL_REJECT_UNAUTHORIZED |
false si el Service Layer usa un certificado autofirmado. |
DB_TYPE |
HANA (producción) o MSSQL (pruebas). Elige la variante de cada consulta SQL. |
COOKIE_SECURE |
true solo cuando la API se publica por HTTPS. |
HTTPS_PFX_PATH / HTTPS_PFX_PASSPHRASE |
Solo producción: certificado .pfx y su clave. La API escucha por HTTPS. |
HTTPS_KEY_PATH / HTTPS_CERT_PATH |
Alternativa al .pfx: clave privada y certificado en PEM (no mezclar con el .pfx). |
HTTP_REDIRECT_PORT |
Con HTTPS: puerto HTTP que redirige (301) al HTTPS, normalmente 80. |
WEB_DIST_DIR |
Carpeta con la web compilada. Por defecto apps/web/dist/web/browser si existe. |
El usuario y la contraseña de SAP no se configuran aquí: se escriben en la pantalla de login y se
usan para el Login del Service Layer. La API reinicia sin conservar sesiones.
Scripts
Se ejecutan con npm run <script> -w api desde la raíz, o directamente desde apps/api.
| Script | Qué hace |
|---|---|
start:dev |
Modo watch (recompila y reinicia; se pierden las sesiones en cada reinicio). |
build / start:prod |
Compila a dist/ y ejecuta node dist/main. |
test |
Tests unitarios (Vitest). |
test:e2e |
Tests e2e (test/). |
test:cov |
Cobertura. |
lint |
oxlint --type-aware src/ test/. |
Endpoints (prefijo /api)
Todos exigen sesión (cookie dp_sid) salvo /health, /auth/info, /auth/login y /auth/logout.
| Área | Rutas |
|---|---|
| Salud y sesión | GET /health · GET /auth/info · POST /auth/login · POST /auth/logout · GET /auth/me |
| Metadatos | GET /metadata/status · POST /metadata/rebuild |
| Catálogos | GET /catalogos · GET /catalogos/almacenes |
| Planificaciones | GET /planificaciones (paginado, con filtros) · GET /planificaciones/abierta · GET /planificaciones/:id |
POST /planificaciones/pegar · POST /planificaciones · PATCH /planificaciones/:id/cabecera · PATCH /planificaciones/:id/lineas/:lineId |
|
POST /planificaciones/:id/devoluciones · POST /planificaciones/:id/reprocesar · POST /planificaciones/:id/cerrar |
|
POST /planificaciones/:id/pdf |
El detalle de cada ruta (parámetros y reglas) está en la tabla de CLAUDE.md.
Ejemplo del listado: GET /api/planificaciones?status=C&whsCode=01&desde=2026-10-01&pagina=2&tamano=20.
Producción
En producción la API sirve también la web compilada (si existe apps/web/dist/web/browser): todo queda
en el mismo origen y en un solo puerto. Las rutas de Angular (sin extensión y fuera de /api) devuelven
index.html; los archivos con hash se cachean un año; se agregan cabeceras de seguridad (y HSTS con HTTPS).
npm run publicar # desde la raíz: arma release/devolucion-proveedores/
Instalación en Windows (servicio con NSSM, HTTPS, firewall, actualizaciones): ../../deploy/windows/DEPLOY.md.
Logs: la API no escribe archivos; usa el Logger de Nest por consola. Como servicio, NSSM captura
esa salida y la rota. Con NO_COLOR=1 el log sale sin códigos de color.
Estructura
src/
├── config/ lectura y validación del .env
├── service-layer/ ServiceLayerClient (axios) y SessionStore (en memoria)
├── auth/ login/logout/me, SessionGuard global y @Public()
├── sql-queries/ consultas guardadas (SQLQueries) con variantes HANA y MSSQL
├── catalogos/ almacenes, series y valores válidos de los UDF
├── planificaciones/ FIFO, UDO LIB_ODEV, Devoluciones, reprocesar y listado
├── pdf/ SOAP de BES (Consulta_TXTDTE) y unión de PDF
├── metadata/ definiciones JSON de tablas/campos/UDO y su reconstrucción
├── health/
├── http-exception.logger.ts registra en el log todo error 4xx/5xx
├── web-estatico.ts sirve la web compilada, fallback a index.html y cabeceras de seguridad
└── https.ts lee el certificado y redirige HTTP → HTTPS
La lógica de dominio pura (FIFO, consolidación por proveedor, parseo del texto de Excel) vive en
libs/shared (@dp/shared), que se consume compilada (dist/): tras cambiarla,
npm run build:shared.
Cosas que conviene saber
- Una sesión del Service Layer no admite peticiones simultáneas: las procesa en serie y cada una
espera unos 7 s.
ServiceLayerClient.requestlas encola por sesión; no uses otro cliente HTTP para hablar con SAP. Una petición que tarde más de 2 s queda avisada en el log. - Consultas SQL: se guardan en SAP como
SQLQueries(DP_Stock,DP_EntradasAbiertas) y la API las crea o actualiza sola. SAP reescribe el SQL al guardarlo, por lo que al modificar una consulta hay que subir suversionensql-queries/sql-queries.definitions.ts. El analizador SQL no admite funciones comoFORMAT; los parámetros van entre comillas simples. - Credenciales del web service DTE (
@DTE_CONFC): se leen en cada descarga de PDF, no se registran en el log y no se devuelven al navegador. - Metadatos: la fuente de verdad son los JSON de
src/metadata/definitions/. Reconstruir crea lo que falta; borrar y recrear un campo solo ocurre con autorización explícita. - Los tipos que aparecen en firmas con decoradores se importan con
import type(porisolatedModules+emitDecoratorMetadata); los DTO, que son clases, se importan como valor. - HANA: las variantes HANA de las consultas ya se probaron contra el Service Layer de HANA y funcionan. Falta confirmar el paginado del listado y los tipos de los metadatos.
Diagnóstico rápido
| Síntoma | Causa probable |
|---|---|
No se pudo conectar con el Service Layer (EHOSTUNREACH) |
Proceso de la API con un estado de red viejo (cambio de red o VPN). Reiniciarla. |
401 Debe iniciar sesión tras tocar el código |
La API se reinició y perdió las sesiones. Volver a iniciar sesión. |
| Respuestas de 20-40 s | Peticiones en paralelo sobre una misma sesión (ver arriba). Mirar los avisos Petición lenta del log. |
Invalid SQL syntax ... Cannot support this function |
El analizador SQL del Service Layer rechazó una función en una consulta guardada. |
SELF_SIGNED_CERT_IN_CHAIN al instalar |
Falta NODE_OPTIONS=--use-system-ca o NODE_EXTRA_CA_CERTS. |