- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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 recomendadomodules/webhooks/- Implementacion completamodules/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:
- BaseEntity - Campos comunes (id, timestamps, tenant_id)
- BaseCrudService - Operaciones CRUD genericas con TypeORM
- BaseCrudController - Endpoints REST estandar
- 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