erp-core/docs/01-analisis-referencias/gamilit/backend-patterns.md
rckrdmrd 4c4e27d9ba feat: Documentation and orchestration updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:35:20 -06:00

25 KiB

Patrones de Backend - GAMILIT

Documento: Analisis de Patrones de Backend Node.js + TypeScript Proyecto de Referencia: GAMILIT Fecha: 2025-11-23 Analista: Architecture-Analyst Agent


1. VISION GENERAL

GAMILIT implementa un backend modular en Node.js 18+ con Express.js y TypeScript 5+ que demuestra excelentes practicas de organizacion, separacion de responsabilidades y mantenibilidad del codigo.

Stack tecnologico:

  • Runtime: Node.js 18+
  • Framework: Express.js
  • Lenguaje: TypeScript 5+ (strict mode)
  • Database Client: node-postgres (pg)
  • Testing: Jest (40 tests, 15% coverage - GAP CRITICO)
  • Process Manager: PM2
  • Linting: ESLint + Prettier

Metricas:

  • LOC: ~45,000 lineas
  • Modulos: 11 modulos funcionales
  • Endpoints: 470+ API endpoints
  • Controllers: ~50
  • Services: ~80
  • DTOs: ~100
  • Entities: ~40

2. ESTRUCTURA MODULAR (11 MODULOS)

2.1 Organizacion del Backend

backend/
├── src/
│   ├── shared/              # Codigo compartido (constants SSOT, utils, types)
│   │   ├── constants/       # ⭐ Single Source of Truth
│   │   │   ├── enums.constants.ts      # 687 lineas de ENUMs
│   │   │   ├── database.constants.ts   # Schemas y tablas
│   │   │   ├── routes.constants.ts     # 368 lineas de rutas API
│   │   │   ├── regex.ts                # Expresiones regulares
│   │   │   └── index.ts                # Barrel export
│   │   ├── types/           # Tipos TypeScript compartidos
│   │   ├── utils/           # Utilidades generales
│   │   └── decorators/      # Decoradores personalizados
│   │
│   ├── middleware/          # Middleware de Express
│   │   ├── auth.middleware.ts          # Autenticacion JWT
│   │   ├── validation.middleware.ts    # Validacion de DTOs
│   │   ├── error.middleware.ts         # Manejo de errores global
│   │   └── logging.middleware.ts       # Logging de requests
│   │
│   ├── config/              # Configuraciones
│   │   ├── database.config.ts          # Configuracion DB
│   │   ├── jwt.config.ts               # Configuracion JWT
│   │   └── cors.config.ts              # Configuracion CORS
│   │
│   ├── database/            # Conexion DB, migrations, seeds
│   │   ├── connection.ts               # Pool de conexiones
│   │   └── pool.ts                     # Singleton pool
│   │
│   ├── modules/             # ⭐ 11 MODULOS DE NEGOCIO
│   │   ├── auth/            # Autenticacion y autorizacion
│   │   ├── educational/     # Contenido educativo
│   │   ├── gamification/    # Sistema de gamificacion
│   │   ├── progress/        # Tracking de progreso
│   │   ├── social/          # Features sociales
│   │   ├── content/         # Content management
│   │   ├── admin/           # Panel de administracion
│   │   ├── teacher/         # Portal de profesor
│   │   ├── analytics/       # Analytics y reportes
│   │   ├── notifications/   # Sistema de notificaciones
│   │   └── system/          # Sistema y configuracion
│   │
│   └── main.ts              # Entry point de la aplicacion
│
├── __tests__/               # Tests (40 tests, 15% coverage)
├── dist/                    # Build output (compilado)
├── logs/                    # Application logs
├── node_modules/            # Dependencies (95 MB)
├── package.json             # NPM config
├── tsconfig.json            # ⭐ TypeScript config (path aliases)
├── jest.config.js           # Jest config
├── .eslintrc.js             # ESLint config
└── README.md                # Documentacion

2.2 Los 11 Modulos Funcionales

Modulo Responsabilidad Endpoints Aplicabilidad ERP
auth/ Autenticacion, autorizacion, usuarios, roles ~40 MAXIMA
educational/ Modulos, ejercicios, recursos educativos ~60 No aplicable
gamification/ Logros, rangos, ML Coins, comodines ~80 No aplicable
progress/ Tracking de progreso, sesiones, attempts ~90 🔧 Adaptar (avance de obra)
social/ Aulas, equipos, amistades, desafios ~70 🔧 Adaptar (jerarquias)
content/ Plantillas, multimedia, Marie Curie ~40 🔧 Adaptar (docs, plantillas)
admin/ Panel de administracion, bulk operations ~30 MAXIMA
teacher/ Portal de profesor, grading, classrooms ~30 🔧 Adaptar (supervisor)
analytics/ Analytics, reportes, metricas ~20 MAXIMA
notifications/ Notificaciones multi-canal ~10 MAXIMA
system/ Configuracion, feature flags, health ~10 MAXIMA

Total endpoints: 470+


3. PATRON DE MODULO TIPICO

Cada modulo en GAMILIT sigue un patron consistente que facilita navegacion y mantenimiento:

3.1 Estructura de un Modulo (ejemplo: auth/)

modules/auth/
├── entities/              # Entidades de base de datos
│   ├── user.entity.ts
│   ├── role.entity.ts
│   ├── session.entity.ts
│   └── tenant.entity.ts
│
├── dtos/                  # Data Transfer Objects (validacion)
│   ├── login.dto.ts
│   ├── register.dto.ts
│   ├── update-profile.dto.ts
│   └── change-password.dto.ts
│
├── services/              # Logica de negocio
│   ├── auth.service.ts           # Servicio principal
│   ├── user.service.ts           # Servicios especializados
│   ├── session.service.ts
│   └── tenant.service.ts
│
├── controllers/           # Controllers Express (rutas)
│   ├── auth.controller.ts
│   └── user.controller.ts
│
├── routes/                # Definicion de rutas
│   ├── auth.routes.ts            # Rutas de autenticacion
│   └── user.routes.ts            # Rutas de usuarios
│
├── middleware/            # Middleware especifico del modulo
│   ├── auth.middleware.ts        # Verificacion JWT
│   └── rate-limit.middleware.ts  # Rate limiting
│
├── validators/            # Validadores personalizados
│   └── user.validator.ts
│
├── types/                 # Tipos TypeScript del modulo
│   └── auth.types.ts
│
└── index.ts               # Barrel export (Public API)

3.2 Capas del Modulo

1. Entities (Entidades):

  • Representacion de tablas de base de datos
  • Mapeo 1:1 con esquema PostgreSQL
  • Tipos TypeScript para type safety

Ejemplo user.entity.ts:

import { DB_SCHEMAS, DB_TABLES } from '@shared/constants';

export interface UserEntity {
  id: string;
  email: string;
  password_hash: string;
  tenant_id: string;
  created_at: Date;
  updated_at: Date;
}

export const USER_TABLE = `${DB_SCHEMAS.AUTH}.${DB_TABLES.AUTH.USERS}`;

2. DTOs (Data Transfer Objects):

  • Validacion de datos de entrada
  • Transformacion de datos
  • Documentacion de contratos

Ejemplo login.dto.ts:

export interface LoginDto {
  email: string;      // Validacion: email valido
  password: string;   // Validacion: minimo 8 caracteres
  tenant_id?: string; // Opcional para multi-tenancy
}

export function validateLoginDto(data: unknown): LoginDto {
  // Validacion con Zod, class-validator, etc.
  // ...
  return data as LoginDto;
}

3. Services (Servicios):

  • Logica de negocio
  • Interaccion con base de datos
  • Orquestacion de operaciones

Ejemplo auth.service.ts:

import { pool } from '@database/pool';
import { USER_TABLE } from './entities/user.entity';
import { DB_SCHEMAS } from '@shared/constants';

export class AuthService {
  async login(dto: LoginDto): Promise<LoginResponse> {
    // 1. Buscar usuario por email
    const user = await this.findUserByEmail(dto.email);

    // 2. Verificar password
    const isValid = await bcrypt.compare(dto.password, user.password_hash);
    if (!isValid) throw new UnauthorizedError();

    // 3. Generar JWT
    const token = jwt.sign({ userId: user.id }, JWT_SECRET);

    // 4. Crear sesion
    await this.createSession(user.id, token);

    return { user, token };
  }

  private async findUserByEmail(email: string): Promise<UserEntity> {
    const result = await pool.query(
      `SELECT * FROM ${USER_TABLE} WHERE email = $1`,
      [email]
    );
    return result.rows[0];
  }
}

4. Controllers (Controladores):

  • Manejo de requests HTTP
  • Validacion de input
  • Delegacion a servicios
  • Manejo de responses

Ejemplo auth.controller.ts:

import { Router } from 'express';
import { AuthService } from './services/auth.service';
import { API_ROUTES } from '@shared/constants';

const router = Router();
const authService = new AuthService();

// POST /api/v1/auth/login
router.post(API_ROUTES.AUTH.LOGIN, async (req, res, next) => {
  try {
    const dto = validateLoginDto(req.body);
    const result = await authService.login(dto);
    res.json(result);
  } catch (error) {
    next(error);
  }
});

export default router;

5. Routes (Rutas):

  • Configuracion de rutas
  • Aplicacion de middleware
  • Documentacion de endpoints

6. Middleware:

  • Autenticacion
  • Autorizacion
  • Validacion
  • Rate limiting

7. Validators:

  • Validaciones personalizadas
  • Reglas de negocio

4. PATH ALIASES (IMPORTS LIMPIOS)

4.1 Configuracion en tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./*"],
      "@shared/*": ["shared/*"],
      "@middleware/*": ["middleware/*"],
      "@config/*": ["config/*"],
      "@database/*": ["database/*"],
      "@modules/*": ["modules/*"]
    }
  }
}

4.2 Comparacion de Imports

SIN PATH ALIASES (malo, fragil):

import { UserEntity } from '../../../modules/auth/entities/user.entity';
import { DB_SCHEMAS } from '../../../shared/constants/database.constants';
import { AuthService } from '../../../modules/auth/services/auth.service';
import { validateLoginDto } from '../../../modules/auth/dtos/login.dto';

CON PATH ALIASES (bueno, mantenible):

import { UserEntity } from '@modules/auth/entities/user.entity';
import { DB_SCHEMAS } from '@shared/constants/database.constants';
import { AuthService } from '@modules/auth/services/auth.service';
import { validateLoginDto } from '@modules/auth/dtos/login.dto';

4.3 Beneficios

  1. Legibilidad: Imports semanticos y claros
  2. Mantenibilidad: Facil refactoring de estructura
  3. Prevencion de errores: No mas ../../../ incorrectos
  4. IDE Support: Autocompletado mejorado
  5. Consistencia: Mismo patron en todo el proyecto

4.4 Aplicabilidad a ERP Generico

(MAXIMA)

Decision: ADOPTAR COMPLETAMENTE

Aliases propuestos para ERP:

{
  "paths": {
    "@/*": ["./*"],
    "@shared/*": ["shared/*"],
    "@middleware/*": ["middleware/*"],
    "@config/*": ["config/*"],
    "@database/*": ["database/*"],
    "@modules/*": ["modules/*"],
    "@shared/*": ["modules/core/*"],
    "@accounting/*": ["modules/accounting/*"],
    "@budgets/*": ["modules/budgets/*"],
    "@purchasing/*": ["modules/purchasing/*"]
  }
}

5. MIDDLEWARE PATTERNS

5.1 Tipos de Middleware Implementados

1. Authentication Middleware:

// middleware/auth.middleware.ts
import jwt from 'jsonwebtoken';

export const authenticate = async (req, res, next) => {
  try {
    const token = extractToken(req.headers.authorization);
    const decoded = jwt.verify(token, JWT_SECRET);

    // Establecer contexto del usuario
    req.user = decoded;
    req.userId = decoded.userId;
    req.tenantId = decoded.tenantId;

    next();
  } catch (error) {
    res.status(401).json({ error: 'Unauthorized' });
  }
};

2. Validation Middleware:

// middleware/validation.middleware.ts
export const validateDto = (schema) => {
  return (req, res, next) => {
    try {
      req.body = schema.parse(req.body);
      next();
    } catch (error) {
      res.status(400).json({ errors: error.errors });
    }
  };
};

// Uso:
router.post('/login', validateDto(loginSchema), authController.login);

3. Error Middleware:

// middleware/error.middleware.ts
export const errorHandler = (err, req, res, next) => {
  console.error(err);

  // Errores conocidos
  if (err instanceof UnauthorizedError) {
    return res.status(401).json({ error: err.message });
  }

  if (err instanceof ValidationError) {
    return res.status(400).json({ errors: err.errors });
  }

  // Error generico
  res.status(500).json({ error: 'Internal server error' });
};

4. Logging Middleware:

// middleware/logging.middleware.ts
export const requestLogger = (req, res, next) => {
  const start = Date.now();

  res.on('finish', () => {
    const duration = Date.now() - start;
    console.log(`${req.method} ${req.url} ${res.statusCode} - ${duration}ms`);
  });

  next();
};

5.2 Aplicabilidad a ERP Generico

(MAXIMA)

Decision: ADOPTAR COMPLETAMENTE

Middleware criticos para ERP:

  • Authentication (JWT con multi-tenancy)
  • Authorization (permisos por rol)
  • Validation (DTOs con Zod)
  • Error handling (global)
  • Logging (auditoria de requests)
  • Rate limiting (proteccion DDoS)

6. ERROR HANDLING

6.1 Jerarquia de Errores Personalizados

// shared/errors/base.error.ts
export class AppError extends Error {
  constructor(
    public statusCode: number,
    public message: string,
    public isOperational = true
  ) {
    super(message);
    Error.captureStackTrace(this, this.constructor);
  }
}

// Errores especificos
export class UnauthorizedError extends AppError {
  constructor(message = 'Unauthorized') {
    super(401, message);
  }
}

export class NotFoundError extends AppError {
  constructor(resource: string) {
    super(404, `${resource} not found`);
  }
}

export class ValidationError extends AppError {
  constructor(public errors: any[]) {
    super(400, 'Validation failed');
  }
}

export class ForbiddenError extends AppError {
  constructor(message = 'Forbidden') {
    super(403, message);
  }
}

export class ConflictError extends AppError {
  constructor(message: string) {
    super(409, message);
  }
}

6.2 Uso en Servicios

// modules/auth/services/auth.service.ts
export class AuthService {
  async findUserById(id: string): Promise<UserEntity> {
    const user = await this.userRepository.findById(id);

    if (!user) {
      throw new NotFoundError('User');
    }

    return user;
  }

  async updateUser(id: string, dto: UpdateUserDto): Promise<UserEntity> {
    // Verificar si email ya existe
    const existing = await this.userRepository.findByEmail(dto.email);
    if (existing && existing.id !== id) {
      throw new ConflictError('Email already in use');
    }

    return await this.userRepository.update(id, dto);
  }
}

6.3 Aplicabilidad a ERP Generico

(MAXIMA)

Decision: ADOPTAR COMPLETAMENTE


7. DATABASE PATTERNS

7.1 Connection Pool (Singleton)

// database/pool.ts
import { Pool } from 'pg';
import { DB_CONFIG } from '@config/database.config';

let pool: Pool | null = null;

export function getPool(): Pool {
  if (!pool) {
    pool = new Pool({
      host: DB_CONFIG.host,
      port: DB_CONFIG.port,
      database: DB_CONFIG.database,
      user: DB_CONFIG.user,
      password: DB_CONFIG.password,
      max: 20,              // Maximo 20 conexiones
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 2000,
    });
  }

  return pool;
}

export const pool = getPool();

7.2 Uso de Constants para Queries

import { pool } from '@database/pool';
import { DB_SCHEMAS, DB_TABLES, getFullTableName } from '@shared/constants';

export class UserRepository {
  private readonly TABLE = getFullTableName(
    DB_SCHEMAS.AUTH,
    DB_TABLES.AUTH.USERS
  );

  async findById(id: string): Promise<UserEntity | null> {
    const result = await pool.query(
      `SELECT * FROM ${this.TABLE} WHERE id = $1`,
      [id]
    );
    return result.rows[0] || null;
  }

  async create(user: CreateUserDto): Promise<UserEntity> {
    const result = await pool.query(
      `INSERT INTO ${this.TABLE} (email, password_hash, tenant_id)
       VALUES ($1, $2, $3)
       RETURNING *`,
      [user.email, user.passwordHash, user.tenantId]
    );
    return result.rows[0];
  }
}

7.3 Transacciones

export class OrderService {
  async createOrderWithItems(dto: CreateOrderDto): Promise<Order> {
    const client = await pool.connect();

    try {
      await client.query('BEGIN');

      // 1. Crear orden
      const order = await this.createOrder(client, dto);

      // 2. Crear items
      await this.createOrderItems(client, order.id, dto.items);

      // 3. Actualizar inventario
      await this.updateInventory(client, dto.items);

      await client.query('COMMIT');
      return order;
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  }
}

7.4 Critica: Sin ORM

Observacion: GAMILIT usa node-postgres (pg) directamente, sin ORM.

Ventajas:

  • Control total sobre queries
  • Performance optimo
  • Queries SQL explicitas

Desventajas:

  • Sin type safety en queries
  • Mapeo manual de resultados
  • Migrations manuales
  • Propenso a SQL injection si no se usan placeholders

Recomendacion para ERP Generico:

(ALTA)

Decision: 🔧 CONSIDERAR TypeORM o Prisma

Justificacion:

  • Type safety completo
  • Migrations automaticas
  • Query builder type-safe
  • Reduccion de codigo boilerplate

8. TESTING PATTERNS

8.1 Metricas de Testing (GAP CRITICO)

Metrica Actual Objetivo Gap
Tests Backend 40 210 -170 (81%)
Coverage 15% 70% -55pp

Critica: Coverage extremadamente bajo. NO copiar este anti-patron.

8.2 Ejemplos de Tests (los pocos que existen)

Test de Servicio:

// modules/auth/__tests__/auth.service.test.ts
describe('AuthService', () => {
  let authService: AuthService;

  beforeEach(() => {
    authService = new AuthService();
  });

  describe('login', () => {
    it('should return token for valid credentials', async () => {
      const dto = { email: 'test@example.com', password: 'password123' };
      const result = await authService.login(dto);

      expect(result).toHaveProperty('token');
      expect(result).toHaveProperty('user');
    });

    it('should throw UnauthorizedError for invalid password', async () => {
      const dto = { email: 'test@example.com', password: 'wrong' };

      await expect(authService.login(dto)).rejects.toThrow(UnauthorizedError);
    });
  });
});

8.3 Recomendacion para ERP Generico

(MAXIMA - CRITICO)

Decision: IMPLEMENTAR TESTING DESDE EL INICIO

Objetivos:

  • Coverage: 70%+ desde el inicio
  • TDD: Test-Driven Development
  • Tests por capa: Unit, Integration, E2E
  • CI/CD: Tests automaticos en pipeline

Herramientas:

  • Jest para unit tests
  • Supertest para integration tests
  • Test containers para tests con DB

9. MATRIZ DE DECISION: ADOPTAR / ADAPTAR / EVITAR

9.1 ADOPTAR COMPLETAMENTE

Patron Descripcion Justificacion Prioridad
Estructura modular 11 modulos funcionales independientes Organizacion clara, escalable P0
Patron de modulo entities, dtos, services, controllers, routes Consistencia en toda la aplicacion P0
Path aliases @shared, @modules, @config, etc. Imports limpios y mantenibles P0
Middleware patterns auth, validation, error, logging Separacion de responsabilidades P0
Error handling Jerarquia de errores personalizados Manejo consistente de errores P0
Connection pool Singleton pool de conexiones PostgreSQL Performance y gestion de conexiones P0
Constants SSOT Backend como fuente de verdad Eliminacion de hardcoding P0

9.2 ADAPTAR / MEJORAR 🔧

Patron Estado Actual Mejora Propuesta Prioridad
Database access node-postgres directo TypeORM o Prisma (type safety) P1
Testing 15% coverage, 40 tests 70%+ coverage, TDD P0 CRITICO
Validation Validacion manual Zod o class-validator P1
Documentation Comentarios en codigo OpenAPI/Swagger specs P1

9.3 EVITAR

Patron Razon Alternativa
Coverage bajo 15% es inaceptable 70%+ coverage desde el inicio
Sin ORM Propenso a errores, sin type safety TypeORM o Prisma
Validacion manual Inconsistente, propenso a errores Zod o class-validator

10. PROPUESTA DE MODULOS PARA ERP GENERICO

Basado en el analisis de GAMILIT, se propone:

backend/src/modules/
├── core/              # Sistema core
│   ├── companies/     # Empresas (multi-tenant)
│   ├── users/         # Usuarios del sistema
│   ├── roles/         # Roles RBAC
│   └── currencies/    # Monedas
│
├── accounting/        # Contabilidad
│   ├── accounts/      # Catalogo de cuentas
│   ├── entries/       # Asientos contables
│   └── reports/       # Reportes financieros
│
├── budgets/           # Presupuestos
│   ├── budgets/       # Presupuestos maestros
│   ├── items/         # Partidas presupuestarias
│   └── tracking/      # Seguimiento de ejecucion
│
├── purchasing/        # Compras
│   ├── suppliers/     # Proveedores
│   ├── orders/        # Ordenes de compra
│   └── invoices/      # Facturas
│
├── inventory/         # Inventario
│   ├── products/      # Productos/Materiales
│   ├── warehouses/    # Almacenes
│   └── movements/     # Movimientos
│
├── projects/          # Proyectos
│   ├── projects/      # Proyectos/Obras
│   ├── phases/        # Fases de proyecto
│   └── team/          # Equipo del proyecto
│
├── hr/                # RRHH
│   ├── employees/     # Empleados
│   ├── payrolls/      # Nominas
│   └── attendance/    # Asistencia
│
├── reports/           # Reportes y Analytics
│   ├── financial/     # Reportes financieros
│   ├── operational/   # Reportes operacionales
│   └── dashboards/    # Dashboards
│
├── notifications/     # Notificaciones
│   └── multi-channel/ # Multi-canal (email, SMS, push)
│
└── admin/             # Administracion
    ├── audit/         # Auditoria
    ├── settings/      # Configuracion
    └── bulk-ops/      # Operaciones bulk

Total modulos propuestos: 10 modulos


11. CONCLUSION Y RECOMENDACIONES

11.1 Hallazgos Clave

  1. Estructura modular excelente:

    • 11 modulos bien organizados
    • Patron consistente por modulo
    • Facil navegacion y mantenimiento
  2. Path aliases son criticos:

    • Imports limpios y semanticos
    • Facil refactoring
  3. Middleware patterns bien implementados:

    • Auth, validation, error, logging
    • Separacion de responsabilidades
  4. Testing es GAP CRITICO:

    • 15% coverage es inaceptable
    • Solo 40 tests para 45,000 LOC
    • NO copiar este anti-patron

11.2 Recomendaciones Finales

ADOPTAR COMPLETAMENTE (Prioridad P0)

  1. Estructura modular (10 modulos para ERP)
  2. Patron de modulo (entities, dtos, services, controllers)
  3. Path aliases (@shared, @modules, @config)
  4. Middleware patterns (auth, validation, error)
  5. Error handling con jerarquia de errores
  6. Connection pool singleton
  7. Constants SSOT (Backend como fuente de verdad)

MEJORAR RESPECTO A GAMILIT 🔧 (Prioridad P0-P1)

  1. Testing: 70%+ coverage desde el inicio (P0 CRITICO)
  2. ORM: Usar TypeORM o Prisma (P1)
  3. Validation: Zod o class-validator (P1)
  4. Documentation: OpenAPI/Swagger (P1)
  5. DevOps: Docker, CI/CD completo (P0)

EVITAR

  1. Coverage bajo (15%)
  2. Sin ORM (propenso a errores)
  3. Validacion manual inconsistente

Documento creado: 2025-11-23 Ultima actualizacion: 2025-11-23 Version: 1.0 Estado: Completado Proximo documento: frontend-patterns.md