Files
basic-erp/CLAUDE.md
T

73 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# basic-erp
ERP base para SAP Business One (Service Layer). Migración del `mini-erp` (React + FastAPI, en `/Users/george/Documents/Desarrollo/React/mini-erp`) a **NestJS + Angular**, ambos en TypeScript. Sirve de base para crear una rama por cliente.
Monorepo npm workspaces:
- `apps/api` — NestJS 12 (ESM): proxy hacia el Service Layer, login, sesión SAP compartida, permisos de menú (SQLite). Ver `apps/api/README.md`.
- `apps/web` — Angular 22 (standalone, zoneless, señales): componentes reutilizables estilo SAP Business One. Ver `apps/web/README.md`.
- `libs/sap-types` — tipos y utilidades compartidos por api y web (`MENU`, evaluador de permisos, tipos de auth/SL). Se compila en `postinstall`.
- `tools/` — mockup `oferta_venta.html` (ejemplo: tiene algunos campos no estándar, pero se conserva la idea).
## Reglas del proyecto base
- Solo campos **estándar** de SAP Business One. Ningún campo de usuario (`U_*`) salvo `U_WEB_USER` / `U_WEB_PASS` de `EmployeesInfo`, usados para el login web.
- Los formularios se construyen con componentes reutilizables y configuración declarativa; no se duplica markup por documento.
- Aspecto por variables CSS (temas). Tema por defecto: claro, con la paleta del mockup. Esquinas contenidas (`--radius*`, como SBO).
- La fila de un formulario es **etiqueta + uno o varios controles** (input, select, número, fecha, botón); la cabecera tiene **como máximo 2 columnas**.
- Impuesto de las líneas: `TaxCode` con el maestro `SalesTaxCodes` (verificado en el Service Layer; `VatGroups` no tiene `Rate`). Un cliente con `VatGroup` lo cambia en su rama.
## Criterios de la interfaz
Es un ERP, no una página de publicidad: **ligera y rápida**. Sin librerías de componentes (Material/PrimeNG), sin webfonts ni animaciones, componentes propios y densos (13 px), zoneless + `OnPush`, rutas con carga diferida, listas largas paginadas en el servidor (50 por página). Presupuesto del bundle inicial en `angular.json` (aviso 300 kB; hoy ~287 kB, 81 kB comprimido: `httpResource` aporta ~18 kB al chunk compartido; si hace falta recuperarlos, reemplazarlo por RxJS).
## Comandos
- `npm install` — **npm 11** (npm 10 falla al resolver las dependencias de Nest 12: `npx npm@11 install`); instala todo y compila `libs/sap-types`.
- `npm run dev:api` (`:3000`) · `npm run dev:web` (`:4200`, proxy `/api`) · `npm run build` · `npm test`.
- Backend contra SAP real (opt-in): `SAP_LIVE=1 npm run test:e2e -w apps/api`.
- Página de componentes **solo desarrollo**: `http://localhost:4200/dev/componentes` (toolbar, ventana, campos, pestañas, grilla y listas de valores con datos reales; no guarda nada).
## Decisiones tomadas (con su porqué)
- **Login web** con `U_WEB_USER`/`U_WEB_PASS` (se mantiene). Mismo mensaje para usuario inexistente y clave errónea; comparación en tiempo constante; 429 tras 5 fallos por usuario / 20 por IP; una sesión por usuario; timeout deslizante 30 min (el servidor informa `sessionTimeoutMinutes`); token `Authorization: Bearer`.
- **Usuario SAP compartido** (hoy Manager de pruebas; luego un usuario de licencia indirecta). Todo sale auditado con ese usuario.
- **Concurrencia hacia el Service Layer = 1** (`SAPB1_SL_MAX_CONCURRENCY`): medido en SAP10 (MSSQL, 32 GB), 12 peticiones tardan 0.6 s en serie y 7.5 s con 2 en paralelo. Un pool de sesiones no ayuda; la cola sí. Repetir la medición en cada cliente.
- **TLS:** `SAPB1_SL_CA_FILE` opcional (certificado autofirmado de SAP o CA de firewall); `VERIFY_SSL=true` por defecto y no se puede apagar en producción. `fortinet.cer` no sirve para SAP10: presenta su propio certificado autofirmado (`apps/api/certs/sap10.pem`, ignorado por git).
- **Proxy `/api/sl/:recurso`**: el frontend arma `$select/$filter/...`; el backend valida y ejecuta solo recursos registrados (`apps/api/src/sl/sl-resources.ts`), con permiso de menú y cabeceras `B1S-*` de lista blanca. Nunca registrar `EmployeesInfo` (tiene `U_WEB_PASS`). `InventoryRequests` no existe: es `InventoryTransferRequests`.
- **Permisos de menú** en SQLite (`SQLITE_PATH`), patrones `*`, `/ventas/*`, `/ventas/ordenes`; `ADMIN_WEB_USERS` garantiza el acceso total; no se puede quitar el último admin.
- **Listas de documentos:** más recientes primero (`DocEntry desc`), 50 por página, **Estado = Abierto por defecto** (como el mini-erp; cambiarlo es un `defaultValue`), filtro de fecha **siempre rango [desde – hasta]**, multi-selección con **chips**, búsqueda numérica por igualdad. **Sin filtro base `DocumentSubType`** (excluiría notas de débito, etc.). El PDF y los reportes se migran después vía API Gateway (otro servicio, con su propia cola y sesión).
- Reportes/PDF **no** se generan en la base; el botón PDF queda pendiente hasta migrar el API Gateway.
## Flujo de las pantallas de documento
Cada menú abre primero una **lista de los últimos documentos** (barra de filtros + búsqueda por columna); desde ahí se crea uno nuevo (`/…/nuevo`, formulario vacío) o se abre uno existente (`/…/:docEntry`, ver/editar; los cerrados/cancelados en solo lectura). Las pantallas se definen en `apps/web/src/app/features/documents/document-screens.ts` (17 documentos: ventas, compras, inventario). Las columnas de línea estándar están en `features/documents/line-columns.ts`.
## Cómo verificar cambios de interfaz
- Probar contra el SAP real con la extensión de Chrome (`list_connected_browsers` debe mostrar un navegador). Si no conecta, usar Chrome headless por CDP.
- **No escribir contraseñas en formularios**: obtener el token con `curl` a `/api/auth/login` (la clave de prueba se lee de `EmployeesInfo` solo para eso, nunca se imprime ni se guarda) e inyectar solo el token en `localStorage` (`erp_session`).
- Al terminar: cerrar la sesión de prueba (`POST /api/auth/logout`), borrar `erp_session`/`erp_theme` del navegador, cerrar la pestaña, apagar los servidores y borrar archivos temporales (token, `apps/api/data/`). No dejar páginas de demostración fuera de `/dev/componentes`.
- **Escrituras a SAP (POST/PATCH):** el usuario autorizó (2026-10-14) escribir en `SBODemoCL`, su ambiente propio de pruebas; ya se probaron crear/actualizar órdenes de venta y de compra, reemplazo de líneas y el 412 por conflicto. Documentos de prueba creados: orden de venta 315 (cerrada, copiada a la entrega 580) y orden de compra 2883 (cerrada, copiada a la recepción 299). Aun así, avisar antes de escribir en cualquier otra base.
- Los tests no detectan todo: el foco tras crear una línea (se pedía antes de que existiera la fila) solo falló en el navegador real.
## Estado y próximos pasos
Hecho (commits en `main`): monorepo · API (config, capa SAP con sesión compartida y cola, login, permisos SQLite, proxy `/api/sl`) · web (temas, login, layout con menú por permisos, `sbo-value-help`, campos y filas compuestas, listas con filtros, ventana/toolbar/pestañas/menús, grilla de líneas, `/dev/componentes`).
Pendiente, en orden:
1. **Paso 9 — formulario de documentos:** hecho para ventas y compras (`document-form.page`, `document-model.ts`: cargar, crear, actualizar con `If-Match`/412, navegación, totales con `SalesTaxCodes` (también en compras), solo lectura), probado con SAP simulado y contra `SBODemoCL` (leer, crear, actualizar, líneas, 412). Un código escrito a mano (socio, artículo, almacén, impuesto) se resuelve al salir del campo con `SlLookupApi` (mismo recurso y filtro base que la lista "…"); si no existe se avisa. "Copiar de/a" hecho (`document-copy.ts`: flujos estándar y `BaseType/BaseEntry/BaseLine`; probado: orden de compra 2883 → recepción 299, orden de venta 315 → entrega 580, ambas órdenes quedaron cerradas). Falta: botón PDF, fila del flete, toolbar de ancho completo, formularios de inventario y solicitudes de compra.
2. Pantallas de maestros (`Items`, `BusinessPartners`: Clientes/Proveedores, Artículos), hoy "no disponible".
3. ~~Pantalla web de permisos~~ — hecha (`/admin/permisos`).
4. Auditoría (`audit_log` en SQLite; hoy solo líneas `AUDIT` en el log) y `nestjs-cls` para el usuario en los logs.
5. Migrar reportes/PDF vía API Gateway (módulo y cola aparte; no registrar credenciales de los `tools/` del mini-erp, traen contraseñas en claro).
6. Revisar las vulnerabilidades de `npm audit` y definir una política para `U_WEB_PASS` (texto plano, claves cortas) antes de producción.
7. Docker/despliegue (HTTPS tras Fortinet; sesiones web en memoria ⇒ un solo proceso).
## Flujo de trabajo por cliente (branches)
1. `main` es la versión base/genérica, sin personalizaciones de cliente.
2. Cada cliente tiene su branch (`cliente/<nombre-cliente>`); ahí viven sus personalizaciones y fixes.
3. Los cambios de una branch de cliente no se mezclan con `main` ni con otro cliente, salvo backport genérico decidido explícitamente.
4. Antes de crear branches, mergear a `main`, o hacer merge/backport entre clientes, confirmar con el usuario. No hacer `git push` sin confirmación. Cada paso termina en un commit propio.