-- JQC Features site schema + seed -- MySQL 8.0 / Ubuntu 24.04 -- Safe to re-run: uses IF NOT EXISTS and idempotent seed inserts. CREATE DATABASE IF NOT EXISTS jqc_features CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE jqc_features; CREATE TABLE IF NOT EXISTS section ( id INT AUTO_INCREMENT PRIMARY KEY, num INT NOT NULL, title VARCHAR(160) NOT NULL, subtitle VARCHAR(255) NULL, sort_order INT NOT NULL DEFAULT 0, UNIQUE KEY uq_section_num (num) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS topic ( id INT AUTO_INCREMENT PRIMARY KEY, section_id INT NOT NULL, slug VARCHAR(80) NOT NULL, title VARCHAR(200) NOT NULL, body_html MEDIUMTEXT NULL, -- rich text content link_url VARCHAR(500) NULL, -- optional external link link_label VARCHAR(120) NULL, media_type ENUM('none','image','video','embed') NOT NULL DEFAULT 'none', media_url VARCHAR(500) NULL, -- image src, video src, or embed URL media_caption VARCHAR(255) NULL, sort_order INT NOT NULL DEFAULT 0, is_published TINYINT(1) NOT NULL DEFAULT 1, UNIQUE KEY uq_topic_slug (slug), KEY idx_topic_section (section_id), CONSTRAINT fk_topic_section FOREIGN KEY (section_id) REFERENCES section(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS audit_log ( id INT AUTO_INCREMENT PRIMARY KEY, actor VARCHAR(80) NULL, action VARCHAR(40) NOT NULL, -- create / update / delete entity VARCHAR(40) NOT NULL, -- section / topic entity_id INT NULL, detail VARCHAR(255) NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_audit_created (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS demo_request ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(120) NOT NULL, company VARCHAR(160) NULL, email VARCHAR(200) NOT NULL, phone VARCHAR(40) NULL, preferred_date DATE NOT NULL, preferred_time VARCHAR(5) NOT NULL, -- 'HH:MM', local business hours message TEXT NULL, status VARCHAR(16) NOT NULL DEFAULT 'new', -- new/scheduled/done/cancelled source_ip VARCHAR(45) NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_demo_slot (preferred_date, preferred_time), KEY idx_demo_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ------------------------------------------------------------------ -- Seed data (idempotent). Re-running updates content in place. -- ------------------------------------------------------------------ INSERT INTO section (num, title, subtitle, sort_order) VALUES (1, 'JQC Inspectors', 'What the Inspector app does in the field', 10), (2, 'Collaborative Quality Control', 'One program, both parties', 20), (3, 'The App Does the Rest', 'Automatic communication and QR access', 30), (4, 'Customer Benefit', 'What you get out of it', 40) ON DUPLICATE KEY UPDATE title=VALUES(title), subtitle=VALUES(subtitle), sort_order=VALUES(sort_order); INSERT INTO topic (section_id, slug, title, body_html, link_url, link_label, media_type, media_url, media_caption, sort_order) VALUES ((SELECT id FROM section WHERE num=1), 'comprehensive-checklists', 'Comprehensive Checklists', '
Full checklists equipped with timestamped photos, ratings, and captured signatures — ensuring transparency and accountability on every visit.
', NULL, NULL, 'none', NULL, NULL, 10), ((SELECT id FROM section WHERE num=1), 'real-time-issue-tracking', 'Real-Time Issue Tracking', 'If any issue arises during an inspection, it is flagged on-the-spot and linked to the exact location where it was found. Standalone issues can be raised, and a re-inspection can be initiated from any previous visit.
', NULL, NULL, 'none', NULL, NULL, 20), ((SELECT id FROM section WHERE num=1), 'seamless-history-access', 'Seamless History Access', 'Inspectors review the full inspection history right on their device, making progress tracking efficient and straightforward.
', NULL, NULL, 'none', NULL, NULL, 30), ((SELECT id FROM section WHERE num=1), 'scheduled-work-made-easy', 'Scheduled Work Made Easy', 'See all scheduled work and get started with the facility and checklist already selected — no setup, just go.
', NULL, NULL, 'none', NULL, NULL, 40), ((SELECT id FROM section WHERE num=1), 'status-updates-with-evidence', 'Status Updates with Evidence', 'Update an issue''s status and attach photos of the fix, streamlining the resolution process end to end.
', NULL, NULL, 'none', NULL, NULL, 50), ((SELECT id FROM section WHERE num=2), 'shared-inspector-access', 'Shared Inspector Access', 'JQC supports the intake of both parties — LT staff and the customer''s QC inspector. Your contract administration inspector can use our JQC apps to perform inspections with the same access as an LT inspector.
', NULL, NULL, 'none', NULL, NULL, 10), ((SELECT id FROM section WHERE num=2), 'director-visibility-sla-alerts', 'Director-Level Visibility & SLA Alerts', 'The customer contract administrator has every piece of information at their fingertips — the same as our director level — and receives Service Level Agreement (SLA) alerts automatically.
', NULL, NULL, 'none', NULL, NULL, 20), ((SELECT id FROM section WHERE num=3), 'notifications-and-qr-access', 'Automatic Notifications & QR Access', 'Communication is effortless. The app automatically notifies everyone involved about new inspections, flags issues, and keeps directors informed of any high-risk SLA concerns.
A simple scan of a QR code lets you or your tenants review QC history and report issues directly from a mobile device — no account or login required.
', NULL, NULL, 'none', NULL, NULL, 10), ((SELECT id FROM section WHERE num=4), 'unified-no-cost-platform', 'Unified, No-Cost Platform', 'Enjoy a unified platform that is paperless, maintenance-free, and backed by complimentary training and support. You are always in the loop about when and where actions are taken.
No subscription charge and no hidden fees.
', NULL, NULL, 'none', NULL, NULL, 10) ON DUPLICATE KEY UPDATE title=VALUES(title), body_html=VALUES(body_html), link_url=VALUES(link_url), link_label=VALUES(link_label), media_type=VALUES(media_type), media_url=VALUES(media_url), media_caption=VALUES(media_caption), sort_order=VALUES(sort_order);