# Proforma Tax Config > Estado: **CURRENT — SSOT fiscal** para Proforma e IssuedInvoice. Las propuestas futuras > deben identificarse expresamente como TARGET; la protección de DELETE de TaxDefinition > permanece **APARCADA**. ## Objetivo Persistir la configuracion fiscal de cabecera de una proforma sin confundirla con los impuestos realmente calculados desde lineas valoradas. ## Alcance - `tax_regime_code` sigue representando el regimen fiscal general - `tax_config` representa los controles fiscales de cabecera usados por la UI - `taxes` sigue representando solo desglose fiscal materializado - `totals` sigue representando solo importes calculados desde lineas valoradas ## Campos persistidos en `proformas` - `tax_mode` - `default_iva_code` - `uses_equivalence_surcharge` - `default_rec_code` - `uses_retention` - `default_retention_code` Estos códigos son referencias fiscales persistidas de la Proforma. No existe todavía una protección transversal consolidada que impida borrar una `TaxDefinition` por estar referenciada. ## Fiscalidad viva de Proforma `Tax` es el objeto operacional obtenido del catálogo: contiene `code`, `name`, `rate`, `group` y `calculationBehavior`. Antes de entrar en una línea de Proforma se convierte explícitamente a `ProformaItemTax`, el snapshot fiscal de la línea: `code`, `name` y `percentage`. Al cargar una Proforma, si existe la `TaxDefinition` para un código, prevalece su definición viva y se vuelve a materializar como `ProformaItemTax`. Si falta, se conserva el snapshot persistido (`code`, `name`, `percentage`) para que la Proforma siga siendo legible. Los importes no forman parte de `ProformaItemTax`: se derivan siempre de `taxableAmount × percentage`. `group` y `calculationBehavior` pertenecen exclusivamente a `Tax`/`TaxDefinition` operacional; no se persisten en `ProformaItem`. ## Disponibilidad fiscal La disponibilidad se evalúa por `companyId`, código fiscal y `proformaDate`: - `available`: puede asignarse, cambiar de estado y emitirse. - `inactive` o `out_of_validity`: una lectura existente se resuelve live, pero no admite nueva asignación, cambio de estado ni emisión. - `missing`: la lectura hace fallback al `ProformaItemTax` persistido; no permite nueva asignación, cambio de estado ni emisión. No hay fallback a defaults de Customer o Company. Readiness expone blockers `tax_unavailable` con razón `inactive`, `out_of_validity` o `missing`; la emisión revalida en ese instante y no confía en un readiness previo. ## Contrato publico `GET /proformas/:id` debe devolver: ```ts { tax_regime: { code: string; name: string; description: string; } | null; tax_config: { tax_mode: "single" | "per_line"; default_iva_code: string | null; uses_equivalence_surcharge: boolean; default_rec_code: string | null; uses_retention: boolean; default_retention_code: string | null; }; } ``` `POST /proformas` y `PATCH /proformas/:id` pueden aceptar `tax_config` como bloque independiente de `items`. ## Regla funcional - una proforma puede existir con `items = []` - en ese caso `taxes = []` - en ese caso todos los totales monetarios deben quedar a `0` - la UI debe hidratar los controles de fiscalidad desde `tax_config`, no desde `taxes` ## Resolucion de defaults en create Los defaults del cliente solo se usan al crear la proforma y el resultado se persiste. Fallback actual: - `tax_mode`: `single` - IVA por defecto: `iva_21` - recargo de equivalencia: desactivado salvo indicacion explicita - retencion: desactivada salvo indicacion explicita - codigo de retencion por defecto si `uses_retention = true`: `retention_15` Si el cliente cambia despues de crear la proforma: - no se reconstruye `tax_config` desde el cliente actual - la proforma conserva su `tax_config` persistido ## Regla de update `tax_config` se actualiza de forma parcial y se mergea sobre la configuracion persistida actual. No debe reconstruirse desde: - `taxes` - el cliente actual - defaults implícitos de frontend Para `items`: `undefined` no toca la colección ni revalida su fiscalidad existente; `[]` borra todas las líneas; una lista reemplaza completamente las líneas y valida todos sus impuestos como activos y vigentes. No existe mantenimiento diferencial por `itemId`. ## IssuedInvoice: snapshot histórico Una factura emitida es un snapshot histórico inmutable. `IssuedInvoiceItem` e `IssuedInvoiceTax` conservan, por IVA/REC/retención según corresponda, código, nombre, porcentaje e importe. Rehidratar, construir DTO o reporte no consulta `TaxDefinition` ni Proforma; cambios posteriores de nombre, porcentaje, actividad o vigencia no alteran la factura. No existe fallback `name = code`: `code != null && name == null` es una inconsistencia legacy. ## Grouping fiscal actual (P10) La identidad actual del breakdown es `ivaCode | recCode | retentionCode`: las tres dimensiones participan, no solo IVA. El porcentaje no forma parte de la key, pero dentro de un grupo el mismo código con nombre distinto o porcentaje distinto produce fail-fast. Esto no afirma que un código tenga un porcentaje históricamente inmutable; afirma que no pueden coexistir valores contradictorios para el mismo código dentro del mismo documento. Se eliminaron las constraints equivalentes a `UNIQUE(document_id, iva_code)` de los breakdowns de Proforma e IssuedInvoice: contradecían la identidad con REC/retención. El dominio garantiza la agrupación única; la BD todavía no tiene una UNIQUE exacta para los tres slots nullable debido a la semántica SQL de `NULL`. Es deuda futura no bloqueante. ## No incluido - nueva tabla para configuracion fiscal - recalculo fiscal fuera del flujo normal de lineas - cambios de Verifacti - cobros o vencimientos vivos - rectificativas