Saltar a contenido

0001. Patrón de capas Router → Service → Repository

Estado: Aceptado Fecha: 2026-08-28 Autor: Duval Alcivar

Contexto

El backend actual del ERP mezcla responsabilidades: lógica de negocio dentro de routers, y en algunos casos SQL directo dentro de código que también maneja HTTP. Esto hace imposible testear reglas de negocio sin una base de datos real, dificulta cambiar de motor de base de datos, y no permite auditar con claridad dónde se toca la base de datos.

La auditoría de código identificó 20 dominios de negocio (bounded contexts) frente a los ~9 del CRM (Ventas y Pedidos, Canal App/B2C, Facturación/CxC, Fuerza de Ventas, Compras/CxP, Inventario/Almacén, Contabilidad, RRHH/Nómina, Producción, Recepción de Materia Prima, Envasado, Etiquetado, Calidad, Mantenimiento de Activos, Workflow/Casos, Reportes y Analítica, Integraciones Contables Externas, Seguridad/Identidad, Tienda/App, Liquidación de Faena Pesquera).

Decisión

Todo el backend se organiza, sin excepción, en tres capas con responsabilidad única:

  • Router — recibe la petición HTTP, valida el esquema de entrada (Pydantic) y el permiso del usuario. No contiene lógica de negocio.
  • Service — contiene las reglas de negocio (ej. "si la integración con Aylen falla, revertir el guardado del cliente"). No sabe nada de HTTP ni de SQL.
  • Repository — es el único lugar que conversa con PostgreSQL, vía ORM parametrizado. Nunca concatena SQL con datos del usuario.

Cada dominio de negocio vive en su propio router + service + repository, en archivos pequeños con una sola responsabilidad. Tocar un dominio (ej. Compras) no debe poder romper otro (ej. Producción) porque no comparten archivo.

Un Pull Request que mezcle responsabilidades entre capas (lógica de negocio en un router, o SQL en un service) se rechaza en revisión de código.

Alternativas descartadas

  • Mantener el patrón actual (módulo monolítico sin capas) — descartado porque es la causa raíz de los problemas de testeo, acoplamiento y auditoría que motivan la migración.
  • Arquitectura hexagonal / ports & adapters completa — descartada por ahora: agrega una capa de abstracción adicional (puertos/interfaces) que el equipo no necesita todavía dado el tamaño del sistema; se puede evolucionar hacia ella más adelante si un dominio lo justifica.

Consecuencias

  • Permite testear la lógica de negocio sin base de datos real (mockeando el repository).
  • Permite cambiar de motor de base de datos sin tocar los services.
  • Permite auditar exactamente dónde se toca la base de datos.
  • Exige disciplina de revisión: cualquier PR que rompa la separación de capas se rechaza, igual que uno que introduce un patrón nuevo sin su ADR correspondiente (ver ADR 0002 y siguientes sobre el proceso de ADR).
  • Particularidades del ERP que no tiene el CRM (capa de integraciones contables externas, scheduled jobs, agregación para reportes pesados) quedan fuera de este ADR y deben documentarse en ADRs propios cuando se construyan.