3.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
CLQMS is a Clinical Laboratory Quality Management System built with CodeIgniter 4 (PHP 8.1+) providing a REST API backend for laboratory operations from patient registration through test resulting. The frontend uses Alpine.js views in app/Views/v2/.
Development Commands
# Install dependencies
composer install
# Run all tests
composer test
php vendor/bin/phpunit
# Run single test file
php vendor/bin/phpunit tests/feature/Patients/PatientIndexTest.php
# Run single test method
php vendor/bin/phpunit tests/feature/Patients/PatientIndexTest.php --filter=testIndexWithoutParams
# Run tests with coverage
php vendor/bin/phpunit --coverage-html build/logs/html
# Run CLI commands
php spark help
php spark db:seed DBSeeder
Architecture
Directory Structure
app/Controllers/{Domain}/- API controllers organized by domain (Patient, Organization, Specimen, Result, Test)app/Models/{Domain}/- Domain modelsapp/Libraries/Data/*.json- Static lookup data (gender, order_priority, specimen_type, etc.)app/Views/v2/- Alpine.js frontend viewsapp/Database/Migrations/- 10 consolidated migrations (2026-01-01-*)tests/feature/- API endpoint tests usingFeatureTestTrait
Key Patterns
Controller Pattern:
class PatientController extends Controller {
use ResponseTrait;
protected $db;
protected $model;
public function __construct() {
$this->db = \Config\Database::connect();
$this->model = new PatientModel();
}
public function index() {
try {
$data = $this->model->findAll();
return $this->respond(['status' => 'success', 'data' => $data], 200);
} catch (\Exception $e) {
return $this->failServerError($e->getMessage());
}
}
}
Model Pattern: Models extend BaseModel which auto-normalizes dates to/from UTC via beforeInsert/beforeUpdate callbacks. Use allowedFields for mass assignment and useSoftDeletes = true with deletedField = 'DelDate' for soft deletes.
API Response Format:
// Success
{"status": "success", "message": "...", "data": [...]}
// Error
{"status": "failed", "message": "..."}
Lookups Library
Use App\Libraries\Lookups for static dropdown values (loaded from JSON files, cached):
use App\Libraries\Lookups;
// Get dropdown-formatted data [{value: '1', label: 'Female'}, ...]
$gender = Lookups::get('gender');
// Get label by key
$label = Lookups::getLabel('gender', '1'); // 'Female'
// Clear cache after modifying lookup data
Lookups::clearCache();
For dynamic values managed at runtime, use the /api/valueset* endpoints instead.
JWT Authentication
Most API endpoints require JWT auth via AuthFilter. Public endpoints include /v2/login, /api/demo/*, /api/auth/*.
Database Conventions
| Element | Convention |
|---|---|
| Tables | snake_case (patient, patvisit) |
| Columns | PascalCase (InternalPID, PatientID) |
| Classes | PascalCase (PatientController, BaseModel) |
| Methods/Variables | camelCase (getPatient(), $internalPID) |
Soft deletes use DelDate field - never hard delete records.
Key Routes
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/login |
JWT authentication |
| GET/POST | /api/patient |
Patient CRUD |
| GET/POST | /api/patvisit |
Patient visits |
| POST | /api/ordertest |
Create orders |
| POST | /api/edge/results |
Instrument integration (tiny-edge middleware) |
Important Notes
- All dates normalized to UTC automatically via
BaseModel - No comments in code unless explicitly requested
- Use transactions for multi-table operations
- Validate input before DB operations using CodeIgniter validation rules