5.3 KiB
📌 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 comoid,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
Mapperpara convertir entre dominio y persistencia. - Repositorios (
ICustomerInvoiceRepository) solo manejan agregados. - Operaciones como
createInvoice,updateInvoice,getInvoiceByIdserán gestionadas enCustomerInvoiceService.
✅ 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 (ValueObjectUniqueID)status: string (ValueObject) (Draft,Emitted,Sent,Rejected)invoiceNumber: string (ValueObject )invoiceSeries: string (ValueObject )customerId: UUID (ValueObject)issueDate: UtcDate (ValueObject)operationDate: UtcDate (ValueObject)lines: array deInvoiceLine, cada una con:productId: (Optional) UUID (ValueObjectUniqueID)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 (CustomerInvoiceService) 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>>).