# Capacidad: Interfaz web interna

Mapa de pantallas y acciones. **Sin diseño visual** — eso viene después. Decisiones de referencia:
**D31** (autenticación prevista y desactivada), **D13**/**D16** (las acciones correctoras son
manuales).

**Regla transversal:** ninguna acción que remita algo a la AEAT o que altere la cadena se ejecuta de
forma automática desde la interfaz. Todas exigen confirmación explícita y quedan en `auditoria`.

## ADDED Requirements

### Requirement: Mapa de pantallas

La interfaz DEBE tener cuatro áreas:

| Área | Ruta base | Contenido |
|---|---|---|
| **(a) Registros** | `/registros` | Listado y detalle |
| **(b) Errores y reenvíos** | `/errores` | Cola de pendientes y fallidos, acciones correctoras |
| **(c) Salud del sistema** | `/salud` | Integridad, certificado, contacto AEAT, incidencias |
| **(d) Configuración** | `/configuracion` | Parámetros editables |

Toda pantalla DEBE mostrar de forma permanente y destacada **el entorno activo** (`PRUEBAS` /
`PRODUCCIÓN`) y **si la cola está pausada**.

#### Scenario: Indicador de entorno

- **WHEN** el sistema opera contra preproducción
- **THEN** todas las pantallas muestran un distintivo visible de "ENTORNO DE PRUEBAS"
- **AND** el distintivo cambia al pasar a producción

#### Scenario: Cola pausada

- **WHEN** `control_flujo.cola_pausada = 1`
- **THEN** todas las pantallas muestran un aviso con el motivo de la pausa
- **AND** desde él se accede directamente a la incidencia que la causó

---

### Requirement: (a) Listado de registros

El listado DEBE mostrar por cada registro: `cadena_orden`, número de factura, fecha de expedición,
cliente, importe total, estado del registro, estado del PDF, estado de XTRF y momento de creación.

DEBE permitir filtrar por estado, rango de fechas, número de factura y cliente, y ordenar por
`cadena_orden`.

#### Scenario: Filtrado por estado

- **WHEN** se filtra por `RECHAZADO`
- **THEN** se listan solo los registros rechazados
- **AND** se indica el total de coincidencias

#### Scenario: Orden natural

- **WHEN** se abre el listado sin filtros
- **THEN** los registros aparecen ordenados por `cadena_orden` descendente
- **AND** el orden refleja la secuencia real de la cadena, no la fecha de la factura

---

### Requirement: (a) Detalle de un registro

El detalle DEBE mostrar, en secciones diferenciadas:

1. **Factura**: todos los datos de negocio y el JSON original recibido de XTRF.
2. **Registro de facturación**: los 31 campos, la `cadena_string` exacta que se hasheó, la huella, la
   huella anterior y la posición en la cadena.
3. **Estado AEAT**: estado, código y descripción del error traducida, **CSV**, datos de presentación.
4. **XML**: el **enviado** y la **respuesta cruda**, descargables.
5. **PDF**: estado, ruta en el share, hash y enlace de visualización.
6. **XTRF**: estado de la notificación y sus intentos.
7. **Historial**: entradas de `auditoria` de ese registro.

#### Scenario: Visualización de la cadena de la huella

- **WHEN** se abre el detalle
- **THEN** se muestra la `cadena_string` completa tal como se hasheó
- **AND** se muestra la huella resultante
- **AND** existe una acción "Recalcular y comparar" que verifica en vivo que ambas siguen cuadrando

#### Scenario: Descarga de los XML

- **WHEN** un operador descarga el XML enviado
- **THEN** obtiene el sobre SOAP exacto que se envió, sin reformatear
- **AND** el acceso queda en `auditoria`

#### Scenario: Navegación por la cadena

- **WHEN** se está en el detalle de un registro
- **THEN** hay enlaces al registro anterior y al siguiente por `cadena_orden`
- **AND** si es el primero, se indica explícitamente que es el inicio de la cadena

---

### Requirement: (b) Cola de pendientes y fallidos

La pantalla de errores DEBE mostrar tres bloques separados:

1. **Pendientes de envío** — en cola, con su posición y el momento en que podrán enviarse según el
   control de flujo.
2. **Bloqueados** — registros en `ESTADO_INDETERMINADO` y el que bloquea la cabecera de la cola.
3. **Fallidos** — `RECHAZADO`, `RECHAZADO_ESTRUCTURA`, `ACEPTADO_CON_ERRORES` con subsanación
   pendiente, PDF fallido y notificación XTRF fallida.

Cada error AEAT DEBE mostrarse con su **descripción traducida** del catálogo cargado desde
`errores.properties`, junto al código numérico.

#### Scenario: Error traducido

- **WHEN** un registro tiene `codigo_error_aeat = 1245`
- **THEN** se muestra "1245 — Si el campo Impuesto está vacío o tiene valor IVA(01) o IPSI(02) o
  IGIC(03) el campo ClaveRegimen debe de estar cumplimentado"
- **AND** los acentos se muestran correctamente

#### Scenario: Motivo del bloqueo

- **WHEN** la cola está bloqueada por un registro indeterminado
- **THEN** el bloque de bloqueados encabeza la pantalla
- **AND** indica cuántos registros están esperando detrás

#### Scenario: Próximo envío posible

- **WHEN** hay registros pendientes y el control de flujo impone espera
- **THEN** se muestra el momento exacto del próximo envío permitido

---

### Requirement: (b) Acciones correctoras, siempre manuales y explícitas

La interfaz DEBE ofrecer estas acciones, **todas manuales**, cada una con confirmación explícita y
**motivo escrito obligatorio**:

| Acción | Precondición | Efecto |
|---|---|---|
| **Consultar en AEAT** | Registro en `ESTADO_INDETERMINADO` | Lanza `ConsultaFactuSistemaFacturacion` |
| **Reenviar como ALTA** | Consulta previa con `SinDatos` | Reencola el mismo registro |
| **Alta por rechazo** | Registro en `RECHAZADO` | Crea registro nuevo con `Subsanacion=S`, `RechazoPrevio=X` |
| **Alta de subsanación** | Registro `ACEPTADO_CON_ERRORES` con `requiere_subsanacion=1`, o `CORRECTO` con dato erróneo detectado | Crea registro nuevo con `Subsanacion=S` |
| **Regenerar PDF** | `pdf_estado` ∈ {`PENDIENTE`,`FALLIDO`} | Regenera y despliega |
| **Reintentar notificación XTRF** | `xtrf_estado = FALLIDA` | Reintenta la llamada |
| **Pausar / reanudar cola** | — | Alterna `cola_pausada` |

**NUNCA** DEBE existir una acción de "reintentar todo" ni un reintento ciego.

#### Scenario: Reenvío bloqueado sin consulta previa

- **WHEN** un operador intenta "Reenviar como ALTA" sobre un registro indeterminado sin consulta
  previa
- **THEN** la acción aparece deshabilitada
- **AND** se explica que primero hay que consultar el estado real en la AEAT

#### Scenario: Consulta que revela que ya está registrado

- **WHEN** la consulta encuentra el registro como `Correcto`
- **THEN** el registro pasa a `CORRECTO` con el CSV recuperado
- **AND** la acción de reenvío desaparece
- **AND** la cola se desbloquea

#### Scenario: Advertencia ante una factura anulada

- **WHEN** la consulta encuentra el registro como `Anulado`
- **THEN** la interfaz muestra una advertencia destacada de que un alta de subsanación **reactivaría**
  la factura
- **AND** ninguna acción correctora queda disponible en fase 1

#### Scenario: Motivo obligatorio

- **WHEN** un operador ejecuta cualquier acción correctora
- **THEN** se le exige un motivo escrito antes de confirmar
- **AND** el motivo se almacena en `auditoria` junto al actor y la IP

#### Scenario: No existe reintento masivo

- **WHEN** hay 20 registros fallidos
- **THEN** cada uno requiere su propia acción individual
- **AND** no existe ningún control de "reintentar todos"

---

### Requirement: (c) Salud del sistema

La pantalla DEBE mostrar:

1. **Integridad de la cadena**: resultado y fecha de la última verificación, número de registros, y
   acción "Verificar ahora".
2. **Certificado**: titular, emisor, fecha de caducidad y **días restantes**, con semáforo.
3. **Último contacto con la AEAT**: momento, entorno y resultado.
4. **Control de flujo**: `tiempo_espera_actual_s` y próximo envío permitido.
5. **Montaje CIFS**: si el share está montado y es escribible.
6. **Reloj**: si NTP está sincronizado.
7. **Incidencias abiertas**: listado por severidad, con cierre manual y motivo.

#### Scenario: Verificación de integridad bajo demanda

- **WHEN** un operador pulsa "Verificar ahora"
- **THEN** se recorre la cadena completa y se muestra el resultado
- **AND** queda registrado en `verificaciones_integridad`

#### Scenario: Certificado próximo a caducar

- **WHEN** faltan 30 días o menos para la caducidad
- **THEN** el semáforo pasa a ámbar y hay incidencia abierta
- **AND** por debajo de 7 días pasa a rojo

#### Scenario: Certificado caducado

- **WHEN** la fecha de caducidad ya pasó
- **THEN** la cola se pausa automáticamente
- **AND** el motivo de pausa es `CERTIFICADO_CADUCADO`

#### Scenario: Cierre de incidencia

- **WHEN** un operador cierra una incidencia
- **THEN** se le exige un motivo
- **AND** la incidencia queda con `cerrada_at` y `cerrada_por`, sin borrarse

---

### Requirement: (d) Configuración

La pantalla DEBE permitir consultar y editar los parámetros de `configuracion`, agrupados por bloque:

| Bloque | Parámetros |
|---|---|
| Entorno AEAT | `aeat.entorno`, endpoints SOAP, URL base del QR, timeouts |
| Obligado emisor | NIF, razón social |
| Sistema informático | `NombreRazon` y NIF de la productora, `NombreSistemaInformatico`, `IdSistemaInformatico`, `Version`, `NumeroInstalacion` |
| XTRF | `xtrf.base_url`, `xtrf.token`, categorías, timeout, interruptor |
| Cola y control de flujo | `envio.max_registros`, `endpoint.max_facturas_dia`, pausa |
| PDF y QR | Tamaño del QR, zona muda, idioma por defecto, ruta del share |
| Autenticación | `auth.habilitada`, `endpoint.token` |

Los parámetros marcados como secretos DEBEN mostrarse enmascarados y no aparecer en logs.

Todo cambio DEBE quedar en `auditoria` con valor anterior y nuevo (salvo secretos, de los que solo se
registra que cambiaron).

#### Scenario: Cambio de parámetro crítico

- **WHEN** se modifica el NIF del obligado, el `IdSistemaInformatico` o el `NumeroInstalacion`
  **después** de que la cadena esté inicializada
- **THEN** la interfaz exige doble confirmación
- **AND** advierte de que cambiarlos altera la identidad de la cadena ante la AEAT y provocará el
  código **2007**
- **AND** registra el cambio con severidad máxima

#### Scenario: Edición de un secreto

- **WHEN** se cambia `xtrf.token`
- **THEN** el valor nuevo no se muestra tras guardar
- **AND** en `auditoria` consta que cambió, pero no el valor

#### Scenario: Validación de IdSistemaInformatico

- **WHEN** se introduce un `IdSistemaInformatico` que no sean exactamente 2 caracteres, cada uno letra
  mayúscula (excepto `Ñ`) o dígito
- **THEN** la interfaz rechaza el valor indicando el formato exigido

---

### Requirement: Autenticación prevista, desactivada

Todas las rutas DEBEN pasar por el middleware `AuthGuard` desde el primer día y DEBEN declarar el rol
que necesitarán: `lectura`, `operacion` o `administracion`.

Con `auth.habilitada = false`, el middleware deja pasar y registra en `auditoria` el acceso sin
autenticar.

#### Scenario: Acceso sin autenticación

- **WHEN** `auth.habilitada = false` y alguien accede a `/registros`
- **THEN** la pantalla se muestra
- **AND** queda una entrada de auditoría con `accion = "UI_SIN_AUTENTICAR"` y la IP

#### Scenario: Activación posterior

- **WHEN** un administrador activa `auth.habilitada`
- **THEN** las rutas empiezan a exigir sesión y rol inmediatamente
- **AND** no hace falta modificar ninguna ruta ni redesplegar

#### Scenario: Reparto de roles al activarse

- **WHEN** la autenticación está activa
- **THEN** `lectura` puede ver registros y salud
- **AND** `operacion` puede además ejecutar acciones correctoras
- **AND** solo `administracion` puede editar configuración y cambiar de entorno

---

### Requirement: Exportación de registros

La interfaz DEBE ofrecer una exportación por rango de fechas que incluya los datos de los registros y
sus XML, en formato electrónico legible.

#### Scenario: Exportación anual

- **WHEN** un operador exporta el ejercicio completo
- **THEN** obtiene un fichero con los registros y sus XML enviados y recibidos
- **AND** la exportación queda en `auditoria`

> No es una comodidad: el art. 8.c del RD 1007/2023 exige que el sistema cuente con *"un procedimiento
> de descarga, volcado y archivo seguro de los registros de facturación"*, exportables a
> almacenamiento externo en formato electrónico legible.
