-- ============================================================================ -- 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 -- ============================================================================