97 lines
4.3 KiB
Markdown
97 lines
4.3 KiB
Markdown
# 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
|