Uecko_ERP/docs/prompt-customer-invoices.md
2025-06-17 18:18:25 +02:00

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 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 CustomerInvoiceService.

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, Emitted, 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 (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>>).