# Como Reproducir las Pruebas del Demo Mercantil

Este documento explica como reproducir las pruebas ejecutadas para el backend Mercantil y el agente MIA en Cognigy.

Ejecutar todo desde:

```bash
cd /home/dunmagno/cognigy-merncantil
```

## 1. Preparar Variables

Usa la URL Cloudflare que este activa en ese momento.

La URL usada en la ultima validacion fue:

```bash
export BASE_URL="https://protest-affiliation-kirk-purse.trycloudflare.com"
```

Configura la API key del backend en tu terminal. No la guardes en este archivo:

```bash
export MERCANTIL_DEMO_API_KEY="<x-api-key-del-backend>"
```

Endpoint REST de Cognigy:

```bash
export COGNIGY_REST_ENDPOINT="https://endpoint-trial.cognigy.ai/aa798a7a5373f8c7efd6b58b3ab0beeb7f48e2323684f642c70682df61f58e07"
```

## 2. Levantar el Backend

Terminal 1:

```bash
HOST=127.0.0.1 PORT=3001 npm start
```

Esperado:

```text
mercantil-demo-backend listening on http://127.0.0.1:3001
```

## 3. Levantar Cloudflare Tunnel

Terminal 2:

```bash
CLOUDFLARED_EDGE_IP_VERSION=4 ./scripts/start_mercantil_demo_services.sh
```

Cuando aparezca una URL `https://...trycloudflare.com`, actualiza `BASE_URL`:

```bash
export BASE_URL="https://TU-URL.trycloudflare.com"
```

Espera este log antes de probar:

```text
Registered tunnel connection
```

Valida:

```bash
curl -sS "$BASE_URL/health"
```

Esperado:

```json
{"status":"ok","service":"mercantil-demo-backend"}
```

Deja esta terminal encendida.

## 4. Pruebas Automaticas Locales

Terminal 3:

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

Esperado:

```text
npm test: all tests pass
npm run check: no syntax errors
```

En la ultima corrida:

```text
19 tests passed
```

## 5. Prueba Integral del Backend Publico

```bash
node scripts/verify_mercantil_demo_services.js --base-url "$BASE_URL"
```

Esperado:

```json
{
  "ok": true
}
```

Este script valida:

- `GET /health`
- `GET /ocr-test`
- `GET /ocr/test_para_OCR.jpeg`
- `POST /auth/enroll`
- `GET /bank/mercantil/demo/users/demo-user-001/cards`
- `POST /bank/mercantil/demo/ticket/extract`
- `POST /bank/mercantil/demo/rules/evaluate`

## 6. Probar Rutas REST Manualmente

### 6.1 Health

```bash
curl -sS "$BASE_URL/health"
```

Esperado:

```json
{"status":"ok","service":"mercantil-demo-backend"}
```

### 6.2 Listar Tarjetas

```bash
curl -sS "$BASE_URL/bank/mercantil/demo/users/demo-user-001/cards" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}"
```

Esperado:

```text
****4821 active
****9134 active
```

### 6.3 Extraer Datos del Ticket OCR Real o Texto OCR

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/ticket/extract" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data "{\"nativeOcrText\":\"Comercio: Farmacia Mercantil Demo\nMonto: Bs 245,70\nFecha: 08/07/2026\nTarjeta: **** 4821\",\"attachments\":[{\"url\":\"$BASE_URL/ocr/test_para_OCR.jpeg\",\"name\":\"test_para_OCR.jpeg\",\"type\":\"image\"}]}"
```

Esperado:

```text
merchant: Farmacia Mercantil Demo
amount: 245.7
currency: VES
cardLast4: 4821
confidence: 0.98
```

### 6.3A Imagen Adjunta sin Texto OCR Legible

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/ticket/extract" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data "{\"attachments\":[{\"url\":\"$BASE_URL/ocr/test_para_OCR.jpeg\",\"name\":\"test_para_OCR.jpeg\",\"type\":\"image\"}]}"
```

Esperado:

```text
ok: false
code: OCR_UNREADABLE_IMAGE
ocrMode: unreadable_attachment
confidence: 0
```

Este caso ya no debe devolver datos demo como comercio, monto, fecha o tarjeta. Si Cognigy no logra leer la imagen y no envia `nativeOcrText`, `ocrText`, `ticketText` o campos estructurados, el flujo debe pasar esa causa al handover para revision manual. Un mensaje conversacional como `quiero reclamar un cobro` no cuenta como OCR cuando hay imagen adjunta.

### 6.3B OCR por WhatsApp

Endpoint WhatsApp:

```text
Mercantil DEMO WS
endpointId: 6a501c77fac4430baec2fc44
URLToken: 9cfa9f540e573a4494a0d9a127788288382806edb8d9814a63bb7b1465b25ff2
```

El transformer de entrada debe estar activo:

```bash
node scripts/update_mercantil_whatsapp_transformer.js --dry-run
```

Si el tunel publico cambia, reaplicar Cognigy con:

```bash
node scripts/update_mercantil_whatsapp_transformer.js --backend-url "$BASE_URL"
```

Esperado en `before` o despues de aplicarlo:

```text
inputTransformerEnabled: true
maskLogging: true
maskAnalytics: true
maskIPAddress: true
```

Prueba manual por WhatsApp:

```text
1. Enviar: quiero reclamar un cobro
2. MIA pide foto del comprobante y tipo de inconveniente.
3. Enviar una imagen del comprobante.
```

Esperado:

```text
MIA no debe volver a pedir la foto.
Si aun falta el tipo de inconveniente, debe pedir solo ese dato.
Si la imagen trae caption con el tipo, debe intentar leer el comprobante y continuar.
```

El transformer importa primero la imagen de WhatsApp al backend publico de Mercantil y luego convierte el payload crudo `messages[0].image` en:

```text
data.inputAttachments[0]
data.attachments[0]
```

La URL del adjunto debe quedar bajo:

```text
https://protest-affiliation-kirk-purse.trycloudflare.com/uploads/...
```

Ademas guarda temporalmente el ultimo adjunto de WhatsApp por 10 minutos para reusarlo si el cliente envia el tipo de inconveniente en el siguiente mensaje.

Prueba del importador publico:

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/whatsapp-media/import" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data "{\"url\":\"$BASE_URL/ocr/test_para_OCR.jpeg\",\"name\":\"whatsapp-test.jpeg\",\"mimeType\":\"image/jpeg\"}"
```

Esperado:

```text
ok: true
url: $BASE_URL/uploads/...
```

### 6.4 Evaluar Reglas de Reclamo

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/rules/evaluate" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data '{
    "identityVerified": true,
    "ticket": {
      "confidence": 0.92,
      "amount": 125.30
    },
    "issueType": "consumo rechazado"
  }'
```

Esperado:

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

### 6.5 Crear Solicitud Comercial

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/applications" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data '{
    "userId": "demo-user-001",
    "productType": "credit_card",
    "fullName": "Maria Silva",
    "documentId": "V11223344",
    "phone": "04125550000",
    "email": "maria.silva@example.com",
    "city": "Caracas",
    "preferredBranchName": "Chacao"
  }'
```

Esperado:

```text
requestId: SOL-YYYY-NNNNNN
status: created
productType: credit_card
```

Guarda el `requestId` para la siguiente prueba:

```bash
export REQUEST_ID="SOL-2026-000001"
```

### 6.6 Consultar Solicitud Comercial

```bash
curl -sS "$BASE_URL/bank/mercantil/demo/applications/$REQUEST_ID" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}"
```

Esperado:

```text
status: created
productType: credit_card
```

### 6.7 Crear Reclamo

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/claims" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data '{
    "identityVerified": true,
    "userId": "demo-user-001",
    "issueType": "consumo rechazado",
    "ticket": {
      "merchant": "Farmacia Mercantil Demo",
      "amount": "245,70",
      "currency": "VES",
      "date": "08/07/2026",
      "time": "14:35",
      "cardLast4": "4821",
      "reference": "9876543210",
      "authorization": "12345"
    },
    "rules": {
      "decision": "needs_human",
      "claimStatus": "needs_human",
      "ruleCode": "RULE_ENGINE_UNABLE_TO_DECIDE"
    }
  }'
```

Esperado:

```text
claimId: MC-YYYY-NNNNNN
status: needs_human
ticket.merchant: Farmacia Mercantil Demo
```

Guarda el `claimId`:

```bash
export CLAIM_ID="MC-2026-000001"
```

### 6.8 Consultar Reclamo

```bash
curl -sS "$BASE_URL/bank/mercantil/demo/claims/$CLAIM_ID" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}"
```

Esperado:

```text
claimId: MC-YYYY-NNNNNN
status: needs_human
ticket.merchant: Farmacia Mercantil Demo
```

## 7. Probar Seguridad de Tarjetas con TOTP

### 7.1 Enrolar TOTP

```bash
curl -sS -X POST "$BASE_URL/auth/enroll" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data '{"userId":"demo-user-001"}'
```

Escanea el QR con Entrust. No pegues secretos en chats ni documentos.

### 7.2 Verificar Codigo TOTP

Reemplaza `123456` por el codigo vigente de Entrust:

```bash
curl -sS -X POST "$BASE_URL/auth/verify-totp" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data '{"userId":"demo-user-001","code":"123456"}'
```

Esperado:

```text
ok: true
identityVerified: true
```

### 7.3 Mostrar QR si no tienes OTP

Si no tienes codigo OTP/TOTP o no has escaneado el QR, reproduce el flujo de enrolamiento:

```bash
curl -sS "$BASE_URL/auth/qr/demo-user-001?format=json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}"
```

Esperado:

```text
userId: demo-user-001
qrDataUrl: data:image/png;base64,...
otpauthUrl: otpauth://...
manualSecret: no debe venir
```

En Cognigy, el agente debe usar `tool_get_totp_qr` y mostrar el QR como imagen. No debe responder que no puede mostrar ni regenerar el QR.

Mensaje de prueba:

```text
No tengo el OTP. Necesito escanear el QR para configurar mi autenticador. Mi userId es demo-user-001.
```

Esperado:

```text
El agente muestra el QR y pide el codigo TOTP de 6 digitos.
```

### 7.4 Bloquear Tarjeta

```bash
curl -sS -X POST "$BASE_URL/bank/mercantil/demo/cards/mc-card-001/block" \
  -H "content-type: application/json" \
  -H "x-api-key: ${MERCANTIL_DEMO_API_KEY}" \
  --data '{"userId":"demo-user-001","reason":"card_lost_or_stolen"}'
```

Esperado:

```text
cardId: mc-card-001
status: blocked
```

## 8. Reproducir Pruebas del Agente Cognigy

Estas pruebas se hacen desde el endpoint REST de Cognigy o desde el MCP `talk_to_agent`.

Endpoint:

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

### 8.1 Listar Tarjetas

Mensaje:

```text
Lista mis tarjetas demo. Mi userId es demo-user-001. Responde con los ultimos 4 y estado.
```

Esperado:

```text
4821 active
9134 active
```

### 8.2 Crear Solicitud Comercial

Mensaje:

```text
Crea una solicitud comercial de tarjeta de credito con productType credit_card. Datos: fullName Maria Silva, documentId V11223344, phone 04125550000, email maria.silva@example.com, city Caracas, preferredBranchName Chacao, userId demo-user-001. Devuelve exactamente el requestId.
```

Esperado:

```text
SOL-YYYY-NNNNNN
```

En la validacion ejecutada devolvio:

```text
SOL-2026-000002
```

### 8.3 Consultar Solicitud Comercial

Mensaje:

```text
Consulta el estado de la solicitud SOL-2026-000002 y responde solo status y productType.
```

Reemplaza `SOL-2026-000002` por el ID que obtuviste.

Esperado:

```text
status: created productType: credit_card
```

### 8.4 Crear Reclamo sin Forzar Handover

Mensaje:

```text
Crea un reclamo demo por consumo rechazado sin ejecutar handover. Datos del comprobante: Farmacia Mercantil Demo, monto Bs 245,70, fecha 08/07/2026 14:35, tarjeta **** **** **** 4821, referencia 9876543210, autorizacion 12345. identityVerified true, userId demo-user-001. Devuelve solo claimId, status y merchant.
```

Esperado:

```json
{"claimId":"MC-YYYY-NNNNNN","status":"needs_human","merchant":"Farmacia Mercantil Demo"}
```

En la validacion ejecutada devolvio:

```json
{"claimId":"MC-2026-000002","status":"needs_human","merchant":"Farmacia Mercantil Demo"}
```

### 8.5 Inicio de Reclamo OCR sin Pedir Datos Manuales

En Webchat, REST endpoint o `talk_to_agent`, iniciar una conversacion nueva y enviar:

```text
quiero reclamar un cobro
```

Esperado:

```text
Con gusto. Para iniciar el reclamo por cobro, por favor envieme solo:

Una foto del comprobante o ticket.

El tipo de inconveniente:
- cobro duplicado
- monto incorrecto
- consumo no reconocido
- reverso no aplicado
- otro
```

No debe pedir en este primer paso:

```text
- monto
- fecha
- hora
- comercio
- referencia
- ultimos 4 digitos de la tarjeta
- explicaciones sobre OCR o sobre no necesitar esos datos manualmente
```

Variante:

```text
quiero reclamar un cobro duplicado por punto de venta
```

Esperado:

```text
MIA debe reconocer el tipo como cobro duplicado y pedir solo la foto del comprobante/ticket. No debe explicar que monto, fecha, comercio o tarjeta se extraen por OCR.
```

### 8.6 Respuesta de Funciones sin Referencias Internas

En Webchat, REST endpoint o `talk_to_agent`, iniciar una conversacion nueva y enviar:

```text
cuales son tus funciones
```

Esperado:

```text
MIA debe responder como agente de Mercantil e indicar que puede orientar sobre productos, requisitos, canales, agencias, horarios, seguridad de tarjetas, bloqueo y reposicion, casos, solicitudes comerciales, reclamos y seguimiento.
```

No debe mencionar:

```text
- demo
- prueba
- base de conocimiento
- tool, herramienta, API, endpoint o flujo
- nombres internos como tool_get_demo_user
```

## 9. Verificar Configuracion Cognigy

### 9.1 Verificar Tools

Con MCP:

```text
mcp__cognigy.list_resources
resourceType: tool
aiAgentId: 6a4e832ad9543729fbb3d497
limit: 100
```

Debe existir:

```text
tool_verify_totp
tool_get_totp_qr
tool_extract_ticket_data
tool_evaluate_claim_rules
tool_create_claim
tool_build_handover_summary
tool_get_demo_user
tool_get_demo_cards
tool_block_demo_card
tool_create_demo_case
tool_get_demo_case
tool_create_card_replacement
tool_create_application
tool_get_application
tool_get_claim
tool_search_mercantil_knowledge
```

### 9.2 Verificar URLs de Tools

```bash
node scripts/get_cognigy_chart.js --flow-id 6a4e832bfac4430baeb38e9e > /tmp/mercantil-flow-chart.json
```

```bash
node -e '
const fs = require("fs");
const c = JSON.parse(fs.readFileSync("/tmp/mercantil-flow-chart.json", "utf8"));
const base = process.env.BASE_URL;
const wrong = (c.nodes || [])
  .filter((node) => node.type === "httpRequest")
  .filter((node) => String(node.preview || "").startsWith("https://") && !String(node.preview || "").startsWith(base));
console.log(JSON.stringify({ wrongCount: wrong.length, wrong }, null, 2));
'
```

Esperado:

```json
{"wrongCount":0,"wrong":[]}
```

### 9.3 Verificar Handover NiCE

El Flow debe conservar este orden:

```text
tool_build_handover_summary - Pre-Process
tool_build_handover_summary - HTTP Request
tool_build_handover_summary - Post-Process
tool_build_handover_summary - Execute NiCE Handover
tool_build_handover_summary - Resolve
```

No uses el handover NiCE como bloqueo para validar lo demas. Si falla, continua con solicitudes, tarjetas, OCR y reclamos.

## 10. Snapshot

Snapshot final creado:

```text
name: Mercantil_Demo_snapshot_backend_bancamiga_cloudflared_validado_20260710
id: 6a510916fac4430baecc982c
hash: e915ade2691ca336d1d1e79cbce0470ce79cf716
```

Para crear otro snapshot:

```bash
node scripts/create_mercantil_snapshot.js \
  --name Mercantil_Demo_snapshot_backend_bancamiga_cloudflared_validado_YYYYMMDD \
  --description "Mercantil demo validated with Bancamiga backend capabilities, Cloudflare tunnel tools, NiCE handover node preserved."
```

## 11. Checklist Rapido

Antes de dar la demo por lista:

```bash
curl -sS "$BASE_URL/health"
node scripts/verify_mercantil_demo_services.js --base-url "$BASE_URL"
npm test
npm run check
```

Y en Cognigy probar estos 3 mensajes:

```text
Lista mis tarjetas demo. Mi userId es demo-user-001. Responde con los ultimos 4 y estado.
```

```text
Crea una solicitud comercial de tarjeta de credito con productType credit_card. Datos: fullName Maria Silva, documentId V11223344, phone 04125550000, email maria.silva@example.com, city Caracas, preferredBranchName Chacao, userId demo-user-001. Devuelve exactamente el requestId.
```

```text
Crea un reclamo demo por consumo rechazado sin ejecutar handover. Datos del comprobante: Farmacia Mercantil Demo, monto Bs 245,70, fecha 08/07/2026 14:35, tarjeta **** **** **** 4821, referencia 9876543210, autorizacion 12345. identityVerified true, userId demo-user-001. Devuelve solo claimId, status y merchant.
```
