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

250 lines
7.5 KiB
Markdown

# 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:
```php
// 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):
```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)
```php
// 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*