template-saas/docs/01-modulos/SAAS-012-crud-base.md
rckrdmrd 50a821a415
Some checks failed
CI / Backend CI (push) Has been cancelled
CI / Frontend CI (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / CI Summary (push) Has been cancelled
[SIMCO-V38] feat: Actualizar a SIMCO v3.8.0
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Actualizaciones de configuracion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:08 -06:00

5.3 KiB

id title type status priority module version created_date updated_date
SAAS-012 Patrones Base CRUD Module Published P2 crud-base 1.0.0 2026-01-07 2026-01-10

SAAS-012: Patrones Base CRUD

Metadata

Campo Valor
Codigo SAAS-012
Modulo crud-base
Prioridad P2
Estado Documentacion
Tipo Guia de Patrones
Ultima Actualizacion 2026-01-10

Descripcion

Este documento describe los patrones CRUD utilizados en el proyecto template-saas. Actualmente cada modulo implementa su propia logica CRUD de forma independiente, siguiendo las convenciones descritas aqui.

Nota importante: Las clases base documentadas (BaseCrudService, BaseCrudController) son patrones recomendados, no clases implementadas. Cada modulo implementa su propia logica siguiendo estos patrones.


Patron Arquitectonico Actual

Estructura por Modulo

Cada modulo backend sigue esta estructura:

modules/[nombre]/
├── [nombre].controller.ts   # Endpoints REST
├── [nombre].module.ts       # Configuracion NestJS
├── [nombre].service.ts      # Logica de negocio (o services/*.service.ts)
├── dto/
│   ├── create-[nombre].dto.ts
│   ├── update-[nombre].dto.ts
│   └── [nombre]-response.dto.ts
├── entities/
│   └── [nombre].entity.ts   # Entidad TypeORM
└── __tests__/
    └── [nombre].service.spec.ts

Ejemplo de Modulos que Siguen el Patron

  • modules/storage/ - Patron mas limpio y recomendado
  • modules/webhooks/ - Implementacion completa
  • modules/tenants/ - Implementacion simple

Campos Base Comunes

Todas las entidades incluyen estos campos base:

Campo Tipo Descripcion
id UUID Primary key, auto-generado
tenant_id UUID Foreign key a tenants (RLS)
created_at TIMESTAMP Fecha de creacion
updated_at TIMESTAMP Fecha ultima modificacion
deleted_at TIMESTAMP Soft delete (nullable)
created_by UUID Usuario que creo (opcional)
updated_by UUID Usuario que modifico (opcional)

Patron de Paginacion

Todos los endpoints de listado soportan paginacion:

Query Parameters

interface PaginationQuery {
  page?: number;      // default: 1
  limit?: number;     // default: 10, max: 100
  sort?: string;      // campo a ordenar
  order?: 'ASC' | 'DESC';  // default: 'DESC'
}

Respuesta Paginada

interface PaginatedResponse<T> {
  data: T[];
  meta: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
  };
}

Patron de Filtros

interface FilterQuery {
  search?: string;    // busqueda full-text
  status?: string;    // filtro por estado
  from?: string;      // fecha inicio (ISO)
  to?: string;        // fecha fin (ISO)
}

Endpoints REST Estandar

Cada modulo CRUD expone estos endpoints:

Metodo Ruta Descripcion
GET /[recurso] Listar con paginacion
GET /[recurso]/:id Obtener por ID
POST /[recurso] Crear nuevo
PATCH /[recurso]/:id Actualizar parcial
DELETE /[recurso]/:id Eliminar (soft delete)

SQL Base para Tablas

Template recomendado para nuevas tablas:

CREATE TABLE schema_name.table_name (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),

  -- Campos especificos aqui --

  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ,
  deleted_at TIMESTAMPTZ
);

-- Indices estandar
CREATE INDEX idx_table_tenant ON schema_name.table_name(tenant_id);
CREATE INDEX idx_table_deleted ON schema_name.table_name(deleted_at)
  WHERE deleted_at IS NULL;

-- RLS
ALTER TABLE schema_name.table_name ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON schema_name.table_name
  USING (tenant_id = auth.get_current_tenant());

-- Trigger updated_at
CREATE TRIGGER set_updated_at
  BEFORE UPDATE ON schema_name.table_name
  FOR EACH ROW EXECUTE FUNCTION update_updated_at();

Decoradores y Validacion

Decoradores Utiles

// Excluir de respuesta
@Exclude()
deleted_at: Date;

// Transformar fecha
@Transform(({ value }) => value?.toISOString())
created_at: Date;

// Validacion condicional
@ValidateIf(o => o.type === 'special')
@IsNotEmpty()
specialField: string;

Interceptores

// Transformar respuesta
@UseInterceptors(ClassSerializerInterceptor)

// Log de audit
@UseInterceptors(AuditInterceptor)

Roadmap: Clases Base Genericas

Implementacion Futura Planificada

Se planea implementar clases base reutilizables para reducir duplicacion:

  1. BaseEntity - Campos comunes (id, timestamps, tenant_id)
  2. BaseCrudService - Operaciones CRUD genericas con TypeORM
  3. BaseCrudController - Endpoints REST estandar
  4. BaseDto - Validaciones comunes

Estado: Pendiente de implementacion Prioridad: Baja (cada modulo funciona correctamente de forma independiente) Ubicacion propuesta: apps/backend/src/shared/


Referencias

  • Implementaciones en: apps/backend/src/modules/*/
  • Ejemplo recomendado: modules/storage/
  • DDL templates: apps/database/ddl/schemas/

Ultima actualizacion: 2026-01-10