clqms-be/docs/examples/edge_workstation.sql

255 lines
12 KiB
MySQL
Raw Normal View History

-- ============================================================
-- 🖥️ CLQMS Edge Workstation - SQLite Database Schema
-- Project Pandaria: Offline-First LIS Architecture
-- ============================================================
-- This is the LOCAL database for each Smart Workstation.
-- Stack: Node.js (Electron) + SQLite
-- Role: "The Cortex" - Immediate Processing
-- ============================================================
-- 🔧 Enable foreign keys (SQLite needs this explicitly)
PRAGMA foreign_keys = ON;
-- ============================================================
-- 1. 📋 CACHED ORDERS (Hot Cache - Last 7 Days)
-- ============================================================
-- Orders downloaded from the Core Server for local processing.
-- Workstation can work 100% offline with this data.
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_order_id TEXT UNIQUE NOT NULL, -- Original ID from Core Server
patient_id TEXT NOT NULL,
patient_name TEXT NOT NULL,
patient_dob DATE,
patient_gender TEXT CHECK(patient_gender IN ('M', 'F', 'O')),
order_date DATETIME NOT NULL,
priority TEXT DEFAULT 'routine' CHECK(priority IN ('stat', 'routine', 'urgent')),
status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'in_progress', 'completed', 'cancelled')),
barcode TEXT,
notes TEXT,
synced_at DATETIME DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_orders_barcode ON orders(barcode);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_patient ON orders(patient_id);
-- ============================================================
-- 2. 🔬 ORDER TESTS (What tests are requested?)
-- ============================================================
-- Each order can have multiple tests (CBC, Urinalysis, etc.)
CREATE TABLE IF NOT EXISTS order_tests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER NOT NULL,
test_code TEXT NOT NULL, -- Standardized code (e.g., 'WBC_TOTAL')
test_name TEXT NOT NULL, -- Display name (e.g., 'White Blood Cell Count')
status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'processing', 'completed', 'failed')),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
);
CREATE INDEX idx_order_tests_order ON order_tests(order_id);
CREATE INDEX idx_order_tests_code ON order_tests(test_code);
-- ============================================================
-- 3. 📊 RESULTS (Machine Output - Normalized)
-- ============================================================
-- Results from lab machines, already translated to standard format.
CREATE TABLE IF NOT EXISTS results (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_test_id INTEGER,
machine_id INTEGER,
test_code TEXT NOT NULL, -- Standardized test code
value REAL NOT NULL, -- Numeric result
unit TEXT NOT NULL, -- Standardized unit
reference_low REAL,
reference_high REAL,
flag TEXT CHECK(flag IN ('L', 'N', 'H', 'LL', 'HH', 'A')), -- Low, Normal, High, Critical Low/High, Abnormal
raw_value TEXT, -- Original value from machine
raw_unit TEXT, -- Original unit from machine
raw_test_code TEXT, -- Original code from machine (before translation)
validated BOOLEAN DEFAULT 0,
validated_by TEXT,
validated_at DATETIME,
machine_timestamp DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (order_test_id) REFERENCES order_tests(id) ON DELETE SET NULL,
FOREIGN KEY (machine_id) REFERENCES machines(id) ON DELETE SET NULL
);
CREATE INDEX idx_results_order_test ON results(order_test_id);
CREATE INDEX idx_results_test_code ON results(test_code);
CREATE INDEX idx_results_validated ON results(validated);
-- ============================================================
-- 4. 📮 OUTBOX QUEUE (Registered Mail Pattern)
-- ============================================================
-- Data waits here until the Core Server confirms receipt (ACK).
-- Zero data loss, even if network blinks!
CREATE TABLE IF NOT EXISTS outbox_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_type TEXT NOT NULL, -- 'result_created', 'result_validated', 'order_updated'
payload TEXT NOT NULL, -- JSON data to sync
target_entity TEXT, -- 'results', 'orders', etc.
target_id INTEGER, -- ID of the record
priority INTEGER DEFAULT 5, -- 1 = highest, 10 = lowest
retry_count INTEGER DEFAULT 0,
max_retries INTEGER DEFAULT 5,
last_error TEXT,
status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'processing', 'sent', 'acked', 'failed')),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
sent_at DATETIME,
acked_at DATETIME
);
CREATE INDEX idx_outbox_status ON outbox_queue(status);
CREATE INDEX idx_outbox_priority ON outbox_queue(priority, created_at);
-- ============================================================
-- 5. 📥 INBOX QUEUE (Messages from Server)
-- ============================================================
-- Incoming messages/orders from Core Server waiting to be processed.
CREATE TABLE IF NOT EXISTS inbox_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_message_id TEXT UNIQUE NOT NULL, -- ID from server for deduplication
event_type TEXT NOT NULL, -- 'new_order', 'order_cancelled', 'config_update'
payload TEXT NOT NULL, -- JSON data
status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'processing', 'completed', 'failed')),
error_message TEXT,
received_at DATETIME DEFAULT CURRENT_TIMESTAMP,
processed_at DATETIME
);
CREATE INDEX idx_inbox_status ON inbox_queue(status);
-- ============================================================
-- 6. 🔌 MACHINES (Connected Lab Equipment)
-- ============================================================
-- Registry of connected machines/analyzers.
CREATE TABLE IF NOT EXISTS machines (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, -- 'Sysmex XN-1000', 'Mindray BC-6800'
manufacturer TEXT,
model TEXT,
serial_number TEXT,
driver_file TEXT NOT NULL, -- 'driver-sysmex-xn1000.js'
connection_type TEXT CHECK(connection_type IN ('RS232', 'TCP', 'USB', 'FILE')),
connection_config TEXT, -- JSON: {"port": "COM3", "baudRate": 9600}
is_active BOOLEAN DEFAULT 1,
last_communication DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================
-- 7. 📖 TEST DICTIONARY (The Translator)
-- ============================================================
-- Maps machine-specific codes to standard codes.
-- Solves the "WBC vs Leukocytes" problem!
CREATE TABLE IF NOT EXISTS test_dictionary (
id INTEGER PRIMARY KEY AUTOINCREMENT,
machine_id INTEGER, -- NULL = universal mapping
raw_code TEXT NOT NULL, -- What the machine sends: 'W.B.C', 'Leukocytes'
standard_code TEXT NOT NULL, -- Our standard: 'WBC_TOTAL'
standard_name TEXT NOT NULL, -- 'White Blood Cell Count'
unit_conversion_factor REAL DEFAULT 1.0, -- Multiply raw value by this (e.g., 10 for g/dL to g/L)
raw_unit TEXT, -- Unit machine sends
standard_unit TEXT, -- Our standard unit
reference_low REAL,
reference_high REAL,
is_active BOOLEAN DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (machine_id) REFERENCES machines(id) ON DELETE CASCADE,
UNIQUE(machine_id, raw_code)
);
CREATE INDEX idx_dictionary_lookup ON test_dictionary(machine_id, raw_code);
-- ============================================================
-- 8. 📜 SYNC LOG (Audit Trail)
-- ============================================================
-- Track all sync activities for debugging & recovery.
CREATE TABLE IF NOT EXISTS sync_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
direction TEXT CHECK(direction IN ('push', 'pull')),
event_type TEXT NOT NULL,
entity_type TEXT,
entity_id INTEGER,
server_response_code INTEGER,
server_message TEXT,
success BOOLEAN,
duration_ms INTEGER,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_sync_log_created ON sync_log(created_at DESC);
-- ============================================================
-- 9. ⚙️ LOCAL CONFIG (Workstation Settings)
-- ============================================================
-- Key-value store for workstation-specific settings.
CREATE TABLE IF NOT EXISTS config (
key TEXT PRIMARY KEY,
value TEXT,
description TEXT,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================
-- 📦 SAMPLE DATA: Machines & Dictionary
-- ============================================================
-- Sample Machines
INSERT INTO machines (name, manufacturer, model, driver_file, connection_type, connection_config) VALUES
('Sysmex XN-1000', 'Sysmex', 'XN-1000', 'driver-sysmex-xn1000.js', 'RS232', '{"port": "COM3", "baudRate": 9600}'),
('Mindray BC-6800', 'Mindray', 'BC-6800', 'driver-mindray-bc6800.js', 'TCP', '{"host": "192.168.1.50", "port": 5000}');
-- Sample Test Dictionary (The Translator)
INSERT INTO test_dictionary (machine_id, raw_code, standard_code, standard_name, raw_unit, standard_unit, unit_conversion_factor, reference_low, reference_high) VALUES
-- Sysmex mappings (machine_id = 1)
(1, 'WBC', 'WBC_TOTAL', 'White Blood Cell Count', '10^3/uL', '10^3/uL', 1.0, 4.0, 11.0),
(1, 'RBC', 'RBC_TOTAL', 'Red Blood Cell Count', '10^6/uL', '10^6/uL', 1.0, 4.5, 5.5),
(1, 'HGB', 'HGB', 'Hemoglobin', 'g/dL', 'g/L', 10.0, 120, 170),
(1, 'PLT', 'PLT_TOTAL', 'Platelet Count', '10^3/uL', '10^3/uL', 1.0, 150, 400),
-- Mindray mappings (machine_id = 2) - Different naming!
(2, 'Leukocytes', 'WBC_TOTAL', 'White Blood Cell Count', 'x10^9/L', '10^3/uL', 1.0, 4.0, 11.0),
(2, 'Erythrocytes', 'RBC_TOTAL', 'Red Blood Cell Count', 'x10^12/L', '10^6/uL', 1.0, 4.5, 5.5),
(2, 'Hb', 'HGB', 'Hemoglobin', 'g/L', 'g/L', 1.0, 120, 170),
(2, 'Thrombocytes', 'PLT_TOTAL', 'Platelet Count', 'x10^9/L', '10^3/uL', 1.0, 150, 400),
-- Universal mappings (machine_id = NULL)
(NULL, 'W.B.C', 'WBC_TOTAL', 'White Blood Cell Count', NULL, '10^3/uL', 1.0, 4.0, 11.0),
(NULL, 'White_Cells', 'WBC_TOTAL', 'White Blood Cell Count', NULL, '10^3/uL', 1.0, 4.0, 11.0);
-- Sample Config
INSERT INTO config (key, value, description) VALUES
('workstation_id', 'LAB-WS-001', 'Unique identifier for this workstation'),
('workstation_name', 'Hematology Station 1', 'Human-readable name'),
('server_url', 'https://clqms-core.example.com/api', 'Core Server API endpoint'),
('cache_days', '7', 'Number of days to keep cached orders'),
('auto_validate', 'false', 'Auto-validate results within normal range'),
('last_sync', NULL, 'Timestamp of last successful sync');
-- Sample Order (for testing)
INSERT INTO orders (server_order_id, patient_id, patient_name, patient_dob, patient_gender, order_date, priority, barcode) VALUES
('ORD-2025-001234', 'PAT-00001', 'John Smith', '1980-01-15', 'M', '2025-12-19 08:00:00', 'routine', 'LAB2025001234');
INSERT INTO order_tests (order_id, test_code, test_name) VALUES
(1, 'WBC_TOTAL', 'White Blood Cell Count'),
(1, 'RBC_TOTAL', 'Red Blood Cell Count'),
(1, 'HGB', 'Hemoglobin'),
(1, 'PLT_TOTAL', 'Platelet Count');
-- ============================================================
-- ✅ DONE! Your Edge Workstation database is ready.
-- ============================================================