[MAE-015] feat: Add assets schema DDL with 11 tables and 9 ENUMs
- asset_categories: Categorias de activos - assets: Catalogo principal de activos - asset_assignments: Asignaciones a proyectos - maintenance_plans: Planes de mantenimiento preventivo - maintenance_schedules: Programacion de mantenimientos - work_orders: Ordenes de trabajo - work_order_parts: Refacciones utilizadas - maintenance_history: Historial de mantenimientos - asset_costs: Costos TCO - asset_locations: Ubicaciones GPS - fuel_logs: Registro de combustible Includes: RLS, indices, triggers, TCO calculation function Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3e3d2d6eac
commit
e927cafc90
964
schemas/09-assets-schema-ddl.sql
Normal file
964
schemas/09-assets-schema-ddl.sql
Normal file
@ -0,0 +1,964 @@
|
||||
-- ============================================================================
|
||||
-- 09-assets-schema-ddl.sql
|
||||
-- Schema: assets
|
||||
-- ERP Construccion - Modulo Activos, Maquinaria y Mantenimiento (MAE-015)
|
||||
-- ============================================================================
|
||||
-- Descripcion: Gestion de activos fijos y maquinaria incluyendo:
|
||||
-- - Catalogo de activos (maquinaria, equipo, vehiculos)
|
||||
-- - Asignaciones a obras/proyectos
|
||||
-- - Planes de mantenimiento preventivo
|
||||
-- - Ordenes de trabajo de mantenimiento
|
||||
-- - Historial de mantenimientos
|
||||
-- - Costeo TCO (Total Cost of Ownership)
|
||||
-- - Rastreo GPS (IoT)
|
||||
-- ============================================================================
|
||||
-- Autor: Claude-Arquitecto-Orquestador
|
||||
-- Fecha: 2026-01-25
|
||||
-- Version: 1.0.0
|
||||
-- ============================================================================
|
||||
|
||||
-- Crear schema si no existe
|
||||
CREATE SCHEMA IF NOT EXISTS assets;
|
||||
|
||||
-- ============================================================================
|
||||
-- ENUMS
|
||||
-- ============================================================================
|
||||
|
||||
-- Tipo de activo
|
||||
CREATE TYPE assets.asset_type AS ENUM (
|
||||
'heavy_machinery', -- Maquinaria pesada (excavadoras, gruas)
|
||||
'light_equipment', -- Equipo ligero (compactadoras, mezcladoras)
|
||||
'vehicle', -- Vehiculos (camiones, camionetas)
|
||||
'tool', -- Herramientas (taladros, sierras)
|
||||
'computer', -- Equipo de computo
|
||||
'furniture', -- Mobiliario
|
||||
'other' -- Otro
|
||||
);
|
||||
|
||||
-- Estado del activo
|
||||
CREATE TYPE assets.asset_status AS ENUM (
|
||||
'available', -- Disponible
|
||||
'assigned', -- Asignado a obra
|
||||
'in_maintenance', -- En mantenimiento
|
||||
'in_transit', -- En transito entre obras
|
||||
'inactive', -- Inactivo
|
||||
'retired', -- Dado de baja
|
||||
'sold' -- Vendido
|
||||
);
|
||||
|
||||
-- Tipo de propiedad
|
||||
CREATE TYPE assets.ownership_type AS ENUM (
|
||||
'owned', -- Propio
|
||||
'leased', -- Arrendado
|
||||
'rented', -- Rentado
|
||||
'borrowed' -- Prestamo
|
||||
);
|
||||
|
||||
-- Tipo de mantenimiento
|
||||
CREATE TYPE assets.maintenance_type AS ENUM (
|
||||
'preventive', -- Preventivo
|
||||
'corrective', -- Correctivo
|
||||
'predictive', -- Predictivo
|
||||
'emergency' -- Emergencia
|
||||
);
|
||||
|
||||
-- Frecuencia de mantenimiento
|
||||
CREATE TYPE assets.maintenance_frequency AS ENUM (
|
||||
'daily', -- Diario
|
||||
'weekly', -- Semanal
|
||||
'biweekly', -- Quincenal
|
||||
'monthly', -- Mensual
|
||||
'quarterly', -- Trimestral
|
||||
'semiannual', -- Semestral
|
||||
'annual', -- Anual
|
||||
'by_hours', -- Por horas de operacion
|
||||
'by_kilometers' -- Por kilometros
|
||||
);
|
||||
|
||||
-- Estado de orden de trabajo
|
||||
CREATE TYPE assets.work_order_status AS ENUM (
|
||||
'draft', -- Borrador
|
||||
'scheduled', -- Programada
|
||||
'in_progress', -- En progreso
|
||||
'on_hold', -- En espera
|
||||
'completed', -- Completada
|
||||
'cancelled' -- Cancelada
|
||||
);
|
||||
|
||||
-- Prioridad de orden de trabajo
|
||||
CREATE TYPE assets.work_order_priority AS ENUM (
|
||||
'low', -- Baja
|
||||
'medium', -- Media
|
||||
'high', -- Alta
|
||||
'critical' -- Critica
|
||||
);
|
||||
|
||||
-- Tipo de costo
|
||||
CREATE TYPE assets.cost_type AS ENUM (
|
||||
'maintenance', -- Mantenimiento
|
||||
'repair', -- Reparacion
|
||||
'fuel', -- Combustible
|
||||
'insurance', -- Seguro
|
||||
'tax', -- Impuestos
|
||||
'depreciation', -- Depreciacion
|
||||
'operator', -- Operador
|
||||
'other' -- Otro
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- TABLAS
|
||||
-- ============================================================================
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 1. Categorias de Activos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.asset_categories (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Informacion basica
|
||||
code VARCHAR(20) NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Jerarquia
|
||||
parent_id UUID REFERENCES assets.asset_categories(id),
|
||||
level INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
-- Configuracion de depreciacion
|
||||
useful_life_years INTEGER,
|
||||
depreciation_method VARCHAR(50), -- straight_line, declining_balance, units_of_production
|
||||
salvage_value_percentage DECIMAL(5,2),
|
||||
|
||||
-- Estado
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
-- Metadatos
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_asset_categories_tenant_code UNIQUE (tenant_id, code)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 2. Activos (Catalogo Principal)
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.assets (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Identificacion
|
||||
asset_code VARCHAR(50) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Clasificacion
|
||||
category_id UUID REFERENCES assets.asset_categories(id),
|
||||
asset_type assets.asset_type NOT NULL,
|
||||
status assets.asset_status NOT NULL DEFAULT 'available',
|
||||
ownership_type assets.ownership_type NOT NULL DEFAULT 'owned',
|
||||
|
||||
-- Especificaciones tecnicas
|
||||
brand VARCHAR(100),
|
||||
model VARCHAR(100),
|
||||
serial_number VARCHAR(100),
|
||||
year_manufactured INTEGER,
|
||||
specifications JSONB,
|
||||
|
||||
-- Capacidades
|
||||
capacity VARCHAR(100),
|
||||
power_rating VARCHAR(50),
|
||||
fuel_type VARCHAR(50),
|
||||
fuel_capacity DECIMAL(10,2),
|
||||
fuel_consumption_rate DECIMAL(10,2), -- litros/hora o km/litro
|
||||
|
||||
-- Metricas de uso
|
||||
current_hours DECIMAL(12,2) DEFAULT 0,
|
||||
current_kilometers DECIMAL(12,2) DEFAULT 0,
|
||||
last_usage_update TIMESTAMPTZ,
|
||||
|
||||
-- Ubicacion actual
|
||||
current_project_id UUID,
|
||||
current_location_name VARCHAR(255),
|
||||
current_latitude DECIMAL(10,8),
|
||||
current_longitude DECIMAL(11,8),
|
||||
last_location_update TIMESTAMPTZ,
|
||||
|
||||
-- Informacion financiera
|
||||
purchase_date DATE,
|
||||
purchase_price DECIMAL(18,2),
|
||||
purchase_currency VARCHAR(3) DEFAULT 'MXN',
|
||||
supplier_id UUID,
|
||||
invoice_number VARCHAR(100),
|
||||
|
||||
-- Depreciacion
|
||||
useful_life_years INTEGER,
|
||||
salvage_value DECIMAL(18,2),
|
||||
current_book_value DECIMAL(18,2),
|
||||
accumulated_depreciation DECIMAL(18,2) DEFAULT 0,
|
||||
depreciation_method VARCHAR(50),
|
||||
last_depreciation_date DATE,
|
||||
|
||||
-- Arrendamiento (si aplica)
|
||||
lease_start_date DATE,
|
||||
lease_end_date DATE,
|
||||
lease_monthly_rate DECIMAL(18,2),
|
||||
lease_contract_number VARCHAR(100),
|
||||
lessor_name VARCHAR(255),
|
||||
|
||||
-- Seguro
|
||||
insurance_policy_number VARCHAR(100),
|
||||
insurance_company VARCHAR(255),
|
||||
insurance_expiry_date DATE,
|
||||
insurance_coverage_amount DECIMAL(18,2),
|
||||
|
||||
-- Documentos
|
||||
photo_url VARCHAR(500),
|
||||
manual_url VARCHAR(500),
|
||||
registration_document_url VARCHAR(500),
|
||||
|
||||
-- Proximo mantenimiento
|
||||
next_maintenance_date DATE,
|
||||
next_maintenance_hours DECIMAL(12,2),
|
||||
next_maintenance_kilometers DECIMAL(12,2),
|
||||
|
||||
-- Operador asignado
|
||||
assigned_operator_id UUID,
|
||||
|
||||
-- Notas y metadatos
|
||||
notes TEXT,
|
||||
tags VARCHAR(255)[],
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_assets_tenant_code UNIQUE (tenant_id, asset_code)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 3. Asignaciones de Activos a Obras
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.asset_assignments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Activo y proyecto
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
project_id UUID NOT NULL,
|
||||
project_code VARCHAR(50),
|
||||
project_name VARCHAR(255),
|
||||
|
||||
-- Periodo de asignacion
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE,
|
||||
is_current BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
-- Ubicacion especifica en obra
|
||||
location_in_project VARCHAR(255),
|
||||
latitude DECIMAL(10,8),
|
||||
longitude DECIMAL(11,8),
|
||||
|
||||
-- Operador asignado
|
||||
operator_id UUID,
|
||||
operator_name VARCHAR(255),
|
||||
|
||||
-- Responsable
|
||||
responsible_id UUID,
|
||||
responsible_name VARCHAR(255),
|
||||
|
||||
-- Metricas al inicio/fin
|
||||
hours_at_start DECIMAL(12,2),
|
||||
hours_at_end DECIMAL(12,2),
|
||||
kilometers_at_start DECIMAL(12,2),
|
||||
kilometers_at_end DECIMAL(12,2),
|
||||
|
||||
-- Tarifas
|
||||
daily_rate DECIMAL(18,2),
|
||||
hourly_rate DECIMAL(18,2),
|
||||
|
||||
-- Razon de transferencia
|
||||
transfer_reason TEXT,
|
||||
transfer_notes TEXT,
|
||||
|
||||
-- Documento de entrega
|
||||
delivery_document_url VARCHAR(500),
|
||||
return_document_url VARCHAR(500),
|
||||
|
||||
-- Metadatos
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 4. Planes de Mantenimiento
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.maintenance_plans (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Identificacion
|
||||
plan_code VARCHAR(50) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Aplica a
|
||||
asset_id UUID REFERENCES assets.assets(id), -- Si es especifico de un activo
|
||||
category_id UUID REFERENCES assets.asset_categories(id), -- Si aplica a categoria
|
||||
asset_type assets.asset_type, -- Si aplica a tipo
|
||||
|
||||
-- Tipo y frecuencia
|
||||
maintenance_type assets.maintenance_type NOT NULL DEFAULT 'preventive',
|
||||
frequency assets.maintenance_frequency NOT NULL,
|
||||
frequency_value INTEGER, -- Cada cuantas unidades (dias, horas, km)
|
||||
|
||||
-- Actividades del plan
|
||||
activities JSONB NOT NULL, -- Array de actividades con checklist
|
||||
|
||||
-- Duracion estimada
|
||||
estimated_duration_hours DECIMAL(5,2),
|
||||
|
||||
-- Recursos necesarios
|
||||
required_parts JSONB, -- Refacciones necesarias
|
||||
required_tools JSONB, -- Herramientas necesarias
|
||||
required_skills VARCHAR(255)[], -- Habilidades requeridas
|
||||
|
||||
-- Costos estimados
|
||||
estimated_labor_cost DECIMAL(18,2),
|
||||
estimated_parts_cost DECIMAL(18,2),
|
||||
estimated_total_cost DECIMAL(18,2),
|
||||
|
||||
-- Estado
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
-- Metadatos
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_maintenance_plans_tenant_code UNIQUE (tenant_id, plan_code)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 5. Programacion de Mantenimientos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.maintenance_schedules (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Activo y plan
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
plan_id UUID REFERENCES assets.maintenance_plans(id),
|
||||
|
||||
-- Programacion
|
||||
scheduled_date DATE NOT NULL,
|
||||
scheduled_hours DECIMAL(12,2), -- Horas del equipo cuando debe hacerse
|
||||
scheduled_kilometers DECIMAL(12,2), -- KM cuando debe hacerse
|
||||
|
||||
-- Estado
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending, completed, skipped, overdue
|
||||
completed_date DATE,
|
||||
|
||||
-- Orden de trabajo generada
|
||||
work_order_id UUID,
|
||||
|
||||
-- Alertas
|
||||
alert_days_before INTEGER DEFAULT 7,
|
||||
alert_sent BOOLEAN DEFAULT FALSE,
|
||||
alert_sent_at TIMESTAMPTZ,
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 6. Ordenes de Trabajo de Mantenimiento
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.work_orders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Identificacion
|
||||
work_order_number VARCHAR(50) NOT NULL,
|
||||
|
||||
-- Activo
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
asset_code VARCHAR(50),
|
||||
asset_name VARCHAR(255),
|
||||
|
||||
-- Tipo y estado
|
||||
maintenance_type assets.maintenance_type NOT NULL,
|
||||
status assets.work_order_status NOT NULL DEFAULT 'draft',
|
||||
priority assets.work_order_priority NOT NULL DEFAULT 'medium',
|
||||
|
||||
-- Origen
|
||||
schedule_id UUID REFERENCES assets.maintenance_schedules(id),
|
||||
plan_id UUID REFERENCES assets.maintenance_plans(id),
|
||||
is_scheduled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Descripcion
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
problem_reported TEXT,
|
||||
diagnosis TEXT,
|
||||
|
||||
-- Ubicacion
|
||||
project_id UUID,
|
||||
project_name VARCHAR(255),
|
||||
location_description VARCHAR(255),
|
||||
|
||||
-- Fechas
|
||||
requested_date DATE NOT NULL,
|
||||
scheduled_start_date DATE,
|
||||
scheduled_end_date DATE,
|
||||
actual_start_date DATE,
|
||||
actual_end_date DATE,
|
||||
|
||||
-- Metricas del equipo al momento
|
||||
hours_at_work_order DECIMAL(12,2),
|
||||
kilometers_at_work_order DECIMAL(12,2),
|
||||
|
||||
-- Asignacion
|
||||
assigned_to_id UUID,
|
||||
assigned_to_name VARCHAR(255),
|
||||
team_ids UUID[],
|
||||
|
||||
-- Solicitante
|
||||
requested_by_id UUID,
|
||||
requested_by_name VARCHAR(255),
|
||||
|
||||
-- Aprobacion
|
||||
approved_by_id UUID,
|
||||
approved_at TIMESTAMPTZ,
|
||||
|
||||
-- Trabajo realizado
|
||||
work_performed TEXT,
|
||||
findings TEXT,
|
||||
recommendations TEXT,
|
||||
|
||||
-- Checklist de actividades
|
||||
activities_checklist JSONB,
|
||||
|
||||
-- Tiempos
|
||||
estimated_hours DECIMAL(5,2),
|
||||
actual_hours DECIMAL(5,2),
|
||||
|
||||
-- Costos
|
||||
labor_cost DECIMAL(18,2) DEFAULT 0,
|
||||
parts_cost DECIMAL(18,2) DEFAULT 0,
|
||||
external_service_cost DECIMAL(18,2) DEFAULT 0,
|
||||
other_costs DECIMAL(18,2) DEFAULT 0,
|
||||
total_cost DECIMAL(18,2) DEFAULT 0,
|
||||
|
||||
-- Partes utilizadas (detalle en tabla separada)
|
||||
parts_used_count INTEGER DEFAULT 0,
|
||||
|
||||
-- Documentos
|
||||
photos_before JSONB, -- URLs de fotos antes
|
||||
photos_after JSONB, -- URLs de fotos despues
|
||||
documents JSONB, -- URLs de documentos adjuntos
|
||||
|
||||
-- Firma de conformidad
|
||||
completed_by_id UUID,
|
||||
completed_by_name VARCHAR(255),
|
||||
completion_signature_url VARCHAR(500),
|
||||
completion_notes TEXT,
|
||||
|
||||
-- Seguimiento
|
||||
requires_followup BOOLEAN DEFAULT FALSE,
|
||||
followup_notes TEXT,
|
||||
followup_work_order_id UUID,
|
||||
|
||||
-- Notas y metadatos
|
||||
notes TEXT,
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
updated_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uq_work_orders_tenant_number UNIQUE (tenant_id, work_order_number)
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 7. Partes/Refacciones Utilizadas en Ordenes de Trabajo
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.work_order_parts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Orden de trabajo
|
||||
work_order_id UUID NOT NULL REFERENCES assets.work_orders(id) ON DELETE CASCADE,
|
||||
|
||||
-- Parte/Refaccion
|
||||
part_id UUID, -- Referencia a inventario si existe
|
||||
part_code VARCHAR(50),
|
||||
part_name VARCHAR(255) NOT NULL,
|
||||
part_description TEXT,
|
||||
|
||||
-- Cantidades
|
||||
quantity_required DECIMAL(10,2) NOT NULL,
|
||||
quantity_used DECIMAL(10,2),
|
||||
|
||||
-- Costos
|
||||
unit_cost DECIMAL(18,2),
|
||||
total_cost DECIMAL(18,2),
|
||||
|
||||
-- Origen
|
||||
from_inventory BOOLEAN DEFAULT FALSE,
|
||||
purchase_order_id UUID, -- Si se compro especificamente
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 8. Historial de Mantenimientos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.maintenance_history (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Activo
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
|
||||
-- Orden de trabajo (si aplica)
|
||||
work_order_id UUID REFERENCES assets.work_orders(id),
|
||||
|
||||
-- Fecha y tipo
|
||||
maintenance_date DATE NOT NULL,
|
||||
maintenance_type assets.maintenance_type NOT NULL,
|
||||
|
||||
-- Descripcion
|
||||
description TEXT NOT NULL,
|
||||
work_performed TEXT,
|
||||
|
||||
-- Metricas al momento del mantenimiento
|
||||
hours_at_maintenance DECIMAL(12,2),
|
||||
kilometers_at_maintenance DECIMAL(12,2),
|
||||
|
||||
-- Costos
|
||||
labor_cost DECIMAL(18,2) DEFAULT 0,
|
||||
parts_cost DECIMAL(18,2) DEFAULT 0,
|
||||
total_cost DECIMAL(18,2) DEFAULT 0,
|
||||
|
||||
-- Ejecutor
|
||||
performed_by_id UUID,
|
||||
performed_by_name VARCHAR(255),
|
||||
vendor_name VARCHAR(255), -- Si fue externo
|
||||
|
||||
-- Documentos
|
||||
documents JSONB,
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 9. Costos de Activos
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.asset_costs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Activo
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
|
||||
-- Periodo
|
||||
period_start DATE NOT NULL,
|
||||
period_end DATE NOT NULL,
|
||||
fiscal_year INTEGER NOT NULL,
|
||||
fiscal_month INTEGER NOT NULL,
|
||||
|
||||
-- Proyecto (si aplica)
|
||||
project_id UUID,
|
||||
project_code VARCHAR(50),
|
||||
|
||||
-- Tipo de costo
|
||||
cost_type assets.cost_type NOT NULL,
|
||||
|
||||
-- Descripcion
|
||||
description VARCHAR(255),
|
||||
reference_document VARCHAR(100),
|
||||
|
||||
-- Monto
|
||||
amount DECIMAL(18,2) NOT NULL,
|
||||
currency VARCHAR(3) DEFAULT 'MXN',
|
||||
|
||||
-- Uso asociado
|
||||
hours_in_period DECIMAL(12,2),
|
||||
kilometers_in_period DECIMAL(12,2),
|
||||
|
||||
-- Calculo de tarifa
|
||||
cost_per_hour DECIMAL(18,4),
|
||||
cost_per_kilometer DECIMAL(18,4),
|
||||
|
||||
-- Origen
|
||||
source_module VARCHAR(50), -- work_order, fuel_log, invoice, etc.
|
||||
source_id UUID,
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
metadata JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 10. Ubicaciones GPS (Historico)
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.asset_locations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Activo
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
|
||||
-- Ubicacion
|
||||
latitude DECIMAL(10,8) NOT NULL,
|
||||
longitude DECIMAL(11,8) NOT NULL,
|
||||
altitude DECIMAL(8,2),
|
||||
accuracy DECIMAL(6,2),
|
||||
heading DECIMAL(5,2),
|
||||
speed DECIMAL(6,2),
|
||||
|
||||
-- Timestamp
|
||||
recorded_at TIMESTAMPTZ NOT NULL,
|
||||
|
||||
-- Contexto
|
||||
project_id UUID,
|
||||
location_name VARCHAR(255),
|
||||
address VARCHAR(500),
|
||||
|
||||
-- Telemetria adicional
|
||||
engine_status VARCHAR(20), -- on, off, idle
|
||||
fuel_level DECIMAL(5,2),
|
||||
odometer DECIMAL(12,2),
|
||||
engine_hours DECIMAL(12,2),
|
||||
battery_voltage DECIMAL(5,2),
|
||||
|
||||
-- Dispositivo
|
||||
device_id VARCHAR(100),
|
||||
device_type VARCHAR(50),
|
||||
|
||||
-- Metadatos
|
||||
raw_data JSONB,
|
||||
|
||||
-- Auditoria
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- 11. Registro de Combustible
|
||||
-- ----------------------------------------------------------------------------
|
||||
CREATE TABLE assets.fuel_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL,
|
||||
|
||||
-- Activo
|
||||
asset_id UUID NOT NULL REFERENCES assets.assets(id),
|
||||
|
||||
-- Fecha y ubicacion
|
||||
log_date DATE NOT NULL,
|
||||
log_time TIME,
|
||||
project_id UUID,
|
||||
location VARCHAR(255),
|
||||
|
||||
-- Combustible
|
||||
fuel_type VARCHAR(50) NOT NULL,
|
||||
quantity_liters DECIMAL(10,2) NOT NULL,
|
||||
unit_price DECIMAL(18,4) NOT NULL,
|
||||
total_cost DECIMAL(18,2) NOT NULL,
|
||||
|
||||
-- Metricas al cargar
|
||||
odometer_reading DECIMAL(12,2),
|
||||
hours_reading DECIMAL(12,2),
|
||||
|
||||
-- Rendimiento calculado
|
||||
kilometers_since_last DECIMAL(12,2),
|
||||
hours_since_last DECIMAL(12,2),
|
||||
liters_per_100km DECIMAL(8,2),
|
||||
liters_per_hour DECIMAL(8,2),
|
||||
|
||||
-- Proveedor
|
||||
vendor_name VARCHAR(255),
|
||||
invoice_number VARCHAR(100),
|
||||
|
||||
-- Operador
|
||||
operator_id UUID,
|
||||
operator_name VARCHAR(255),
|
||||
|
||||
-- Notas
|
||||
notes TEXT,
|
||||
|
||||
-- Auditoria
|
||||
created_by UUID,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- INDICES
|
||||
-- ============================================================================
|
||||
|
||||
-- Asset Categories
|
||||
CREATE INDEX idx_asset_categories_tenant ON assets.asset_categories(tenant_id);
|
||||
CREATE INDEX idx_asset_categories_parent ON assets.asset_categories(parent_id);
|
||||
|
||||
-- Assets
|
||||
CREATE INDEX idx_assets_tenant ON assets.assets(tenant_id);
|
||||
CREATE INDEX idx_assets_tenant_type ON assets.assets(tenant_id, asset_type);
|
||||
CREATE INDEX idx_assets_tenant_status ON assets.assets(tenant_id, status);
|
||||
CREATE INDEX idx_assets_tenant_category ON assets.assets(tenant_id, category_id);
|
||||
CREATE INDEX idx_assets_current_project ON assets.assets(tenant_id, current_project_id);
|
||||
CREATE INDEX idx_assets_serial ON assets.assets(tenant_id, serial_number);
|
||||
|
||||
-- Asset Assignments
|
||||
CREATE INDEX idx_asset_assignments_tenant ON assets.asset_assignments(tenant_id);
|
||||
CREATE INDEX idx_asset_assignments_asset ON assets.asset_assignments(tenant_id, asset_id);
|
||||
CREATE INDEX idx_asset_assignments_project ON assets.asset_assignments(tenant_id, project_id);
|
||||
CREATE INDEX idx_asset_assignments_current ON assets.asset_assignments(tenant_id, is_current) WHERE is_current = TRUE;
|
||||
|
||||
-- Maintenance Plans
|
||||
CREATE INDEX idx_maintenance_plans_tenant ON assets.maintenance_plans(tenant_id);
|
||||
CREATE INDEX idx_maintenance_plans_asset ON assets.maintenance_plans(tenant_id, asset_id);
|
||||
CREATE INDEX idx_maintenance_plans_category ON assets.maintenance_plans(tenant_id, category_id);
|
||||
|
||||
-- Maintenance Schedules
|
||||
CREATE INDEX idx_maintenance_schedules_tenant ON assets.maintenance_schedules(tenant_id);
|
||||
CREATE INDEX idx_maintenance_schedules_asset ON assets.maintenance_schedules(tenant_id, asset_id);
|
||||
CREATE INDEX idx_maintenance_schedules_date ON assets.maintenance_schedules(tenant_id, scheduled_date);
|
||||
CREATE INDEX idx_maintenance_schedules_status ON assets.maintenance_schedules(tenant_id, status);
|
||||
|
||||
-- Work Orders
|
||||
CREATE INDEX idx_work_orders_tenant ON assets.work_orders(tenant_id);
|
||||
CREATE INDEX idx_work_orders_asset ON assets.work_orders(tenant_id, asset_id);
|
||||
CREATE INDEX idx_work_orders_status ON assets.work_orders(tenant_id, status);
|
||||
CREATE INDEX idx_work_orders_scheduled_date ON assets.work_orders(tenant_id, scheduled_start_date);
|
||||
CREATE INDEX idx_work_orders_project ON assets.work_orders(tenant_id, project_id);
|
||||
|
||||
-- Work Order Parts
|
||||
CREATE INDEX idx_work_order_parts_work_order ON assets.work_order_parts(work_order_id);
|
||||
|
||||
-- Maintenance History
|
||||
CREATE INDEX idx_maintenance_history_tenant ON assets.maintenance_history(tenant_id);
|
||||
CREATE INDEX idx_maintenance_history_asset ON assets.maintenance_history(tenant_id, asset_id);
|
||||
CREATE INDEX idx_maintenance_history_date ON assets.maintenance_history(tenant_id, maintenance_date);
|
||||
|
||||
-- Asset Costs
|
||||
CREATE INDEX idx_asset_costs_tenant ON assets.asset_costs(tenant_id);
|
||||
CREATE INDEX idx_asset_costs_asset ON assets.asset_costs(tenant_id, asset_id);
|
||||
CREATE INDEX idx_asset_costs_period ON assets.asset_costs(tenant_id, period_start, period_end);
|
||||
CREATE INDEX idx_asset_costs_type ON assets.asset_costs(tenant_id, cost_type);
|
||||
CREATE INDEX idx_asset_costs_project ON assets.asset_costs(tenant_id, project_id);
|
||||
|
||||
-- Asset Locations
|
||||
CREATE INDEX idx_asset_locations_tenant ON assets.asset_locations(tenant_id);
|
||||
CREATE INDEX idx_asset_locations_asset ON assets.asset_locations(tenant_id, asset_id);
|
||||
CREATE INDEX idx_asset_locations_recorded ON assets.asset_locations(tenant_id, recorded_at);
|
||||
CREATE INDEX idx_asset_locations_geo ON assets.asset_locations USING gist (
|
||||
ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)
|
||||
) WHERE longitude IS NOT NULL AND latitude IS NOT NULL;
|
||||
|
||||
-- Fuel Logs
|
||||
CREATE INDEX idx_fuel_logs_tenant ON assets.fuel_logs(tenant_id);
|
||||
CREATE INDEX idx_fuel_logs_asset ON assets.fuel_logs(tenant_id, asset_id);
|
||||
CREATE INDEX idx_fuel_logs_date ON assets.fuel_logs(tenant_id, log_date);
|
||||
|
||||
-- ============================================================================
|
||||
-- ROW LEVEL SECURITY (RLS)
|
||||
-- ============================================================================
|
||||
|
||||
ALTER TABLE assets.asset_categories ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.assets ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.asset_assignments ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.maintenance_plans ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.maintenance_schedules ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.work_orders ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.work_order_parts ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.maintenance_history ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.asset_costs ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.asset_locations ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE assets.fuel_logs ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- ============================================================================
|
||||
-- TRIGGERS DE AUDITORIA
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION assets.set_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_asset_categories_updated_at
|
||||
BEFORE UPDATE ON assets.asset_categories
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_assets_updated_at
|
||||
BEFORE UPDATE ON assets.assets
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_asset_assignments_updated_at
|
||||
BEFORE UPDATE ON assets.asset_assignments
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_maintenance_plans_updated_at
|
||||
BEFORE UPDATE ON assets.maintenance_plans
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_maintenance_schedules_updated_at
|
||||
BEFORE UPDATE ON assets.maintenance_schedules
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_work_orders_updated_at
|
||||
BEFORE UPDATE ON assets.work_orders
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_work_order_parts_updated_at
|
||||
BEFORE UPDATE ON assets.work_order_parts
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_asset_costs_updated_at
|
||||
BEFORE UPDATE ON assets.asset_costs
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_fuel_logs_updated_at
|
||||
BEFORE UPDATE ON assets.fuel_logs
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.set_updated_at();
|
||||
|
||||
-- ============================================================================
|
||||
-- FUNCIONES AUXILIARES
|
||||
-- ============================================================================
|
||||
|
||||
-- Funcion para calcular TCO de un activo
|
||||
CREATE OR REPLACE FUNCTION assets.calculate_asset_tco(
|
||||
p_asset_id UUID,
|
||||
p_tenant_id UUID,
|
||||
p_from_date DATE DEFAULT NULL,
|
||||
p_to_date DATE DEFAULT NULL
|
||||
)
|
||||
RETURNS TABLE (
|
||||
total_cost DECIMAL(18,2),
|
||||
maintenance_cost DECIMAL(18,2),
|
||||
fuel_cost DECIMAL(18,2),
|
||||
depreciation_cost DECIMAL(18,2),
|
||||
other_costs DECIMAL(18,2),
|
||||
total_hours DECIMAL(12,2),
|
||||
total_kilometers DECIMAL(12,2),
|
||||
cost_per_hour DECIMAL(18,4),
|
||||
cost_per_kilometer DECIMAL(18,4)
|
||||
) AS $$
|
||||
DECLARE
|
||||
v_from_date DATE;
|
||||
v_to_date DATE;
|
||||
BEGIN
|
||||
v_from_date := COALESCE(p_from_date, '1900-01-01'::DATE);
|
||||
v_to_date := COALESCE(p_to_date, CURRENT_DATE);
|
||||
|
||||
RETURN QUERY
|
||||
SELECT
|
||||
COALESCE(SUM(ac.amount), 0) AS total_cost,
|
||||
COALESCE(SUM(CASE WHEN ac.cost_type IN ('maintenance', 'repair') THEN ac.amount END), 0) AS maintenance_cost,
|
||||
COALESCE(SUM(CASE WHEN ac.cost_type = 'fuel' THEN ac.amount END), 0) AS fuel_cost,
|
||||
COALESCE(SUM(CASE WHEN ac.cost_type = 'depreciation' THEN ac.amount END), 0) AS depreciation_cost,
|
||||
COALESCE(SUM(CASE WHEN ac.cost_type NOT IN ('maintenance', 'repair', 'fuel', 'depreciation') THEN ac.amount END), 0) AS other_costs,
|
||||
COALESCE(SUM(ac.hours_in_period), 0) AS total_hours,
|
||||
COALESCE(SUM(ac.kilometers_in_period), 0) AS total_kilometers,
|
||||
CASE WHEN SUM(ac.hours_in_period) > 0 THEN SUM(ac.amount) / SUM(ac.hours_in_period) ELSE 0 END AS cost_per_hour,
|
||||
CASE WHEN SUM(ac.kilometers_in_period) > 0 THEN SUM(ac.amount) / SUM(ac.kilometers_in_period) ELSE 0 END AS cost_per_kilometer
|
||||
FROM assets.asset_costs ac
|
||||
WHERE ac.asset_id = p_asset_id
|
||||
AND ac.tenant_id = p_tenant_id
|
||||
AND ac.period_start >= v_from_date
|
||||
AND ac.period_end <= v_to_date;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Funcion para actualizar proximo mantenimiento de un activo
|
||||
CREATE OR REPLACE FUNCTION assets.update_next_maintenance()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
-- Actualizar proximo mantenimiento del activo
|
||||
UPDATE assets.assets a
|
||||
SET
|
||||
next_maintenance_date = (
|
||||
SELECT MIN(scheduled_date)
|
||||
FROM assets.maintenance_schedules ms
|
||||
WHERE ms.asset_id = a.id
|
||||
AND ms.status = 'pending'
|
||||
),
|
||||
updated_at = NOW()
|
||||
WHERE a.id = COALESCE(NEW.asset_id, OLD.asset_id);
|
||||
|
||||
RETURN COALESCE(NEW, OLD);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_update_next_maintenance
|
||||
AFTER INSERT OR UPDATE OR DELETE ON assets.maintenance_schedules
|
||||
FOR EACH ROW EXECUTE FUNCTION assets.update_next_maintenance();
|
||||
|
||||
-- ============================================================================
|
||||
-- COMENTARIOS DE DOCUMENTACION
|
||||
-- ============================================================================
|
||||
|
||||
COMMENT ON SCHEMA assets IS 'Modulo de Activos, Maquinaria y Mantenimiento (MAE-015) - ERP Construccion';
|
||||
|
||||
COMMENT ON TABLE assets.asset_categories IS 'Categorias de activos para clasificacion';
|
||||
COMMENT ON TABLE assets.assets IS 'Catalogo principal de activos (maquinaria, equipo, vehiculos)';
|
||||
COMMENT ON TABLE assets.asset_assignments IS 'Asignaciones de activos a proyectos/obras';
|
||||
COMMENT ON TABLE assets.maintenance_plans IS 'Planes de mantenimiento preventivo';
|
||||
COMMENT ON TABLE assets.maintenance_schedules IS 'Programacion de mantenimientos por activo';
|
||||
COMMENT ON TABLE assets.work_orders IS 'Ordenes de trabajo de mantenimiento';
|
||||
COMMENT ON TABLE assets.work_order_parts IS 'Partes/refacciones utilizadas en ordenes de trabajo';
|
||||
COMMENT ON TABLE assets.maintenance_history IS 'Historial de mantenimientos realizados';
|
||||
COMMENT ON TABLE assets.asset_costs IS 'Costos de operacion y mantenimiento de activos';
|
||||
COMMENT ON TABLE assets.asset_locations IS 'Historial de ubicaciones GPS de activos';
|
||||
COMMENT ON TABLE assets.fuel_logs IS 'Registro de cargas de combustible';
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DEL SCRIPT
|
||||
-- ============================================================================
|
||||
Loading…
Reference in New Issue
Block a user