# Document Series Design ## Objetivo del módulo `document-series` es un módulo propio porque la serie documental no es un catálogo estático: mantiene reglas de vigencia, flags de activación, defaults y estado transaccional de numeración. ## Por qué no vive en catalogs Los catálogos del ERP resuelven valores de referencia. Aquí hay concurrencia, bloqueo de fila y mutación transaccional de `next_number`, así que el comportamiento es operativo y no meramente descriptivo. ## Por qué numeración y serie viven juntas La numeración depende del estado de la serie: - si está activa - si está vigente - si es la serie por defecto - cuál es su prefijo, sufijo y padding Separarlo introduciría doble escritura o lecturas no atómicas. ## Modelo conceptual - `DocumentType`: tipo documental cerrado en V1 - `DocumentSeries`: agregado con configuración y contador - `AssignedDocumentNumber`: resultado de asignación atómica ## Campos principales - `companyId`, `branchId` - `documentType` - `code`, `name`, `description` - `prefix`, `suffix` - `nextNumber`, `padding` - `validFrom`, `validTo` - `isDefault`, `isActive` ## Reglas V1 - tipos soportados: `proforma`, `issued_invoice` - no asigna si la serie está inactiva - no asigna si la serie está fuera de vigencia - default por empresa + tipo, con prioridad de `branch_id` cuando aplica - formato de referencia: `prefix + padded(next_number) + suffix` ## Concurrencia La asignación usa transacción obligatoria y bloqueo de fila con `LOCK.UPDATE` sobre `document_series`. El incremento de `next_number` se persiste dentro de la misma transacción y con comprobación optimista del valor previo para evitar dobles consumos. ## Integracion con customer-invoices En V1: - `issued-invoices` delega la asignacion de numero en `document-series` - `proformas` delega la asignacion de referencia en `document-series` - `proformas` persiste `document_series_id` y `proforma_number` como snapshot tecnico adicional a `proforma_reference` - `proformas.document_series_id` identifica la serie documental usada para numerar la proforma - `proformas.proforma_number` guarda el numero propio de la proforma - `proformas.proforma_reference` guarda la referencia visible de la proforma - `proforma_series_code` es el input funcional de create para elegir la serie de `document_type = proforma` - `proformas.target_invoice_series_code` es opcional y, cuando existe, apunta a una serie de `issued_invoice`, nunca a una serie de `proforma` - create de proforma solo usa `document-series` para numerar la cabecera inicial - create de proforma puede persistir `tax_config` sin materializar impuestos - una proforma puede crearse sin lineas y seguir siendo valida como borrador inicial - si no hay lineas valoradas, `proforma_taxes` debe quedar vacia y los totales monetarios a `0` - si `proformas.target_invoice_series_code` es `NULL`, la emision resuelve la serie default activa de `issued_invoice` - en Fase 2E, `series` deja de ser el contrato nuevo para create/update de proformas - la UI consulta `GET /document-series` con filtro por `document_type` y `is_active = true` - la UI no consume `POST /document-series/assign-next` para previsualizar numeracion - `/catalogs/invoice-series` deja de existir como endpoint runtime - `customer_invoice_series` no participa ya en flujos activos de lectura o numeracion ## Migracion conservadora - la migracion historica de `issued_invoice` parte de `customer_invoice_series` - la creacion de series default de `proforma` usa `companies` como fuente - las validaciones SQL se mantienen separadas del script de migracion - no hay ejecucion automatica ni cutover productivo en esta fase - la DDL de `proformas` usa `information_schema` + SQL dinamico para mantener compatibilidad MariaDB/MySQL sin depender de `IF NOT EXISTS` en `ALTER TABLE` ## Branch scope pendiente El modelo ya contempla `branchId`, y la resolucion default da prioridad a `branch_id` cuando existe. Aun asi, `customer-invoices` no propaga un contexto real de sucursal hasta `assignNextNumber(...)`, asi que en esta fase toda la integracion sigue operando con alcance de empresa. ## Límites V1 - sin `format_pattern` - sin reseteos anuales automáticos - sin reservas de numeración - sin huecos justificados - sin migración productiva automática de legacy ## Extensiones futuras - nuevos `DocumentType` - seeds/migraciones controladas de series heredadas