Files
devolucion_proveedores/apps/api/README.md
T

138 lines
7.6 KiB
Markdown
Raw Normal View History

# 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`](../../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` (o `NODE_EXTRA_CA_CERTS`)
antes de usar `npm`.
## Puesta en marcha
Desde la raíz del monorepo (`devolucion-proveedores-web/`):
```bash
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` |
| PDF | `POST /planificaciones/:id/pdf` |
El detalle de cada ruta (parámetros y reglas) está en la tabla de [`CLAUDE.md`](../../CLAUDE.md#api-prefijo-api).
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).
```bash
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`](../../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.request` las 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 su `version`** en `sql-queries/sql-queries.definitions.ts`. El analizador SQL no admite
funciones como `FORMAT`; 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` (por
`isolatedModules` + `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`. |