- Added SequelizeProformaV2RecipientDomainMapper for mapping recipient data to domain model. - Introduced SequelizeProformaV2TaxesDomainMapper for handling tax data mapping. - Created SequelizeProformaV2RecipientSummaryMapper for summarizing recipient information. - Developed SequelizeProformaV2SummaryMapper for mapping Proforma summary data. - Implemented SequelizeProformaRepositoryV2 for managing Proforma data persistence. - Added SequelizeProformaV2NumberGenerator for generating Proforma numbers.
671 lines
18 KiB
Markdown
671 lines
18 KiB
Markdown
# Split Proformas / Issued Invoices
|
|
|
|
Estado: diseno tecnico / fases 1A-1D
|
|
Estado del backend: persistencia V2 activada; SQL de desarrollo preparado; sin ejecucion confirmada de migracion DB
|
|
|
|
## Objetivo
|
|
|
|
Preparar el esquema fisico para separar:
|
|
|
|
- `customer_invoices` -> `proformas`
|
|
- `customer_invoices` -> `issued_invoices`
|
|
- `customer_invoice_items` -> `proforma_items`
|
|
- `customer_invoice_items` -> `issued_invoice_items`
|
|
- `customer_invoice_taxes` -> `proforma_taxes`
|
|
- `customer_invoice_taxes` -> `issued_invoice_taxes`
|
|
- `verifactu_records.invoice_id` -> `verifactu_records.issued_invoice_id`
|
|
|
|
## Decisiones de fase 1A
|
|
|
|
- `proforma_reference` es el identificador visible canonico de proforma.
|
|
- `target_invoice_series_code` sustituye la semantica legacy de `series` en proformas.
|
|
- `issued_invoices` usa `invoice_series_code`, `invoice_number`, `invoice_date` y `source_proforma_id`.
|
|
- `proformas` no guarda `issued_invoice_id`; la relacion se resuelve con `issued_invoices.source_proforma_id`.
|
|
- Los impuestos del esquema actual son por documento, no por linea: `proforma_taxes` y `issued_invoice_taxes`.
|
|
- `payment_method` y `payment_term` en `issued_invoices` son snapshot historico, no estado vivo de cobro.
|
|
- No hay doble escritura.
|
|
- Legacy queda congelado solo para validacion y rollback cuando se haga el cutover.
|
|
|
|
## Estado de fase 1B
|
|
|
|
- Existen mappers Sequelize V2 sobre `proformas`, `proforma_items`, `proforma_taxes`.
|
|
- Existen mappers Sequelize V2 sobre `issued_invoices`, `issued_invoice_items`, `issued_invoice_taxes`.
|
|
- Existen repositorios Sequelize V2 listos para convivir con los repositorios legacy.
|
|
- El wiring activo legacy no se ha sustituido todavia.
|
|
- El dominio/application sigue arrastrando naming legacy en algunos contratos (`series`, `invoiceNumber`, `linkedProformaId`); la traduccion queda encapsulada en Infrastructure V2.
|
|
- `payment_term` sigue sin soporte real en el dominio actual de customer invoices; en persistencia V2 queda preparado pero no conectado funcionalmente.
|
|
|
|
## Estado de fase 1C
|
|
|
|
- El wiring activo del modulo usa persistencia V2 en los composition roots principales.
|
|
- `buildV2ProformaPersistence(...)` queda activo en:
|
|
- `modules/customer-invoices/src/api/infrastructure/proformas/di/proformas.di.ts`
|
|
- `modules/customer-invoices/src/api/infrastructure/proformas/di/proforma-public-services.ts`
|
|
- `buildV2IssuedInvoicePersistence(...)` queda activo en:
|
|
- `modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoices.di.ts`
|
|
- `modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-public-services.ts`
|
|
- La persistencia legacy no se borra, pero deja de ser la ruta operativa principal.
|
|
- La emision `Proforma -> IssuedInvoice` ahora encadena sobre V2:
|
|
- lee `proformas`
|
|
- crea `issued_invoices`
|
|
- crea `issued_invoice_items`
|
|
- crea `issued_invoice_taxes`
|
|
- marca la proforma como `issued`
|
|
- usa `issued_invoices.source_proforma_id`
|
|
- No hay doble escritura: cada composition root sigue instanciando una sola familia de repositorios.
|
|
- `VerifactuRecord` queda preparado para la ruta V2 mediante `issued_invoice_id` como relacion principal.
|
|
- La migracion/backfill real sigue pendiente. Si la BD real no tiene las tablas nuevas, el backend no podra arrancar correctamente con este wiring.
|
|
|
|
## Estado de fase 1D
|
|
|
|
- Existen scripts SQL separados para desarrollo:
|
|
- `docs/customer-invoices/sql/dev-split-proformas-issued-invoices.sql`
|
|
- `docs/customer-invoices/sql/validate-split-proformas-issued-invoices.sql`
|
|
- El SQL de desarrollo es idempotente y conservador:
|
|
- crea tablas V2 con `CREATE TABLE IF NOT EXISTS`
|
|
- hace backfill con `NOT EXISTS`
|
|
- no usa `DROP`, `TRUNCATE` ni `DELETE`
|
|
- no sobrescribe filas ya migradas
|
|
- no toca datos legacy salvo la columna transicional `verifactu_records.issued_invoice_id`
|
|
- Se documenta el orden de ejecucion en `docs/customer-invoices/sql/README.md`.
|
|
- En este workspace no se encontro una configuracion de BD de desarrollo inequivoca (`.env*` no presente en raiz del repo), por lo que no se ejecuto SQL real.
|
|
- Tampoco se hizo validacion funcional contra runtime real porque falta una BD de desarrollo confirmada y migrada para esta fase.
|
|
|
|
## Dependencias compartidas y exclusivas
|
|
|
|
### Compartidas entre legacy y V2
|
|
|
|
- contratos de Application (`IProformaRepository`, `IIssuedInvoiceRepository`)
|
|
- use cases, servicios de dominio y assemblers
|
|
- `TransactionManager`
|
|
- `InvoiceSeriesNumberAssigner` para `IssuedInvoice`
|
|
- resolvers de catalogos
|
|
- servicios de documentos PDF/preview
|
|
|
|
### Exclusivas de legacy
|
|
|
|
- `CustomerInvoiceModel` como storage real de Proforma e IssuedInvoice
|
|
- numerador de proformas sobre `customer_invoices.invoice_number` con `is_proforma = true`
|
|
- repositorios Sequelize legacy de `customer_invoices`
|
|
|
|
### Exclusivas de V2
|
|
|
|
- tablas `proformas`, `proforma_items`, `proforma_taxes`
|
|
- tablas `issued_invoices`, `issued_invoice_items`, `issued_invoice_taxes`
|
|
- numerador V2 de proformas sobre `proformas.proforma_reference`
|
|
- mappers y repositorios Sequelize V2
|
|
|
|
## Tablas nuevas previstas
|
|
|
|
### proformas
|
|
|
|
- `id`
|
|
- `company_id`
|
|
- `status`
|
|
- `proforma_reference`
|
|
- `proforma_date`
|
|
- `operation_date`
|
|
- `target_invoice_series_code`
|
|
- `reference`
|
|
- `description`
|
|
- `notes`
|
|
- `language_code`
|
|
- `currency_code`
|
|
- `customer_id`
|
|
- snapshot cliente
|
|
- `payment_method_id`
|
|
- `payment_term_id`
|
|
- `tax_regime_code`
|
|
- totales monetarios actuales
|
|
- `created_at`
|
|
- `updated_at`
|
|
- `deleted_at`
|
|
|
|
### issued_invoices
|
|
|
|
- `id`
|
|
- `company_id`
|
|
- `status`
|
|
- `source_proforma_id`
|
|
- `invoice_series_code`
|
|
- `invoice_number`
|
|
- `invoice_date`
|
|
- `operation_date`
|
|
- `reference`
|
|
- `description`
|
|
- `notes`
|
|
- `language_code`
|
|
- `currency_code`
|
|
- `customer_id`
|
|
- snapshot cliente
|
|
- `payment_method_id`
|
|
- `payment_method_name`
|
|
- `payment_method_description`
|
|
- `payment_term_id`
|
|
- `payment_term_name`
|
|
- `payment_term_description`
|
|
- `payment_term_snapshot_json`
|
|
- `tax_regime_code`
|
|
- `tax_regime_description`
|
|
- totales monetarios actuales
|
|
- `created_at`
|
|
- `updated_at`
|
|
- `deleted_at`
|
|
|
|
### Items y taxes
|
|
|
|
- `proforma_items.proforma_id`
|
|
- `issued_invoice_items.issued_invoice_id`
|
|
- `proforma_taxes.proforma_id`
|
|
- `issued_invoice_taxes.issued_invoice_id`
|
|
|
|
### Verifactu
|
|
|
|
- `verifactu_records.issued_invoice_id` nuevo
|
|
- `verifactu_records.invoice_id` legacy temporal durante la transicion de fase 1A
|
|
|
|
## SQL orientativo de backfill
|
|
|
|
### Proformas
|
|
|
|
```sql
|
|
INSERT INTO proformas (
|
|
id,
|
|
company_id,
|
|
status,
|
|
proforma_reference,
|
|
proforma_date,
|
|
operation_date,
|
|
target_invoice_series_code,
|
|
reference,
|
|
description,
|
|
notes,
|
|
language_code,
|
|
currency_code,
|
|
customer_id,
|
|
customer_tin,
|
|
customer_name,
|
|
customer_street,
|
|
customer_street2,
|
|
customer_city,
|
|
customer_province,
|
|
customer_postal_code,
|
|
customer_country,
|
|
payment_method_id,
|
|
payment_term_id,
|
|
tax_regime_code,
|
|
subtotal_amount_value,
|
|
subtotal_amount_scale,
|
|
items_discount_amount_value,
|
|
items_discount_amount_scale,
|
|
global_discount_percentage_value,
|
|
global_discount_percentage_scale,
|
|
global_discount_amount_value,
|
|
global_discount_amount_scale,
|
|
total_discount_amount_value,
|
|
total_discount_amount_scale,
|
|
taxable_amount_value,
|
|
taxable_amount_scale,
|
|
iva_amount_value,
|
|
iva_amount_scale,
|
|
rec_amount_value,
|
|
rec_amount_scale,
|
|
retention_amount_value,
|
|
retention_amount_scale,
|
|
taxes_amount_value,
|
|
taxes_amount_scale,
|
|
total_amount_value,
|
|
total_amount_scale,
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
)
|
|
SELECT
|
|
id,
|
|
company_id,
|
|
status,
|
|
CASE
|
|
WHEN series IS NULL OR series = '' THEN invoice_number
|
|
ELSE CONCAT(series, '-', invoice_number)
|
|
END AS proforma_reference,
|
|
invoice_date,
|
|
operation_date,
|
|
series,
|
|
reference,
|
|
description,
|
|
notes,
|
|
language_code,
|
|
currency_code,
|
|
customer_id,
|
|
customer_tin,
|
|
customer_name,
|
|
customer_street,
|
|
customer_street2,
|
|
customer_city,
|
|
customer_province,
|
|
customer_postal_code,
|
|
customer_country,
|
|
payment_method_id,
|
|
NULL AS payment_term_id,
|
|
tax_regime_code,
|
|
subtotal_amount_value,
|
|
subtotal_amount_scale,
|
|
items_discount_amount_value,
|
|
items_discount_amount_scale,
|
|
global_discount_percentage_value,
|
|
global_discount_percentage_scale,
|
|
global_discount_amount_value,
|
|
global_discount_amount_scale,
|
|
total_discount_amount_value,
|
|
total_discount_amount_scale,
|
|
taxable_amount_value,
|
|
taxable_amount_scale,
|
|
iva_amount_value,
|
|
iva_amount_scale,
|
|
rec_amount_value,
|
|
rec_amount_scale,
|
|
retention_amount_value,
|
|
retention_amount_scale,
|
|
taxes_amount_value,
|
|
taxes_amount_scale,
|
|
total_amount_value,
|
|
total_amount_scale,
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
FROM customer_invoices
|
|
WHERE is_proforma = 1;
|
|
```
|
|
|
|
### Issued invoices
|
|
|
|
```sql
|
|
INSERT INTO issued_invoices (
|
|
id,
|
|
company_id,
|
|
status,
|
|
source_proforma_id,
|
|
invoice_series_code,
|
|
invoice_number,
|
|
invoice_date,
|
|
operation_date,
|
|
reference,
|
|
description,
|
|
notes,
|
|
language_code,
|
|
currency_code,
|
|
customer_id,
|
|
customer_tin,
|
|
customer_name,
|
|
customer_street,
|
|
customer_street2,
|
|
customer_city,
|
|
customer_province,
|
|
customer_postal_code,
|
|
customer_country,
|
|
payment_method_id,
|
|
payment_method_name,
|
|
payment_method_description,
|
|
payment_term_id,
|
|
payment_term_name,
|
|
payment_term_description,
|
|
payment_term_snapshot_json,
|
|
tax_regime_code,
|
|
tax_regime_description,
|
|
subtotal_amount_value,
|
|
subtotal_amount_scale,
|
|
items_discount_amount_value,
|
|
items_discount_amount_scale,
|
|
global_discount_percentage_value,
|
|
global_discount_percentage_scale,
|
|
global_discount_amount_value,
|
|
global_discount_amount_scale,
|
|
total_discount_amount_value,
|
|
total_discount_amount_scale,
|
|
taxable_amount_value,
|
|
taxable_amount_scale,
|
|
iva_amount_value,
|
|
iva_amount_scale,
|
|
rec_amount_value,
|
|
rec_amount_scale,
|
|
retention_amount_value,
|
|
retention_amount_scale,
|
|
taxes_amount_value,
|
|
taxes_amount_scale,
|
|
total_amount_value,
|
|
total_amount_scale,
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
)
|
|
SELECT
|
|
id,
|
|
company_id,
|
|
status,
|
|
proforma_id,
|
|
series,
|
|
invoice_number,
|
|
invoice_date,
|
|
operation_date,
|
|
reference,
|
|
description,
|
|
notes,
|
|
language_code,
|
|
currency_code,
|
|
customer_id,
|
|
customer_tin,
|
|
customer_name,
|
|
customer_street,
|
|
customer_street2,
|
|
customer_city,
|
|
customer_province,
|
|
customer_postal_code,
|
|
customer_country,
|
|
payment_method_id,
|
|
payment_method_description,
|
|
payment_method_description,
|
|
NULL AS payment_term_id,
|
|
NULL AS payment_term_name,
|
|
NULL AS payment_term_description,
|
|
NULL AS payment_term_snapshot_json,
|
|
tax_regime_code,
|
|
COALESCE(tax_regime_description, tax_regime_code),
|
|
subtotal_amount_value,
|
|
subtotal_amount_scale,
|
|
items_discount_amount_value,
|
|
items_discount_amount_scale,
|
|
global_discount_percentage_value,
|
|
global_discount_percentage_scale,
|
|
global_discount_amount_value,
|
|
global_discount_amount_scale,
|
|
total_discount_amount_value,
|
|
total_discount_amount_scale,
|
|
taxable_amount_value,
|
|
taxable_amount_scale,
|
|
iva_amount_value,
|
|
iva_amount_scale,
|
|
rec_amount_value,
|
|
rec_amount_scale,
|
|
retention_amount_value,
|
|
retention_amount_scale,
|
|
taxes_amount_value,
|
|
taxes_amount_scale,
|
|
total_amount_value,
|
|
total_amount_scale,
|
|
created_at,
|
|
updated_at,
|
|
deleted_at
|
|
FROM customer_invoices
|
|
WHERE is_proforma = 0;
|
|
```
|
|
|
|
### Items
|
|
|
|
```sql
|
|
INSERT INTO proforma_items (
|
|
item_id,
|
|
proforma_id,
|
|
position,
|
|
description,
|
|
quantity_value,
|
|
quantity_scale,
|
|
unit_amount_value,
|
|
unit_amount_scale,
|
|
subtotal_amount_value,
|
|
subtotal_amount_scale,
|
|
item_discount_percentage_value,
|
|
item_discount_percentage_scale,
|
|
item_discount_amount_value,
|
|
item_discount_amount_scale,
|
|
global_discount_percentage_value,
|
|
global_discount_percentage_scale,
|
|
global_discount_amount_value,
|
|
global_discount_amount_scale,
|
|
total_discount_amount_value,
|
|
total_discount_amount_scale,
|
|
taxable_amount_value,
|
|
taxable_amount_scale,
|
|
iva_code,
|
|
iva_percentage_value,
|
|
iva_percentage_scale,
|
|
iva_amount_value,
|
|
iva_amount_scale,
|
|
rec_code,
|
|
rec_percentage_value,
|
|
rec_percentage_scale,
|
|
rec_amount_value,
|
|
rec_amount_scale,
|
|
retention_code,
|
|
retention_percentage_value,
|
|
retention_percentage_scale,
|
|
retention_amount_value,
|
|
retention_amount_scale,
|
|
taxes_amount_value,
|
|
taxes_amount_scale,
|
|
total_amount_value,
|
|
total_amount_scale
|
|
)
|
|
SELECT
|
|
i.item_id,
|
|
i.invoice_id,
|
|
i.position,
|
|
i.description,
|
|
i.quantity_value,
|
|
i.quantity_scale,
|
|
i.unit_amount_value,
|
|
i.unit_amount_scale,
|
|
i.subtotal_amount_value,
|
|
i.subtotal_amount_scale,
|
|
i.item_discount_percentage_value,
|
|
i.item_discount_percentage_scale,
|
|
i.item_discount_amount_value,
|
|
i.item_discount_amount_scale,
|
|
i.global_discount_percentage_value,
|
|
i.global_discount_percentage_scale,
|
|
i.global_discount_amount_value,
|
|
i.global_discount_amount_scale,
|
|
i.total_discount_amount_value,
|
|
i.total_discount_amount_scale,
|
|
i.taxable_amount_value,
|
|
i.taxable_amount_scale,
|
|
i.iva_code,
|
|
i.iva_percentage_value,
|
|
i.iva_percentage_scale,
|
|
i.iva_amount_value,
|
|
i.iva_amount_scale,
|
|
i.rec_code,
|
|
i.rec_percentage_value,
|
|
i.rec_percentage_scale,
|
|
i.rec_amount_value,
|
|
i.rec_amount_scale,
|
|
i.retention_code,
|
|
i.retention_percentage_value,
|
|
i.retention_percentage_scale,
|
|
i.retention_amount_value,
|
|
i.retention_amount_scale,
|
|
i.taxes_amount_value,
|
|
i.taxes_amount_scale,
|
|
i.total_amount_value,
|
|
i.total_amount_scale
|
|
FROM customer_invoice_items i
|
|
JOIN customer_invoices ci ON ci.id = i.invoice_id
|
|
WHERE ci.is_proforma = 1;
|
|
|
|
INSERT INTO issued_invoice_items (...)
|
|
SELECT ...
|
|
FROM customer_invoice_items i
|
|
JOIN customer_invoices ci ON ci.id = i.invoice_id
|
|
WHERE ci.is_proforma = 0;
|
|
```
|
|
|
|
### Taxes
|
|
|
|
```sql
|
|
INSERT INTO proforma_taxes (
|
|
tax_id,
|
|
proforma_id,
|
|
taxable_amount_value,
|
|
taxable_amount_scale,
|
|
iva_code,
|
|
iva_percentage_value,
|
|
iva_percentage_scale,
|
|
iva_amount_value,
|
|
iva_amount_scale,
|
|
rec_code,
|
|
rec_percentage_value,
|
|
rec_percentage_scale,
|
|
rec_amount_value,
|
|
rec_amount_scale,
|
|
retention_code,
|
|
retention_percentage_value,
|
|
retention_percentage_scale,
|
|
retention_amount_value,
|
|
retention_amount_scale,
|
|
taxes_amount_value,
|
|
taxes_amount_scale
|
|
)
|
|
SELECT
|
|
t.tax_id,
|
|
t.invoice_id,
|
|
t.taxable_amount_value,
|
|
t.taxable_amount_scale,
|
|
t.iva_code,
|
|
t.iva_percentage_value,
|
|
t.iva_percentage_scale,
|
|
t.iva_amount_value,
|
|
t.iva_amount_scale,
|
|
t.rec_code,
|
|
t.rec_percentage_value,
|
|
t.rec_percentage_scale,
|
|
t.rec_amount_value,
|
|
t.rec_amount_scale,
|
|
t.retention_code,
|
|
t.retention_percentage_value,
|
|
t.retention_percentage_scale,
|
|
t.retention_amount_value,
|
|
t.retention_amount_scale,
|
|
t.taxes_amount_value,
|
|
t.taxes_amount_scale
|
|
FROM customer_invoice_taxes t
|
|
JOIN customer_invoices ci ON ci.id = t.invoice_id
|
|
WHERE ci.is_proforma = 1;
|
|
|
|
INSERT INTO issued_invoice_taxes (...)
|
|
SELECT ...
|
|
FROM customer_invoice_taxes t
|
|
JOIN customer_invoices ci ON ci.id = t.invoice_id
|
|
WHERE ci.is_proforma = 0;
|
|
```
|
|
|
|
### Verifactu
|
|
|
|
```sql
|
|
UPDATE verifactu_records vr
|
|
JOIN customer_invoices ci ON ci.id = vr.invoice_id
|
|
SET vr.issued_invoice_id = vr.invoice_id
|
|
WHERE ci.is_proforma = 0;
|
|
```
|
|
|
|
## Validaciones SQL
|
|
|
|
### Conteos
|
|
|
|
```sql
|
|
SELECT COUNT(*) FROM customer_invoices WHERE is_proforma = 1;
|
|
SELECT COUNT(*) FROM proformas;
|
|
|
|
SELECT COUNT(*) FROM customer_invoices WHERE is_proforma = 0;
|
|
SELECT COUNT(*) FROM issued_invoices;
|
|
|
|
SELECT COUNT(*)
|
|
FROM customer_invoice_items i
|
|
JOIN customer_invoices ci ON ci.id = i.invoice_id
|
|
WHERE ci.is_proforma = 1;
|
|
SELECT COUNT(*) FROM proforma_items;
|
|
|
|
SELECT COUNT(*)
|
|
FROM customer_invoice_taxes t
|
|
JOIN customer_invoices ci ON ci.id = t.invoice_id
|
|
WHERE ci.is_proforma = 0;
|
|
SELECT COUNT(*) FROM issued_invoice_taxes;
|
|
```
|
|
|
|
### Duplicados fiscales
|
|
|
|
```sql
|
|
SELECT company_id, invoice_series_code, invoice_number, COUNT(*)
|
|
FROM issued_invoices
|
|
GROUP BY company_id, invoice_series_code, invoice_number
|
|
HAVING COUNT(*) > 1;
|
|
```
|
|
|
|
### Huerfanos
|
|
|
|
```sql
|
|
SELECT COUNT(*)
|
|
FROM issued_invoices ii
|
|
LEFT JOIN proformas p ON p.id = ii.source_proforma_id
|
|
WHERE ii.source_proforma_id IS NOT NULL
|
|
AND p.id IS NULL;
|
|
|
|
SELECT COUNT(*)
|
|
FROM verifactu_records vr
|
|
LEFT JOIN issued_invoices ii ON ii.id = vr.issued_invoice_id
|
|
WHERE vr.issued_invoice_id IS NOT NULL
|
|
AND ii.id IS NULL;
|
|
```
|
|
|
|
### Totales
|
|
|
|
```sql
|
|
SELECT SUM(total_amount_value) FROM customer_invoices WHERE is_proforma = 1;
|
|
SELECT SUM(total_amount_value) FROM proformas;
|
|
|
|
SELECT SUM(total_amount_value) FROM customer_invoices WHERE is_proforma = 0;
|
|
SELECT SUM(total_amount_value) FROM issued_invoices;
|
|
```
|
|
|
|
## No incluido en fase 1A
|
|
|
|
- no cutover del backend
|
|
- no borrado de tablas legacy
|
|
- no doble escritura
|
|
- no ejecucion de migraciones en una BD real
|
|
- no integracion Verifactu externa
|
|
- no dominio de cobros, vencimientos vivos o conciliacion
|
|
|
|
## No incluido en fase 1C
|
|
|
|
- no borrado de legacy
|
|
- no backfill real
|
|
- no ejecucion de migraciones
|
|
- no doble escritura
|
|
- no integracion Verifactu funcional nueva
|
|
- no cambios en controllers, rutas o DTOs publicos
|
|
|
|
## No incluido en fase 1D
|
|
|
|
- no ejecucion en produccion
|
|
- no borrado de tablas legacy
|
|
- no eliminacion de modelos/repositorios legacy
|
|
- no integracion Verifacti funcional
|
|
- no dominio de cobros
|
|
- no doble escritura
|
|
|
|
## Resultado de validacion tecnica fase 1D
|
|
|
|
- `tsc` modulo `customer-invoices`: esperado ejecutar en esta fase
|
|
- `biome lint` sobre `src/api/infrastructure` y `docs/customer-invoices`: esperado ejecutar en esta fase
|
|
- `tsc` raiz: esperado ejecutar en esta fase
|
|
- Validacion SQL real: no ejecutada por falta de entorno de desarrollo inequivoco
|
|
- Validacion runtime real contra BD migrada: no ejecutada por la misma razon
|
|
|
|
## Siguiente fase recomendada
|
|
|
|
- confirmar `.env`/credenciales de una BD de desarrollo segura
|
|
- ejecutar `dev-split-proformas-issued-invoices.sql`
|
|
- ejecutar `validate-split-proformas-issued-invoices.sql`
|
|
- levantar el backend contra esa BD y validar `create`, `update`, `get`, `list` e `issue proforma`
|
|
- validar numeracion de proformas V2 y asignacion de serie/numero de factura emitida
|
|
- revisar la ruta `VerifactuRecord -> issued_invoice_id` ya con persistencia V2 activa
|