# Resumen - Mercantil Reclamos Demo

## Objetivo

Este proyecto implementa una demo operativa para Mercantil que permite atender reclamos por consumos rechazados o no decididos por motor de reglas desde un flujo conversacional de Cognigy.AI, con soporte para extraccion OCR real desde Cognigy Vision o texto OCR ya disponible, evaluacion de reglas, creacion de reclamos y escalamiento a un operador humano por NiCE CXone.

El flujo esta pensado para WhatsApp/NiCE, pero tambien puede probarse por el endpoint REST de Cognigy.

## Que hace la solucion

La solucion permite:

- Verificar identidad del usuario con un OTP demo.
- Recibir datos de un comprobante por texto OCR o adjunto.
- Extraer datos seguros del comprobante:
  - comercio
  - monto
  - moneda
  - fecha
  - hora
  - ultimos 4 digitos de la tarjeta
  - referencia enmascarada
  - autorizacion enmascarada
  - confianza de OCR
  - modo OCR
- Evaluar reglas del reclamo.
- Crear reclamos con formato `MC-YYYY-NNNNNN`.
- Marcar como `needs_human` los casos donde el motor no puede decidir.
- Construir un resumen seguro para el operador humano.
- Escalar a NiCE CXone con atributos personalizados sanitizados.
- Evitar guardar o exponer datos sensibles como PAN completo, CVV, PIN, OTP, contrasenas, URLs de comprobantes o texto OCR crudo.

## Componentes creados

### Backend demo local

Archivos principales:

- `src/server.js`
- `src/mercantilDemo.js`

Endpoints disponibles:

- `GET /health`
- `GET /ocr-test`
- `GET /ocr/:filename`
- `GET /uploads/:uploadId/:filename`
- `GET /bank/mercantil/demo/state`
- `POST /bank/mercantil/demo/reset`
- `POST /bank/mercantil/demo/uploads`
- `POST /bank/mercantil/demo/cognigy-rest-test`
- `POST /bank/mercantil/demo/identity/verify`
- `POST /bank/mercantil/demo/ticket/extract`
- `POST /bank/mercantil/demo/rules/evaluate`
- `POST /bank/mercantil/demo/claims`
- `GET /bank/mercantil/demo/claims/:claimId`
- `POST /bank/mercantil/demo/handover-summary`

El backend no usa dependencias externas. Corre con Node.js usando:

```bash
npm start
```

Por defecto escucha en:

```text
http://127.0.0.1:3001
```

### Cognigy.AI

Proyecto objetivo:

```text
Mercantil_Demo
projectId: 6a4e7963fac4430baeb323a4
```

AI Agent creado:

```text
Mercantil Reclamos Demo
aiAgentId: 6a4e832ad9543729fbb3d497
flowId: 6a4e832bfac4430baeb38e9e
flow referenceId: e9884b6c-e60f-4468-9463-0ed5ffb17a10
```

Endpoint REST:

```text
https://endpoint-trial.cognigy.ai/aa798a7a5373f8c7efd6b58b3ab0beeb7f48e2323684f642c70682df61f58e07
```

Endpoint NiCE CXone:

```text
https://endpoint-trial.cognigy.ai/96739c9fa340f1f997ca1cddbb0912b24164bf64264669aa39a3d928233ae507
```

### LLM y handover

Se importaron desde `Bancamiga_DEMO` hacia `Mercantil_Demo`:

- LLM `Banca LLM` con su connection.
- Handover provider NiCE demo con su connection.

No se importo el Flow completo de Bancamiga para evitar arrastrar marca, comportamiento o logica especifica de Bancamiga.

### Tools del AI Agent

Se crearon estas tools:

- `tool_verify_identity`
- `tool_extract_ticket_data`
- `tool_evaluate_claim_rules`
- `tool_create_claim`
- `tool_build_handover_summary`

Cada tool invoca el backend demo por HTTP mediante el tunel publico y guarda solo contexto seguro de sesion.

### Handover a operador humano

Se creo un nodo `handoverToAgent` dentro de la rama de `tool_build_handover_summary`.

El resumen enviado a NiCE usa atributos `mc_*` sanitizados:

- `mc_claimId`
- `mc_issueType`
- `mc_ruleDecision`
- `mc_identityVerified`
- `mc_ticketSummary`
- `mc_amount`
- `mc_currency`
- `mc_merchant`
- `mc_cardLast4`
- `mc_channel`
- `mc_ocrConfidence`

No se envia PAN completo, CVV, PIN, OTP, contrasenas, URLs del ticket ni texto OCR crudo.

## Como funciona el flujo

1. El cliente escribe por WhatsApp/NiCE o REST que quiere reclamar un consumo rechazado.
2. El AI Agent solicita o usa los datos disponibles:
   - OTP demo.
   - Texto del comprobante o adjunto.
   - Descripcion corta del problema.
3. `tool_verify_identity` verifica el OTP.
4. `tool_extract_ticket_data` extrae datos seguros del comprobante.
5. `tool_evaluate_claim_rules` evalua si el motor puede decidir.
6. Para reclamos rechazados/no decididos, la regla devuelve:

```text
decision: needs_human
ruleCode: RULE_ENGINE_UNABLE_TO_DECIDE
claimStatus: needs_human
```

7. `tool_create_claim` crea un reclamo con ID `MC-YYYY-NNNNNN`.
8. `tool_build_handover_summary` arma un resumen seguro.
9. El nodo de handover envia el caso al proveedor NiCE configurado.
10. El AI Agent responde al cliente con el numero de reclamo y confirma que un especialista continuara la gestion.

## OCR

La demo usa una estrategia hibrida:

- Cognigy AI Agent tiene habilitado procesamiento de imagenes para una demo rapida.
- El backend expone `POST /bank/mercantil/demo/ticket/extract` como adapter reemplazable.
- El backend tambien expone imagenes de prueba bajo `GET /ocr/:filename` para que Cognigy pueda descargar tickets locales desde el tunel publico.
- Mientras no existan APIs reales de Mercantil, QA, SAFE u OCR productivo, el adapter acepta texto OCR, resultados de vision del AI Agent y campos estructurados ya extraidos.
- Si llega una imagen/adjunto sin texto OCR ni campos extraidos, el backend no inventa datos demo: responde `OCR_UNREADABLE_IMAGE` para que el caso pase a revision manual.

Importante:

- Para pruebas automatizadas, es mas confiable enviar texto OCR.
- Si se prueba con imagenes, la URL debe ser real y alcanzable por Cognigy.
- En REST, el formato que activo OCR fue `data.inputAttachments` con objetos `{ "url", "name", "type": "image" }`.
- El adjunto por si solo no se considera OCR exitoso. Cognigy debe enviar texto OCR (`nativeOcrText`, `ocrText`, `ticketText`) o campos estructurados extraidos.
- Si hay adjunto, el mensaje conversacional del usuario no se usa como OCR; evita que frases como "quiero reclamar un cobro" generen una extraccion falsa.
- En WhatsApp, el endpoint usa `scripts/update_mercantil_whatsapp_transformer.js` para importar la media privada de Meta por `POST /bank/mercantil/demo/whatsapp-media/import`, publicarla temporalmente bajo `/uploads/...`, y convertirla en `data.inputAttachments` y `data.attachments`. Tambien guarda el adjunto por 10 minutos para reusarlo si el cliente envia el tipo de inconveniente en el siguiente mensaje. Si cambia el tunel, reaplicar con `node scripts/update_mercantil_whatsapp_transformer.js --backend-url <public-url>`.
- El ticket real de prueba usa el formato venezolano `MONTObs. 87.079,04`; el backend lo normaliza como `87079.04` y el agente lo muestra como monto seguro.
- No usar URLs ficticias como `https://example.com/ticket-demo.png`, porque Cognigy intenta procesar la imagen y puede devolver respuestas vacias o incompletas.

## Prueba con subida de imagen desde navegador

El Webchat oficial de Cognigy requiere un File Storage Provider real para subir archivos. Si el endpoint no tiene una conexion Azure/AWS/GCS valida, el usuario vera `Upload Failed`.

Para poder probar la experiencia de subir una imagen sin configurar storage cloud, el backend demo expone:

```text
https://locator-scan-fotos-continues.trycloudflare.com/ocr-test
```

Esta pagina permite seleccionar una imagen local, la guarda temporalmente en memoria del backend demo, la publica bajo `/uploads/...` y llama al REST endpoint de Cognigy con `data.inputAttachments`. La prueba verificada devolvio:

```text
Comercio: CECOSESOLA LARA EL C
Monto: 87.079,04 VES
Fecha: 04/07/2026
Hora: 11:15:06 a. m.
Tarjeta: ****9956
ID de reclamo: MC-2026-000001
```

## Seguridad y privacidad

Configuracion aplicada:

- `storeDataPayload=false`
- `maskLogging=true`
- `maskAnalytics=true`
- `maskIPAddress=true`

El backend y los transformers redaccionan o evitan exponer:

- PAN completo.
- CVV/CVC.
- PIN.
- OTP.
- claves o contrasenas.
- URLs de comprobantes.
- texto OCR crudo.

El resumen de handover contiene solo datos minimos y seguros.

## Scripts reutilizables

Scripts creados o usados para operaciones Cognigy:

- `scripts/cognigy_api_client.js`
- `scripts/get_cognigy_flow_node.js`
- `scripts/list_cognigy_flow_nodes.js`
- `scripts/get_cognigy_chart.js`
- `scripts/update_cognigy_ai_agent_job.js`
- `scripts/update_cognigy_endpoint_privacy.js`
- `scripts/create_or_update_mercantil_handover.js`
- `scripts/create_or_update_mercantil_nice_endpoint.js`
- `scripts/test_cognigy_nice_endpoint.js`

Estos scripts leen credenciales desde el entorno o configuracion local, pero no imprimen secretos.

## Pruebas implementadas

Archivos:

- `test/mercantilDemo.test.js`
- `test/server.test.js`

Cobertura principal:

- extraccion segura de comprobante
- caso sin adjunto ni texto OCR
- parser de ultimos 4 digitos de tarjeta
- regresion cuando referencia/autorizacion siguen a la tarjeta en la misma frase
- decision `needs_human`
- creacion de reclamo Mercantil
- resumen NiCE sanitizado
- OTP incorrecto
- endpoints HTTP principales del backend

Comandos:

```bash
npm test
npm run check
```

Resultado verificado:

```text
npm test: 9 tests passed
npm run check: passed
```

## URLs actuales de prueba

Backend por tunel Cloudflare:

```text
https://locator-scan-fotos-continues.trycloudflare.com
```

Health check:

```text
https://locator-scan-fotos-continues.trycloudflare.com/health
```

Estado demo:

```text
https://locator-scan-fotos-continues.trycloudflare.com/bank/mercantil/demo/state
```

Nota: el tunel Cloudflare es temporal. Si se reinicia, hay que actualizar las tools Cognigy con la nueva URL publica.

## Hallazgos documentados en AGENTS.md

Se agregaron entradas operativas sobre:

- NiCE requiere `verify-token` para pruebas directas.
- Crear endpoint `niceCXOne` por `POST /endpoints` puede fallar con 500; la via segura es importar un endpoint por paquete y retargetearlo.
- Process Images necesita URLs reales alcanzables.
- El handover debe validarse en el canal NiCE, no solo por REST.
- El parser OCR debe tomar los ultimos 4 digitos solo del segmento de tarjeta, no de referencia/autorizacion.
