# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. --- ## Tool Preference: Use Serena MCP **Always prioritize Serena MCP tools for code operations to minimize tool calls:** - **Use `find_symbol` / `get_symbols_overview`** instead of `Read` for exploring code structure - **Use `replace_symbol_body`** instead of `Edit` for modifying functions, methods, classes - **Use `insert_before_symbol` / `insert_after_symbol`** for adding new code symbols - **Use `search_for_pattern`** instead of `Grep` for searching code patterns - **Use `list_dir` / `find_file`** instead of `Glob` for file discovery This leverages semantic code understanding for this PHP codebase. --- ## Common Commands ### Testing ```bash # Run all tests vendor/bin/phpunit # Run specific test file vendor/bin/phpunit tests/feature/UniformShowTest.php # Run tests in a directory vendor/bin/phpunit app/Models # Generate code coverage report vendor/bin/phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m ``` ### Database ```bash # Run migrations spark migrate # Rollback migrations spark migrate:rollback # Seed database spark db:seed DBSeeder # Refresh all migrations and seed spark migrate:refresh --seed ``` ### CodeIgniter CLI ```bash # General help spark help # Generate code (scaffolding) spark make:model ModelName spark make:controller ControllerName spark make:migration MigrationName ``` ### API Documentation ```bash # Keep api-docs.yaml updated whenever controllers change # File: public/api-docs.yaml # After modifying controllers, update the OpenAPI schema definitions # to reflect new field names, types, and response formats ``` --- ## Architecture Overview ### Core Pattern: MVC + Libraries CLQMS follows CodeIgniter 4 conventions with these key architectural patterns: **Controllers** (`app/Controllers/`) - Organized by domain: `Patient/`, `Organization/`, `Specimen/`, `Test/`, `Contact/` - Root-level controllers for cross-domain concerns: `AuthController`, `EdgeController`, `ValueSetController` - All controllers extend `BaseController` which provides request/response helpers **Models** (`app/Models/`) - Organized by domain matching controllers: `Patient/`, `Organization/`, `Specimen/`, `Test/`, etc. - All models extend `BaseModel` which provides automatic UTC date normalization - Model callbacks: `beforeInsert/Update` normalize dates to UTC, `afterFind/Insert/Update` convert to UTC ISO format **Libraries** (`app/Libraries/`) - `ValueSet` - Static lookup system using JSON files (see "Lookup System" below) ### Lookup System: ValueSet Library The system uses a **JSON file-based lookup system** instead of database queries for static values. **Location:** `app/Libraries/Data/*.json` (44+ JSON files) **Key Files:** - `_meta.json` - Metadata about lookup definitions - `sex.json`, `order_status.json`, `specimen_type.json`, `test_type.json`, etc. **Usage:** ```php use App\Libraries\ValueSet; // Get dropdown-formatted options $options = ValueSet::get('sex'); // [["value"=>"1","label"=>"Female"],...] // Get raw data $raw = ValueSet::getRaw('sex'); // [["key"=>"1","value"=>"Female"],...] // Get label for a specific key $label = ValueSet::getLabel('sex', '1'); // "Female" // Transform database records with lookup text labels $data = ValueSet::transformLabels($patients, ['Sex' => 'sex']); // Clear cache after modifying JSON files ValueSet::clearCache(); ``` **When to use ValueSet vs API:** - **ValueSet library** - Static values that rarely change (fast, cached) - **API `/api/valueset*`** - Dynamic values managed by admins at runtime ### Database Migrations Structure Migrations are numbered sequentially starting with `2026-01-01-`: | Migration | Tables Created | |-----------|----------------| | 000001 | valueset, counter, containerdef, occupation, specialty | | 000002 | account, site, location, discipline, department | | 000003 | patient, patidentifier, pataddress, patcontact | | 000004 | contact, contactdetail, userdevices, loginattempts | | 000005 | patvisit, patinsurance | | 000006 | porder, orderitem | | 000007 | specimen, specmenactivity, containerdef | | 000008 | testdefinition, testactivity, refnum, reftxt | | 000009 | patresult, patresultdetail, patresultcomment | | 000010 | edgeres, edgestatus, edgeack, workstation | ### Authentication & Authorization - **JWT-based authentication** using `firebase/php-jwt` - **AuthFilter** - Route filter protecting API endpoints - **AuthController** - Login/logout endpoints (`POST /api/login`, `POST /api/logout`) - **AuthV2Controller** - V2 authentication endpoints ### Edge API (Instrument Integration) The `EdgeController` provides endpoints for laboratory instrument integration via `tiny-edge` middleware: - `POST /api/edge/results` - Receive instrument results (stored in `edgeres` table) - `GET /api/edge/orders` - Fetch pending orders for instruments - `POST /api/edge/orders/:id/ack` - Acknowledge order delivery - `POST /api/edge/status` - Log instrument status updates **Workflow:** `Instrument → tiny-edge → edgeres table → [Processing] → patresult table` ### Test Types System Tests in `testdefinition` table support multiple types via `TestType` field: | Code | Type | Description | |------|------|-------------| | TEST | Technical | Individual lab test with specs | | PARAM | Parameter | Non-lab measurement | | CALC | Calculated | Test with formula | | GROUP | Panel/Profile | Contains multiple tests | | TITLE | Section | Report organization header | ### Reference Range Architecture Reference ranges support multiple types for result validation: | Type | Table | Purpose | |------|-------|---------| | Numeric | `refnum` | Ranges with age/sex criteria | | Threshold | `refthold` | Critical values | | Text | `reftxt` | Text-based references | | Value Set | `refvset` | Coded references | ### Routes Organization Routes are defined in `app/Config/Routes.php`: - API routes: `/api/{resource}` - Auth-protected routes use `AuthFilter` --- ## Project Structure Notes - **Language:** PHP 8.1+ (PSR-compliant) - **Framework:** CodeIgniter 4 - **Database:** MySQL with migration-based schema management - **Testing:** PHPUnit 10.5+ (tests in `tests/` directory) - **Entry point:** `public/index.php` (web), `spark` (CLI) - **Environment config:** `.env` file (copy from `env` template)