Files
MarineMaintenance/schema.sql
T
alro65 67a0e674ca Initial commit — MarineMaintenance v1.0
Marine maintenance management: work orders with photos, ISM/SWP procedures,
MSDS, inventory, RFQ/purchases, vessel history, bilingual PDF reports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 01:54:20 -04:00

425 lines
14 KiB
SQL

-- MARINE MAINTENANCE SYSTEM
-- Database Schema v2.0
PRAGMA foreign_keys = ON;
-- COMPAÑÍAS
CREATE TABLE IF NOT EXISTS companies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
address TEXT,
phone TEXT,
email TEXT,
website TEXT,
logo_path TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- USUARIOS (roles: superadmin | admin | technician)
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
username TEXT NOT NULL UNIQUE,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
full_name TEXT,
role TEXT NOT NULL DEFAULT 'technician',
is_active INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP
);
-- EMBARCACIONES
CREATE TABLE IF NOT EXISTS vessels (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
name TEXT NOT NULL,
registration TEXT,
vessel_type TEXT,
make TEXT,
model TEXT,
year INTEGER,
length_ft REAL,
flag TEXT,
port_of_registry TEXT,
engine_type TEXT,
engine_hours REAL DEFAULT 0,
owner_name TEXT,
owner_phone TEXT,
owner_email TEXT,
captain_name TEXT,
captain_phone TEXT,
captain_email TEXT,
notes TEXT,
photo_path TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- EQUIPOS DE LA EMBARCACIÓN
CREATE TABLE IF NOT EXISTS vessel_equipment (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vessel_id INTEGER NOT NULL REFERENCES vessels(id) ON DELETE CASCADE,
name TEXT NOT NULL,
equipment_type TEXT,
make TEXT,
model TEXT,
serial_number TEXT,
year INTEGER,
position TEXT,
engine_hours REAL DEFAULT 0,
last_service_date DATE,
last_service_hours REAL,
notes TEXT,
is_active INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- DOCUMENTOS ADJUNTOS (por embarcación / equipo)
CREATE TABLE IF NOT EXISTS vessel_documents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vessel_id INTEGER NOT NULL REFERENCES vessels(id) ON DELETE CASCADE,
equipment_id INTEGER REFERENCES vessel_equipment(id),
doc_type TEXT NOT NULL DEFAULT 'other',
title TEXT NOT NULL,
description TEXT,
filename TEXT NOT NULL,
original_filename TEXT,
file_size INTEGER,
uploaded_by TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- CATEGORÍAS DE REPUESTOS
CREATE TABLE IF NOT EXISTS parts_categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT
);
-- INVENTARIO
CREATE TABLE IF NOT EXISTS parts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
category_id INTEGER REFERENCES parts_categories(id),
part_number TEXT,
name TEXT NOT NULL,
description TEXT,
brand TEXT,
location TEXT,
quantity REAL DEFAULT 0,
unit TEXT DEFAULT 'pcs',
min_quantity REAL DEFAULT 0,
cost_price REAL DEFAULT 0,
sale_price REAL DEFAULT 0,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- PROVEEDORES
CREATE TABLE IF NOT EXISTS suppliers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
name TEXT NOT NULL,
contact_name TEXT,
phone TEXT,
email TEXT,
address TEXT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- COMPRAS
CREATE TABLE IF NOT EXISTS purchases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
supplier_id INTEGER REFERENCES suppliers(id),
vessel_id INTEGER REFERENCES vessels(id), -- embarcación destino
work_order_id INTEGER REFERENCES work_orders(id), -- WO relacionada (opcional)
purchase_number TEXT, -- número interno
invoice_number TEXT, -- número factura proveedor
purchase_date DATE NOT NULL,
delivery_date DATE, -- fecha entrega esperada
received_date DATE, -- fecha recibido real
status TEXT DEFAULT 'requested', -- requested|approved|ordered|received|paid|cancelled
requested_by TEXT,
approved_by TEXT,
payment_method TEXT, -- cash|transfer|check|credit
payment_reference TEXT,
invoice_photo TEXT, -- archivo adjunto factura
total_amount REAL DEFAULT 0,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS purchase_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
purchase_id INTEGER NOT NULL REFERENCES purchases(id) ON DELETE CASCADE,
part_id INTEGER REFERENCES parts(id),
description TEXT,
part_number TEXT, -- número de parte fabricante
quantity REAL NOT NULL,
unit_cost REAL NOT NULL,
total_cost REAL GENERATED ALWAYS AS (quantity * unit_cost) STORED,
quantity_received REAL DEFAULT 0, -- lo que realmente llegó
notes TEXT
);
-- HISTORIAL DE MOVIMIENTOS DE INVENTARIO
CREATE TABLE IF NOT EXISTS inventory_movements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
part_id INTEGER NOT NULL REFERENCES parts(id),
movement_type TEXT NOT NULL, -- in|out|adjustment
quantity REAL NOT NULL, -- positivo=entrada, negativo=salida
reference_type TEXT, -- purchase|work_order|adjustment
reference_id INTEGER, -- id de la compra o WO
vessel_id INTEGER REFERENCES vessels(id),
notes TEXT,
created_by TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ÓRDENES DE TRABAJO
CREATE TABLE IF NOT EXISTS work_orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vessel_id INTEGER NOT NULL REFERENCES vessels(id),
equipment_id INTEGER REFERENCES vessel_equipment(id),
order_number TEXT UNIQUE,
status TEXT DEFAULT 'open',
work_type TEXT,
scope TEXT,
description TEXT,
root_cause TEXT,
repairs_done TEXT,
technician TEXT,
start_date DATE,
end_date DATE,
engine_hours_start REAL,
engine_hours_end REAL,
labor_hours REAL DEFAULT 0,
labor_rate REAL DEFAULT 0,
billing_type TEXT DEFAULT 'labor_materials', -- lump_sum | labor_only | labor_materials
total_parts_cost REAL DEFAULT 0,
total_labor_cost REAL GENERATED ALWAYS AS (labor_hours * labor_rate) STORED,
notes TEXT,
invoice_exported INTEGER DEFAULT 0,
system_id INTEGER REFERENCES systems(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS work_order_parts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
work_order_id INTEGER NOT NULL REFERENCES work_orders(id) ON DELETE CASCADE,
part_id INTEGER REFERENCES parts(id),
description TEXT,
quantity REAL NOT NULL,
unit_cost REAL NOT NULL,
total_cost REAL GENERATED ALWAYS AS (quantity * unit_cost) STORED
);
CREATE TABLE IF NOT EXISTS work_order_photos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
work_order_id INTEGER NOT NULL REFERENCES work_orders(id) ON DELETE CASCADE,
photo_type TEXT NOT NULL,
filename TEXT NOT NULL,
caption TEXT,
taken_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS maintenance_schedules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vessel_id INTEGER NOT NULL REFERENCES vessels(id),
equipment_id INTEGER REFERENCES vessel_equipment(id),
task_name TEXT NOT NULL,
description TEXT,
frequency_days INTEGER,
frequency_hours REAL,
last_done_date DATE,
last_done_hours REAL,
next_due_date DATE,
next_due_hours REAL,
is_active INTEGER DEFAULT 1,
notes TEXT
);
-- SISTEMAS (predefinidos + personalizados)
CREATE TABLE IF NOT EXISTS systems (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
name TEXT NOT NULL,
description TEXT,
is_default INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- EQUIPOS TRABAJADOS EN UNA ORDEN (múltiples por WO)
CREATE TABLE IF NOT EXISTS work_order_equipment (
id INTEGER PRIMARY KEY AUTOINCREMENT,
work_order_id INTEGER NOT NULL REFERENCES work_orders(id) ON DELETE CASCADE,
equipment_id INTEGER REFERENCES vessel_equipment(id),
description TEXT,
notes TEXT,
labor_hours REAL DEFAULT 0,
labor_rate REAL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Sistemas predefinidos
INSERT OR IGNORE INTO systems (id, name, is_default) VALUES
(1, 'Propulsión', 1),
(2, 'Generación', 1),
(3, 'Navegación y Comunicaciones', 1),
(4, 'Sistema Eléctrico', 1),
(5, 'Baterías y Carga', 1),
(6, 'Hidráulico', 1),
(7, 'HVAC / Climatización', 1),
(8, 'Plomería / Agua', 1),
(9, 'Seguridad', 1),
(10, 'Casco y Estructura', 1),
(11, 'Otro', 1);
INSERT OR IGNORE INTO parts_categories (name) VALUES
('Motor'),('Hidráulico'),('Eléctrico'),('Electrónico'),
('Casco y cubierta'),('Plomería / Sistema de agua'),
('HVAC'),('Seguridad'),('Varios');
-- CONFIGURACIÓN EMAIL POR COMPAÑÍA
CREATE TABLE IF NOT EXISTS email_config (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
smtp_host TEXT,
smtp_port INTEGER DEFAULT 587,
smtp_user TEXT,
smtp_password TEXT,
from_name TEXT,
from_email TEXT,
use_tls INTEGER DEFAULT 1,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- FIRMAS Y PDF GUARDADO en work_orders (columnas extra)
-- Se agregan via ALTER TABLE al iniciar si no existen
-- LOG DE EMAILS ENVIADOS
CREATE TABLE IF NOT EXISTS email_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
work_order_id INTEGER REFERENCES work_orders(id),
sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
to_email TEXT NOT NULL,
to_name TEXT,
subject TEXT,
lang TEXT DEFAULT 'es',
pdf_filename TEXT,
status TEXT DEFAULT 'sent',
error_msg TEXT,
sent_by TEXT
);
CREATE TABLE IF NOT EXISTS po_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
po_id INTEGER NOT NULL REFERENCES purchase_orders(id) ON DELETE CASCADE,
rfq_item_id INTEGER REFERENCES rfq_items(id),
description TEXT NOT NULL,
quantity REAL DEFAULT 1,
unit TEXT DEFAULT 'pcs',
unit_cost REAL DEFAULT 0,
total_cost REAL GENERATED ALWAYS AS (quantity * unit_cost) STORED,
part_id INTEGER REFERENCES parts(id),
received_qty REAL DEFAULT 0,
notes TEXT
);
-- MOVIMIENTOS DE INVENTARIO
CREATE TABLE IF NOT EXISTS inventory_movements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
part_id INTEGER REFERENCES parts(id),
po_id INTEGER REFERENCES purchase_orders(id),
work_order_id INTEGER REFERENCES work_orders(id),
vessel_id INTEGER REFERENCES vessels(id),
movement_type TEXT NOT NULL, -- in|out|assign_vessel|assign_wo
quantity REAL NOT NULL,
unit_cost REAL DEFAULT 0,
notes TEXT,
created_by TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ═══════════════════════════════════════════════════════
-- MÓDULO ISM — PROCEDIMIENTOS DE TRABAJO SEGURO
-- ═══════════════════════════════════════════════════════
-- PROCEDIMIENTOS MAESTRO
CREATE TABLE IF NOT EXISTS swp (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
code TEXT NOT NULL, -- SWP-001, SWP-002...
title TEXT NOT NULL,
category TEXT NOT NULL, -- electrical|mechanical|chemical|confined|height|welding|hull|other
status TEXT DEFAULT 'active', -- active|archived
current_version_id INTEGER, -- FK a swp_versions (se actualiza al aprobar)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- VERSIONES DEL PROCEDIMIENTO
CREATE TABLE IF NOT EXISTS swp_versions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
swp_id INTEGER NOT NULL REFERENCES swp(id) ON DELETE CASCADE,
version TEXT NOT NULL, -- v1.0, v1.1, v2.0
purpose TEXT,
scope TEXT,
hazards TEXT, -- JSON array
ppe TEXT, -- JSON array
tools TEXT, -- JSON array (herramientas y materiales)
steps TEXT, -- JSON array numerado
emergency TEXT,
ref_standards TEXT, -- JSON array (ISM, SOLAS, OSHA...)
status TEXT DEFAULT 'draft', -- draft|active|superseded|archived
change_reason TEXT,
diff_summary TEXT,
created_by TEXT,
approved_by TEXT,
approved_at TIMESTAMP,
effective_date DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- FIRMA DEL TÉCNICO AL LEER EL PROCEDIMIENTO EN UNA WO
CREATE TABLE IF NOT EXISTS swp_acknowledgements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
swp_id INTEGER NOT NULL REFERENCES swp(id),
swp_version_id INTEGER NOT NULL REFERENCES swp_versions(id),
work_order_id INTEGER NOT NULL REFERENCES work_orders(id),
technician TEXT NOT NULL,
signature TEXT, -- filename de firma
acknowledged_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
notes TEXT
);
-- MSDS — FICHAS TÉCNICAS DE SEGURIDAD
CREATE TABLE IF NOT EXISTS msds (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER REFERENCES companies(id),
part_id INTEGER REFERENCES parts(id), -- vinculada a inventario
product_name TEXT NOT NULL,
manufacturer TEXT,
version TEXT DEFAULT 'v1.0',
hazard_class TEXT, -- GHS class
hazards TEXT, -- descripción de riesgos
first_aid TEXT,
ppe_required TEXT,
handling TEXT,
storage TEXT,
spill_procedure TEXT,
disposal TEXT,
ref_standards TEXT,
pdf_filename TEXT, -- PDF oficial del fabricante
created_by TEXT,
updated_by TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);