CLQMS (Clinical Laboratory Quality Management System)
The core backend engine for modern clinical laboratory workflows.
CLQMS is a robust, mission-critical API suite designed to streamline laboratory operations, ensure data integrity, and manage complex diagnostic workflows. Built on a foundation of precision and regulatory compliance, this system handles everything from patient registration to high-throughput test resulting.
🏛️ Core Architecture & Design
The system is currently undergoing a strategic Architectural Redesign to consolidate legacy structures into a high-performance, maintainable schema. This design, spearheaded by leadership, focuses on reducing technical debt and improving data consistency across:
- Unified Test Definitions: Consolidating technical, calculated, and site-specific test data.
- Reference Range Centralization: A unified engine for numeric, threshold, text, and coded results.
- Ordered Workflow Management: Precise tracking of orders from collection to verification.
🛡️ Strategic Pillars
- Precision & Accuracy: Strict validation for all laboratory parameters and reference ranges.
- Scalability: Optimized for high-volume diagnostic environments.
- Compliance: Built-in audit trails and status history for full traceability.
- Interoperability: Modular architecture designed for LIS, HIS, and analyzer integrations.
🛠️ Technical Stack
| Component | Specification |
|---|---|
| Language | PHP 8.1+ (PSR-compliant) |
| Framework | CodeIgniter 4 |
| Security | JWT (JSON Web Tokens) Authorization |
| Database | MySQL (Optimized Schema Migration in progress) |
📂 Documentation & Specifications
For detailed architectural blueprints and API specifications, please refer to the internal documentation:
👉 Internal Documentation Index
Key documents:
- Database Schema Redesign Proposal
- API Contract: Patient Registration
- Database Design Review (Reference)
Lookups Library (app/Libraries/ValueSet.php)
CLQMS uses a JSON file-based lookup system loaded via App\Libraries\Lookups class. All lookup data is stored as JSON files in app/Libraries/Data/valuesets/ for easy maintenance and versioning.
How It Works
Lookupsclass extendsValueSetwhich handles caching and file loading- Each lookup is stored as
app/Libraries/Data/valuesets/{name}.json - Lookup names are lowercase with underscores (e.g.,
gender.json,order_priority.json)
Available Lookups
| Lookup File | Description | Example Values |
|---|---|---|
gender |
Patient gender | Female, Male, Unknown |
order_priority |
Order priority levels | Stat, ASAP, Routine, Preop |
order_status |
Order lifecycle status | STC, SCtd, SArrv, SRcvd |
specimen_type |
Specimen types | BLD, SER, PLAS, UR, CSF |
specimen_status |
Specimen status | Ordered, Collected, Received |
specimen_condition |
Specimen quality flags | HEM, ITC, LIP, CLOT |
specimen_activity |
Specimen workflow events | COLLECT, RECEIVE, REJECT |
result_type |
Result data types | NMRIC, RANGE, TEXT, VSET |
result_unit |
Common measurement units | g/dL, mg/dL, x10^6/mL |
result_status |
Result validation status | Preliminary, Final, Corrected |
test_type |
Test definition types | TEST, PARAM, CALC, GROUP |
test_activity |
Test workflow activities | Order, Analyse, VER, REV |
test_status |
Test active status | Active, Inactive, Discontinued |
priority |
General priority values | STAT, HIGH, NORMAL, LOW |
race |
Ethnicity/race categories | Jawa, Sunda, Batak, etc. |
religion |
Religious affiliations | Islam, Kristen, Katolik, Hindu |
marital_status |
Marital status | Single, Married, Divorced |
death_indicator |
Death status flags | Yes, No |
identifier_type |
ID document types | KTP, Passport, SSN, SIM |
operation |
CRUD operation types | Create, Read, Update, Delete |
site_type |
Healthcare facility types | GH, PH, GHL, PHL, GL, PL |
site_class |
Facility classification | A, B, C, D, Utm, Ptm |
ws_type |
Workstation types | Primary, Secondary |
enable_disable |
Boolean toggle states | Enabled, Disabled |
entity_type |
Entity classification | Patient, Provider, Site |
requested_entity |
Requestor types | Physician, Nurse, Lab |
location_type |
Location categories | OPD, IPD, ER, LAB |
area_class |
Geographic classifications | Urban, Rural, Suburban |
adt_event |
ADT event types | Admission, Transfer, Discharge |
body_site |
Collection sites | Left Arm, Right Arm, Finger |
collection_method |
Specimen collection methods | Venipuncture, Fingerstick |
container_size |
Tube/container volumes | 3mL, 5mL, 10mL |
container_class |
Container types | Vacutainer, Tube, Cup |
container_cap_color |
Tube cap colors | Red, Purple, Blue, Green |
additive |
Tube additives | EDTA, Heparin, Fluoride |
fasting_status |
Fasting requirement flags | Fasting, Non-Fasting |
ethnic |
Ethnicity categories | Various regional groups |
math_sign |
Mathematical operators | +, -, *, /, =, <, > |
formula_language |
Formula expression types | Formula, Expression |
generate_by |
Generation methods | Auto, Manual, Import |
did_type |
Device identification types | Serial, MAC, UUID |
activity_result |
Activity outcomes | Success, Fail, Retry |
reference_type |
Reference value types | NMRIC, TEXT, LIST |
range_type |
Range calculation types | REF, CRTC, VAL, RERUN |
numeric_ref_type |
Numeric ref types | Reference, Critical, Valid |
text_ref_type |
Text reference types | Normal, Abnormal, Critical |
request_status |
Request status | Pending, Approved, Rejected |
v_category |
ValueSet categories | Various categories |
Usage
use App\Libraries\Lookups;
// Get all lookups (loads all JSON files, cached)
$allLookups = Lookups::getAll();
// Get single lookup formatted for dropdowns
$gender = Lookups::get('gender');
// Returns: [{"value":"1","label":"Female"},{"value":"2","label":"Male"},...]
// Get raw data without formatting
$raw = Lookups::getRaw('gender');
// Returns: [{"key":"1","value":"Female"},{"key":"2","value":"Male"},...]
// Get label for a specific key
$label = Lookups::getLabel('gender', '1'); // Returns 'Female'
// Get key/value pairs for select inputs
$options = Lookups::getOptions('gender');
// Returns: [["key":"1","value":"Female"],...]
// Transform database records with lookup text labels
$patients = [
['ID' => 1, 'Sex' => '1', 'Priority' => 'S'],
['ID' => 2, 'Sex' => '2', 'Priority' => 'R'],
];
$labeled = Lookups::transformLabels($patients, [
'Sex' => 'gender',
'Priority' => 'order_priority'
]);
// Result: [['ID'=>1, 'Sex'=>'1', 'SexText'=>'Female', 'Priority'=>'S', 'PriorityText'=>'Stat'],...]
// Clear cache after modifying valueset data
Lookups::clearCache();
Frontend Usage (Alpine.js)
<?php
// In your PHP view file
use App\Libraries\Lookups;
$allLookups = Lookups::getAll();
?>
<script>
const LOOKUPS = <?= json_encode($allLookups) ?>;
console.log(LOOKUPS.gender);
// Output: {"values":[{"key":"1","value":"Female"},{"key":"2","value":"Male"},...]}
// Convenience accessors
const genderValues = LOOKUPS.gender.values;
const genderDropdown = LOOKUPS.gender.values.map(v => ({value: v.key, label: v.value}));
</script>
When to Use
| Approach | Use Case |
|---|---|
| Lookups Library | Static values that rarely change (gender, status, types) - fast, cached |
API /api/valueset* |
Dynamic values managed by admins at runtime |
Adding New Lookups
- Create
app/Libraries/Data/valuesets/{name}.json:
{
"name": "example_lookup",
"description": "Example lookup description",
"values": [
{"key": "1", "value": "Option One"},
{"key": "2", "value": "Option Two"},
{"key": "3", "value": "Option Three"}
]
}
- Access via
Lookups::get('example_lookup')
📋 Master Data Management
CLQMS provides comprehensive master data management for laboratory operations. All master data is accessible via the V2 UI at /v2/master/* endpoints.
🧪 Laboratory Tests (/v2/master/tests)
The Test Definitions module manages all laboratory test configurations including parameters, calculated tests, and test panels.
Test Types
| Type Code | Description | Table |
|---|---|---|
TEST |
Individual laboratory test with technical specs | testdefsite + testdeftech |
PARAM |
Parameter value (non-lab measurement) | testdefsite + testdeftech |
CALC |
Calculated test with formula | testdefsite + testdefcal |
GROUP |
Panel/profile containing multiple tests | testdefsite + testdefgrp |
TITLE |
Section title for report organization | testdefsite |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/tests |
List all tests with optional filtering |
GET |
/api/tests/{id} |
Get test details with type-specific data |
POST |
/api/tests |
Create new test definition |
PATCH |
/api/tests |
Update existing test |
DELETE |
/api/tests |
Soft delete test (sets EndDate) |
Filtering Parameters
TestSiteName- Search by test name (partial match)TestType- Filter by test type VID (1-5)VisibleScr- Filter by screen visibility (0/1)VisibleRpt- Filter by report visibility (0/1)
Test Response Structure
{
"status": "success",
"message": "Data fetched successfully",
"data": [
{
"TestSiteID": 1,
"TestSiteCode": "CBC",
"TestSiteName": "Complete Blood Count",
"TestType": 4,
"TypeCode": "GROUP",
"TypeName": "Group Test",
"SeqScr": 50,
"VisibleScr": 1,
"VisibleRpt": 1
}
]
}
📏 Reference Ranges (/v2/master/refrange)
Reference Ranges define normal and critical values for test results. The system supports multiple reference range types based on patient demographics.
Reference Range Types
| Type | Table | Description |
|---|---|---|
| Numeric | refnum |
Numeric ranges with age/sex criteria |
| Threshold | refthold |
Critical threshold values |
| Text | reftxt |
Text-based reference values |
| Value Set | refvset |
Coded reference values |
Numeric Reference Range Structure
| Field | Description |
|---|---|
NumRefType |
Type: REF (Reference), CRTC (Critical), VAL (Validation), RERUN |
RangeType |
RANGE or THOLD |
Sex |
Gender filter (0=All, 1=Female, 2=Male) |
AgeStart |
Minimum age (years) |
AgeEnd |
Maximum age (years) |
LowSign |
Low boundary sign (=, <, <=) |
Low |
Low boundary value |
HighSign |
High boundary sign (=, >, >=) |
High |
High boundary value |
Flag |
Result flag (H, L, A, etc.) |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/refnum |
List numeric reference ranges |
GET |
/api/refnum/{id} |
Get reference range details |
POST |
/api/refnum |
Create reference range |
PATCH |
/api/refnum |
Update reference range |
DELETE |
/api/refnum |
Soft delete reference range |
📑 Value Sets (/v2/master/valuesets)
Value Sets are configurable dropdown options used throughout the system. Each Value Set Definition (VSetDef) contains multiple Value Set Values (ValueSet).
Value Set Hierarchy
valuesetdef (VSetDefID, VSName, VSDesc)
└── valueset (VID, VSetID, VValue, VDesc, VOrder, VCategory)
Common Value Sets
| VSetDefID | Name | Example Values |
|---|---|---|
| 1 | Priority | STAT (S), ASAP (A), Routine (R), Preop (P) |
| 2 | Enable/Disable | Disabled (0), Enabled (1) |
| 3 | Gender | Female (1), Male (2), Unknown (3) |
| 10 | Order Status | STC, SCtd, SArrv, SRcvd, SAna, etc. |
| 15 | Specimen Type | BLD, SER, PLAS, UR, CSF, etc. |
| 16 | Unit | L, mL, g/dL, mg/dL, etc. |
| 27 | Test Type | TEST, PARAM, CALC, GROUP, TITLE |
| 28 | Result Unit | g/dL, g/L, mg/dL, x10^6/mL, etc. |
| 35 | Test Activity | Order, Analyse, VER, REV, REP |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/valuesetdef |
List all value set definitions |
GET |
/api/valuesetdef/{id} |
Get valueset with all values |
GET |
/api/valuesetdef/{id}/values |
Get values for specific valueset |
POST |
/api/valuesetdef |
Create new valueset definition |
PATCH |
/api/valuesetdef |
Update valueset definition |
DELETE |
/api/valuesetdef |
Delete valueset definition |
Value Set Response Structure
{
"status": "success",
"data": {
"VSetDefID": 27,
"VSName": "Test Type",
"VSDesc": "testdefsite.TestType",
"values": [
{ "VID": 1, "VValue": "TEST", "VDesc": "Test", "VOrder": 1 },
{ "VID": 2, "VValue": "PARAM", "VDesc": "Parameter", "VOrder": 2 },
{ "VID": 3, "VValue": "CALC", "VDesc": "Calculated Test", "VOrder": 3 },
{ "VID": 4, "VValue": "GROUP", "VDesc": "Group Test", "VOrder": 4 },
{ "VID": 5, "VValue": "TITLE", "VDesc": "Title", "VOrder": 5 }
]
}
}
📊 Database Tables Summary
| Category | Tables | Purpose |
|---|---|---|
| Tests | testdefsite, testdeftech, testdefcal, testdefgrp, testmap |
Test definitions |
| Reference Ranges | refnum, refthold, reftxt, refvset |
Result validation |
| Value Sets | valuesetdef, valueset |
Configurable options |
🔌 Edge API - Instrument Integration
The Edge API provides endpoints for integrating laboratory instruments via the tiny-edge middleware. Results from instruments are staged in the edgeres table before processing into the main patient results (patres).
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/edge/results |
Receive instrument results (stored in edgeres) |
GET |
/api/edge/orders |
Fetch pending orders for an instrument |
POST |
/api/edge/orders/:id/ack |
Acknowledge order delivery to instrument |
POST |
/api/edge/status |
Log instrument status updates |
Workflow
Instrument → tiny-edge → POST /api/edge/results → edgeres table → [Manual/Auto Processing] → patres table
Key Features:
- Staging Table: All results land in
edgeresfirst for validation - Rerun Handling: Duplicate
SampleID+TestSiteCodeincrementsAspCntinpatres - Configurable Processing: Auto or manual processing based on settings
- Status Tracking: Full audit trail via
edgestatusandedgeacktables
📜 Usage Notice
This repository contains proprietary information intended for the 5Panda Team and authorized collaborators.
© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.