67a0e674ca
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>
425 lines
14 KiB
SQL
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
|
|
);
|