19 KiB
Architecture
Overview
ERP Suite es una suite empresarial multi-vertical diseñada para SaaS simple autocontratado y proyectos integrales personalizados. La arquitectura maximiza la reutilización de código mediante un core genérico (60-70% compartido) que es extendido por verticales especializadas según el giro de negocio.
Diseño basado en Odoo: La arquitectura sigue los patrones de diseño de Odoo ERP, adaptados para Node.js/React.
Tech Stack
- Backend: Node.js 20+ + Express.js 4.18+ + TypeScript 5.3+
- Frontend Web: React 18.3+ + Vite 5.4+ + TypeScript 5.6+ + Tailwind CSS
- Frontend Mobile: React Native (future)
- Database: PostgreSQL 15+ con RLS (Row-Level Security)
- State Management: Zustand 5.0
- Validation: Zod 3.22+
- Auth: JWT + bcryptjs
- ORM: pg (raw queries, no ORM pesado)
Module Structure
Project-Level Organization (Autocontenido)
erp-suite/
├── apps/
│ ├── erp-core/ # ERP Base (60-70% compartido)
│ │ ├── backend/ # Node.js + Express + TypeScript
│ │ │ └── src/
│ │ │ ├── modules/ # 14 módulos core
│ │ │ │ ├── auth/ # JWT, bcrypt, refresh tokens
│ │ │ │ ├── users/ # CRUD usuarios
│ │ │ │ ├── companies/ # Multi-company management
│ │ │ │ ├── core/ # Catálogos (monedas, países, UoM)
│ │ │ │ ├── partners/ # Clientes/proveedores
│ │ │ │ ├── inventory/ # Productos, almacenes, stock
│ │ │ │ ├── financial/ # Contabilidad
│ │ │ │ ├── purchases/ # Órdenes de compra
│ │ │ │ ├── sales/ # Cotizaciones, pedidos
│ │ │ │ ├── projects/ # Proyectos, tareas, timesheets
│ │ │ │ ├── crm/ # Leads, oportunidades
│ │ │ │ ├── hr/ # Nómina básica
│ │ │ │ └── system/ # Mensajes, notificaciones
│ │ │ ├── shared/ # Código compartido
│ │ │ │ ├── services/ # BaseService genérico
│ │ │ │ ├── middleware/ # Auth, error handling
│ │ │ │ ├── utils/ # Helpers
│ │ │ │ └── types/ # TypeScript types
│ │ │ ├── config/ # Configuration
│ │ │ └── routes/ # API routes
│ │ │
│ │ ├── frontend/ # React + Vite + Tailwind
│ │ │ └── src/
│ │ │ ├── modules/ # Feature modules
│ │ │ ├── shared/ # Shared components
│ │ │ └── layouts/ # App layouts
│ │ │
│ │ ├── database/ # PostgreSQL
│ │ │ ├── ddl/ # Schema definitions
│ │ │ │ └── schemas/ # 12 schemas, 144 tables
│ │ │ ├── migrations/ # Database migrations
│ │ │ └── seeds/ # Test data
│ │ │
│ │ ├── docs/ # Documentación PROPIA del core
│ │ └── orchestration/ # Sistema de agentes PROPIO
│ │
│ ├── verticales/
│ │ ├── construccion/ # Vertical INFONAVIT (35%)
│ │ │ ├── backend/ # Extensiones backend
│ │ │ │ └── src/
│ │ │ │ ├── modules/ # 15 módulos específicos
│ │ │ │ │ ├── projects/ # Override core projects
│ │ │ │ │ ├── budgets/ # Presupuestos obra
│ │ │ │ │ ├── construction/ # Control de obra
│ │ │ │ │ ├── quality/ # Calidad y postventa
│ │ │ │ │ ├── infonavit/ # Integración INFONAVIT
│ │ │ │ │ └── ...
│ │ │ │ └── shared/ # Extensiones compartidas
│ │ │ │
│ │ │ ├── frontend/ # UI específica construcción
│ │ │ ├── database/ # Schemas adicionales
│ │ │ │ └── ddl/
│ │ │ │ └── schemas/ # 7 schemas verticales
│ │ │ ├── docs/ # 403 docs (5.9 MB)
│ │ │ └── orchestration/ # Sistema de agentes PROPIO
│ │ │
│ │ ├── vidrio-templado/ # Vertical (0%)
│ │ │ ├── docs/
│ │ │ └── orchestration/
│ │ │
│ │ ├── mecanicas-diesel/ # Vertical (30%)
│ │ │ ├── docs/
│ │ │ └── orchestration/
│ │ │
│ │ ├── retail/ # Vertical POS
│ │ └── clinicas/ # Vertical Clínicas
│ │
│ ├── saas/ # Capa SaaS (billing, multi-tenant)
│ │ ├── onboarding/ # Onboarding de tenants
│ │ ├── admin/ # Admin panel SaaS
│ │ ├── billing/ # Facturación SaaS
│ │ └── portal/ # Portal cliente
│ │
│ └── shared-libs/ # Librerías compartidas
│ └── core/ # Utilidades cross-project
│
├── docs/ # Documentación GENERAL del suite
└── orchestration/ # Orquestación GENERAL del suite
Database Schemas
ERP Core (12 schemas, 144 tables)
| Schema | Purpose | Tables | Key Entities |
|---|---|---|---|
| auth | Autenticación, usuarios, roles | 10 | users, roles, permissions, sessions |
| core | Partners, catálogos | 12 | partners, currencies, countries, uom |
| analytics | Contabilidad analítica | 7 | analytic_accounts, cost_centers |
| financial | Facturas, pagos | 15 | invoices, payments, journals, accounts |
| products | Productos, categorías | 8 | products, categories, pricelists |
| inventory | Almacenes, stock | 14 | warehouses, locations, stock_moves |
| sales | Ventas | 10 | quotations, sales_orders, deliveries |
| purchases | Compras | 12 | purchase_orders, receptions |
| projects | Proyectos, tareas | 18 | projects, tasks, timesheets |
| hr | Recursos humanos | 12 | employees, contracts, payroll |
| crm | CRM | 10 | leads, opportunities, campaigns |
| system | Sistema | 16 | messages, notifications, settings |
Vertical Construcción (7 schemas adicionales, 60+ tables)
| Schema | Purpose | Tables |
|---|---|---|
| project_management | Proyectos, desarrollos, fases | 15 |
| financial_management | Presupuestos, estimaciones | 12 |
| construction_management | Avances, recursos, materiales | 10 |
| quality_management | Inspecciones, pruebas | 8 |
| infonavit_management | Integración INFONAVIT | 7 |
| purchasing_management | Compras específicas | 6 |
| crm_management | CRM Derechohabientes | 5 |
Data Flow Architecture
┌──────────────┐
│ Frontend │ (React SPA)
│ (Browser) │
└──────┬───────┘
│ HTTP
▼
┌─────────────────────────────────────────┐
│ Backend API (Express.js) │
│ ┌─────────────────────────────────┐ │
│ │ Routes (REST Endpoints) │ │
│ └────────┬────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Controllers │ │
│ └────────┬────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Services (Business Logic) │ │
│ │ - BaseService<T> │ │
│ │ - Multi-tenancy enforcement │ │
│ └────────┬────────────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Database (pg driver) │ │
│ │ - Raw SQL queries │ │
│ │ - Parameterized │ │
│ └─────────────────────────────────┘ │
└───────────┼──────────────────────────────┘
▼
┌─────────────────┐
│ PostgreSQL │
│ (RLS enabled) │
│ tenant_id │
└─────────────────┘
Multi-Tenancy Flow
1. User login → JWT with tenant_id
2. Request to API with JWT
3. Middleware extracts tenant_id
4. SET LOCAL app.current_tenant_id = 'tenant-uuid'
5. RLS policies filter data automatically
6. Only tenant's data returned
Key Design Decisions
1. BaseService Pattern (Elimina duplicación de código)
Decision: Implementar servicio genérico base que todos los módulos extienden.
Rationale:
- Elimina ~80% de código duplicado CRUD
- Multi-tenancy enforcement automático
- Paginación, filtrado, búsqueda consistente
- Soft-delete por defecto
- Transactions simplificadas
Implementation:
// shared/services/base.service.ts
abstract class BaseService<T, CreateDto, UpdateDto> {
constructor(
protected tableName: string,
protected schema: string
) {}
async findAll(
tenantId: string,
filters?: Filters,
pagination?: Pagination
): Promise<PaginatedResult<T>> {
// Auto-adds tenant_id filter
// Supports: search, sort, pagination
// Returns: { data, total, page, limit }
}
async findById(id: string, tenantId: string): Promise<T | null> {}
async create(data: CreateDto, tenantId: string, userId: string): Promise<T> {}
async update(id: string, data: UpdateDto, tenantId: string, userId: string): Promise<T> {}
async softDelete(id: string, tenantId: string, userId: string): Promise<boolean> {}
async withTransaction<R>(fn: (client: PoolClient) => Promise<R>): Promise<R> {}
}
Usage:
// modules/products/product.service.ts
class ProductService extends BaseService<Product, CreateProductDto, UpdateProductDto> {
constructor() {
super('products', 'products');
}
// Override only when needed
async findByBarcode(barcode: string, tenantId: string): Promise<Product | null> {
// Custom query
}
}
2. Schema-Level Multi-Tenancy + RLS
Decision: Usar tenant_id en cada tabla + Row-Level Security de PostgreSQL.
Rationale:
- Aislamiento a nivel de base de datos (más seguro)
- RLS previene acceso cruzado incluso con bugs
- No requiere filtros manuales en cada query
- Compatible con herramientas de BI
Implementation:
-- Todas las tablas
CREATE TABLE products.products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
name VARCHAR(255) NOT NULL,
-- ...
deleted_at TIMESTAMPTZ
);
-- RLS Policy estándar
ALTER TABLE products.products ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON products.products
USING (tenant_id = current_setting('app.current_tenant_id')::uuid);
Backend:
// Middleware sets tenant context
app.use(async (req, res, next) => {
const tenantId = req.user.tenantId;
await pool.query(`SET LOCAL app.current_tenant_id = $1`, [tenantId]);
next();
});
3. Vertical Extension Pattern (Herencia de Módulos)
Decision: Las verticales extienden módulos del core sin modificarlos.
Rationale:
- Core permanece genérico y reutilizable
- Verticales no "rompen" el core
- Actualizaciones del core no afectan verticales
- Basado en patrón de Odoo ERP
Pattern:
// Core: erp-core/backend/src/modules/projects/project.service.ts
class ProjectService extends BaseService<Project, CreateProjectDto, UpdateProjectDto> {
// Logic genérica
}
// Vertical: construccion/backend/src/modules/projects/construction-project.service.ts
class ConstructionProjectService extends ProjectService {
// Override methods
async create(data: CreateConstructionProjectDto, tenantId, userId) {
// Add construction-specific logic
const project = await super.create(data, tenantId, userId);
await this.createDevelopment(project.id, data.development);
return project;
}
// Add new methods
async createPhase(projectId: string, phase: PhaseDto) {}
async linkToINFONAVIT(projectId: string, infonavitData: any) {}
}
4. Raw SQL over Heavy ORM
Decision: Usar driver pg con queries SQL en lugar de ORM (TypeORM, Prisma).
Rationale:
- Mayor control sobre queries complejas
- Mejor performance (no overhead ORM)
- DDL mantenido manualmente = documentación viva
- Compatible con RLS (muchos ORMs tienen problemas)
- Evita migraciones automáticas peligrosas
Trade-off:
- Más código SQL manual
- No hay auto-migrations
- Type-safety requiere interfaces manuales
Mitigación:
- BaseService abstrae CRUD común
- TypeScript interfaces tipan resultados
- SQL formateado y versionado en DDL
5. Soft Delete por Defecto
Decision: Todas las tablas tienen deleted_at para soft delete.
Rationale:
- Cumplimiento regulatorio (auditoría)
- Recuperación de datos borrados
- Integridad referencial preservada
- Historial completo
Implementation:
ALTER TABLE products.products
ADD COLUMN deleted_at TIMESTAMPTZ;
-- BaseService auto-filtra deleted_at IS NULL
6. Pattern-Based on Odoo
Decision: Replicar patrones de diseño de Odoo ERP (módulos, herencia, vistas).
Rationale:
- Odoo es el ERP open-source más exitoso
- Patrones probados en miles de empresas
- Equipo familiarizado con Odoo
- Facilita migración futura de datos Odoo
Patterns Adopted:
- Modular architecture
- Inheritance (core → vertical)
- Catálogos (countries, currencies, UoM)
- Multi-company
- Wizard pattern for complex operations
Ver: /home/isem/workspace/core/knowledge-base/patterns/PATRON-CORE-ODOO.md
Dependencies
Critical Dependencies
| Dependency | Purpose | Criticality |
|---|---|---|
| PostgreSQL 15+ | Database with RLS | CRITICAL |
| Node.js 20+ | Runtime | CRITICAL |
| Express.js | Web framework | CRITICAL |
| React 18+ | Frontend | CRITICAL |
| pg | PostgreSQL driver | CRITICAL |
| Zod | Validation | HIGH |
| Zustand | State management | MEDIUM |
Internal Dependencies
- erp-core: Base compartida para todas las verticales
- Verticales: Dependen de erp-core (herencia)
- SaaS layer: Depende de erp-core y verticales
Security Considerations
- Authentication: JWT con refresh tokens
- Authorization: RBAC (Role-Based Access Control)
- Multi-tenancy: RLS garantiza aislamiento de datos
- Password Hashing: bcryptjs (10 rounds)
- Input Validation: Zod schemas
- SQL Injection: Parameterized queries (pg)
- XSS Protection: React auto-escape
- CORS: Configurado por entorno
Ver documentación completa: MULTI-TENANCY.md
Performance Optimizations
Database
- Indexes en columnas frecuentes (
tenant_id,created_at, foreign keys) - Partitioning en tablas grandes (future)
- Connection pooling (pg.Pool)
- EXPLAIN ANALYZE para optimización
Backend
- Response caching (future: Redis)
- Pagination obligatoria en listas
- Lazy loading de relaciones
- Batch operations
Frontend
- Code splitting (React.lazy)
- Virtual scrolling para listas largas
- Debouncing en búsquedas
- Optimistic UI updates
Deployment Strategy
Current: Development environment
Future Production:
- Docker containers
- Kubernetes orchestration
- Multi-region for latency
- Database replicas (read/write split)
Monitoring & Observability
Planned:
- Winston logging
- Error tracking (Sentry)
- Performance monitoring (Datadog)
- Database monitoring (pgAdmin, pg_stat_statements)
Vertical Development Order
Recomendado:
- ERP Core (base genérica) - 60% completado
- Construcción (más avanzado) - 35% completado
- Vidrio Templado - 0%
- Mecánicas Diesel - 30%
- Retail - 0%
- Clínicas - 0%
Module Breakdown (ERP Core)
Auth Module
- JWT authentication
- Refresh tokens
- Password reset
- Email verification
- RBAC (roles, permissions)
Users Module
- CRUD usuarios
- User profiles
- Preferences
- Activity tracking
Companies Module
- Multi-company support
- Company settings
- Fiscal configuration
Partners Module
- Clientes y proveedores
- Contactos
- Direcciones
- Categorías
Inventory Module
- Productos
- Categorías
- Almacenes
- Movimientos de stock
- Valoración (FIFO, LIFO, Average)
Financial Module
- Plan de cuentas
- Diarios contables
- Asientos contables
- Conciliación bancaria
- Reportes financieros
Sales Module
- Cotizaciones
- Órdenes de venta
- Entregas
- Facturación
Purchases Module
- Solicitudes de compra
- Órdenes de compra
- Recepciones
- Facturas de proveedor
Projects Module
- Proyectos
- Tareas
- Timesheets
- Planificación
HR Module
- Empleados
- Contratos
- Nómina básica
- Asistencias
CRM Module
- Leads
- Oportunidades
- Campañas
- Pipeline
Future Improvements
Short-term
- Completar modules faltantes en erp-core
- Implementar tests unitarios
- Agregar Redis caching
- Mobile app (React Native)
Medium-term
- Completar vertical Construcción
- Implementar vertical Vidrio Templado
- SaaS layer (billing, onboarding)
- Marketplace de módulos
Long-term
- Multi-currency completo
- Integración con pasarelas de pago
- BI/Analytics integrado
- AI-powered features
- White-label solution