# Emisión automática de DTE al cerrar venta POS

Flujo activado al crear una venta (`POST /api/posVentas`) cuando
`par_empresas.facturacion == 1`. Si la empresa no factura, la venta se guarda
sin documento tributario.

## Flujo

1. **Emisión LOCAL (síncrona, instantánea).** `DteEmissionService::emitirLocal()`
   reserva folio, mapea, construye XML + TED, firma el sobre, persiste el
   `DteDocumento` en estado `firmado`, guarda el XML y genera el PDF de muestra.
   La venta cierra de inmediato; no espera al SII. Se vincula
   `pos_ventas.dte_documento_id`.
2. **Envío al SII (en cola).** Tras el `commit`, el controlador despacha
   `EnviarDteAlSiiJob` a la cola `dte`. El job llama
   `DteEmissionService::enviarPendiente()`, que transmite el sobre y persiste
   `track_id` + estado `enviado` en `dte_documentos`. El job es **idempotente**:
   no reenvía si el DTE ya tiene `track_id` o está `enviado`/`aceptado`.
3. **Tolerancia a fallos** (`DTE_FAIL_MODE=warn`): si la emisión local falla, la
   venta se guarda igual y el DTE queda pendiente; no bloquea la caja. Con
   `DTE_FAIL_MODE=abort` la venta se revierte si el DTE falla.

## Correr el worker (transmisión real al SII)

Mientras el worker NO esté corriendo, los jobs quedan en la tabla `jobs` y
**nada se transmite al SII**. Levantar el worker es el disparador del envío:

```bash
php artisan queue:work --queue=dte
# desarrollo (recarga código en cada job):
php artisan queue:listen --queue=dte
```

En producción conviene un supervisor (systemd / Supervisor) con
`queue:work --queue=dte --tries=5`.

## Reintento de pendientes

Recupera DTE emitidos localmente pero no transmitidos (estado
`firmado`/`fallido` sin `track_id`):

```bash
php artisan dte:reenviar-pendientes                 # encola los pendientes
php artisan dte:reenviar-pendientes --empresa=1     # solo una empresa
php artisan dte:reenviar-pendientes --sync          # envía en el acto (diagnóstico)
php artisan dte:reenviar-pendientes --limit=100
```

Reintento automático (desactivado por defecto): `DTE_REINTENTO_AUTO=true` activa
la tarea programada cada 10 min (requiere `schedule:run` / cron y el worker).

## Configuración (`.env`)

| Variable | Default | Descripción |
|---|---|---|
| `QUEUE_CONNECTION` | `database` | Driver de cola (tablas `jobs`/`failed_jobs`). |
| `DTE_QUEUE` | `dte` | Cola donde se despacha el envío al SII. |
| `DTE_SEND_SYNC` | `true` | Envío síncrono en los endpoints manuales (no afecta al POS). |
| `DTE_FAIL_MODE` | `warn` | `warn`: venta sí, DTE pendiente. `abort`: revierte la venta. |
| `DTE_REINTENTO_AUTO` | `false` | Activa el reintento programado cada 10 min. |

> El POS siempre emite local y encola el envío (independiente de
> `DTE_SEND_SYNC`), porque pasa `enviar_sii=false` al motor y despacha el job.

## Tipos habilitados desde POS

33, 34, 39, 41, 52, 56, 61.

> **Gap conocido:** las guías (52) requieren datos de Transporte que aún no se
> mapean en `DataMapper`. Falta CAF tipo 41 en certificación.
