# Plan ADAPTADO — Conciliación Bancaria con IA (módulo independiente)

> Adaptación **anclada al código real** de `plan-conciliacion-bancaria-ia-independiente.md`.
> El plan original asume "solo extraer y reutilizar el motor de Tesorería"; la exploración del
> código mostró que eso **sobrestima la reutilización**: el auto-match actual es *línea-de-extracto
> vs `tes_movimientos` (DB)*, acoplado a escribir movimientos/saldos/contabilidad — **no existe**
> un motor puro file-vs-file, ni parser DOCX/TXT, ni score de confianza, ni generación de Excel.
> Este documento reordena el trabajo para minimizar riesgo.

## Decisiones fijadas (confirmadas con el usuario · 2026-07-26)

1. **Standalone primero, unificar después.** Se construye el módulo nuevo con lógica **propia y
   pura** (portando prompt IA + `parseCsv` + heurística de scoring a utilidades sin efectos
   secundarios). **`TesConciliacionService` NO se toca en v1.** La unificación "un solo motor
   compartido" (Fase 3 del plan original) se difiere a un refactor posterior, ya con el motor
   probado por el módulo nuevo. → invierte el orden del plan original (que la ponía como
   prerequisito) para no meter regresión en un módulo en producción.
2. **PDF en `generador-pdf` (template nuevo) + Excel local con `xlsx`.** El PDF sigue el patrón
   existente (POST a `envs.apiGeneradorPDF`, devuelve `pdf_base64`). El Excel se genera en el
   backend con la lib `xlsx@0.18.5` **ya instalada** (soporta escritura). Sin dependencias nuevas.
3. **Formatos MVP: PDF + CSV/XLSX estructurado.** Se arranca con lo que ya funciona gratis
   (`pdf-parse`+IA y detección de columnas). DOCX (`mammoth`), TXT heurístico y fallback-IA para
   archivos no estructurados quedan para la Fase 2. Sin deps nuevas en el MVP.

Decisiones del plan original que se mantienen sin cambio: módulo independiente (#1), cuenta como
texto libre (#2), una cuenta por sesión (#3), score de confianza por línea (#5, se implementa en el
módulo nuevo), estados de sesión (#7), persistencia completa de la sesión (#9), permisos propios
`CONC_IA_*` (#10), multiempresa por `empresa_id` (#11).

---

## Mapa de reutilización real (qué se copia y de dónde)

| Pieza | Fuente real | Cómo se reutiliza en v1 |
|---|---|---|
| Prompt IA + pipeline pdf-parse | `tes-conciliacion.service.ts` → `extraerTransaccionesConIA` (L601-678), `importarExtractoPdf` (L517-599) | **Portar** a `ArchivoMovimientosParserService` del módulo nuevo, agregando `confianza` por línea al prompt. Consume `AiProviderService.completar(empresaId, USER, SYSTEM)`. |
| Parser CSV multi-banco | `tes-conciliacion.service.ts` → `parseCsv` (L698-772), `parseDate` (L774-782) | **Portar** tal cual (columnas de Continental/BNF/Itaú/Sudameris, columna única con signo). Se le suma lectura XLSX con `xlsx` → mismas cabeceras. |
| Heurística de matching | `tes-conciliacion.service.ts` → `findBestMovimiento` (L834-884), `scoreCandidato` (L886-894) | **Portar la lógica de scoring** (monto+tipo+fecha+ref/desc) a una función **pura** `autoMatch(A[], B[], opts)` — hoy no existe en forma pura, hay que escribirla (~40 líneas) reusando el criterio. |
| Generación PDF | `contabilidad-conciliacion.service.ts` → `generarPDFReporte` (L1263-1312) | **Mismo patrón**: POST a `${envs.apiGeneradorPDF}/api/conciliacion-bancaria-ia/generate-pdf`, recibe `{status, pdf_base64}`. Requiere **template nuevo en el repo `generador-pdf`**. |
| Seed de módulo/privilegios | `seguridad/seeds/seguridad.seed-data.ts` (estructura módulo→submódulos→privilegios `{codigo,desc,recurso,accion}`) | Agregar bloque `CONCILIACION_BANCARIA_IA` siguiendo el patrón. |
| AI provider | `ai-dashboard/ai-provider/ai-provider.service.ts` (`.completar()`) | Se inyecta directo, sin cambios. |

**Nada de esto toca `TesConciliacionService`.** Las funciones portadas viven en el módulo nuevo;
la deduplicación real con Tesorería es un refactor posterior (ver Fase 6).

---

## Modelo de datos (igual al plan original — 3 tablas nuevas)

`conc_ia_sesiones`, `conc_ia_movimientos` (incluye `confianza_ia`), `conc_ia_matches`.
Sin tabla de "resultado": el resumen se calcula en vivo desde movimientos + matches.
Migración Prisma nueva `*_conc_ia_bancaria/migration.sql` + modelos en `schema.prisma`.
Estados de sesión: `CREADA → ARCHIVOS_CARGADOS → INTERPRETADA → CONCILIANDO → FINALIZADA`.

---

## Arquitectura del módulo nuevo (`src/conciliacion-bancaria-ia/`)

```
conciliacion-bancaria-ia.module.ts
conciliacion-bancaria-ia.controller.ts     → endpoints /conciliacion-bancaria-ia/*
conciliacion-bancaria-ia.service.ts        → orquestación de sesión
lib/
  archivo-movimientos.parser.ts            → interpretar(buffer, mime) → MovimientoNormalizado[]
                                             (PDF→pdf-parse+IA · CSV/XLSX→columnas · [F2] DOCX/TXT/IA)
  match-engine.ts                          → autoMatch(A[], B[], opts): PURA, sin DB
  resultado.builder.ts                     → arma resumen/conciliadas/pendientes en vivo
  excel-resultado.ts                       → genera Buffer XLSX con `xlsx`
registry.seed.ts / seed en seguridad.seed-data.ts → módulo + privilegios CONC_IA_*
dto/*.dto.ts
```

Endpoints (idénticos al plan original, base `/conciliacion-bancaria-ia`, privilegios `CONC_IA_*`):
`POST /sesiones`, `GET /sesiones`, `POST /sesiones/:id/archivo-propio`,
`POST /sesiones/:id/archivo-banco`, `PATCH /sesiones/:id/movimiento/:movId`,
`POST /sesiones/:id/conciliar-auto`, `POST /sesiones/:id/match-manual`,
`DELETE /sesiones/:id/match/:matchId`, `PATCH .../movimiento/:movId/sin-correspondencia`,
`GET /sesiones/:id/resultado`, `GET /sesiones/:id/resultado/pdf`,
`GET /sesiones/:id/resultado/excel`, `DELETE /sesiones/:id`.

---

## Fases (reordenadas por riesgo)

### Fase 1 — Base standalone (sin IA, sin refactor de Tesorería)
- Migración + 3 tablas + modelos Prisma.
- CRUD de sesión + endpoints básicos + módulo/privilegios `CONC_IA_*` en el seed.
- `archivo-movimientos.parser.ts`: **solo estructurado** — CSV (portar `parseCsv`) + XLSX (`xlsx`).
- **Entregable**: crear sesión, subir dos CSV/Excel bien formados de ambos lados, ver líneas cargadas.

### Fase 2 — Interpretación IA (parser universal)
- Portar el prompt IA + `pdf-parse` desde Tesorería → soporta PDF libre en ambos lados.
- Agregar `confianza` por línea al prompt; preview editable con aviso visual en baja confianza.
- Sumar DOCX (`mammoth` — **dep nueva**) y TXT (heurística + fallback IA).
- **Entregable**: subir Word/TXT/PDF libres y que la IA los interprete.

### Fase 3 — Motor de conciliación (puro, propio)
- `match-engine.ts`: `autoMatch(A[], B[], {toleranciaDias, toleranciaMonto})` **pura**, portando el
  scoring de `findBestMovimiento`/`scoreCandidato`. Débito↔egreso / crédito↔ingreso, fecha ±N días.
- Endpoints conciliar-auto, match-manual, desconciliar, marcar sin correspondencia.
- **Entregable**: auto-match file-vs-file funcionando con métricas comparables a Tesorería.

### Fase 4 — Documento de resultado
- PDF: template nuevo en repo `generador-pdf` + `generarPDF()` (patrón `generarPDFReporte`).
- Excel: `excel-resultado.ts` con `xlsx` — hojas Conciliadas / Pendientes(propio) / Pendientes(banco) / Resumen.
- **Entregable**: al finalizar, se descarga PDF + Excel listos para entregar a un tercero.

### Fase 5 — Frontend (novasispy-erp)
- Ruta `/conciliacion-bancaria-ia` + item de menú (módulo propio), UI siguiendo `docs/ui-standards.md`
  y `_standards` (ScreenGuia, ListToolbar, EmptyState, MonedaInput, `fmtMoneda`, `fmtFecha*`).
- Wizard 3 pasos (datos → subir ambos archivos con preview editable → conciliar + resultado con pestañas).
- Historial de sesiones, reabrir/reexportar sin volver a subir.

### Fase 6 — Unificación con Tesorería (refactor diferido, opcional)
- Recién acá se extrae el motor/parser a un módulo compartido y se apunta `TesConciliacionService`
  a él, eliminando la duplicación. Se hace con el motor ya probado por el módulo nuevo y con tests
  de regresión sobre Tesorería. **No bloquea nada de las Fases 1-5.**

### Fase 7 — Integración contable / tesorería del asiento (opcional, diferida) — DISEÑO
> Decidido 2026-08-16: **no implementar todavía**; queda documentado para más adelante.
> Hoy el asiento sugerido (`lib/hallazgos.builder.ts → analizarResultado.asientoSugerido`) es
> solo **referencia** (nombres de cuenta genéricos, en pantalla + PDF/Excel). El módulo debe
> seguir funcionando **standalone** para empresas que solo usan Conciliación.

**Principio:** el asiento sugerido es el artefacto universal (para todos); postear es una **capa
opcional** que se activa solo si la empresa tiene el módulo, sin romper a quien no lo usa.

**7a — Postear asiento a Contabilidad (empresas con módulo CONTABILIDAD):**
- Botón frontend **"Registrar en Contabilidad"** en el resultado, visible solo si la empresa tiene
  el módulo (front: `usePermission`/`PermisosStore`; back: guard `tieneModuloContabilidad(empresaId)`
  igual que `contabilidad/services/integracion.service.ts`).
- Backend: nuevo método que arma las líneas resolviendo cuentas vía
  `MapeoCuentasService.getCuentaPorConcepto(empresaId, concepto)` y crea el asiento con
  `AsientosService.crear(empresaId, usuarioId, dto)` (valida partida doble + período abierto).
- **Conceptos de mapeo (ya existen en `plan-cuentas-paraguay.seed.ts`):** `GASTOS_BANCARIOS`
  (6.3.1.02, comisiones/diferencias), `INTERESES_BANCARIOS` (6.3.1.01), `GASTOS_SEGUROS`
  (6.1.2.07), `BANCO_PYG`/`BANCOS_DEFAULT` (Haber). **Falta agregar concepto `ITF`** (hoy caería a
  `GASTOS_BANCARIOS`); mapear en el catálogo + pantalla Mapeo de Cuentas.
- Si falta un mapeo, error accionable que linkea a **Contabilidad → Mapeo de Cuentas**.
- Persistir el `asiento_id` generado en la sesión (`conc_ia_sesiones`) para no re-postear y poder verlo.
- `hallazgos.builder` debe exponer, por línea del asiento, el **concepto** (no solo el nombre), para
  que el posteo resuelva la cuenta real.

**7b — Movimiento en Tesorería (empresas con módulo TESORERIA):**
- Al "Registrar" un cargo del banco (comisión/ITF/débito), además crear el `tes_movimiento` real en
  la cuenta, si la empresa usa Tesorería (guard análogo). Mayor acople; posterior a 7a.

**Matriz de comportamiento por perfil de empresa:**
| Perfil | Asiento | Tesorería |
|---|---|---|
| Solo Conciliación | Sugerencia (referencia, sin postear) | — |
| + Contabilidad | Botón "Registrar en Contabilidad" (postea asiento real) | — |
| + Tesorería | idem | Crea `tes_movimiento` al registrar cargos |

---

## Archivos a crear / tocar (rutas reales)

**Backend `novasispy-backend-api`**
- `prisma/migrations/*_conc_ia_bancaria/migration.sql` (nuevo) + `prisma/schema.prisma` (3 modelos).
- `src/conciliacion-bancaria-ia/` (módulo completo, ver arriba).
- `src/seguridad/seeds/seguridad.seed-data.ts` (bloque módulo `CONCILIACION_BANCARIA_IA` + privilegios).
- `src/app.module.ts` (registrar `ConciliacionBancariaIaModule`).
- `package.json` (solo Fase 2: agregar `mammoth`). `xlsx` ya está.

**Repo externo `generador-pdf`** (solo Fase 4)
- Endpoint + template `POST /api/conciliacion-bancaria-ia/generate-pdf`.

**Frontend `novasispy-erp`** (Fase 5)
- `src/api/conciliacion-bancaria-ia.service.js` + hook en `tanstack/`.
- `src/pages/ConciliacionBancariaIa.jsx` + componentes (wizard, preview, resultado).
- `src/routers/routes.jsx` (ruta lazy) + `src/utils/dataEstatica.jsx` (item de menú).

---

## Verificación (end-to-end)

1. Migración aplicada: 3 tablas existen; `conc_ia_movimientos.confianza_ia` presente.
2. Crear sesión → subir 2 CSV/Excel estructurados (propio + banco) → líneas cargadas (Fase 1).
3. Subir PDF/Word libres → IA interpreta, líneas de baja confianza marcadas y editables (Fase 2).
4. `conciliar-auto` → matches file-vs-file por monto+tipo+fecha±N; pendientes de cada lado separados.
5. Match manual / desconciliar / marcar sin correspondencia funcionan y recalculan el resumen.
6. Descargar PDF (generador-pdf) + Excel (xlsx local) con las 4 secciones.
7. Reabrir sesión finalizada y reexportar sin volver a subir archivos.
8. `TesConciliacionService` intacto: sus tests (`tes-conciliacion.service.spec.ts`) siguen verdes.
9. `npx tsc --noEmit` backend limpio; eslint de archivos frontend sin errores nuevos.

## Limitaciones asumidas (MVP)
- Fase 1 solo estructurado (CSV/XLSX con columnas reconocibles) + PDF-IA; DOCX/TXT en Fase 2.
- Saldos inicial/final son informativos (no hay `tes_cuentas` de referencia en modo standalone).
- Duplicación temporal de lógica con Tesorería, resuelta recién en Fase 6 (aceptado a cambio de
  no meter riesgo en producción).
