📌 CONTEXTO DEL PROYECTO:
Estoy desarrollando una API en **Node.js** con **TypeScript**, **Express.js**, **Sequelize**, y **Arquitectura Hexagonal (Ports & Adapters)** bajo los principios de **DDD (Domain-Driven Design)** y **SOLID**.  
Este módulo es para **facturas de cliente (Customer Invoices)** y debe cumplir con los estándares definidos previamente para el contexto de autenticación, adaptados a los datos, reglas y operaciones de las facturas.

📌 PRINCIPIOS Y PATRONES A APLICAR:
✅ **DDD (Domain-Driven Design)**  
   - Las **facturas** serán agregados raíz (`CustomerInvoice`) con propiedades como `id`, `customerId`, `invoiceNumber`, `date`, `lines`, `totals`, etc.  
   - Las **líneas de factura** (`InvoiceLine`) se modelan como entidades o value objects dentro del agregado.  
   - Se usará un `Mapper` para convertir entre dominio y persistencia.  
   - Repositorios (`ICustomerInvoiceRepository`) solo manejan agregados.  
   - Operaciones como `createInvoice`, `updateInvoice`, `getInvoiceById` serán gestionadas en `CustomerInvoiceApplicationService`.

✅ **SOLID**  
   - Usar SRP: cada clase con una responsabilidad clara.  
   - Usar interfaces como `ICustomerInvoiceRepository`, `ITransactionManager`, `IInvoicePresenter`.  
   - Evitar acoplamientos entre capa de aplicación y capa de infraestructura.  
   - Controladores deben transformar los datos en DTOs antes de enviarlos.  

📌 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` para validaciones en Value Objects (`InvoiceNumber`, `InvoiceDate`, `InvoiceLine`).  
✅ No se deben lanzar excepciones para errores de validación. Usar `Result<T, E>` como en autenticación.  

📌 PRESENTACIÓN:
✅ Los controladores convierten el agregado `CustomerInvoice` a `CustomerInvoiceDTO`.  
✅ Se usan `Presenters` (`CustomerInvoicePresenter`) para construir los DTOs.  
✅ DTOs solo exponen campos necesarios: nada sensible, nada interno.  
✅ Se puede extender con `CsvInvoicePresenter`, `PdfInvoicePresenter`, etc.

📌 AUTORIZACIÓN Y ACCESO:
✅ Se protegerán rutas con middleware JWT (`authenticateJWT`).  
✅ Se validará que el usuario autenticado pueda acceder/modificar la factura (p. ej. pertenece a su empresa).  

📌 PERSISTENCIA:
✅ `SequelizeCustomerInvoiceRepository` no accede directamente al modelo de Sequelize, lo hace a través de `Mapper`.  
✅ La clase `CustomerInvoiceMapper` mapea de/agregado <-> persistencia.  
✅ Soporta transacciones Sequelize (`TransactionManager.complete(...)`).
✅ Los nombres de los campos y las tablas en la base de datos seguirán la notación "snake_case".
✅ Los nombres de los campos en los modelos Sequelize seguirán la notación "snake_case".
✅ Los modelos Sequelize de los agregados tienen campos 'timestamp' con los nombres "created_at", "updated_at" y "deleted_at".


📌 ERRORES:
✅ Usar `ApiError` para errores en la API.  
✅ Los repositorios deben capturar errores de Sequelize (`UniqueConstraintError`, etc.) y convertirlos a errores de dominio con mensajes claros y específicos (mediante `errorMapper`).  

📌 TESTING:
✅ Los servicios (`CustomerInvoiceApplicationService`) serán testeados con mocks de repositorio.  
✅ Las rutas serán testeadas con `supertest`.  
✅ Las validaciones de ValueObjects tendrán pruebas unitarias.  

📌 NOMENCLATURA:
- Agregado: `CustomerInvoice`  
- Línea: `CustomerInvoiceLine`  
- DTOs: `CustomerInvoiceDTO`, `InvoiceLineDTO`  
- Presentadores: `CustomerInvoicePresenter`  
- Repositorio: `ICustomerInvoiceRepository`, `SequelizeCustomerInvoiceRepository`  
- ValueObjects: `CustomerInvoiceNumber`, `CustomerInvoiceDate`, `CustomerInvoiceTotal`, `CustomerInvoiceItemQuantity`, etc.

⚠️ IMPORTANTE:
- NO incluir `passwords`, `tokens`, o datos sensibles en respuestas.  
- NO usar Sequelize directamente en servicios ni controladores.  
- NO devolver el agregado como respuesta bruta. Usar DTOs.  
- TODO debe estar tipado, incluso los métodos de los servicios (`Promise<Result<T, Error>>`).  
