# ARCHIVADO — Prompt Customer Invoices > Estado: **HISTÓRICO — NO NORMATIVO**. Describe el agregado híbrido `CustomerInvoice` y servicios retirados. No usar para cambios nuevos; consultar [arquitectura normativa](../../architecture/README.md) y [documentación actual de customer-invoices](../../customer-invoices/README.md). --- # Prompt Customer Invoices Base comun reutilizada: [`backend-prompt-base.md`](./backend-prompt-base.md) Este prompt añade solo las reglas especificas de `customer-invoices`. ## Contexto especifico Este modulo es para facturas de cliente y adapta la base comun a datos, reglas y operaciones de facturacion. ## DDD y SOLID aplicados - `CustomerInvoice` es agregado raiz - `InvoiceLine` se modela como entidad o Value Object dentro del agregado - usar mapper para dominio <-> persistencia - `ICustomerInvoiceRepository` maneja agregados - operaciones como `createInvoice`, `updateInvoice` y `getInvoiceById` viven en `CustomerInvoiceApplicationService` - usar SRP y contratos como `ICustomerInvoiceRepository`, `ITransactionManager` e `IInvoicePresenter` ## Estructura de datos La entidad `CustomerInvoice` tendrá: - `id`: UUID (ValueObject `UniqueID`) - `status`: string (ValueObject) (`Draft`, `Issued`, `Sent`, `Rejected`) - `invoiceNumber`: string (ValueObject ) - `invoiceSeries`: string (ValueObject ) - `customerId`: UUID (ValueObject) - `issueDate`: UtcDate (ValueObject) - `operationDate`: UtcDate (ValueObject) - `lines`: array de `InvoiceLine`, cada una con: - `productId`: (Optional) UUID (ValueObject `UniqueID`) - `description`: string (ValueObject) - `quantity`: Amount (number) and scale (number) (ValueObject Quantity) - `unitPrice`: Amount (number), scale (number) and currency (string) (ValueObject MoneyValue) - `totalLineAmount`: Amount (number), scale (number) and currency (string) (ValueObject MoneyValue) - `subtotalPrice`: Amount (number), scale (number) and currency (string) (ValueObject MoneyValue) - `discount`: Amount (number) and scale (number) (ValueObject Percentage) - `tax`: Amount (number) and scale (number) (ValueObject Percentage) - `totalAmount`: Amount (number), scale (number) and currency (string) (ValueObject MoneyValue) ## Operaciones principales - `createInvoice(data: CreateCustomerInvoiceDTO)` - `getInvoiceById(id: string)` - `updateInvoice(id: string, changes: UpdateCustomerInvoiceDTO)` - `listInvoices(filter?)` - `deleteInvoice(id: string)` - `markAsPaid(id: string)` ## Validaciones - usar `Zod` en Value Objects como `InvoiceNumber`, `InvoiceDate` e `InvoiceLine` - no lanzar excepciones para errores de validacion esperados; usar `Result` ## Presentacion - los controladores convierten el agregado a `CustomerInvoiceDTO` - usar `CustomerInvoicePresenter` para construir DTOs - DTOs solo exponen campos necesarios - se puede extender con `CsvInvoicePresenter`, `PdfInvoicePresenter`, etc. ## Autorizacion y acceso - proteger rutas con middleware JWT o equivalente vigente del modulo - validar que el usuario autenticado pueda acceder o modificar la factura de su empresa ## Persistencia - `SequelizeCustomerInvoiceRepository` accede mediante mapper - `CustomerInvoiceMapper` mapea agregado <-> persistencia - soportar transacciones con `TransactionManager.complete(...)` - seguir `snake_case` en tablas, columnas y timestamps `created_at`, `updated_at`, `deleted_at` ## Errores - usar `ApiError` para errores de API - capturar errores de Sequelize y convertirlos con mensajes claros mediante `errorMapper` ## Testing - testear `CustomerInvoiceApplicationService` con mocks de repositorio - testear rutas con `supertest` - cubrir Value Objects con pruebas unitarias ## Nomenclatura - Agregado: `CustomerInvoice` - Línea: `CustomerInvoiceLine` - DTOs: `CustomerInvoiceDTO`, `InvoiceLineDTO` - Presentadores: `CustomerInvoicePresenter` - Repositorio: `ICustomerInvoiceRepository`, `SequelizeCustomerInvoiceRepository` - ValueObjects: `CustomerInvoiceNumber`, `CustomerInvoiceDate`, `CustomerInvoiceTotal`, `CustomerInvoiceItemQuantity`, etc. ## Restricciones - no incluir `passwords`, `tokens` u otros datos sensibles en responses - no usar Sequelize directamente en servicios ni controllers - no devolver el agregado bruto; usar DTOs - tipar explicitamente metodos y resultados