Uecko_ERP/docs/customer-invoices/invoice-series.md

164 lines
3.2 KiB
Markdown
Raw Normal View History

2026-07-07 20:21:50 +00:00
# InvoiceSeries
## Decisión consolidada
El recurso backend para las series de facturación de cliente se llama:
```txt
InvoiceSeries
```
Su tabla Sequelize asociada es:
```txt
customer_invoice_series
```
No se usa ya un recurso backend genérico `series`, ni `document-series`, ni `issued-invoice-series`.
## Alcance funcional
`InvoiceSeries` representa la serie usada para numerar facturas emitidas de cliente.
La proforma:
```txt
- guarda una referencia legacy en Proforma.series
- ese valor corresponde a InvoiceSeries.code
- no consume numeración de factura emitida
```
## Modelo mínimo
Campos activos en V1:
```txt
id
company_id
code
next_number
padding_length
is_default
is_active
created_at
updated_at
```
No existen en V1:
```txt
prefix
name
description
document_type
```
## Reglas de numeración
`next_number` es obligatorio y es la fuente de verdad para asignar el siguiente número de factura emitida.
El flujo de emisión desde proforma es:
```txt
1. leer la proforma
2. tomar Proforma.series como InvoiceSeries.code
3. buscar InvoiceSeries por company_id + code
4. validar que la serie existe y está activa
5. bloquear la fila de customer_invoice_series dentro de la misma transacción
6. leer next_number
7. asignar ese número a la issued invoice
8. incrementar next_number
9. confirmar issued invoice + increment en una sola transacción
```
No se permite:
```txt
- MAX(invoice_number) + 1
- consumir numeración al crear o actualizar proformas
- separar el lock y el update en transacciones distintas
```
## Formato visible
El formato visible deriva de:
```txt
formatted_number = code + "-" + number.padStart(padding_length, "0")
```
Ejemplo:
```txt
code = A
number = 23
padding_length = 6
=> A-000023
```
En V1 no existe `prefix`.
`code` actúa a la vez como identificador funcional y prefijo visible.
## Integridad defensiva
En `customer_invoice_series` debe existir:
```sql
UNIQUE (company_id, code)
```
En `customer_invoices` la regla defensiva para numeración emitida es:
```txt
company + series + invoice_number debe ser único
```
Actualmente el modelo Sequelize usa:
```sql
UNIQUE (company_id, series, invoice_number, is_proforma)
```
Esto evita colisiones entre proformas y facturas emitidas mientras ambas comparten `customer_invoices`.
## Seeds e inicialización
No se ha añadido seed automático por empresa porque el repo no expone un sistema real de seeders versionados ni una estrategia fiable para inicializar todas las companies existentes.
Regla operativa:
```txt
cada company necesita al menos una InvoiceSeries activa antes de emitir facturas
```
Serie mínima recomendada:
```txt
code = A
next_number = 1
padding_length = 6
is_default = true
is_active = true
```
## Estado técnico del repo
En este repo no se localizó un framework de migraciones versionadas con `sequelize-cli`, `umzug` o equivalente.
El arranque del servidor registra modelos Sequelize y sincroniza base de datos mediante:
```txt
database.sync({ alter: true })
```
Por eso el SQL manual asociado a `customer_invoice_series` vive en:
[customer-invoice-series.sql](/Z:/docs/dev/customer-invoice-series.sql)
Ese archivo debe integrarse en el pipeline real de despliegue DB cuando exista.
## Frontend
No se ha tocado frontend como parte de esta decisión.