maintaince module

This commit is contained in:
2026-08-12 21:29:55 +03:00
parent 41c4838dab
commit 55d83c12b0
51 changed files with 8200 additions and 48 deletions
@@ -0,0 +1,59 @@
DELIMITER $$
DROP PROCEDURE IF EXISTS manutenzioni_migrate_step1 $$
CREATE PROCEDURE manutenzioni_migrate_step1()
BEGIN
DECLARE v_db VARCHAR(64);
SET v_db = DATABASE();
-- 1. Rename production_tools -> inv_equipment
IF EXISTS (SELECT 1 FROM information_schema.tables
WHERE table_schema = v_db AND table_name = 'production_tools')
AND NOT EXISTS (SELECT 1 FROM information_schema.tables
WHERE table_schema = v_db AND table_name = 'inv_equipment') THEN
RENAME TABLE production_tools TO inv_equipment;
END IF;
-- 2. Normalise charset/collation (was utf8mb4_general_ci; the rest of
-- the new modules are utf8mb4_unicode_ci — mixing them breaks joins
-- on string columns with "Illegal mix of collations")
ALTER TABLE inv_equipment CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 3. Registry columns (all nullable: existing rows stay valid)
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = v_db AND table_name = 'inv_equipment'
AND column_name = 'category_id') THEN
ALTER TABLE inv_equipment
ADD COLUMN category_id INT UNSIGNED NULL AFTER name,
ADD COLUMN line_id INT NULL AFTER category_id,
ADD COLUMN batch_lot VARCHAR(100) NULL AFTER serial_number,
ADD COLUMN purchase_date DATE NULL AFTER batch_lot,
ADD COLUMN commissioning_date DATE NULL AFTER purchase_date,
ADD COLUMN department_id INT UNSIGNED NULL AFTER manufacturer,
ADD COLUMN location VARCHAR(255) NULL AFTER department_id,
ADD COLUMN notes TEXT NULL AFTER description,
ADD COLUMN cover_file_id INT UNSIGNED NULL AFTER notes,
ADD COLUMN created_by INT UNSIGNED NULL AFTER cover_file_id,
ADD KEY idx_inv_equipment_category (category_id),
ADD KEY idx_inv_equipment_line (line_id),
ADD KEY idx_inv_equipment_department (department_id);
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = v_db AND table_name = 'inv_equipment'
AND column_name = 'status') THEN
ALTER TABLE inv_equipment
ADD COLUMN status ENUM('active','decommissioned','out_of_service') NULL AFTER location;
UPDATE inv_equipment SET status = IF(is_active = 1, 'active', 'decommissioned');
ALTER TABLE inv_equipment
MODIFY COLUMN status ENUM('active','decommissioned','out_of_service')
NOT NULL DEFAULT 'active';
ALTER TABLE inv_equipment DROP COLUMN is_active;
ALTER TABLE inv_equipment ADD KEY idx_inv_equipment_status (status);
END IF;
END $$
DELIMITER ;
CALL manutenzioni_migrate_step1();
DROP PROCEDURE manutenzioni_migrate_step1;
@@ -0,0 +1,171 @@
CREATE TABLE IF NOT EXISTS inv_categories (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(150) NOT NULL,
code VARCHAR(50) NULL,
description TEXT NULL,
color VARCHAR(20) NOT NULL DEFAULT '#6c757d',
-- when 1, the equipment form requires a production line
requires_line TINYINT(1) NOT NULL DEFAULT 0,
sort_order INT UNSIGNED NOT NULL DEFAULT 999,
is_active TINYINT(1) NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uniq_inv_categories_name (name),
KEY idx_inv_categories_active (is_active, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS inv_equipment_files (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
equipment_id INT NOT NULL,
kind VARCHAR(10) NOT NULL DEFAULT 'file',
original_name VARCHAR(500) NOT NULL,
stored_name VARCHAR(500) NOT NULL,
mime_type VARCHAR(100) NULL,
size INT UNSIGNED NULL,
uploaded_by INT UNSIGNED NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_inv_files_equipment (equipment_id, kind),
CONSTRAINT fk_inv_files_equipment FOREIGN KEY (equipment_id)
REFERENCES inv_equipment (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS maint_maintenances (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
equipment_id INT NOT NULL,
-- letter code as used on the paper form (A, B, C, ...)
code VARCHAR(10) NULL,
title VARCHAR(500) NOT NULL,
description TEXT NULL,
intervention_type VARCHAR(20) NOT NULL DEFAULT 'scheduled',
execution_type VARCHAR(20) NOT NULL DEFAULT 'internal',
is_critical TINYINT(1) NOT NULL DEFAULT 0,
-- frequency: NULL value + unit 'on_demand' means "no automatic due date"
frequency_value SMALLINT UNSIGNED NULL,
frequency_unit VARCHAR(20) NOT NULL DEFAULT 'month',
-- free text for the irregular cases in the client's sheets
-- ("prima dell'accensione / d'estate settimanale / dopo lo spegnimento")
frequency_note VARCHAR(500) NULL,
alert_days SMALLINT UNSIGNED NOT NULL DEFAULT 7,
assignee_employee_id INT UNSIGNED NULL,
supervisor_employee_id INT UNSIGNED NULL,
supplier_id INT NULL,
is_active TINYINT(1) NOT NULL DEFAULT 1,
-- denormalised, recomputed on every intervention change
last_done_date DATE NULL,
next_due_date DATE NULL,
notes TEXT NULL,
created_by INT UNSIGNED NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_maint_equipment (equipment_id),
KEY idx_maint_due (next_due_date),
KEY idx_maint_type (intervention_type, is_active),
CONSTRAINT fk_maint_equipment FOREIGN KEY (equipment_id)
REFERENCES inv_equipment (id) ON DELETE CASCADE,
CONSTRAINT fk_maint_assignee FOREIGN KEY (assignee_employee_id)
REFERENCES employees (id) ON DELETE SET NULL,
CONSTRAINT fk_maint_supervisor FOREIGN KEY (supervisor_employee_id)
REFERENCES employees (id) ON DELETE SET NULL,
CONSTRAINT fk_maint_supplier FOREIGN KEY (supplier_id)
REFERENCES suppliers (idsupplier) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS maint_maintenance_files (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
maintenance_id INT UNSIGNED NOT NULL,
original_name VARCHAR(500) NOT NULL,
stored_name VARCHAR(500) NOT NULL,
mime_type VARCHAR(100) NULL,
size INT UNSIGNED NULL,
uploaded_by INT UNSIGNED NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_mmf_maintenance (maintenance_id),
CONSTRAINT fk_mmf_maintenance FOREIGN KEY (maintenance_id)
REFERENCES maint_maintenances (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS maint_interventions (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
maintenance_id INT UNSIGNED NOT NULL,
-- denormalised so the equipment history is a single-table scan
equipment_id INT NOT NULL,
performed_at DATE NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'completed',
result VARCHAR(20) NULL,
notes TEXT NULL,
materials TEXT NULL,
operator_employee_id INT UNSIGNED NULL,
-- free text operator for external technicians not present in employees
operator_name VARCHAR(191) NULL,
signature_path VARCHAR(255) NULL,
supplier_id INT NULL,
created_by INT UNSIGNED NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_int_maintenance (maintenance_id, performed_at),
KEY idx_int_equipment (equipment_id, performed_at),
KEY idx_int_status (status),
CONSTRAINT fk_int_maintenance FOREIGN KEY (maintenance_id)
REFERENCES maint_maintenances (id) ON DELETE CASCADE,
CONSTRAINT fk_int_equipment FOREIGN KEY (equipment_id)
REFERENCES inv_equipment (id) ON DELETE CASCADE,
CONSTRAINT fk_int_operator FOREIGN KEY (operator_employee_id)
REFERENCES employees (id) ON DELETE SET NULL,
CONSTRAINT fk_int_supplier FOREIGN KEY (supplier_id)
REFERENCES suppliers (idsupplier) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS maint_intervention_files (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
intervention_id INT UNSIGNED NOT NULL,
original_name VARCHAR(500) NOT NULL,
stored_name VARCHAR(500) NOT NULL,
mime_type VARCHAR(100) NULL,
size INT UNSIGNED NULL,
uploaded_by INT UNSIGNED NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_mif_intervention (intervention_id),
CONSTRAINT fk_mif_intervention FOREIGN KEY (intervention_id)
REFERENCES maint_interventions (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS maint_histories (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
equipment_id INT NULL,
maintenance_id INT UNSIGNED NULL,
intervention_id INT UNSIGNED NULL,
user_id INT UNSIGNED NULL,
action VARCHAR(50) NOT NULL,
changes TEXT NULL,
notes TEXT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_hist_equipment (equipment_id, created_at),
KEY idx_hist_maintenance (maintenance_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS maint_notifications (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
maintenance_id INT UNSIGNED NOT NULL,
employee_id INT UNSIGNED NULL,
email VARCHAR(191) NOT NULL,
type VARCHAR(20) NOT NULL,
sent_date DATE NOT NULL,
sent_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uniq_maint_notif (maintenance_id, email, type, sent_date),
CONSTRAINT fk_notif_maintenance FOREIGN KEY (maintenance_id)
REFERENCES maint_maintenances (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT IGNORE INTO ws_lookup_options (category, value, label, sort_order, is_default, is_active) VALUES
('maint_status', 'planned', 'Pianificato', 10, 0, 1),
('maint_status', 'in_progress', 'In corso', 20, 0, 1),
('maint_status', 'completed', 'Completato', 30, 1, 1),
('maint_result', 'compliant', 'Conforme', 10, 1, 1),
('maint_result', 'not_compliant','Non conforme', 20, 0, 1),
('maint_result', 'blocked', 'Bloccato', 30, 0, 1),
('maint_result', 'partial', 'Parziale', 40, 0, 1),
('equipment_status', 'active', 'Attivo', 10, 1, 1),
('equipment_status', 'out_of_service', 'Fuori servizio', 20, 0, 1),
('equipment_status', 'decommissioned', 'Dismesso', 30, 0, 1);
@@ -0,0 +1,68 @@
INSERT IGNORE INTO inv_categories (name, code, color, requires_line, sort_order) VALUES
('Linea di produzione', 'line', '#dc2626', 1, 10),
('Attrezzature', 'equipment', '#0d6efd', 0, 20),
('Accessori', 'accessories', '#20c997', 0, 30),
('Qualità', 'quality', '#6f42c1', 0, 40);
UPDATE inv_equipment
SET category_id = (SELECT id FROM inv_categories WHERE code = 'equipment')
WHERE category_id IS NULL AND line_id IS NULL;
INSERT INTO inv_equipment (name, category_id, line_id, status, description, created_at, updated_at)
SELECT
pl.name,
(SELECT id FROM inv_categories WHERE code = 'line'),
pl.id,
IF(pl.status = 'active', 'active', 'out_of_service'),
CONCAT_WS(' ', NULLIF(pl.brand, ''), NULLIF(pl.model, '')),
NOW(), NOW()
FROM production_lines pl
WHERE NOT EXISTS (
SELECT 1 FROM inv_equipment e WHERE e.line_id = pl.id
);
DELIMITER $$
DROP PROCEDURE IF EXISTS manutenzioni_migrate_step3 $$
CREATE PROCEDURE manutenzioni_migrate_step3()
BEGIN
DECLARE v_db VARCHAR(64);
SET v_db = DATABASE();
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_schema = v_db AND table_name = 'inv_equipment'
AND constraint_name = 'fk_inv_equipment_category') THEN
ALTER TABLE inv_equipment
ADD CONSTRAINT fk_inv_equipment_category FOREIGN KEY (category_id)
REFERENCES inv_categories (id) ON DELETE SET NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_schema = v_db AND table_name = 'inv_equipment'
AND constraint_name = 'fk_inv_equipment_line') THEN
ALTER TABLE inv_equipment
ADD CONSTRAINT fk_inv_equipment_line FOREIGN KEY (line_id)
REFERENCES production_lines (id) ON DELETE SET NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_schema = v_db AND table_name = 'inv_equipment'
AND constraint_name = 'fk_inv_equipment_department') THEN
ALTER TABLE inv_equipment
ADD CONSTRAINT fk_inv_equipment_department FOREIGN KEY (department_id)
REFERENCES departments (id) ON DELETE SET NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE table_schema = v_db AND table_name = 'inv_equipment'
AND constraint_name = 'fk_inv_equipment_cover') THEN
ALTER TABLE inv_equipment
ADD CONSTRAINT fk_inv_equipment_cover FOREIGN KEY (cover_file_id)
REFERENCES inv_equipment_files (id) ON DELETE SET NULL;
END IF;
END $$
DELIMITER ;
CALL manutenzioni_migrate_step3();
DROP PROCEDURE manutenzioni_migrate_step3;
@@ -0,0 +1,19 @@
INSERT IGNORE INTO auth_permissions
(name, display_name, description, removable, created_at, updated_at)
VALUES
('maintenance.equipment.view', 'View Equipment Registry', 'Can view the equipment registry.', 1, NOW(), NOW()),
('maintenance.maintenances.view','View Maintenances', 'Can view maintenances and the intervention log.', 1, NOW(), NOW()),
('maintenance.calendar.view', 'View Maintenance Calendar','Can view the maintenance calendar.', 1, NOW(), NOW()),
('maintenance.categories.view', 'View Equipment Categories','Can view equipment categories.', 1, NOW(), NOW()),
('maintenance.manage', 'Manage Maintenance', 'Can create/edit equipment, maintenances and interventions.', 1, NOW(), NOW());
INSERT IGNORE INTO auth_permission_role (permission_id, role_id)
SELECT p.id, 1
FROM auth_permissions p
WHERE p.name IN (
'maintenance.equipment.view',
'maintenance.maintenances.view',
'maintenance.calendar.view',
'maintenance.categories.view',
'maintenance.manage'
);
File diff suppressed because it is too large Load Diff