# Sprint 2 · Documentos, PDF carta, Ticket térmico y Correo

**ZIP:** `facturaos_sprint2.zip`
**Archivos nuevos:** 8
**Acumulado total:** 40 archivos

---

## Qué resuelve este sprint

El ciclo de entrega del comprobante al cliente. Una factura aceptada por Hacienda sin PDF ni correo no sirve de nada en la operación diaria. Este sprint cierra el ciclo: el cliente recibe su comprobante en el formato correcto, el contador puede imprimir en carta o en ticket POS, y el sistema envía el correo automáticamente al aceptarse.

Al terminar este sprint el sistema puede:
- Listar todos los comprobantes con filtros y estado Hacienda en tiempo real
- Elegir formato de impresión: PDF carta o ticket térmico 80mm
- Descargar el XML firmado aceptado por Hacienda
- Reenviar el correo al cliente en cualquier momento
- Reintentar facturas rechazadas o en contingencia desde la UI
- Emitir una nota de crédito desde una factura aceptada
- Convertir una proforma en factura con un clic
- Enviar correo automático al aceptarse con PDF y XML adjuntos

---

## Archivos del sprint

### `app/Livewire/Documentos/DocumentosIndex.php`

**Qué hace:** Componente Livewire del listado completo de comprobantes emitidos.

**Filtros disponibles:**
- Búsqueda por texto: número de FE, clave Hacienda, nombre o cédula del cliente
- Tipo de documento: FE, ND, NC, Tiquete, FEC, REP, Proforma
- Estado Hacienda: aceptado, rechazado, contingencia, enviado, en cola
- Estado de cobro: contado, pendiente, parcial, pagado, vencido
- Rango de fechas (desde/hasta)

**KPIs del período filtrado:**
Muestra en tiempo real: total de documentos, aceptadas, monto total, documentos con atención requerida (rechazadas + contingencia).

**Acciones por comprobante:**

| Acción | Cuándo aparece |
|---|---|
| 👁 Ver detalle | Siempre |
| 🖨️ Imprimir/PDF | Aceptadas y proformas |
| 📝 Descargar XML | Solo aceptadas |
| ✉️ Reenviar correo | Aceptadas con email de receptor |
| 🔄 Reintentar | Rechazadas y contingencia |
| 🔄 NC — Nota de crédito | FE aceptadas tipo 01 |
| ✓ Facturar | Proformas |

**Modal selector de formato:**
Al hacer clic en 🖨️ aparece un modal con dos opciones:
- PDF carta (A4) — con logo, colores, firma
- Ticket térmico 80mm — formato POS compacto

El formato elegido se guarda en `facturas_venta.formato_impresion` para historial.

**Paginación:** 20 documentos por página con links de paginación nativos de Laravel.

**Query string:** Los filtros de tipo, estado y búsqueda se reflejan en la URL para poder compartir o guardar vistas filtradas.

**Conecta con:**
- `PdfCartaService.php` — genera el PDF al hacer clic en descargar
- `TicketTermicoService.php` — genera el ticket al elegir ese formato
- `EnviarCorreoFactura.php` — se despacha al hacer clic en reenviar
- `EnviarFacturaHacienda.php` — se despacha al reintentar
- `FacturaVenta` (modelo) — fuente de datos con scopes

---

### `resources/views/livewire/documentos/index.blade.php`

**Qué hace:** Vista Blade del listado de documentos.

**Componentes visuales:**
- Barra de filtros con inputs flotantes en pills (border-radius 50px)
- Tabla con columnas: tipo (emoji + código), número (link al detalle), cliente, fecha, total, medio de pago, estado Hacienda, estado cobro, acciones
- Estados con chips de colores: verde aceptado, rojo rechazado, naranja contingencia, azul en proceso
- Mensaje de error de Hacienda visible en rojo bajo el estado (truncado con title para ver completo)
- Modal de selector de formato con radio buttons estilizados
- Alertas de éxito/error con auto-dismiss a los 4 segundos
- Mensaje vacío cuando no hay resultados

---

### `app/Services/Documentos/PdfCartaService.php`

**Qué hace:** Genera el PDF del comprobante en tamaño carta usando Laravel DomPDF.

**Métodos:**
- `descargar(FacturaVenta $factura)` — devuelve `StreamedResponse` para descarga directa
- `contenido(FacturaVenta $factura)` — devuelve el PDF como `string` para adjuntar en correo

**Configuración DomPDF:**
- Papel: Letter (carta) portrait
- DPI: 150 (balance calidad/tamaño)
- HTML5 parser habilitado
- Imágenes remotas deshabilitadas (seguridad)

**Conecta con:**
- `resources/views/pdf/factura-carta.blade.php` — plantilla del diseño
- `CorreoFacturaService.php` — usa `contenido()` para el adjunto
- `DocumentosIndex.php` — usa `descargar()` al hacer clic en imprimir

---

### `resources/views/pdf/factura-carta.blade.php`

**Qué hace:** Plantilla HTML/CSS del PDF carta con diseño profesional personalizable.

**Estructura del documento (de arriba a abajo):**

1. **Header** — logo de la empresa (o nombre si no hay logo) + datos de contacto a la derecha
2. **Línea separadora**
3. **Banda de título** — columna izquierda oscura con el tipo de documento en color secundario; columna derecha con datos del receptor y datos del comprobante (consecutivo, fecha, clave, vencimiento si aplica)
4. **Alerta de crédito** — si es a crédito, banda amarilla con plazo y fecha de vencimiento
5. **Alerta de devolución IVA** — si aplica, banda verde con el monto y referencia legal
6. **Tabla de líneas** — CABYS, descripción, cantidad, precio unitario, descuento, IVA%, total. Filas alternadas gris/blanco. Notas de exoneración y datos de medicamento si aplica
7. **Área de totales** — izquierda: métodos de pago + nota devolución IVA; derecha: subtotales por tarifa, descuentos, total con color secundario
8. **Firma** — si la empresa tiene `doc_responsable_nombre` configurado
9. **Notas** — campo libre del comprobante
10. **Footer** — banda oscura con mensaje de agradecimiento y términos

**Parámetros personalizables desde `empresas`:**

| Campo en BD | Efecto en el PDF |
|---|---|
| `logo_path` | Logo en el header |
| `doc_color_primario` | Color de la banda título y footer |
| `doc_color_secundario` | Color del tipo de documento y total |
| `doc_mensaje_footer` | Texto en el footer |
| `doc_terminos` | Términos y condiciones en el footer |
| `doc_responsable_nombre` | Nombre sobre la línea de firma |
| `doc_responsable_cargo` | Cargo bajo el nombre de firma |

**Casos especiales renderizados:**
- Proformas: sin clave Hacienda, título "Proforma"
- Notas de crédito: incluye datos de la referencia
- Medicamentos: muestra registro sanitario y forma farmacéutica
- Exoneraciones: muestra el artículo de ley
- Devolución IVA: box verde con monto y artículo legal
- Pago a crédito: box amarillo con fecha de vencimiento y nota de REP

---

### `app/Services/Documentos/TicketTermicoService.php`

**Qué hace:** Genera el comprobante en formato ticket 80mm para impresoras POS.

**Configuración del papel:**
- Ancho: 80mm (226.77 puntos)
- Alto: variable según contenido
- Fuente: Courier New monoespaciada
- 42 caracteres por línea como referencia

**Métodos:**
- `descargar(FacturaVenta $factura)` — StreamedResponse
- `contenido(FacturaVenta $factura)` — string para adjunto

**Conecta con:**
- `resources/views/pdf/ticket-termico.blade.php`
- `DocumentosIndex.php` — al elegir formato ticket

---

### `resources/views/pdf/ticket-termico.blade.php`

**Qué hace:** Plantilla HTML minimalista del ticket 80mm.

**Estructura:**
1. Nombre comercial de la empresa (grande, centrado)
2. Cédula, teléfono, email
3. Separador sólido
4. Tipo de documento en mayúsculas (`*** FACTURA ELECTRÓNICA ***`)
5. Separador punteado
6. Datos del comprobante: consecutivo, fecha, condición
7. Datos del cliente si aplica
8. Separador punteado
9. Tabla de líneas: descripción (22 chars), cantidad, total. Precio unitario e IVA en línea secundaria
10. Separador sólido
11. Totales por tarifa
12. Separador punteado
13. **TOTAL** en grande y con borde
14. Medios de pago
15. Box de devolución IVA (si aplica) con borde punteado verde
16. Clave Hacienda en fuente pequeña
17. Mensaje de agradecimiento
18. Pie legal

**Principio de diseño:** máxima legibilidad con mínimo espacio. Sin imágenes, sin colores, solo contraste tipográfico.

---

### `app/Services/Documentos/CorreoFacturaService.php`

**Qué hace:** Arma y envía el correo HTML al receptor con PDF y XML adjuntos.

**Variables en plantillas de correo:**

| Variable | Reemplazado por |
|---|---|
| `{cliente}` | Nombre del receptor |
| `{numero}` | Número consecutivo |
| `{total}` | Monto total formateado con ₡ |
| `{fecha}` | Fecha de emisión dd/mm/YYYY |
| `{empresa}` | Nombre comercial del emisor |
| `{vencimiento}` | Fecha de vencimiento si es crédito |

**Estructura del HTML del correo:**
1. Header oscuro con nombre de la empresa y tipo de comprobante
2. Banda de datos: consecutivo, fecha, total, alerta de crédito si aplica, alerta de devolución IVA si aplica
3. Cuerpo del correo (plantilla personalizada o texto por defecto)
4. Box de adjuntos: lista los archivos incluidos
5. Firma (plantilla personalizada o nombre de la empresa)
6. Footer oscuro con la clave de 50 dígitos

**Adjuntos:**
- `FE-{consecutivo}.pdf` — generado por `PdfCartaService`
- `FE-{consecutivo}.xml` — XML firmado almacenado en `facturas_venta.xml_enviado`

**Configuración SMTP:**
Usa la configuración de correo estándar de Laravel (`.env`). La configuración SMTP por empresa (desde el módulo de Configuración) se implementa en Sprint 5.

**Conecta con:**
- `PdfCartaService.php` — genera el PDF para adjuntar
- `EnviarCorreoFactura.php` — este Service es llamado desde el Job
- `Empresa.php` — lee `correo_asunto_fe`, `correo_cuerpo_fe`, `correo_firma`, `correo_color_boton`

---

### `app/Jobs/EnviarCorreoFactura.php`

**Qué hace:** Job de cola que despacha el envío del correo de forma asíncrona.

**Cola separada de Hacienda:**
El correo va en la cola `default`. Los jobs de Hacienda van en la misma cola pero tienen prioridad mayor porque afectan el estado legal del comprobante. Si el SMTP falla, no bloquea el proceso fiscal.

**Reintentos:**
| Intento | Espera |
|---|---|
| 1 | 1 minuto |
| 2 | 5 minutos |
| 3 | 15 minutos |

Si los 3 reintentos fallan: log de error pero **sin revertir nada** — la factura ya fue aceptada por Hacienda, el correo es complementario.

**Se despacha desde:**
- `ConsultarEstadoHacienda.php` — automáticamente al aceptarse
- `DocumentosIndex.php` — manualmente al hacer clic en "reenviar"

---

## Flujo completo del sprint

```
Factura aceptada por Hacienda
        ↓
ConsultarEstadoHacienda detecta "aceptado"
        ↓
EnviarCorreoFactura::dispatch($factura_id)
        ↓ (async, cola)
EnviarCorreoFactura Job ejecuta
        ↓
CorreoFacturaService::enviar($factura)
        ├── PdfCartaService::contenido($factura)  → PDF en memoria
        ├── $factura->xml_enviado                 → XML firmado
        └── Mail::send() con ambos adjuntos
                ↓
        Correo recibido por el cliente

En paralelo, el usuario puede:
        ↓
DocumentosIndex → clic en 🖨️
        ↓
Modal selecciona formato
        ├── carta  → PdfCartaService::descargar()
        └── ticket → TicketTermicoService::descargar()
```

---

## Personalización desde Configuración

Todo el diseño de los documentos se configura en **Configuración → Personalización de documentos** (Sprint 5). Los campos de la tabla `empresas` que afectan este sprint:

**PDF carta:**
```
doc_color_primario     → banda título, footer
doc_color_secundario   → tipo de documento, fila total
doc_mensaje_footer     → texto en footer
doc_terminos           → términos en footer
doc_responsable_nombre → nombre en la firma
doc_responsable_cargo  → cargo en la firma
logo_path              → logo en el header
```

**Correo:**
```
correo_asunto_fe       → asunto para facturas
correo_cuerpo_fe       → cuerpo para facturas (con variables)
correo_asunto_nc       → asunto para notas de crédito
correo_cuerpo_nc       → cuerpo para notas de crédito
correo_color_boton     → color del botón (reservado para futuro)
correo_firma           → bloque de firma del correo
```

---

## Qué viene en el Sprint 3

| Módulo | Archivos |
|---|---|
| Módulo CxC | `Livewire/CxC/CxCIndex.php` + vista |
| Registrar pago CxC | `Livewire/CxC/RegistrarPago.php` + REP automático |
| Módulo CxP | `Livewire/CxP/CxPIndex.php` + vista |
| Gastos XML | `Livewire/Gastos/GastosIndex.php` + vista |
| XmlParser | `Services/Hacienda/XmlParser.php` |
| ProcesarXmlCompra Job | `Jobs/ProcesarXmlCompra.php` |
| SincronizarXmlHacienda Command | `Console/Commands/SincronizarXmlHacienda.php` |
