Files
backend/migrations/001_initial_schema.sql
T
2026-06-02 20:37:06 +02:00

244 lines
9.5 KiB
SQL

CREATE TABLE IF NOT EXISTS users (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
fiscal_code VARCHAR(16) NOT NULL,
birth_date DATE NULL,
birth_place VARCHAR(150) NULL,
phone VARCHAR(30) NULL,
points INT NOT NULL DEFAULT 0,
banned BOOLEAN NOT NULL DEFAULT FALSE,
must_change_password BOOLEAN NOT NULL DEFAULT FALSE,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY users_email_unique (email),
UNIQUE KEY users_fiscal_code_unique (fiscal_code)
);
CREATE TABLE IF NOT EXISTS roles (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
description TEXT NULL,
UNIQUE KEY roles_name_unique (name)
);
CREATE TABLE IF NOT EXISTS permissions (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT NULL,
UNIQUE KEY permissions_name_unique (name)
);
CREATE TABLE IF NOT EXISTS role_permissions (
role_id BIGINT UNSIGNED NOT NULL,
permission_id BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (role_id, permission_id),
CONSTRAINT role_permissions_role_fk FOREIGN KEY (role_id) REFERENCES roles(id),
CONSTRAINT role_permissions_permission_fk FOREIGN KEY (permission_id) REFERENCES permissions(id)
);
CREATE TABLE IF NOT EXISTS user_roles (
user_id BIGINT UNSIGNED NOT NULL,
role_id BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (user_id, role_id),
CONSTRAINT user_roles_user_fk FOREIGN KEY (user_id) REFERENCES users(id),
CONSTRAINT user_roles_role_fk FOREIGN KEY (role_id) REFERENCES roles(id)
);
CREATE TABLE IF NOT EXISTS otp_challenges (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
code_hash VARCHAR(255) NOT NULL,
expires_at DATETIME NOT NULL,
consumed_at DATETIME NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT otp_challenges_user_fk FOREIGN KEY (user_id) REFERENCES users(id),
KEY otp_challenges_user_expires_idx (user_id, expires_at)
);
CREATE TABLE IF NOT EXISTS api_tokens (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
token_hash VARCHAR(255) NOT NULL,
expires_at DATETIME NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
revoked_at DATETIME NULL,
UNIQUE KEY api_tokens_hash_unique (token_hash),
CONSTRAINT api_tokens_user_fk FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS report_categories (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(120) NOT NULL,
description TEXT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
UNIQUE KEY report_categories_name_unique (name)
);
CREATE TABLE IF NOT EXISTS areas (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(120) NOT NULL,
description TEXT NULL,
boundary_geojson JSON NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
UNIQUE KEY areas_name_unique (name)
);
CREATE TABLE IF NOT EXISTS team_categories (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(120) NOT NULL,
description TEXT NULL,
UNIQUE KEY team_categories_name_unique (name)
);
CREATE TABLE IF NOT EXISTS teams (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
team_category_id BIGINT UNSIGNED NOT NULL,
area_id BIGINT UNSIGNED NULL,
name VARCHAR(120) NOT NULL,
description TEXT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
UNIQUE KEY teams_name_unique (name),
CONSTRAINT teams_category_fk FOREIGN KEY (team_category_id) REFERENCES team_categories(id),
CONSTRAINT teams_area_fk FOREIGN KEY (area_id) REFERENCES areas(id)
);
CREATE TABLE IF NOT EXISTS reports (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
category_id BIGINT UNSIGNED NOT NULL,
area_id BIGINT UNSIGNED NULL,
latitude DECIMAL(10, 7) NOT NULL,
longitude DECIMAL(10, 7) NOT NULL,
address VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
status ENUM('OPEN','UNDER_REVIEW','ASSIGNED','IN_PROGRESS','RESOLVED','REJECTED','CLOSED') NOT NULL DEFAULT 'OPEN',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT reports_user_fk FOREIGN KEY (user_id) REFERENCES users(id),
CONSTRAINT reports_category_fk FOREIGN KEY (category_id) REFERENCES report_categories(id),
CONSTRAINT reports_area_fk FOREIGN KEY (area_id) REFERENCES areas(id),
KEY reports_status_idx (status),
KEY reports_category_idx (category_id),
KEY reports_area_idx (area_id)
);
CREATE TABLE IF NOT EXISTS report_status_history (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
report_id BIGINT UNSIGNED NOT NULL,
old_status VARCHAR(30) NULL,
new_status VARCHAR(30) NOT NULL,
changed_by_user_id BIGINT UNSIGNED NULL,
note TEXT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT status_history_report_fk FOREIGN KEY (report_id) REFERENCES reports(id),
CONSTRAINT status_history_user_fk FOREIGN KEY (changed_by_user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS assignments (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
report_id BIGINT UNSIGNED NOT NULL,
team_id BIGINT UNSIGNED NOT NULL,
assigned_by_user_id BIGINT UNSIGNED NOT NULL,
assigned_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ended_at DATETIME NULL,
CONSTRAINT assignments_report_fk FOREIGN KEY (report_id) REFERENCES reports(id),
CONSTRAINT assignments_team_fk FOREIGN KEY (team_id) REFERENCES teams(id),
CONSTRAINT assignments_user_fk FOREIGN KEY (assigned_by_user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS report_photos (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
report_id BIGINT UNSIGNED NOT NULL,
url VARCHAR(500) NOT NULL,
uploaded_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT report_photos_report_fk FOREIGN KEY (report_id) REFERENCES reports(id)
);
CREATE TABLE IF NOT EXISTS messages (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
report_id BIGINT UNSIGNED NOT NULL,
user_id BIGINT UNSIGNED NOT NULL,
body TEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT messages_report_fk FOREIGN KEY (report_id) REFERENCES reports(id),
CONSTRAINT messages_user_fk FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE IF NOT EXISTS feedback (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
report_id BIGINT UNSIGNED NOT NULL,
user_id BIGINT UNSIGNED NOT NULL,
rating TINYINT UNSIGNED NOT NULL,
comment TEXT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY feedback_report_unique (report_id),
CONSTRAINT feedback_report_fk FOREIGN KEY (report_id) REFERENCES reports(id),
CONSTRAINT feedback_user_fk FOREIGN KEY (user_id) REFERENCES users(id),
CONSTRAINT feedback_rating_check CHECK (rating BETWEEN 1 AND 5)
);
CREATE TABLE IF NOT EXISTS reward_events (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
report_id BIGINT UNSIGNED NULL,
points INT NOT NULL,
reason VARCHAR(120) NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT reward_events_user_fk FOREIGN KEY (user_id) REFERENCES users(id),
CONSTRAINT reward_events_report_fk FOREIGN KEY (report_id) REFERENCES reports(id)
);
INSERT IGNORE INTO roles (name, description) VALUES
('admin', 'System administrator'),
('operator', 'Municipal operator'),
('citizen', 'Registered citizen');
INSERT IGNORE INTO permissions (name, description) VALUES
('reports.read_all', 'Read every report'),
('reports.manage', 'Manage report state and assignments'),
('admin.manage', 'Manage administrative data');
INSERT IGNORE INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id FROM roles r JOIN permissions p
WHERE r.name = 'admin';
INSERT IGNORE INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id FROM roles r JOIN permissions p
WHERE r.name = 'operator' AND p.name IN ('reports.read_all', 'reports.manage');
INSERT IGNORE INTO report_categories (name, description) VALUES
('Buche stradali', 'Problemi relativi al manto stradale'),
('Illuminazione guasta', 'Lampioni o impianti di illuminazione non funzionanti'),
('Rifiuti abbandonati', 'Rifiuti fuori dalle aree autorizzate'),
('Altro', 'Altri disservizi urbani');
INSERT IGNORE INTO team_categories (name, description) VALUES
('Manutenzione strade', 'Squadre per interventi stradali'),
('Illuminazione pubblica', 'Squadre per rete elettrica e lampioni'),
('Igiene urbana', 'Squadre per rifiuti e decoro');
INSERT IGNORE INTO users (
first_name,
last_name,
email,
password_hash,
fiscal_code,
phone,
must_change_password
) VALUES (
'System',
'Admin',
'[email protected]',
'pbkdf2_sha256$210000$local-dev-admin-salt$A4683BDB63C1598400B6B196F53C830F8434BA645C4A4A70AB311B278223E698',
'ADMINVISIONE0000',
'+390000000000',
TRUE
);
INSERT IGNORE INTO user_roles (user_id, role_id)
SELECT u.id, r.id FROM users u JOIN roles r
WHERE u.email = '[email protected]' AND r.name = 'admin';