clqms-be/docs/mvp_plan.md
mahdahar 85c7e96405 feat: implement comprehensive result management and lab reporting system
- Add full CRUD operations for results (index, show, update, delete)
- Implement result validation with reference range checking (L/H flags)
- Add cumulative patient results retrieval across all orders
- Create ReportController for HTML lab report generation
- Add lab report view with patient info, order details, and test results
- Implement soft delete for results with transaction safety
- Update API routes with /api/results/* endpoints for CRUD
- Add /api/reports/{orderID} endpoint for report viewing
- Update OpenAPI docs with results and reports schemas/paths
- Add documentation for manual result entry and MVP plan
2026-03-04 16:48:12 +07:00

7.5 KiB

CLQMS MVP Sprint Plan

Scope: Result Entry + Validation + Reporting (2-week sprint)
Removed: Edge API, Worklists, Calculated Tests, QC, Instrument Integration


Current State

What's Working

  • Patient CRUD + Identifiers + Addresses
  • Patient Visit + ADT
  • Lab Orders (create with specimen generation)
  • Test Definitions + Reference Ranges (refnum)
  • Authentication (JWT)
  • Master Data (ValueSets, Locations, etc.)

Critical Gap

  • ResultController only returns JWT payload (no CRUD)
  • PatResultModel has no validation logic
  • No PDF generation capability
  • Only 1 working route: GET /api/result (returns auth check only)

Phase 1: Result CRUD + Validation (Week 1)

Day 1-2: PatResultModel Enhancement

Location: app/Models/PatResultModel.php

Add methods:

  • validateAndFlag($resultID, $value) - Compare result against refnum ranges
    • Check patient age, sex from order
    • Match refnum criteria
    • Return 'L', 'H', or null
  • getByOrder($orderID) - Fetch all results for an order with test names
  • getByPatient($internalPID) - Get cumulative patient results
  • updateWithValidation($resultID, $data) - Update + auto-validate

Day 3-4: ResultController

Location: app/Controllers/ResultController.php

Replace placeholder with full CRUD:

Method Endpoint Description
index() GET /api/results List results (filter by order/patient)
show($id) GET /api/results/{id} Get single result
update($id) PATCH /api/results/{id} Update result + auto-validate
delete($id) DELETE /api/results/{id} Soft delete result

Features:

  • Filter by order_id or patient_id query param
  • Include test name from testdefsite
  • Auto-calculate flags on update
  • Return standardized ResponseTrait format

Day 5: Routes & Testing

Location: app/Config/Routes.php

Replace line 18:

// OLD
$routes->get('result', 'ResultController::index');

// NEW
$routes->group('results', function ($routes) {
    $routes->get('/', 'ResultController::index');
    $routes->get('(:num)', 'ResultController::show/$1');
    $routes->patch('(:num)', 'ResultController::update/$1');
    $routes->delete('(:num)', 'ResultController::delete/$1');
});

Testing: Manual API testing with Postman/Insomnia


Phase 2: HTML Report Viewing (Week 2)

Day 1-2: Report View & Controller

Create Report View: app/Views/reports/lab_report.php Template sections:

  • Patient header (Name, DOB, ID)
  • Order info (OrderID, Date, Doctor)
  • Results table (Test, Result, Units, Reference, Flag)
  • Footer (Lab info, signature)
  • Print-friendly CSS with @media print support

Create ReportController: app/Controllers/ReportController.php

Method Endpoint Description
view($orderID) GET /api/reports/{orderID} Generate HTML lab report

Logic:

  • Fetch order with patient details
  • Get all results for order (with flags)
  • Include test definitions (name, units, ref range)
  • Render HTML view using CodeIgniter's view() function
  • Users can print/save as PDF via browser

Day 3-4: Routes & Polish

Routes (add to Routes.php):

$routes->get('reports/(:num)', 'ReportController::view/$1');

HTML Styling:

  • Professional lab report format
  • Show abnormal flags (L/H) highlighted
  • Include reference ranges
  • Signature line for pathologist
  • Responsive design with print button

Testing:

  • Generate report with actual data
  • Verify formatting
  • Test print functionality
  • Test edge cases (no results, all normal, mix of flags)

Note: PDF generation deferred to post-MVP. Users can use browser's "Print to PDF" feature for now.


Database Schema Reference

patres (Results)

Column Type Notes
ResultID INT PK
OrderID INT FK to ordertest
TestSiteID INT FK to testdefsite
Result VARCHAR(255) The actual value
ResultDateTime DATETIME When entered
RefNumID INT Applied reference range

refnum (Reference Ranges)

Column Type Notes
RefNumID INT PK
TestSiteID INT Which test
Sex VARCHAR M/F/ALL
AgeStart/AgeEnd INT Age criteria
Low/High DECIMAL Range values
LowSign/HighSign VARCHAR <=, <, etc

API Endpoints Summary

Endpoint Method Auth Description
/api/results GET Yes List results (filter: ?order_id= or ?patient_id=)
/api/results/{id} GET Yes Get single result
/api/results/{id} PATCH Yes Update result + auto-flag
/api/results/{id} DELETE Yes Soft delete result
/api/reports/{orderID} GET Yes Generate PDF report

Flag Logic (Reference Range Validation)

// Pseudo-code for validation
function validateResult($resultValue, $refNumID) {
    $ref = getRefNum($refNumID);
    $patient = getPatientFromOrder($orderID);
    
    // Match criteria (sex, age)
    if (!matchesCriteria($ref, $patient)) {
        return null; // No flag if criteria don't match
    }
    
    $value = floatval($resultValue);
    $low = floatval($ref['Low']);
    $high = floatval($ref['High']);
    
    // Check low
    if ($ref['LowSign'] === '<=' && $value <= $low) return 'L';
    if ($ref['LowSign'] === '<' && $value < $low) return 'L';
    
    // Check high
    if ($ref['HighSign'] === '>=' && $value >= $high) return 'H';
    if ($ref['HighSign'] === '>' && $value > $high) return 'H';
    
    return null; // Normal
}

Out of Scope (Post-MVP)

  • Edge API: Instrument integration (app/Controllers/EdgeController.php)
  • Worklist Generation: Technician worklists
  • Calculated Tests: Formula execution (CALC type)
  • Quality Control: QC samples, Levy-Jennings charts
  • Calculated Test Execution: Deferred to later
  • Delta Checking: Result trending
  • Critical Result Alerts: Notification system
  • Audit Trail: Complete audit logging

Success Criteria

  • Can enter result values via API
  • Results auto-validate against refnum ranges
  • Abnormal results show L/H flags
  • Can view all results for an order
  • Can generate PDF lab report
  • Report shows patient, order, results with flags

Files to Create/Modify

Create

  1. app/Controllers/ReportController.php - HTML report controller
  2. app/Views/reports/lab_report.php - HTML report template with dynamic flag calculation
  3. app/Database/Migrations/2026-03-04-073950_RemoveFlagColumnFromPatRes.php - Remove Flag column
  4. public/paths/reports.yaml - OpenAPI documentation for reports endpoint

Modify

  1. app/Models/PatResultModel.php - Add validation methods (validateAndFlag, getByOrder, getByPatient, updateWithValidation, getWithRelations, softDelete)
  2. app/Controllers/ResultController.php - Full CRUD (index, show, update, delete)
  3. app/Config/Routes.php - New routes for results and reports
  4. public/paths/results.yaml - Updated OpenAPI documentation
  5. public/api-docs.yaml - Added Reports tag
  6. Regenerated public/api-docs.bundled.yaml

Note: Flag is calculated dynamically at runtime, not stored in database. This allows for:

  • Real-time validation against current reference ranges
  • Support for reference range updates without re-processing historical results
  • Reduced storage requirements

API Documentation: Remember to run node public/bundle-api-docs.js after updating YAML files to regenerate the bundled documentation.


Last Updated: 2026-03-04
Sprint Duration: 2 weeks
Team Size: 1 developer