Ensure auth accepts cookie or bearer tokens while aligning ADT and result create/update flows with expected IDs and persisted fields.
CLQMS (Clinical Laboratory Quality Management System)
A REST API backend for modern clinical laboratory workflows.
🤖 For Claude Code
When working in this repository, prioritize Serena MCP tools for code operations:
- Use
find_symbol/get_symbols_overviewinstead ofReadfor exploring code structure - Use
replace_symbol_bodyinstead ofEditfor modifying functions, methods, classes - Use
insert_before_symbol/insert_after_symbolfor adding new code symbols - Use
search_for_patterninstead ofGrepfor searching code patterns - Use
list_dir/find_fileinstead ofGlobfor file discovery
This minimizes tool calls and leverages semantic code understanding for this PHP codebase.
CLQMS is a headless REST API backend designed to streamline laboratory operations, ensure data integrity, and manage complex diagnostic workflows. Built on a foundation of precision and regulatory compliance, this system provides comprehensive JSON endpoints for laboratory operations.
Key Characteristic: This is an API-only system with no view layer. Frontend applications (web, mobile, desktop) consume these REST endpoints to build laboratory information systems.
🏛️ Core Architecture & Design
CLQMS is a headless REST API system following a clean architecture pattern. The system is designed to be consumed by any frontend client (web, mobile, desktop) through comprehensive JSON endpoints.
API-First Architecture:
- No View Layer: This system provides REST APIs only - no HTML views, no server-side rendering
- Frontend Agnostic: Any client can consume these APIs (React, Vue, Angular, mobile apps, desktop apps)
- JSON-First: All requests/responses use JSON format
- Stateless: Each API request is independent with JWT authentication
The system is currently undergoing a strategic Architectural Redesign to consolidate legacy structures into a high-performance, maintainable schema. This design 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 (API-only mode) |
| Security | JWT (JSON Web Tokens) Authorization |
| Database | MySQL (Optimized Schema Migration in progress) |
| API Format | RESTful JSON |
| Testing | PHPUnit 10.5+ |
📂 Documentation & Specifications
Key Documents
| Document | Location | Description |
|---|---|---|
| PRD | PRD.md |
Complete Product Requirements Document (API-focused) |
| Technical Guide | CLAUDE.md |
Architecture, coding standards, common commands |
| API Overview | This file | REST API documentation and endpoints |
| Database Migrations | app/Database/Migrations/ |
Database schema history |
API Documentation
All API endpoints follow REST conventions:
Base URL: /api
Authentication: JWT token required for most endpoints (except /api/login, /api/demo/*)
Response Format:
{
"status": "success|error",
"message": "Human-readable message",
"data": { ... }
}
🔌 REST API Overview
API Endpoint Categories
Authentication & Authorization
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/login |
User login, returns JWT token | No |
POST |
/api/logout |
Invalidate JWT token | Yes |
POST |
/api/refresh |
Refresh JWT token | Yes |
Patient Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/patient |
List patients with pagination | Yes |
GET |
/api/patient/{id} |
Get patient details | Yes |
POST |
/api/patient |
Create new patient | Yes |
PATCH |
/api/patient/{id} |
Update patient | Yes |
DELETE |
/api/patient/{id} |
Soft delete patient | Yes |
Order Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/ordertest |
List orders | Yes |
GET |
/api/ordertest/{id} |
Get order details | Yes |
POST |
/api/ordertest |
Create order | Yes |
PATCH |
/api/ordertest/{id} |
Update order | Yes |
DELETE |
/api/ordertest/{id} |
Delete order | Yes |
POST |
/api/ordertest/status |
Update order status | Yes |
Demo/Test Endpoints (No Auth)
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/demo/order |
Create demo order with patient | No |
Specimen Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/specimen |
List specimens | Yes |
GET |
/api/specimen/{id} |
Get specimen details | Yes |
POST |
/api/specimen |
Create specimen | Yes |
PATCH |
/api/specimen/{id} |
Update specimen | Yes |
POST |
/api/specimen/status |
Update specimen status | Yes |
Result Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/patresult |
List patient results | Yes |
GET |
/api/patresult/{id} |
Get result details | Yes |
POST |
/api/patresult |
Enter new result | Yes |
PATCH |
/api/patresult/{id} |
Update result | Yes |
POST |
/api/patresult/status |
Verify result (VER/REV/REP) | Yes |
Edge API (Instrument Integration)
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/edge/result |
Receive instrument results | API Key |
GET |
/api/edge/order |
Fetch pending orders | API Key |
POST |
/api/edge/order/{id}/ack |
Acknowledge order | API Key |
POST |
/api/edge/status |
Log instrument status | API Key |
API Response Format
All API endpoints return JSON in this format:
Success Response:
{
"status": "success",
"message": "Operation completed successfully",
"data": {
// Response data here
}
}
Error Response:
{
"status": "error",
"message": "Error description",
"errors": [
{
"field": "field_name",
"message": "Validation error message"
}
]
}
Authentication
Most endpoints require JWT authentication:
Request Headers:
Authorization: Bearer {jwt_token}
Content-Type: application/json
Login Request Example:
POST /api/login
{
"username": "labuser",
"password": "password123"
}
Login Response:
{
"status": "success",
"message": "Login successful",
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_in": 3600,
"user": {
"id": 1,
"username": "labuser",
"name": "Lab User"
}
}
}
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();
When to Use
| Approach | Use Case |
|---|---|
| Lookups Library | Server-side static values that rarely change (gender, status, types) - fast, cached |
API /api/valueset* |
Dynamic values managed by admins at runtime, or for frontend clients needing lookup data |
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 REST API endpoints.
🧪 Laboratory 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
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 |
| Text | reftxt |
Text-based 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
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, reftxt |
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/result |
Receive instrument results (stored in edgeres) |
GET |
/api/edge/order |
Fetch pending orders for an instrument |
POST |
/api/edge/order/:id/ack |
Acknowledge order delivery to instrument |
POST |
/api/edge/status |
Log instrument status updates |
Workflow
Instrument → tiny-edge → POST /api/edge/result → 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 is an API-only backend system. There are no views, HTML templates, or server-side rendering components. Frontend applications should consume these REST endpoints to build user interfaces for laboratory operations.
This repository contains proprietary information intended for the 5Panda Team and authorized collaborators.
© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.