365 lines
14 KiB
SQL
365 lines
14 KiB
SQL
-- This schema supports the phase-1 hybrid proof of concept.
|
|
-- The database stores centrally managed configuration only: templates,
|
|
-- lookup values, image policy, export settings, and lightweight app flags.
|
|
-- Completed reports are intentionally excluded from the server in this phase;
|
|
-- they remain browser-local artifacts exported by the client.
|
|
|
|
CREATE DATABASE IF NOT EXISTS check_list CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
USE check_list;
|
|
|
|
-- Template identity stays separate from version rows so a single checklist can
|
|
-- publish multiple definitions over time while preserving a stable code.
|
|
CREATE TABLE IF NOT EXISTS templates (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
code VARCHAR(100) NOT NULL,
|
|
name VARCHAR(200) NOT NULL,
|
|
description TEXT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_templates_code (code)
|
|
);
|
|
|
|
-- Each template version stores a full JSON definition snapshot. That keeps the
|
|
-- frontend contract simple because the client can render a form from one payload
|
|
-- without performing additional joins or reconstruction logic.
|
|
CREATE TABLE IF NOT EXISTS template_versions (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
template_id BIGINT UNSIGNED NOT NULL,
|
|
version_number INT NOT NULL,
|
|
status ENUM('draft', 'active', 'retired') NOT NULL DEFAULT 'draft',
|
|
definition_json JSON NOT NULL,
|
|
published_at DATETIME NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_template_version (template_id, version_number),
|
|
KEY idx_template_versions_template_status (template_id, status),
|
|
CONSTRAINT fk_template_versions_template
|
|
FOREIGN KEY (template_id) REFERENCES templates (id)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- Lookup sets support dropdown-style fields in a normalized way. The template
|
|
-- JSON references the set by code, while individual values remain editable as
|
|
-- data rather than hardcoded frontend options.
|
|
CREATE TABLE IF NOT EXISTS lookup_sets (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
code VARCHAR(100) NOT NULL,
|
|
name VARCHAR(200) NOT NULL,
|
|
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_lookup_sets_code (code)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS lookup_values (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
lookup_set_id BIGINT UNSIGNED NOT NULL,
|
|
value VARCHAR(100) NOT NULL,
|
|
label VARCHAR(200) NOT NULL,
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
is_default TINYINT(1) NOT NULL DEFAULT 0,
|
|
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_lookup_value (lookup_set_id, value),
|
|
KEY idx_lookup_values_lookup_set (lookup_set_id),
|
|
CONSTRAINT fk_lookup_values_lookup_set
|
|
FOREIGN KEY (lookup_set_id) REFERENCES lookup_sets (id)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- Image rules are server-managed so administrators can tighten or relax client
|
|
-- behavior, such as size limits or attachment counts, without changing browser
|
|
-- code. The client reads the active row and enforces it locally.
|
|
CREATE TABLE IF NOT EXISTS image_rules (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
code VARCHAR(100) NOT NULL,
|
|
name VARCHAR(200) NOT NULL,
|
|
allowed_mime_types_json JSON NOT NULL,
|
|
max_file_size_bytes INT UNSIGNED NOT NULL,
|
|
max_width_px INT UNSIGNED NOT NULL,
|
|
max_height_px INT UNSIGNED NOT NULL,
|
|
jpeg_quality INT UNSIGNED NOT NULL,
|
|
oversize_behavior ENUM('auto_optimize', 'warn_then_optimize', 'block') NOT NULL DEFAULT 'auto_optimize',
|
|
max_attachments_per_field INT UNSIGNED NOT NULL DEFAULT 5,
|
|
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_image_rules_code (code)
|
|
);
|
|
|
|
-- Export profiles represent the eventual shape of the generated ZIP/XLSX output.
|
|
-- The current PoC only reads this information, but separating it now makes later
|
|
-- export customization easier.
|
|
CREATE TABLE IF NOT EXISTS export_profiles (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
code VARCHAR(100) NOT NULL,
|
|
name VARCHAR(200) NOT NULL,
|
|
zip_image_dir VARCHAR(100) NOT NULL DEFAULT 'images',
|
|
excel_sheet_name VARCHAR(100) NOT NULL DEFAULT 'Checklist',
|
|
include_template_version TINYINT(1) NOT NULL DEFAULT 1,
|
|
include_export_timestamp TINYINT(1) NOT NULL DEFAULT 1,
|
|
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_export_profiles_code (code)
|
|
);
|
|
|
|
-- Small application settings that do not justify dedicated tables are stored as
|
|
-- JSON key/value pairs. This keeps the schema lean during the PoC phase while
|
|
-- still allowing centrally managed frontend behavior.
|
|
CREATE TABLE IF NOT EXISTS app_config (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
config_key VARCHAR(100) NOT NULL,
|
|
config_value_json JSON NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_app_config_key (config_key)
|
|
);
|
|
|
|
-- Submitted reports are stored server-side for centralized review and archival.
|
|
-- The browser creates reports locally first; this table receives them when the
|
|
-- operator explicitly submits. The report_uuid links back to the browser-local
|
|
-- report ID so resubmissions are idempotent via ON DUPLICATE KEY UPDATE.
|
|
CREATE TABLE IF NOT EXISTS reports (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
report_uuid CHAR(36) NOT NULL,
|
|
report_number VARCHAR(100) NOT NULL,
|
|
template_code VARCHAR(100) NOT NULL,
|
|
template_version INT NOT NULL,
|
|
status ENUM('draft', 'final', 'in_progress', 'ready_for_export', 'exported', 'archived') NOT NULL DEFAULT 'draft',
|
|
answers_json JSON NOT NULL,
|
|
submitted_at DATETIME NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_reports_uuid (report_uuid),
|
|
KEY idx_reports_template (template_code, template_version),
|
|
KEY idx_reports_status (status)
|
|
);
|
|
|
|
-- The audit log captures every administrative mutation so the team can trace
|
|
-- when configuration changed and what the previous value was. Each row stores
|
|
-- the entity type, the entity identifier, the action, and JSON snapshots of
|
|
-- the old and new values.
|
|
CREATE TABLE IF NOT EXISTS audit_log (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
entity_type VARCHAR(100) NOT NULL,
|
|
entity_code VARCHAR(200) NOT NULL,
|
|
action VARCHAR(50) NOT NULL,
|
|
old_value_json JSON NULL,
|
|
new_value_json JSON NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY idx_audit_entity (entity_type, entity_code)
|
|
);
|
|
|
|
-- Report images are stored as binary BLOBs in the database alongside metadata.
|
|
-- This keeps image storage self-contained without filesystem dependencies.
|
|
CREATE TABLE IF NOT EXISTS report_images (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
report_uuid CHAR(36) NOT NULL,
|
|
record_id VARCHAR(100) NOT NULL,
|
|
image_index SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
|
file_name VARCHAR(500) NOT NULL,
|
|
file_size INT UNSIGNED NOT NULL DEFAULT 0,
|
|
mime_type VARCHAR(100) NOT NULL DEFAULT 'image/jpeg',
|
|
width_px INT UNSIGNED NULL,
|
|
height_px INT UNSIGNED NULL,
|
|
exif_json JSON NULL,
|
|
image_data LONGBLOB NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY idx_report_images_report (report_uuid),
|
|
KEY idx_report_images_record (report_uuid, record_id),
|
|
CONSTRAINT fk_report_images_report
|
|
FOREIGN KEY (report_uuid) REFERENCES reports (report_uuid)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════════
|
|
-- Admin entity tables — store all admin-managed data relationally so it
|
|
-- persists across Docker restarts and browser sessions.
|
|
-- ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
-- Categories for template settings (e.g. "Electrical", "Mechanical")
|
|
CREATE TABLE IF NOT EXISTS admin_categories (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_categories_value (value)
|
|
);
|
|
|
|
-- Sub-categories are children of categories
|
|
CREATE TABLE IF NOT EXISTS admin_sub_categories (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
category_id BIGINT UNSIGNED NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY idx_sub_categories_category (category_id),
|
|
CONSTRAINT fk_sub_categories_category
|
|
FOREIGN KEY (category_id) REFERENCES admin_categories (id)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- Severity levels
|
|
CREATE TABLE IF NOT EXISTS admin_severities (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_severities_value (value)
|
|
);
|
|
|
|
-- Status options
|
|
CREATE TABLE IF NOT EXISTS admin_statuses (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
require_handled_by TINYINT(1) NOT NULL DEFAULT 0,
|
|
require_comment TINYINT(1) NOT NULL DEFAULT 0,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_statuses_value (value)
|
|
);
|
|
|
|
-- Handled By options
|
|
CREATE TABLE IF NOT EXISTS admin_handled_by (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_handled_by_value (value)
|
|
);
|
|
|
|
-- Projects for task settings
|
|
CREATE TABLE IF NOT EXISTS admin_projects (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_projects_value (value)
|
|
);
|
|
|
|
-- Processes are children of projects
|
|
CREATE TABLE IF NOT EXISTS admin_processes (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
value VARCHAR(200) NOT NULL,
|
|
project_id BIGINT UNSIGNED NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY idx_processes_project (project_id),
|
|
CONSTRAINT fk_processes_project
|
|
FOREIGN KEY (project_id) REFERENCES admin_projects (id)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- Users managed by the admin console
|
|
CREATE TABLE IF NOT EXISTS admin_users (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
email VARCHAR(255) NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL DEFAULT '',
|
|
name VARCHAR(200) NOT NULL,
|
|
family_name VARCHAR(200) NOT NULL,
|
|
company VARCHAR(200) NOT NULL DEFAULT '',
|
|
role VARCHAR(50) NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_users_email (email)
|
|
);
|
|
|
|
-- Sites managed by the admin console
|
|
CREATE TABLE IF NOT EXISTS admin_sites (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
site_code VARCHAR(100) NOT NULL,
|
|
host VARCHAR(50) NOT NULL DEFAULT '',
|
|
obe_site_code VARCHAR(100) NOT NULL DEFAULT '',
|
|
pxs_site_code VARCHAR(100) NOT NULL DEFAULT '',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_sites_code (site_code)
|
|
);
|
|
|
|
-- Check list records (inspection items)
|
|
CREATE TABLE IF NOT EXISTS admin_cl_records (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
category VARCHAR(200) NOT NULL DEFAULT '',
|
|
sub_category VARCHAR(200) NOT NULL DEFAULT '',
|
|
severity VARCHAR(200) NOT NULL DEFAULT '',
|
|
image_required TINYINT(1) NOT NULL DEFAULT 0,
|
|
description_en TEXT NOT NULL,
|
|
description_fr TEXT NOT NULL,
|
|
description_nl TEXT NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_cl_records_sort (sort_order)
|
|
);
|
|
|
|
-- Check list templates
|
|
CREATE TABLE IF NOT EXISTS admin_cl_templates (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
name VARCHAR(200) NOT NULL,
|
|
scope VARCHAR(50) NOT NULL DEFAULT '',
|
|
version VARCHAR(50) NOT NULL DEFAULT '',
|
|
valid_from DATE NULL,
|
|
valid_till DATE NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id)
|
|
);
|
|
|
|
-- Join table: which records belong to which template
|
|
CREATE TABLE IF NOT EXISTS admin_cl_template_records (
|
|
template_id BIGINT UNSIGNED NOT NULL,
|
|
record_id BIGINT UNSIGNED NOT NULL,
|
|
PRIMARY KEY (template_id, record_id),
|
|
CONSTRAINT fk_tpl_rec_template
|
|
FOREIGN KEY (template_id) REFERENCES admin_cl_templates (id)
|
|
ON DELETE CASCADE,
|
|
CONSTRAINT fk_tpl_rec_record
|
|
FOREIGN KEY (record_id) REFERENCES admin_cl_records (id)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- Task assignments (user + site + template + project/process)
|
|
CREATE TABLE IF NOT EXISTS admin_tasks (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
site_id BIGINT UNSIGNED NOT NULL,
|
|
user_id BIGINT UNSIGNED NOT NULL,
|
|
template_id BIGINT UNSIGNED NOT NULL,
|
|
project VARCHAR(200) NOT NULL DEFAULT '',
|
|
process VARCHAR(200) NOT NULL DEFAULT '',
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY idx_tasks_user (user_id),
|
|
KEY idx_tasks_site (site_id),
|
|
CONSTRAINT fk_tasks_site
|
|
FOREIGN KEY (site_id) REFERENCES admin_sites (id)
|
|
ON DELETE CASCADE,
|
|
CONSTRAINT fk_tasks_user
|
|
FOREIGN KEY (user_id) REFERENCES admin_users (id)
|
|
ON DELETE CASCADE,
|
|
CONSTRAINT fk_tasks_template
|
|
FOREIGN KEY (template_id) REFERENCES admin_cl_templates (id)
|
|
ON DELETE CASCADE
|
|
);
|
|
|
|
-- Admin credentials for application administrator login
|
|
CREATE TABLE IF NOT EXISTS admin_credentials (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
username VARCHAR(100) NOT NULL,
|
|
password VARCHAR(255) NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_admin_credentials_username (username)
|
|
);
|