# Plan de Pruebas — Bancard VPOS + Compra Asistida

**Fecha**: 2026-04-27
**Alcance**: Solo fases implementadas ✅ (1A, 1B, 1C, 2A, 2B, 2C, 2D, 2E, 2I)
**Pendiente**: 2F (Facturar), 2G (Asiento contable), 2H (CA_REFUND), 1E (Bancard real)

---

## Entorno de prueba

| Item             | Valor                          |
| ---------------- | ------------------------------ |
| Backend          | `http://localhost:3000/api/v1` |
| Frontend         | `http://localhost:5173`        |
| BD               | psql local (desarrollo)        |
| Usuario operador | rol normal sin `CA_REFUND`     |
| Usuario admin    | rol con permiso `CA_REFUND`    |

**Orden recomendado**: CA-01 → CA-02 → CA-09 → CA-12 → CA-15 → CA-18 → CA-08 (secuencia completa hasta `entregado`) → casos negativos

---

## Módulo 1 — CRUD y máquina de estados (Fase 2B + 2I)

| ID    | Caso                                     | Pasos                                                                             | Resultado esperado                                 |
| ----- | ---------------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------- |
| CA-01 | Crear CA en borrador                     | `POST /compra-asistida` con items, cliente, totales USD                           | `id` retornado, `estado = borrador`                |
| CA-02 | Transición válida borrador → cotizado    | `PATCH /compra-asistida/:id/estado { estado: "cotizado" }`                        | Estado `cotizado`, `cotizacion_usd_gs` congelada   |
| CA-03 | Transición inválida borrador → entregado | Misma ruta con `"entregado"`                                                      | `400 Bad Request` "Transición no permitida"        |
| CA-04 | Avanzar cotizado → pago_recibido manual  | `PATCH` con `"pago_recibido"` (sin pasar por webhook)                             | `400` — solo vía webhook/mock                      |
| CA-05 | Cancelar desde borrador                  | `PATCH` con `"cancelado"`                                                         | `200 OK`, `estado = cancelado`                     |
| CA-06 | Cancelar desde cotizado                  | `PATCH` con `"cancelado"`                                                         | `200 OK`, `estado = cancelado`                     |
| CA-07 | Cancelar desde pago_recibido sin permiso | `PATCH` con `"cancelado"`, usuario sin `CA_REFUND`                                | `403 Forbidden`                                    |
| CA-08 | Secuencia completa post-pago             | `pago_recibido → en_compra_china → en_transito → en_aduana → entregado` (4 PATCH) | Cada transición `200 OK`, estado final `entregado` |
| CA-09 | Estado "confirmado" no existe            | Intentar PATCH con `"confirmado"`                                                 | `400` — no es estado válido del enum               |

---

## Módulo 2 — Link de pago público (Fase 2D)

| ID    | Caso                                | Pasos                                            | Resultado esperado                                      |
| ----- | ----------------------------------- | ------------------------------------------------ | ------------------------------------------------------- |
| CA-10 | Generar link en `cotizado`          | `POST /compra-asistida/:id/generar-link` (JWT)   | `{ url: ".../pay/ca/:token", token, fecha_expiracion }` |
| CA-11 | Generar link en `borrador`          | Misma ruta, CA en borrador                       | `400 Bad Request`                                       |
| CA-12 | Regenerar link invalida el anterior | `POST /compra-asistida/:id/regenerar-link`       | Token previo → `cancelado` en BD; nuevo token activo    |
| CA-13 | GET datos de pago — token válido    | `GET /pago-publico/:token` (sin JWT)             | JSON con empresa, cliente, items, monto total, desglose |
| CA-14 | GET datos — token expirado          | Idem con `fecha_expiracion` < now (manipular BD) | `410 Gone`                                              |
| CA-15 | GET datos — token ya pagado         | Token con `estado = pagado`                      | `400 Bad Request` "Pago ya realizado"                   |
| CA-16 | GET datos — token cancelado         | Token con `estado = cancelado`                   | `400` o `410` según implementación                      |

---

## Módulo 3 — Flujo de pago mock (Fase 2D + 2E)

| ID    | Caso                                    | Pasos                                                       | Resultado esperado                                                      |
| ----- | --------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------- |
| CA-17 | Pago con tarjeta mock                   | Abrir `/pay/ca/:token` → tarjeta → completar form → "PAGAR" | Loading 2-3s → pantalla éxito, `{ aprobado: true, ticket: "MOCK-xxx" }` |
| CA-18 | Pago con QR mock                        | Seleccionar QR                                              | QR falso visible, countdown 60s, confirmación mock exitosa              |
| CA-19 | Pago con Zimple mock                    | Ingresar celular → "Enviar push"                            | Confirmación mock exitosa                                               |
| CA-20 | Post-hook: CA avanza a pago_recibido    | Consultar CA luego de CA-17                                 | `estado = pago_recibido`, `pago_bancard_id` asignado                    |
| CA-21 | `pago_bancard` registrado correctamente | Verificar en BD                                             | `estado = aprobado`, `meta_json.mock = true`, `shop_process_id` único   |
| CA-22 | Segundo intento en link ya pagado       | Recargar `/pay/ca/:token` del test CA-17                    | `400 Bad Request` "Pago ya realizado" (sin reprocesar)                  |
| CA-23 | `pago_link.estado` actualizado          | Verificar tabla `pago_link` en BD                           | `estado = pagado`, `pago_bancard_id` vinculado                          |

---

## Módulo 4 — Configuración Bancard (Fase 1B + 1C)

| ID    | Caso                                    | Pasos                                                          | Resultado esperado                                     |
| ----- | --------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------ |
| CA-24 | Guardar credenciales en panel           | Panel config → ingresar `public_key` + `private_key` → Guardar | `200 OK`                                               |
| CA-25 | Verificar cifrado en BD                 | `SELECT private_key FROM bancard_config` en psql               | Valor cifrado AES-256-CBC, no texto plano              |
| CA-26 | GET config devuelve campos enmascarados | `GET /bancard/config`                                          | `private_key` retorna `"***"` o null, no el valor real |

---

## Módulo 5 — UI Compra Asistida (Fase 2C)

| ID    | Caso                                         | Pasos                                                 | Resultado esperado                                          |
| ----- | -------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------- |
| CA-27 | Crear CA desde UI                            | Finanzas → Compra Asistida → "Nueva" → completar form | CA creada en lista con estado `borrador`                    |
| CA-28 | Menú "Generar link" visible solo en cotizado | Abrir menú en CA `cotizado` vs `borrador`             | Opción solo aparece en `cotizado`                           |
| CA-29 | Modal de link con opciones compartir         | Click "Generar link" en CA cotizada                   | Modal con URL completa, botón "Copiar", "WhatsApp", "Email" |
| CA-30 | Estado "confirmado" no aparece en UI         | Revisar selector de estado y lista de CAs en BD       | Sin rastro de `confirmado` en ninguna parte                 |
| CA-31 | Página `/pay/ca/:token` accesible sin login  | Abrir URL en ventana de incógnito                     | Carga correctamente, sin redirección a login                |

---

## Casos negativos adicionales

| ID    | Caso                                                   | Resultado esperado                          |
| ----- | ------------------------------------------------------ | ------------------------------------------- |
| CA-32 | `POST /compra-asistida` sin JWT                        | `401 Unauthorized`                          |
| CA-33 | `GET /pago-publico/:token` con token inexistente       | `404 Not Found`                             |
| CA-34 | Generar link para CA de otra empresa (otro empresa_id) | `403` o `404`                               |
| CA-35 | CA sin cliente asignado — intentar generar link        | `400` "La compra no tiene cliente asignado" |

---

## Fuera del alcance (pendiente de implementación)

| Fase | Descripción                                                                               |
| ---- | ----------------------------------------------------------------------------------------- |
| 2F   | `POST /compra-asistida/:id/facturar` — botón Facturar + form precargado                   |
| 2G   | Asiento contable post-facturación (Bancard por liquidar / Ventas / IVA)                   |
| 2H   | Permiso `CA_REFUND` + flujo refund admin (`POST /compra-asistida/:id/forzar-cancelacion`) |
| 1E   | Tests T01-T10 con tarjetas staging reales de Bancard                                      |
