# FRASA API Gateway Backend Node.js que conecta las 3 apps web del ecosistema FRASA (cotizador :3001, alta-clientes :3002, cobranza :3003) con Monday.com y da persistencia real (Prisma + SQLite en dev, Postgres 16 en prod). ## Stack Express 5 · TypeScript estricto · zod · Prisma (SQLite dev) · multer 2 · vitest ## Cómo correr en dev ```bash npm install npx prisma migrate dev # crea/actualiza prisma/dev.db npm run dev # tsx watch en :3000 ``` Las credenciales de Monday y los board IDs se leen del `.env` raíz del ecosistema (`../.env`); el servicio también acepta un `.env` local (Prisma CLI lo requiere para `DATABASE_URL`). El token NUNCA se imprime en logs. ## Tests ```bash npm test # vitest: fórmulas del cotizador (fixture U-101), cobranza, monday.service con fetch mockeado ``` ## Endpoints (prefijo /api) | Método | Ruta | Descripción | |---|---|---| | GET | `/api/health` | `{status, monday: 'up'|'down'}` | | GET | `/api/unidades` | Inventario desde Monday (`?disponibles=true` filtra) | | GET | `/api/unidades/:codigo` | Una unidad (404 si no existe) | | POST | `/api/cotizaciones` | Calcula propuesta (server-side), persiste y crea Oportunidad en Monday | | GET | `/api/cotizaciones` · `/api/cotizaciones/:id` | Consulta | | POST | `/api/clientes` | Alta de cliente: persiste payload completo, crea Contacto y Apartado en Monday | | GET | `/api/clientes/:id` | Cliente con documentos | | POST | `/api/clientes/:id/documentos` | Multipart (campo `archivos`, máx 10, pdf/jpg/png, 10 MB) | | GET | `/api/clientes/:id/documentos` | Lista documentos | | POST | `/api/planes` | Crea plan de pago con calendario generado | | GET | `/api/planes` · `/api/planes/:id` | Con saldo/status calculados | | GET | `/api/planes/cobranza-del-dia` | Urgencias de cobranza (`?diasAnticipacion=7`) | | POST | `/api/planes/:id/abonos` | Aplica abono (estricto al centavo) | | POST | `/api/planes/:id/notas` | Agrega nota a la bitácora | | POST | `/api/planes/:id/cancelar` | Cancela el plan | | POST | `/api/webhooks/monday` | Handshake `challenge` + log de eventos | ## Notas de arquitectura - **Monday service** (`src/services/monday.service.ts`): resuelve column IDs por TÍTULO en runtime (los slugs autogenerados nunca se hardcodean), paginación por cursor, retry con backoff ante 429/complejidad, `column_values` siempre via `JSON.stringify` en variables, cache de unidades 5 min con invalidación tras escrituras. - **Cálculos del cotizador** (`src/services/cotizacion.service.ts`): port exacto del Excel de producción (quirks incluidos: Infonavit usa precio de lista en mensualidades; enganche bancario sobre precio lista). NO corregir. - **Cobranza** (`src/services/cobranza.service.ts`): espejo de la lógica del frontend; los controllers mapean Prisma → dominio, ejecutan las funciones puras y persisten. - **Dinero como `Float`** por ahora — TODO prod: `Decimal` en Postgres. - **Webhooks de Monday no están firmados** → el payload se trata como no confiable; antes de actuar, re-consultar vía API (por ahora solo se loggea). ## TODO producción (pendientes deliberados) - Auth (JWT ya hay vars en .env), helmet, rate-limit — es red interna por ahora. - Postgres 16 (`provider = "postgresql"`, `Decimal`), Redis para cache de unidades. - CORS restringido a los orígenes de las apps. ## Docker ```bash docker build -t frasa-api-gateway . docker run -p 3000:3000 --env-file ../.env frasa-api-gateway # El arranque corre `prisma migrate deploy` antes de levantar el server ```