erp-construccion-database-v2/schemas/03-hse-schema-ddl.sql
rckrdmrd bf97e26cdf Migración desde erp-construccion/database - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:11:21 -06:00

1269 lines
54 KiB
PL/PgSQL

-- ============================================================================
-- HSE Schema DDL - Seguridad, Salud Ocupacional y Medio Ambiente
-- Modulo: MAA-017 Seguridad HSE
-- Version: 1.0.0
-- Fecha: 2025-12-06
-- ============================================================================
-- Verificar prerequisitos
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'core') THEN
RAISE EXCEPTION 'Schema core no existe. Ejecutar primero erp-core DDL.';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'construction') THEN
RAISE EXCEPTION 'Schema construction no existe. Ejecutar primero construction-schema-ddl.sql';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'hr') THEN
RAISE EXCEPTION 'Schema hr no existe. Ejecutar primero hr-schema-ddl.sql';
END IF;
END $$;
-- Crear schema HSE
CREATE SCHEMA IF NOT EXISTS hse;
-- Configurar search_path
SET search_path TO hse, core, construction, hr, public;
-- ============================================================================
-- EXTENSION PostGIS para geolocalizacion
-- ============================================================================
CREATE EXTENSION IF NOT EXISTS postgis;
-- ============================================================================
-- TIPOS ENUMERADOS
-- ============================================================================
-- Tipos de incidentes
CREATE TYPE hse.tipo_incidente AS ENUM ('accidente', 'incidente', 'casi_accidente');
CREATE TYPE hse.gravedad_incidente AS ENUM ('leve', 'moderado', 'grave', 'fatal');
CREATE TYPE hse.estado_incidente AS ENUM ('abierto', 'en_investigacion', 'cerrado');
CREATE TYPE hse.rol_involucrado AS ENUM ('lesionado', 'testigo', 'responsable');
CREATE TYPE hse.factor_causa AS ENUM ('acto_inseguro', 'condicion_insegura');
-- Tipos de capacitaciones
CREATE TYPE hse.tipo_capacitacion AS ENUM ('induccion', 'especifica', 'certificacion', 'reentrenamiento');
CREATE TYPE hse.estado_sesion AS ENUM ('programada', 'en_curso', 'completada', 'cancelada');
-- Tipos de inspecciones
CREATE TYPE hse.frecuencia AS ENUM ('diaria', 'semanal', 'quincenal', 'mensual', 'eventual');
CREATE TYPE hse.estado_inspeccion AS ENUM ('programada', 'en_progreso', 'completada', 'cancelada', 'vencida');
CREATE TYPE hse.resultado_evaluacion AS ENUM ('cumple', 'no_cumple', 'no_aplica');
CREATE TYPE hse.gravedad_hallazgo AS ENUM ('critico', 'mayor', 'menor');
CREATE TYPE hse.estado_hallazgo AS ENUM ('abierto', 'en_correccion', 'verificando', 'cerrado', 'reabierto');
CREATE TYPE hse.tipo_evidencia AS ENUM ('hallazgo', 'correccion');
-- Tipos de EPP
CREATE TYPE hse.categoria_epp AS ENUM ('cabeza', 'ojos', 'auditiva', 'respiratoria', 'manos', 'pies', 'caidas', 'ropa');
CREATE TYPE hse.estado_epp AS ENUM ('activo', 'vencido', 'danado', 'perdido', 'devuelto');
CREATE TYPE hse.estado_inspeccion_epp AS ENUM ('bueno', 'regular', 'malo', 'danado');
CREATE TYPE hse.motivo_baja_epp AS ENUM ('vencimiento', 'danado', 'perdido', 'terminacion_laboral');
CREATE TYPE hse.tipo_movimiento_epp AS ENUM ('entrada', 'salida', 'transferencia', 'ajuste');
-- Tipos STPS
CREATE TYPE hse.estado_comision AS ENUM ('activa', 'vencida', 'renovada');
CREATE TYPE hse.rol_comision AS ENUM ('presidente', 'secretario', 'vocal_patronal', 'vocal_trabajador');
CREATE TYPE hse.representacion AS ENUM ('patronal', 'trabajadores');
CREATE TYPE hse.estado_recorrido AS ENUM ('programado', 'realizado', 'cancelado', 'pendiente');
CREATE TYPE hse.estado_programa AS ENUM ('borrador', 'activo', 'finalizado');
CREATE TYPE hse.tipo_actividad_programa AS ENUM ('capacitacion', 'inspeccion', 'simulacro', 'campana', 'otro');
CREATE TYPE hse.estado_actividad AS ENUM ('pendiente', 'en_progreso', 'completada', 'cancelada');
CREATE TYPE hse.tipo_documento_stps AS ENUM ('dc1', 'dc2', 'dc3', 'dc4', 'st7', 'st9');
CREATE TYPE hse.tipo_auditoria AS ENUM ('interna', 'simulada', 'stps', 'cliente', 'certificadora');
CREATE TYPE hse.resultado_auditoria AS ENUM ('aprobada', 'aprobada_observaciones', 'no_aprobada');
CREATE TYPE hse.estado_cumplimiento AS ENUM ('cumple', 'parcial', 'no_cumple', 'no_aplica');
-- Tipos ambientales
CREATE TYPE hse.categoria_residuo AS ENUM ('peligroso', 'manejo_especial', 'urbano');
CREATE TYPE hse.unidad_residuo AS ENUM ('kg', 'litros', 'm3', 'piezas');
CREATE TYPE hse.estado_residuo AS ENUM ('almacenado', 'en_transito', 'dispuesto');
CREATE TYPE hse.estado_almacen AS ENUM ('operativo', 'lleno', 'mantenimiento');
CREATE TYPE hse.tipo_proveedor_ambiental AS ENUM ('transportista', 'reciclador', 'confinamiento');
CREATE TYPE hse.estado_manifiesto AS ENUM ('emitido', 'en_transito', 'entregado', 'cerrado');
CREATE TYPE hse.tipo_impacto AS ENUM ('ruido', 'polvo', 'vibraciones', 'agua', 'emision', 'vegetacion', 'otro');
CREATE TYPE hse.severidad AS ENUM ('bajo', 'medio', 'alto');
CREATE TYPE hse.probabilidad AS ENUM ('baja', 'media', 'alta');
CREATE TYPE hse.nivel_riesgo AS ENUM ('tolerable', 'moderado', 'significativo');
CREATE TYPE hse.estado_impacto AS ENUM ('identificado', 'mitigando', 'controlado');
CREATE TYPE hse.origen_queja AS ENUM ('vecino', 'autoridad', 'interno', 'anonimo');
CREATE TYPE hse.tipo_queja AS ENUM ('ruido', 'polvo', 'olores', 'agua', 'otro');
CREATE TYPE hse.estado_queja AS ENUM ('recibida', 'atendiendo', 'cerrada');
-- Tipos permisos de trabajo
CREATE TYPE hse.estado_permiso AS ENUM ('borrador', 'solicitado', 'aprobado_parcial', 'autorizado', 'en_ejecucion', 'suspendido', 'cerrado', 'rechazado', 'vencido');
CREATE TYPE hse.rol_permiso AS ENUM ('ejecutor', 'supervisor', 'vigia', 'operador', 'senalero');
CREATE TYPE hse.decision_autorizacion AS ENUM ('aprobado', 'rechazado');
CREATE TYPE hse.momento_checklist AS ENUM ('pre_trabajo', 'durante', 'post_trabajo');
CREATE TYPE hse.tipo_evento_permiso AS ENUM ('inicio', 'suspension', 'reanudacion', 'extension', 'anomalia', 'cierre');
-- Tipos indicadores
CREATE TYPE hse.tipo_indicador AS ENUM ('reactivo', 'proactivo', 'ambiental');
CREATE TYPE hse.frecuencia_calculo AS ENUM ('diario', 'semanal', 'mensual');
CREATE TYPE hse.periodo_tipo AS ENUM ('diario', 'semanal', 'mensual', 'anual');
CREATE TYPE hse.estado_semaforo AS ENUM ('verde', 'amarillo', 'rojo');
CREATE TYPE hse.fuente_horas AS ENUM ('asistencia', 'manual');
CREATE TYPE hse.tipo_reporte_hse AS ENUM ('semanal', 'mensual', 'trimestral', 'anual');
CREATE TYPE hse.formato_reporte AS ENUM ('pdf', 'excel', 'ambos');
CREATE TYPE hse.tipo_alerta_indicador AS ENUM ('meta_superada', 'tendencia_negativa', 'sin_datos');
-- ============================================================================
-- RF-MAA017-001: GESTION DE INCIDENTES
-- ============================================================================
-- Tabla: Incidentes
CREATE TABLE hse.incidentes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
folio VARCHAR(20) NOT NULL,
fecha_hora TIMESTAMPTZ NOT NULL,
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
ubicacion_descripcion TEXT,
ubicacion_geo GEOMETRY(Point, 4326),
tipo hse.tipo_incidente NOT NULL,
gravedad hse.gravedad_incidente NOT NULL,
descripcion TEXT NOT NULL,
causa_inmediata TEXT,
causa_basica TEXT,
estado hse.estado_incidente NOT NULL DEFAULT 'abierto',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id),
CONSTRAINT uq_incidentes_folio UNIQUE (tenant_id, folio)
);
-- Tabla: Involucrados en incidentes
CREATE TABLE hse.incidente_involucrados (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
incidente_id UUID NOT NULL REFERENCES hse.incidentes(id) ON DELETE CASCADE,
employee_id UUID NOT NULL REFERENCES hr.employees(id),
rol hse.rol_involucrado NOT NULL,
descripcion_lesion TEXT,
parte_cuerpo VARCHAR(100),
dias_incapacidad INTEGER DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Investigacion de incidentes
CREATE TABLE hse.incidente_investigacion (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
incidente_id UUID NOT NULL REFERENCES hse.incidentes(id) ON DELETE CASCADE,
fecha_inicio DATE NOT NULL,
fecha_cierre DATE,
investigador_id UUID REFERENCES hr.employees(id),
metodologia VARCHAR(100),
factor_causa hse.factor_causa,
analisis_causas TEXT,
conclusiones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Acciones correctivas de incidentes
CREATE TABLE hse.incidente_acciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
incidente_id UUID NOT NULL REFERENCES hse.incidentes(id) ON DELETE CASCADE,
descripcion TEXT NOT NULL,
tipo VARCHAR(50) NOT NULL,
responsable_id UUID REFERENCES hr.employees(id),
fecha_compromiso DATE NOT NULL,
fecha_cierre DATE,
estado VARCHAR(20) NOT NULL DEFAULT 'pendiente',
evidencia_url VARCHAR(500),
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Evidencias de incidentes (fotos)
CREATE TABLE hse.incidente_evidencias (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
incidente_id UUID NOT NULL REFERENCES hse.incidentes(id) ON DELETE CASCADE,
tipo VARCHAR(50) NOT NULL DEFAULT 'foto',
archivo_url VARCHAR(500) NOT NULL,
descripcion VARCHAR(200),
ubicacion_geo GEOMETRY(Point, 4326),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id)
);
-- ============================================================================
-- RF-MAA017-002: CONTROL DE CAPACITACIONES
-- ============================================================================
-- Tabla: Catalogo de capacitaciones
CREATE TABLE hse.capacitaciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(200) NOT NULL,
descripcion TEXT,
tipo hse.tipo_capacitacion NOT NULL,
duracion_horas DECIMAL(4,1) NOT NULL,
validez_meses INTEGER,
norma_referencia VARCHAR(50),
requiere_evaluacion BOOLEAN NOT NULL DEFAULT false,
calificacion_minima INTEGER DEFAULT 70,
contenido_tematico TEXT,
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_capacitaciones_codigo UNIQUE (tenant_id, codigo)
);
-- Tabla: Matriz de capacitacion por puesto
CREATE TABLE hse.capacitacion_matriz (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
puesto_id UUID NOT NULL,
capacitacion_id UUID NOT NULL REFERENCES hse.capacitaciones(id),
es_obligatoria BOOLEAN NOT NULL DEFAULT true,
plazo_dias INTEGER DEFAULT 30,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Instructores
CREATE TABLE hse.instructores (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
nombre VARCHAR(200) NOT NULL,
registro_stps VARCHAR(50),
especialidades TEXT,
es_interno BOOLEAN NOT NULL DEFAULT false,
employee_id UUID REFERENCES hr.employees(id),
contacto_telefono VARCHAR(20),
contacto_email VARCHAR(100),
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Sesiones de capacitacion
CREATE TABLE hse.capacitacion_sesiones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
capacitacion_id UUID NOT NULL REFERENCES hse.capacitaciones(id),
fraccionamiento_id UUID REFERENCES construction.fraccionamientos(id),
instructor_id UUID REFERENCES hse.instructores(id),
fecha_programada DATE NOT NULL,
hora_inicio TIME NOT NULL,
hora_fin TIME NOT NULL,
lugar VARCHAR(200),
cupo_maximo INTEGER,
estado hse.estado_sesion NOT NULL DEFAULT 'programada',
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Asistencia a capacitaciones
CREATE TABLE hse.capacitacion_asistentes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sesion_id UUID NOT NULL REFERENCES hse.capacitacion_sesiones(id) ON DELETE CASCADE,
employee_id UUID NOT NULL REFERENCES hr.employees(id),
asistio BOOLEAN DEFAULT false,
hora_entrada TIME,
hora_salida TIME,
calificacion INTEGER,
aprobado BOOLEAN,
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Constancias DC-3
CREATE TABLE hse.constancias_dc3 (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
folio VARCHAR(30) NOT NULL,
asistente_id UUID NOT NULL REFERENCES hse.capacitacion_asistentes(id),
employee_id UUID NOT NULL REFERENCES hr.employees(id),
capacitacion_id UUID NOT NULL REFERENCES hse.capacitaciones(id),
fecha_emision DATE NOT NULL,
fecha_vencimiento DATE,
documento_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_constancias_dc3_folio UNIQUE (tenant_id, folio)
);
-- ============================================================================
-- RF-MAA017-003: INSPECCIONES DE SEGURIDAD
-- ============================================================================
-- Tabla: Tipos de inspeccion
CREATE TABLE hse.tipos_inspeccion (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(200) NOT NULL,
descripcion TEXT,
frecuencia hse.frecuencia NOT NULL,
norma_referencia VARCHAR(50),
duracion_estimada_min INTEGER,
requiere_firma BOOLEAN NOT NULL DEFAULT true,
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_tipos_inspeccion_codigo UNIQUE (tenant_id, codigo)
);
-- Tabla: Items de checklist
CREATE TABLE hse.checklist_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tipo_inspeccion_id UUID NOT NULL REFERENCES hse.tipos_inspeccion(id) ON DELETE CASCADE,
numero_orden INTEGER NOT NULL,
categoria VARCHAR(100),
descripcion TEXT NOT NULL,
criterio_cumplimiento TEXT,
es_critico BOOLEAN NOT NULL DEFAULT false,
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Programa de inspecciones
CREATE TABLE hse.programa_inspecciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
tipo_inspeccion_id UUID NOT NULL REFERENCES hse.tipos_inspeccion(id),
inspector_id UUID REFERENCES hr.employees(id),
fecha_programada DATE NOT NULL,
hora_programada TIME,
zona_area VARCHAR(200),
estado hse.estado_inspeccion NOT NULL DEFAULT 'programada',
motivo_cancelacion TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Inspecciones ejecutadas
CREATE TABLE hse.inspecciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
programa_id UUID REFERENCES hse.programa_inspecciones(id),
tipo_inspeccion_id UUID NOT NULL REFERENCES hse.tipos_inspeccion(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
inspector_id UUID NOT NULL REFERENCES hr.employees(id),
fecha_inicio TIMESTAMPTZ NOT NULL,
fecha_fin TIMESTAMPTZ,
ubicacion_geo GEOMETRY(Point, 4326),
items_evaluados INTEGER DEFAULT 0,
items_cumple INTEGER DEFAULT 0,
items_no_cumple INTEGER DEFAULT 0,
items_no_aplica INTEGER DEFAULT 0,
porcentaje_cumplimiento DECIMAL(5,2),
observaciones_generales TEXT,
firma_inspector TEXT,
estado VARCHAR(20) NOT NULL DEFAULT 'borrador',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Evaluaciones de inspeccion
CREATE TABLE hse.inspeccion_evaluaciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
inspeccion_id UUID NOT NULL REFERENCES hse.inspecciones(id) ON DELETE CASCADE,
checklist_item_id UUID NOT NULL REFERENCES hse.checklist_items(id),
resultado hse.resultado_evaluacion NOT NULL,
observacion TEXT,
genera_hallazgo BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Hallazgos de inspeccion
CREATE TABLE hse.hallazgos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
inspeccion_id UUID NOT NULL REFERENCES hse.inspecciones(id),
evaluacion_id UUID REFERENCES hse.inspeccion_evaluaciones(id),
folio VARCHAR(20) NOT NULL,
gravedad hse.gravedad_hallazgo NOT NULL,
tipo hse.factor_causa NOT NULL,
descripcion TEXT NOT NULL,
ubicacion_descripcion VARCHAR(500),
ubicacion_geo GEOMETRY(Point, 4326),
responsable_correccion_id UUID REFERENCES hr.employees(id),
fecha_limite DATE NOT NULL,
estado hse.estado_hallazgo NOT NULL DEFAULT 'abierto',
fecha_correccion TIMESTAMPTZ,
descripcion_correccion TEXT,
verificador_id UUID REFERENCES hr.employees(id),
fecha_verificacion TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_hallazgos_folio UNIQUE (tenant_id, folio)
);
-- Tabla: Evidencias de hallazgos
CREATE TABLE hse.hallazgo_evidencias (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
hallazgo_id UUID NOT NULL REFERENCES hse.hallazgos(id) ON DELETE CASCADE,
tipo hse.tipo_evidencia NOT NULL,
archivo_url VARCHAR(500) NOT NULL,
descripcion VARCHAR(200),
ubicacion_geo GEOMETRY(Point, 4326),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id)
);
-- ============================================================================
-- RF-MAA017-004: CONTROL DE EPP
-- ============================================================================
-- Tabla: Catalogo de EPP
CREATE TABLE hse.epp_catalogo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(200) NOT NULL,
categoria hse.categoria_epp NOT NULL,
descripcion TEXT,
especificaciones TEXT,
vida_util_dias INTEGER NOT NULL,
norma_referencia VARCHAR(50),
requiere_certificacion BOOLEAN NOT NULL DEFAULT false,
requiere_inspeccion_periodica BOOLEAN NOT NULL DEFAULT false,
frecuencia_inspeccion_dias INTEGER,
alerta_dias_antes INTEGER DEFAULT 15,
imagen_url VARCHAR(500),
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_epp_catalogo_codigo UNIQUE (tenant_id, codigo)
);
-- Tabla: Matriz EPP por puesto
CREATE TABLE hse.epp_matriz_puesto (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
puesto_id UUID NOT NULL,
epp_id UUID NOT NULL REFERENCES hse.epp_catalogo(id),
es_obligatorio BOOLEAN NOT NULL DEFAULT true,
actividad_especifica VARCHAR(200),
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Asignaciones de EPP
CREATE TABLE hse.epp_asignaciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
employee_id UUID NOT NULL REFERENCES hr.employees(id),
epp_id UUID NOT NULL REFERENCES hse.epp_catalogo(id),
fraccionamiento_id UUID REFERENCES construction.fraccionamientos(id),
fecha_entrega DATE NOT NULL,
fecha_vencimiento DATE NOT NULL,
numero_serie VARCHAR(100),
numero_lote VARCHAR(100),
firma_trabajador TEXT,
foto_entrega_url VARCHAR(500),
capacitacion_uso BOOLEAN NOT NULL DEFAULT false,
estado hse.estado_epp NOT NULL DEFAULT 'activo',
costo_unitario DECIMAL(10,2),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id)
);
-- Tabla: Inspecciones de EPP
CREATE TABLE hse.epp_inspecciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
asignacion_id UUID NOT NULL REFERENCES hse.epp_asignaciones(id) ON DELETE CASCADE,
inspector_id UUID NOT NULL REFERENCES hr.employees(id),
fecha_inspeccion DATE NOT NULL,
estado_epp hse.estado_inspeccion_epp NOT NULL,
observaciones TEXT,
requiere_reemplazo BOOLEAN NOT NULL DEFAULT false,
foto_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Bajas de EPP
CREATE TABLE hse.epp_bajas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
asignacion_id UUID NOT NULL REFERENCES hse.epp_asignaciones(id),
fecha_baja DATE NOT NULL,
motivo hse.motivo_baja_epp NOT NULL,
descripcion TEXT,
descuento_aplicado BOOLEAN NOT NULL DEFAULT false,
monto_descuento DECIMAL(10,2),
autorizado_por UUID REFERENCES hr.employees(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Inventario de EPP
CREATE TABLE hse.epp_inventario (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
epp_id UUID NOT NULL REFERENCES hse.epp_catalogo(id),
almacen_id UUID,
cantidad_disponible INTEGER NOT NULL DEFAULT 0,
cantidad_minima INTEGER DEFAULT 0,
cantidad_maxima INTEGER,
costo_promedio DECIMAL(10,2),
ultima_entrada DATE,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Movimientos de EPP
CREATE TABLE hse.epp_movimientos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
epp_id UUID NOT NULL REFERENCES hse.epp_catalogo(id),
almacen_origen_id UUID,
almacen_destino_id UUID,
tipo hse.tipo_movimiento_epp NOT NULL,
cantidad INTEGER NOT NULL,
referencia VARCHAR(100),
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id)
);
-- ============================================================================
-- RF-MAA017-005: CUMPLIMIENTO STPS
-- ============================================================================
-- Tabla: Catalogo de normas STPS
CREATE TABLE hse.normas_stps (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
codigo VARCHAR(30) NOT NULL UNIQUE,
nombre VARCHAR(300) NOT NULL,
descripcion TEXT,
fecha_publicacion DATE,
ultima_actualizacion DATE,
aplica_construccion BOOLEAN NOT NULL DEFAULT true,
documento_url VARCHAR(500),
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Requisitos por norma
CREATE TABLE hse.norma_requisitos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
norma_id UUID NOT NULL REFERENCES hse.normas_stps(id) ON DELETE CASCADE,
numero VARCHAR(20) NOT NULL,
descripcion TEXT NOT NULL,
tipo_evidencia VARCHAR(200),
es_critico BOOLEAN NOT NULL DEFAULT false,
aplica_a VARCHAR(100),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Cumplimiento por obra
CREATE TABLE hse.cumplimiento_obra (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
norma_id UUID NOT NULL REFERENCES hse.normas_stps(id),
requisito_id UUID REFERENCES hse.norma_requisitos(id),
estado hse.estado_cumplimiento NOT NULL DEFAULT 'no_cumple',
evidencia_url VARCHAR(500),
observaciones TEXT,
fecha_evaluacion DATE NOT NULL,
evaluador_id UUID REFERENCES hr.employees(id),
fecha_compromiso DATE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Comisiones de seguridad e higiene
CREATE TABLE hse.comision_seguridad (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
fecha_constitucion DATE NOT NULL,
numero_acta VARCHAR(50),
vigencia_inicio DATE NOT NULL,
vigencia_fin DATE NOT NULL,
estado hse.estado_comision NOT NULL DEFAULT 'activa',
documento_acta_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Integrantes de comision
CREATE TABLE hse.comision_integrantes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
comision_id UUID NOT NULL REFERENCES hse.comision_seguridad(id) ON DELETE CASCADE,
employee_id UUID NOT NULL REFERENCES hr.employees(id),
rol hse.rol_comision NOT NULL,
representacion hse.representacion NOT NULL,
fecha_nombramiento DATE NOT NULL,
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Recorridos de comision
CREATE TABLE hse.comision_recorridos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
comision_id UUID NOT NULL REFERENCES hse.comision_seguridad(id) ON DELETE CASCADE,
fecha_programada DATE NOT NULL,
fecha_realizada DATE,
numero_acta VARCHAR(50),
areas_recorridas TEXT,
hallazgos TEXT,
recomendaciones TEXT,
estado hse.estado_recorrido NOT NULL DEFAULT 'programado',
documento_acta_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Programa de seguridad anual
CREATE TABLE hse.programa_seguridad (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
anio INTEGER NOT NULL,
objetivo_general TEXT,
metas JSONB,
presupuesto DECIMAL(12,2),
estado hse.estado_programa NOT NULL DEFAULT 'borrador',
aprobado_por UUID REFERENCES hr.employees(id),
fecha_aprobacion DATE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Actividades del programa
CREATE TABLE hse.programa_actividades (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
programa_id UUID NOT NULL REFERENCES hse.programa_seguridad(id) ON DELETE CASCADE,
actividad VARCHAR(300) NOT NULL,
tipo hse.tipo_actividad_programa NOT NULL,
fecha_programada DATE NOT NULL,
fecha_realizada DATE,
responsable_id UUID REFERENCES hr.employees(id),
recursos TEXT,
estado hse.estado_actividad NOT NULL DEFAULT 'pendiente',
evidencia_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Documentos STPS emitidos
CREATE TABLE hse.documentos_stps (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
tipo hse.tipo_documento_stps NOT NULL,
folio VARCHAR(30) NOT NULL,
fraccionamiento_id UUID REFERENCES construction.fraccionamientos(id),
employee_id UUID REFERENCES hr.employees(id),
fecha_emision DATE NOT NULL,
fecha_vencimiento DATE,
datos_documento JSONB,
documento_url VARCHAR(500),
firmado BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id),
CONSTRAINT uq_documentos_stps_folio UNIQUE (tenant_id, tipo, folio)
);
-- Tabla: Auditorias
CREATE TABLE hse.auditorias (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
tipo hse.tipo_auditoria NOT NULL,
fecha_programada DATE NOT NULL,
fecha_realizada DATE,
auditor VARCHAR(200),
resultado hse.resultado_auditoria,
no_conformidades INTEGER DEFAULT 0,
observaciones TEXT,
informe_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- ============================================================================
-- RF-MAA017-006: GESTION AMBIENTAL
-- ============================================================================
-- Tabla: Catalogo de residuos
CREATE TABLE hse.residuos_catalogo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
codigo VARCHAR(20) NOT NULL UNIQUE,
nombre VARCHAR(200) NOT NULL,
categoria hse.categoria_residuo NOT NULL,
caracteristicas_cretib VARCHAR(6),
norma_referencia VARCHAR(50),
manejo_requerido TEXT,
tiempo_max_almacen_dias INTEGER,
requiere_manifiesto BOOLEAN NOT NULL DEFAULT false,
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Generacion de residuos
CREATE TABLE hse.residuos_generacion (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
residuo_id UUID NOT NULL REFERENCES hse.residuos_catalogo(id),
fecha_generacion DATE NOT NULL,
cantidad DECIMAL(10,2) NOT NULL,
unidad hse.unidad_residuo NOT NULL,
area_generacion VARCHAR(200),
fuente VARCHAR(200),
contenedor_id VARCHAR(50),
foto_url VARCHAR(500),
ubicacion_geo GEOMETRY(Point, 4326),
estado hse.estado_residuo NOT NULL DEFAULT 'almacenado',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id)
);
-- Tabla: Almacenes temporales
CREATE TABLE hse.almacen_temporal (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
nombre VARCHAR(100) NOT NULL,
ubicacion VARCHAR(200),
capacidad_m3 DECIMAL(8,2),
tiene_contencion BOOLEAN NOT NULL DEFAULT true,
tiene_techo BOOLEAN NOT NULL DEFAULT true,
senalizacion_ok BOOLEAN NOT NULL DEFAULT true,
estado hse.estado_almacen NOT NULL DEFAULT 'operativo',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Proveedores ambientales
CREATE TABLE hse.proveedores_ambientales (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
razon_social VARCHAR(300) NOT NULL,
rfc VARCHAR(13),
tipo hse.tipo_proveedor_ambiental NOT NULL,
numero_autorizacion VARCHAR(50),
entidad_autorizadora VARCHAR(100),
fecha_autorizacion DATE,
fecha_vencimiento DATE,
servicios TEXT,
contacto_nombre VARCHAR(200),
contacto_telefono VARCHAR(20),
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Manifiestos de residuos
CREATE TABLE hse.manifiestos_residuos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
folio VARCHAR(30) NOT NULL,
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
transportista_id UUID NOT NULL REFERENCES hse.proveedores_ambientales(id),
destino_id UUID NOT NULL REFERENCES hse.proveedores_ambientales(id),
fecha_recoleccion DATE NOT NULL,
fecha_entrega DATE,
estado hse.estado_manifiesto NOT NULL DEFAULT 'emitido',
observaciones TEXT,
documento_url VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_manifiestos_residuos_folio UNIQUE (tenant_id, folio)
);
-- Tabla: Detalle de manifiestos
CREATE TABLE hse.manifiesto_detalle (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
manifiesto_id UUID NOT NULL REFERENCES hse.manifiestos_residuos(id) ON DELETE CASCADE,
residuo_id UUID NOT NULL REFERENCES hse.residuos_catalogo(id),
generacion_ids UUID[],
cantidad DECIMAL(10,2) NOT NULL,
unidad hse.unidad_residuo NOT NULL,
descripcion TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Impacto ambiental
CREATE TABLE hse.impacto_ambiental (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
aspecto VARCHAR(200) NOT NULL,
tipo_impacto hse.tipo_impacto NOT NULL,
severidad hse.severidad NOT NULL,
probabilidad hse.probabilidad NOT NULL,
nivel_riesgo hse.nivel_riesgo NOT NULL,
medidas_mitigacion TEXT,
responsable_id UUID REFERENCES hr.employees(id),
estado hse.estado_impacto NOT NULL DEFAULT 'identificado',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Quejas ambientales
CREATE TABLE hse.quejas_ambientales (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
fecha_queja TIMESTAMPTZ NOT NULL,
origen hse.origen_queja NOT NULL,
tipo hse.tipo_queja NOT NULL,
descripcion TEXT NOT NULL,
nombre_quejoso VARCHAR(200),
contacto_quejoso VARCHAR(100),
acciones_tomadas TEXT,
estado hse.estado_queja NOT NULL DEFAULT 'recibida',
fecha_cierre DATE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- ============================================================================
-- RF-MAA017-007: PERMISOS DE TRABAJO
-- ============================================================================
-- Tabla: Tipos de permiso de trabajo
CREATE TABLE hse.tipos_permiso_trabajo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(200) NOT NULL,
descripcion TEXT,
norma_referencia VARCHAR(50),
vigencia_max_horas INTEGER NOT NULL,
requiere_autorizacion_nivel INTEGER NOT NULL DEFAULT 2,
documentos_requeridos JSONB,
requisitos_personal JSONB,
equipos_requeridos JSONB,
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_tipos_permiso_trabajo_codigo UNIQUE (tenant_id, codigo)
);
-- Tabla: Permisos de trabajo
CREATE TABLE hse.permisos_trabajo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
folio VARCHAR(30) NOT NULL,
tipo_permiso_id UUID NOT NULL REFERENCES hse.tipos_permiso_trabajo(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
solicitante_id UUID NOT NULL REFERENCES hr.employees(id),
descripcion_trabajo TEXT NOT NULL,
ubicacion VARCHAR(300) NOT NULL,
ubicacion_geo GEOMETRY(Point, 4326),
fecha_inicio_programada TIMESTAMPTZ NOT NULL,
fecha_fin_programada TIMESTAMPTZ NOT NULL,
fecha_inicio_real TIMESTAMPTZ,
fecha_fin_real TIMESTAMPTZ,
estado hse.estado_permiso NOT NULL DEFAULT 'borrador',
motivo_rechazo TEXT,
motivo_suspension TEXT,
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_permisos_trabajo_folio UNIQUE (tenant_id, folio)
);
-- Tabla: Personal del permiso
CREATE TABLE hse.permiso_personal (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
permiso_id UUID NOT NULL REFERENCES hse.permisos_trabajo(id) ON DELETE CASCADE,
employee_id UUID NOT NULL REFERENCES hr.employees(id),
rol hse.rol_permiso NOT NULL,
verificacion_capacitacion BOOLEAN NOT NULL DEFAULT false,
verificacion_epp BOOLEAN NOT NULL DEFAULT false,
verificacion_aptitud BOOLEAN NOT NULL DEFAULT false,
observaciones TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Autorizaciones de permiso
CREATE TABLE hse.permiso_autorizaciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
permiso_id UUID NOT NULL REFERENCES hse.permisos_trabajo(id) ON DELETE CASCADE,
nivel INTEGER NOT NULL,
autorizador_id UUID NOT NULL REFERENCES hr.employees(id),
rol_autorizador VARCHAR(100),
decision hse.decision_autorizacion NOT NULL,
observaciones TEXT,
firma_digital TEXT,
fecha_decision TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Checklist del permiso
CREATE TABLE hse.permiso_checklist (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
permiso_id UUID NOT NULL REFERENCES hse.permisos_trabajo(id) ON DELETE CASCADE,
momento hse.momento_checklist NOT NULL,
item_verificacion VARCHAR(300) NOT NULL,
cumple BOOLEAN,
observacion TEXT,
verificador_id UUID REFERENCES hr.employees(id),
fecha_verificacion TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Monitoreos durante permiso
CREATE TABLE hse.permiso_monitoreos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
permiso_id UUID NOT NULL REFERENCES hse.permisos_trabajo(id) ON DELETE CASCADE,
fecha_hora TIMESTAMPTZ NOT NULL,
tipo VARCHAR(100) NOT NULL,
valor_medicion VARCHAR(50),
unidad VARCHAR(20),
dentro_rango BOOLEAN NOT NULL DEFAULT true,
observaciones TEXT,
responsable_id UUID NOT NULL REFERENCES hr.employees(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Eventos del permiso
CREATE TABLE hse.permiso_eventos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
permiso_id UUID NOT NULL REFERENCES hse.permisos_trabajo(id) ON DELETE CASCADE,
fecha_hora TIMESTAMPTZ NOT NULL DEFAULT NOW(),
tipo_evento hse.tipo_evento_permiso NOT NULL,
descripcion TEXT,
accion_tomada TEXT,
responsable_id UUID NOT NULL REFERENCES hr.employees(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Documentos del permiso
CREATE TABLE hse.permiso_documentos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
permiso_id UUID NOT NULL REFERENCES hse.permisos_trabajo(id) ON DELETE CASCADE,
tipo_documento VARCHAR(100) NOT NULL,
nombre VARCHAR(200) NOT NULL,
archivo_url VARCHAR(500) NOT NULL,
fecha_subida TIMESTAMPTZ NOT NULL DEFAULT NOW(),
subido_por UUID REFERENCES auth.users(id)
);
-- ============================================================================
-- RF-MAA017-008: INDICADORES HSE
-- ============================================================================
-- Tabla: Configuracion de indicadores
CREATE TABLE hse.indicadores_config (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(200) NOT NULL,
descripcion TEXT,
formula TEXT,
unidad VARCHAR(50),
tipo hse.tipo_indicador NOT NULL,
meta_global DECIMAL(10,4),
umbral_verde DECIMAL(10,4),
umbral_amarillo DECIMAL(10,4),
umbral_rojo DECIMAL(10,4),
frecuencia_calculo hse.frecuencia_calculo NOT NULL DEFAULT 'mensual',
activo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_indicadores_config_codigo UNIQUE (tenant_id, codigo)
);
-- Tabla: Metas por obra
CREATE TABLE hse.indicadores_meta_obra (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
indicador_id UUID NOT NULL REFERENCES hse.indicadores_config(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
anio INTEGER NOT NULL,
meta DECIMAL(10,4) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Valores calculados de indicadores
CREATE TABLE hse.indicadores_valores (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
indicador_id UUID NOT NULL REFERENCES hse.indicadores_config(id),
fraccionamiento_id UUID REFERENCES construction.fraccionamientos(id),
periodo_tipo hse.periodo_tipo NOT NULL,
periodo_fecha DATE NOT NULL,
valor DECIMAL(15,4),
numerador DECIMAL(15,4),
denominador DECIMAL(15,4),
estado hse.estado_semaforo,
calculado_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Horas trabajadas
CREATE TABLE hse.horas_trabajadas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
fecha DATE NOT NULL,
horas_totales DECIMAL(12,2) NOT NULL,
trabajadores_promedio INTEGER NOT NULL,
fuente hse.fuente_horas NOT NULL DEFAULT 'manual',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_horas_trabajadas UNIQUE (tenant_id, fraccionamiento_id, fecha)
);
-- Tabla: Dias sin accidente
CREATE TABLE hse.dias_sin_accidente (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
fecha_inicio_conteo DATE NOT NULL,
dias_acumulados INTEGER NOT NULL DEFAULT 0,
record_historico INTEGER NOT NULL DEFAULT 0,
ultimo_incidente_id UUID REFERENCES hse.incidentes(id),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_dias_sin_accidente UNIQUE (tenant_id, fraccionamiento_id)
);
-- Tabla: Reportes programados
CREATE TABLE hse.reportes_programados (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
nombre VARCHAR(200) NOT NULL,
tipo_reporte hse.tipo_reporte_hse NOT NULL,
indicadores UUID[],
fraccionamientos UUID[],
destinatarios VARCHAR[],
dia_envio INTEGER,
hora_envio TIME,
formato hse.formato_reporte NOT NULL DEFAULT 'pdf',
activo BOOLEAN NOT NULL DEFAULT true,
ultimo_envio TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tabla: Alertas de indicadores
CREATE TABLE hse.alertas_indicadores (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
indicador_id UUID NOT NULL REFERENCES hse.indicadores_config(id),
fraccionamiento_id UUID REFERENCES construction.fraccionamientos(id),
tipo_alerta hse.tipo_alerta_indicador NOT NULL,
mensaje TEXT NOT NULL,
valor_actual DECIMAL(10,4),
valor_meta DECIMAL(10,4),
leida BOOLEAN NOT NULL DEFAULT false,
fecha_alerta TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- ============================================================================
-- INDICES
-- ============================================================================
-- Incidentes
CREATE INDEX idx_incidentes_tenant ON hse.incidentes(tenant_id);
CREATE INDEX idx_incidentes_fraccionamiento ON hse.incidentes(fraccionamiento_id);
CREATE INDEX idx_incidentes_fecha ON hse.incidentes(fecha_hora);
CREATE INDEX idx_incidentes_estado ON hse.incidentes(estado);
CREATE INDEX idx_incidentes_tipo ON hse.incidentes(tipo);
CREATE INDEX idx_incidentes_gravedad ON hse.incidentes(gravedad);
CREATE INDEX idx_incidente_involucrados_employee ON hse.incidente_involucrados(employee_id);
-- Capacitaciones
CREATE INDEX idx_capacitaciones_tenant ON hse.capacitaciones(tenant_id);
CREATE INDEX idx_capacitacion_sesiones_fecha ON hse.capacitacion_sesiones(fecha_programada);
CREATE INDEX idx_capacitacion_asistentes_employee ON hse.capacitacion_asistentes(employee_id);
CREATE INDEX idx_constancias_dc3_employee ON hse.constancias_dc3(employee_id);
CREATE INDEX idx_constancias_dc3_vencimiento ON hse.constancias_dc3(fecha_vencimiento);
-- Inspecciones
CREATE INDEX idx_inspecciones_tenant ON hse.inspecciones(tenant_id);
CREATE INDEX idx_inspecciones_fraccionamiento ON hse.inspecciones(fraccionamiento_id);
CREATE INDEX idx_inspecciones_fecha ON hse.inspecciones(fecha_inicio);
CREATE INDEX idx_programa_inspecciones_fecha ON hse.programa_inspecciones(fecha_programada);
CREATE INDEX idx_hallazgos_estado ON hse.hallazgos(estado);
CREATE INDEX idx_hallazgos_fecha_limite ON hse.hallazgos(fecha_limite);
-- EPP
CREATE INDEX idx_epp_asignaciones_employee ON hse.epp_asignaciones(employee_id);
CREATE INDEX idx_epp_asignaciones_vencimiento ON hse.epp_asignaciones(fecha_vencimiento);
CREATE INDEX idx_epp_asignaciones_estado ON hse.epp_asignaciones(estado);
-- STPS
CREATE INDEX idx_comision_seguridad_vigencia ON hse.comision_seguridad(vigencia_fin);
CREATE INDEX idx_documentos_stps_vencimiento ON hse.documentos_stps(fecha_vencimiento);
-- Ambiental
CREATE INDEX idx_residuos_generacion_fecha ON hse.residuos_generacion(fecha_generacion);
CREATE INDEX idx_manifiestos_estado ON hse.manifiestos_residuos(estado);
-- Permisos
CREATE INDEX idx_permisos_trabajo_estado ON hse.permisos_trabajo(estado);
CREATE INDEX idx_permisos_trabajo_fecha ON hse.permisos_trabajo(fecha_inicio_programada);
-- Indicadores
CREATE INDEX idx_indicadores_valores_fecha ON hse.indicadores_valores(periodo_fecha);
CREATE INDEX idx_horas_trabajadas_fecha ON hse.horas_trabajadas(fecha);
-- ============================================================================
-- ROW LEVEL SECURITY (RLS)
-- ============================================================================
-- Habilitar RLS en todas las tablas con tenant_id
ALTER TABLE hse.incidentes ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.capacitaciones ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.capacitacion_sesiones ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.instructores ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.constancias_dc3 ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.tipos_inspeccion ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.programa_inspecciones ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.inspecciones ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.hallazgos ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.epp_catalogo ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.epp_asignaciones ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.epp_inventario ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.epp_movimientos ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.cumplimiento_obra ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.comision_seguridad ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.programa_seguridad ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.documentos_stps ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.auditorias ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.residuos_generacion ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.almacen_temporal ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.proveedores_ambientales ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.manifiestos_residuos ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.impacto_ambiental ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.quejas_ambientales ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.tipos_permiso_trabajo ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.permisos_trabajo ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.indicadores_config ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.indicadores_valores ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.horas_trabajadas ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.dias_sin_accidente ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.reportes_programados ENABLE ROW LEVEL SECURITY;
ALTER TABLE hse.alertas_indicadores ENABLE ROW LEVEL SECURITY;
-- Politicas RLS (ejemplo para incidentes, replicar para las demas)
CREATE POLICY tenant_isolation_incidentes ON hse.incidentes
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY tenant_isolation_capacitaciones ON hse.capacitaciones
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY tenant_isolation_inspecciones ON hse.inspecciones
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY tenant_isolation_hallazgos ON hse.hallazgos
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY tenant_isolation_epp_asignaciones ON hse.epp_asignaciones
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY tenant_isolation_permisos_trabajo ON hse.permisos_trabajo
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY tenant_isolation_indicadores_valores ON hse.indicadores_valores
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
-- ============================================================================
-- TRIGGERS PARA UPDATED_AT
-- ============================================================================
CREATE OR REPLACE FUNCTION hse.update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Aplicar trigger a tablas con updated_at
CREATE TRIGGER trg_incidentes_updated_at
BEFORE UPDATE ON hse.incidentes
FOR EACH ROW EXECUTE FUNCTION hse.update_updated_at();
CREATE TRIGGER trg_capacitaciones_updated_at
BEFORE UPDATE ON hse.capacitaciones
FOR EACH ROW EXECUTE FUNCTION hse.update_updated_at();
CREATE TRIGGER trg_inspecciones_updated_at
BEFORE UPDATE ON hse.inspecciones
FOR EACH ROW EXECUTE FUNCTION hse.update_updated_at();
CREATE TRIGGER trg_hallazgos_updated_at
BEFORE UPDATE ON hse.hallazgos
FOR EACH ROW EXECUTE FUNCTION hse.update_updated_at();
CREATE TRIGGER trg_epp_asignaciones_updated_at
BEFORE UPDATE ON hse.epp_asignaciones
FOR EACH ROW EXECUTE FUNCTION hse.update_updated_at();
CREATE TRIGGER trg_permisos_trabajo_updated_at
BEFORE UPDATE ON hse.permisos_trabajo
FOR EACH ROW EXECUTE FUNCTION hse.update_updated_at();
-- ============================================================================
-- DATOS INICIALES - CATALOGO DE NORMAS STPS
-- ============================================================================
INSERT INTO hse.normas_stps (codigo, nombre, descripcion, aplica_construccion) VALUES
('NOM-001-STPS-2008', 'Edificios, locales e instalaciones', 'Condiciones de seguridad', true),
('NOM-002-STPS-2010', 'Prevencion y proteccion contra incendios', 'Prevencion y proteccion contra incendios en centros de trabajo', true),
('NOM-004-STPS-1999', 'Sistemas de proteccion y dispositivos de seguridad en maquinaria', 'Sistemas de proteccion en maquinaria y equipo', true),
('NOM-005-STPS-1998', 'Manejo de sustancias quimicas peligrosas', 'Relativa a condiciones de seguridad e higiene', true),
('NOM-006-STPS-2014', 'Manejo y almacenamiento de materiales', 'Condiciones de seguridad y salud en el trabajo', true),
('NOM-009-STPS-2011', 'Trabajos en altura', 'Condiciones de seguridad para realizar trabajos en altura', true),
('NOM-011-STPS-2001', 'Ruido', 'Condiciones de seguridad e higiene donde se genere ruido', true),
('NOM-017-STPS-2008', 'Equipo de proteccion personal', 'Seleccion, uso y manejo en centros de trabajo', true),
('NOM-019-STPS-2011', 'Comisiones de seguridad e higiene', 'Constitucion, integracion, organizacion y funcionamiento', true),
('NOM-026-STPS-2008', 'Senales de seguridad', 'Colores y senales de seguridad e higiene', true),
('NOM-029-STPS-2011', 'Mantenimiento de instalaciones electricas', 'Condiciones de seguridad para realizar actividades', true),
('NOM-030-STPS-2009', 'Servicios preventivos de seguridad y salud', 'Funciones y actividades', true),
('NOM-031-STPS-2011', 'Construccion', 'Condiciones de seguridad y salud en el trabajo', true);
-- ============================================================================
-- DATOS INICIALES - CATALOGO DE RESIDUOS COMUNES EN CONSTRUCCION
-- ============================================================================
INSERT INTO hse.residuos_catalogo (codigo, nombre, categoria, caracteristicas_cretib, norma_referencia, tiempo_max_almacen_dias, requiere_manifiesto) VALUES
('RP-001', 'Aceites usados', 'peligroso', 'IT', 'NOM-052-SEMARNAT', 180, true),
('RP-002', 'Solventes usados', 'peligroso', 'IT', 'NOM-052-SEMARNAT', 180, true),
('RP-003', 'Pinturas y barnices', 'peligroso', 'IT', 'NOM-052-SEMARNAT', 180, true),
('RP-004', 'Baterias y acumuladores', 'peligroso', 'CT', 'NOM-052-SEMARNAT', 180, true),
('RP-005', 'Envases contaminados', 'peligroso', 'T', 'NOM-052-SEMARNAT', 180, true),
('RP-006', 'Trapos y estopas impregnados', 'peligroso', 'I', 'NOM-052-SEMARNAT', 180, true),
('RME-001', 'Escombro y cascajo', 'manejo_especial', NULL, 'LGPGIR', 365, false),
('RME-002', 'Tierra excavada', 'manejo_especial', NULL, 'LGPGIR', 365, false),
('RME-003', 'Material de demolicion', 'manejo_especial', NULL, 'LGPGIR', 365, false),
('RSU-001', 'Carton y papel', 'urbano', NULL, NULL, NULL, false),
('RSU-002', 'Plasticos', 'urbano', NULL, NULL, NULL, false),
('RSU-003', 'Residuos organicos', 'urbano', NULL, NULL, NULL, false);
-- ============================================================================
-- COMENTARIOS DE DOCUMENTACION
-- ============================================================================
COMMENT ON SCHEMA hse IS 'Schema para gestion de Seguridad, Salud Ocupacional y Medio Ambiente (HSE) - MAA-017';
COMMENT ON TABLE hse.incidentes IS 'Registro de incidentes y accidentes de trabajo';
COMMENT ON TABLE hse.capacitaciones IS 'Catalogo de capacitaciones de seguridad';
COMMENT ON TABLE hse.inspecciones IS 'Registro de inspecciones de seguridad ejecutadas';
COMMENT ON TABLE hse.hallazgos IS 'Hallazgos detectados en inspecciones';
COMMENT ON TABLE hse.epp_asignaciones IS 'Asignacion de EPP a trabajadores';
COMMENT ON TABLE hse.permisos_trabajo IS 'Permisos para trabajos de alto riesgo';
COMMENT ON TABLE hse.indicadores_valores IS 'Valores calculados de indicadores HSE';
-- ============================================================================
-- FIN DEL DDL
-- ============================================================================