164 lines
3.2 KiB
Markdown
164 lines
3.2 KiB
Markdown
|
|
# 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.
|