-- ============================================================================= -- ERP TRANSPORTISTAS - Schema Maintenance DDL -- ============================================================================= -- Archivo: 05-maintenance-schema-ddl.sql -- Version: 1.0.0 -- Fecha: 2026-01-25 -- Descripcion: Mantenimiento preventivo, correctivo, ordenes de trabajo -- ============================================================================= -- ============================================================================= -- TIPOS ENUMERADOS -- ============================================================================= CREATE TYPE maintenance.tipo_mantenimiento AS ENUM ( 'PREVENTIVO', 'CORRECTIVO', 'PREDICTIVO', 'EMERGENCIA' ); CREATE TYPE maintenance.prioridad AS ENUM ( 'BAJA', 'MEDIA', 'ALTA', 'URGENTE' ); CREATE TYPE maintenance.estado_orden AS ENUM ( 'BORRADOR', 'PROGRAMADA', 'EN_PROCESO', 'ESPERANDO_REFACCIONES', 'COMPLETADA', 'CANCELADA' ); CREATE TYPE maintenance.tipo_servicio AS ENUM ( 'CAMBIO_ACEITE', 'FRENOS', 'LLANTAS', 'SUSPENSION', 'MOTOR', 'TRANSMISION', 'ELECTRICO', 'CARROCERIA', 'REFRIGERACION', 'ALINEACION_BALANCEO', 'REVISION_GENERAL', 'OTRO' ); -- ============================================================================= -- TABLA: planes_mantenimiento -- ============================================================================= CREATE TABLE maintenance.planes_mantenimiento ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id), -- Identificación codigo VARCHAR(50) NOT NULL, nombre VARCHAR(200) NOT NULL, descripcion TEXT, -- Tipo de unidad que aplica aplica_tipo_unidad fleet.tipo_unidad[], aplica_todas_unidades BOOLEAN DEFAULT FALSE, -- Frecuencia frecuencia_km INT, frecuencia_dias INT, frecuencia_horas_motor INT, -- Servicios incluidos servicios maintenance.tipo_servicio[] NOT NULL, -- Costos estimados costo_estimado_mano_obra DECIMAL(12, 2), costo_estimado_refacciones DECIMAL(12, 2), tiempo_estimado_horas DECIMAL(6, 2), -- Estado activo BOOLEAN DEFAULT TRUE, -- Auditoría created_at TIMESTAMPTZ DEFAULT NOW(), created_by_id UUID NOT NULL, updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_plan_tenant ON maintenance.planes_mantenimiento(tenant_id); CREATE UNIQUE INDEX idx_plan_codigo ON maintenance.planes_mantenimiento(tenant_id, codigo); -- ============================================================================= -- TABLA: programacion_mantenimiento -- ============================================================================= CREATE TABLE maintenance.programacion_mantenimiento ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id), -- Unidad y plan unidad_id UUID NOT NULL, plan_id UUID REFERENCES maintenance.planes_mantenimiento(id), -- Tipo tipo maintenance.tipo_mantenimiento NOT NULL, -- Próximo mantenimiento proximo_km INT, proxima_fecha DATE, proximas_horas_motor INT, -- Último mantenimiento ultimo_km INT, ultima_fecha DATE, ultima_orden_id UUID, -- Estado vencido BOOLEAN DEFAULT FALSE, dias_para_vencer INT, -- Auditoría updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_programacion_unidad ON maintenance.programacion_mantenimiento(unidad_id); CREATE INDEX idx_programacion_vencido ON maintenance.programacion_mantenimiento(tenant_id, vencido); CREATE INDEX idx_programacion_proxima ON maintenance.programacion_mantenimiento(proxima_fecha); -- ============================================================================= -- TABLA: ordenes_trabajo -- ============================================================================= CREATE TABLE maintenance.ordenes_trabajo ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id), -- Identificación numero_orden VARCHAR(50) NOT NULL, -- Unidad unidad_id UUID NOT NULL, remolque_id UUID, -- Tipo y prioridad tipo maintenance.tipo_mantenimiento NOT NULL, prioridad maintenance.prioridad DEFAULT 'MEDIA', -- Diagnóstico inicial descripcion_falla TEXT, reportado_por VARCHAR(200), reportado_fecha TIMESTAMPTZ, -- Programación fecha_programada DATE, hora_programada TIME, taller_id UUID, taller_externo_nombre VARCHAR(200), es_taller_externo BOOLEAN DEFAULT FALSE, -- Ejecución fecha_inicio TIMESTAMPTZ, fecha_fin TIMESTAMPTZ, mecanico_responsable VARCHAR(200), -- Odómetro odometro_entrada INT, odometro_salida INT, -- Diagnóstico final diagnostico_final TEXT, trabajos_realizados TEXT, -- Costos costo_mano_obra DECIMAL(12, 2) DEFAULT 0, costo_refacciones DECIMAL(12, 2) DEFAULT 0, costo_otros DECIMAL(12, 2) DEFAULT 0, costo_total DECIMAL(12, 2) DEFAULT 0, -- Plan relacionado plan_id UUID REFERENCES maintenance.planes_mantenimiento(id), -- Estado estado maintenance.estado_orden DEFAULT 'BORRADOR', -- Garantía tiene_garantia BOOLEAN DEFAULT FALSE, garantia_dias INT, garantia_km INT, -- Auditoría created_at TIMESTAMPTZ DEFAULT NOW(), created_by_id UUID NOT NULL, updated_at TIMESTAMPTZ DEFAULT NOW(), updated_by_id UUID ); CREATE INDEX idx_ot_tenant ON maintenance.ordenes_trabajo(tenant_id); CREATE INDEX idx_ot_unidad ON maintenance.ordenes_trabajo(unidad_id); CREATE INDEX idx_ot_estado ON maintenance.ordenes_trabajo(tenant_id, estado); CREATE INDEX idx_ot_fecha ON maintenance.ordenes_trabajo(fecha_programada); CREATE UNIQUE INDEX idx_ot_numero ON maintenance.ordenes_trabajo(tenant_id, numero_orden); -- ============================================================================= -- TABLA: lineas_orden_trabajo (Refacciones usadas) -- ============================================================================= CREATE TABLE maintenance.lineas_orden_trabajo ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id), orden_id UUID NOT NULL REFERENCES maintenance.ordenes_trabajo(id), -- Tipo de línea tipo VARCHAR(20) NOT NULL, -- 'REFACCION', 'MANO_OBRA', 'OTRO' -- Refacción (si aplica) producto_id UUID, numero_parte VARCHAR(100), descripcion VARCHAR(500) NOT NULL, -- Cantidades cantidad DECIMAL(10, 3) NOT NULL, unidad_medida VARCHAR(20), -- Precios precio_unitario DECIMAL(12, 2) NOT NULL, descuento DECIMAL(12, 2) DEFAULT 0, total DECIMAL(12, 2) NOT NULL, -- Proveedor proveedor_id UUID, proveedor_nombre VARCHAR(200), -- Factura factura_proveedor VARCHAR(50) ); CREATE INDEX idx_linea_ot ON maintenance.lineas_orden_trabajo(orden_id); -- ============================================================================= -- TABLA: checklist_mantenimiento -- ============================================================================= CREATE TABLE maintenance.checklist_items ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id), orden_id UUID NOT NULL REFERENCES maintenance.ordenes_trabajo(id), -- Item categoria VARCHAR(100), descripcion VARCHAR(500) NOT NULL, obligatorio BOOLEAN DEFAULT FALSE, -- Resultado resultado VARCHAR(20), -- 'OK', 'REPARADO', 'PENDIENTE', 'NO_APLICA' observaciones TEXT, -- Evidencia foto_url TEXT, -- Revisado revisado_por VARCHAR(200), revisado_fecha TIMESTAMPTZ ); CREATE INDEX idx_checklist_orden ON maintenance.checklist_items(orden_id); -- ============================================================================= -- RLS POLICIES -- ============================================================================= ALTER TABLE maintenance.planes_mantenimiento ENABLE ROW LEVEL SECURITY; ALTER TABLE maintenance.programacion_mantenimiento ENABLE ROW LEVEL SECURITY; ALTER TABLE maintenance.ordenes_trabajo ENABLE ROW LEVEL SECURITY; ALTER TABLE maintenance.lineas_orden_trabajo ENABLE ROW LEVEL SECURITY; ALTER TABLE maintenance.checklist_items ENABLE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation_planes ON maintenance.planes_mantenimiento USING (tenant_id = current_setting('app.tenant_id')::uuid); CREATE POLICY tenant_isolation_programacion ON maintenance.programacion_mantenimiento USING (tenant_id = current_setting('app.tenant_id')::uuid); CREATE POLICY tenant_isolation_ordenes ON maintenance.ordenes_trabajo USING (tenant_id = current_setting('app.tenant_id')::uuid); CREATE POLICY tenant_isolation_lineas ON maintenance.lineas_orden_trabajo USING (tenant_id = current_setting('app.tenant_id')::uuid); CREATE POLICY tenant_isolation_checklist ON maintenance.checklist_items USING (tenant_id = current_setting('app.tenant_id')::uuid); -- ============================================================================= -- COMENTARIOS -- ============================================================================= COMMENT ON TABLE maintenance.planes_mantenimiento IS 'Planes de mantenimiento preventivo'; COMMENT ON TABLE maintenance.programacion_mantenimiento IS 'Programación de próximos mantenimientos por unidad'; COMMENT ON TABLE maintenance.ordenes_trabajo IS 'Órdenes de trabajo de mantenimiento'; COMMENT ON TABLE maintenance.lineas_orden_trabajo IS 'Líneas de detalle de órdenes de trabajo'; COMMENT ON TABLE maintenance.checklist_items IS 'Items de checklist de mantenimiento'; -- ============================================================================= -- FIN DDL MAINTENANCE -- =============================================================================