diff --git a/.factory/config.json b/.factory/config.json new file mode 100644 index 0000000..8a75ea0 --- /dev/null +++ b/.factory/config.json @@ -0,0 +1,12 @@ +{ + "custom_models": [ + { + "model_display_name": "MiniMax-M2.1", + "model": "MiniMax-M2.1", + "base_url": "https://api.minimax.io/anthropic", + "api_key": "sk-cp-eMsvq_OqP6UiCBirrr3W6gZlG6-NXnIQeneGNpAJ8aWxywzNq5I9mibfQFBBy84C2Mm7jCqMtjKmbpnx6h02nz_D7xG6ETmBY4K6Nog454cYs_ZkYgMyG_g", + "provider": "anthropic", + "max_tokens": 64000 + } + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5b495ab..be05392 100644 --- a/.gitignore +++ b/.gitignore @@ -124,4 +124,9 @@ _modules/* /results/ /phpunit*.xml -/public/.htaccess \ No newline at end of file +/public/.htaccess + +#------------------------- +# Claude +#------------------------- +.claude \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 5af0c47..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,86 +0,0 @@ -# Valueset Data Scanning - Agent Instructions - -## Quick Reference - -**Database Tables:** -- [`valuesetdef`](app/Models/ValueSet/ValueSetDefModel.php:8) - Category definitions (VSetID, VSName, VSDesc) -- [`valueset`](app/Models/ValueSet/ValueSetModel.php:8) - Actual values (VID, VSetID, VValue, VDesc, VOrder) - -## Agent Workflow for Valueset Queries - -### Step 1: Identify the Request Type - -**Category Search:** -``` -User: "Show me all values in [CATEGORY_NAME]" -Agent: Search valuesetdef by VSName → Get VSetID → Query values by VSetID -``` - -**Reference Search:** -``` -User: "Show me values for [TABLE.COLUMN]" -Agent: Search valuesetdef by VSDesc → Get VSetID → Query values by VSetID -``` - -**ID Search:** -``` -User: "Show me values for VSetDefID [ID]" -Agent: Directly query values by VSetID -``` - -**Filtered Search:** -``` -User: "Find values containing [TERM] in [CATEGORY]" -Agent: Search valuesetdef by VSName → Get VSetID → Query values with LIKE filter -``` - -### Step 2: Execute Query - -**Model Methods:** -- [`ValueSetDefModel::getValueSetDefs($param)`](app/Models/ValueSet/ValueSetDefModel.php:18) - Search categories -- [`ValueSetModel::getValueSetByValueSetDef($VSetID)`](app/Models/ValueSet/ValueSetModel.php:52) - Get values by category -- [`ValueSetModel::getValueSets($param, $page, $limit, $VSetID)`](app/Models/ValueSet/ValueSetModel.php:18) - Get values with filters - -### Step 3: Return Results - -**Response Format:** -```json -{ - "VSetID": 27, - "VSName": "Test Type", - "values": [ - { "VID": 1, "VValue": "TEST", "VDesc": "Test", "VOrder": 1 }, - { "VID": 2, "VValue": "PARAM", "VDesc": "Parameter", "VOrder": 2 } - ] -} -``` - -## Common Valuesets - -| VSetDefID | VSName | VSDesc | Search Keywords | -|-----------|--------|--------|-----------------| -| 3 | Gender | - | gender, sex | -| 27 | Test Type | `testdefsite.TestType` | test, type, testdefsite | -| 15 | Specimen Type | - | specimen, type, blood, urine | -| 31 | Range Types | `refnum.RangeType` | range, refnum | -| 46 | Num Ref Type | `refnum.NumRefType` | numeric, reference | - -## Example Agent Conversations - -**User:** "Show me Gender values" -**Agent:** -1. `getValueSetDefs("Gender")` → VSetID = 3 -2. `getValueSetByValueSetDef(3)` → Returns values -3. Output: Female, Male, Unknown - -**User:** "What values for testdefsite.TestType?" -**Agent:** -1. `getValueSetDefs("testdefsite.TestType")` → VSetID = 27 -2. `getValueSetByValueSetDef(27)` → Returns values -3. Output: TEST, PARAM, CALC, GROUP, TITLE - -**User:** "Find values with 'STAT' in Priority" -**Agent:** -1. `getValueSetDefs("Priority")` → VSetID = 1 -2. `getValueSets("STAT", null, 50, 1)` → Returns matching values -3. Output: STAT, STAT2 (if exists) diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0c9e95e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,174 @@ +# CLQMS Backend - Claude Code Instructions + +**Project:** Clinical Laboratory Quality Management System (CLQMS) Backend +**Framework:** CodeIgniter 4 (PHP) +**Platform:** Windows - Use PowerShell or CMD for terminal commands +**Frontend:** Alpine.js (views/v2 directory contains Alpine.js components) + +### Views/V2 Structure +``` +app/Views/v2/ +├── layout/ +│ └── main_layout.php # Main layout with sidebar, navbar, Alpine.js layout() component +├── auth/ +│ └── login.php # Login page +├── dashboard/ +│ └── dashboard_index.php # Dashboard view +├── patients/ +│ ├── patients_index.php # Patient list with x-data="patients()" component +│ └── dialog_form.php # Patient form dialog +├── requests/ +│ └── requests_index.php # Lab requests +├── settings/ +│ └── settings_index.php # Settings page +└── master/ + ├── organization/ # Organization management (accounts, sites, disciplines, departments, workstations) + ├── specimen/ # Specimen management (containers, preparations) + ├── tests/ # Lab tests (tests_index, param_dialog, grp_dialog, calc_dialog) + └── valuesets/ # Value sets management +``` + +### Alpine.js Patterns +- **Global layout:** `layout()` function in `main_layout.php` handles sidebar state, theme toggle, and navigation +- **Page components:** Each page uses `x-data="componentName()"` (e.g., `x-data="patients()"`) +- **API calls:** Use `fetch()` with `BASEURL` global variable and `credentials: 'include'` +- **Dialogs:** Modals use `x-show` with `@click.self` backdrop click to close +- **TailwindCSS 4:** Loaded via CDN with custom CSS variables for theming + +## Quick Reference + +**Static Library:** +- [`Lookups`](app/Libraries/Lookups.php) - Static lookup constants (no database queries) + +**Usage:** +```php +use App\Libraries\Lookups; + +// Get formatted lookup [{value: 'KEY', label: 'Label'}, ...] +Lookups::get('gender'); + +// Get raw associative array ['KEY' => 'Label', ...] +Lookups::getRaw('gender'); + +// Get all lookups for frontend +Lookups::getAll(); +``` + +## Agent Workflow for Valueset Queries + +Use `Lookups` class for all lookup queries - no database queries needed. + +### Step 1: Identify the Lookup Constant + +**By Category Name:** Match VSName to constant name (e.g., "Gender" → `Lookups::GENDER`) +**By Reference:** Match VSDesc to constant name (e.g., `testdefsite.TestType` → `Lookups::TEST_TYPE`) +**By VSetDefID:** Map VSetDefID to constant (see Common Lookups table below) + +### Step 2: Retrieve Values + +```php +// Formatted for frontend dropdowns +Lookups::get('gender'); // [{value: '1', label: 'Female'}, ...] + +// Raw key-value pairs +Lookups::getRaw('gender'); // ['1' => 'Female', '2' => 'Male', ...] +``` + +### Step 3: Return Results + +**Response Format (formatted):** +```json +[ + { "value": "1", "label": "Female" }, + { "value": "2", "label": "Male" }, + { "value": "3", "label": "Unknown" } +] +``` + +## Common Lookups + +| VSetDefID | Constant | Search Keywords | +|-----------|----------|-----------------| +| 1 | `WS_TYPE` | workstation, type | +| 2 | `ENABLE_DISABLE` | enable, disable | +| 3 | `GENDER` | gender, sex | +| 4 | `MARITAL_STATUS` | marital, status | +| 5 | `DEATH_INDICATOR` | death, indicator | +| 6 | `IDENTIFIER_TYPE` | identifier, type, KTP, passport | +| 7 | `OPERATION` | operation, CRUD | +| 8 | `DID_TYPE` | device, ID, AAID, IDFA | +| 9 | `REQUESTED_ENTITY` | requested, entity, patient, insurance | +| 10 | `ORDER_PRIORITY` | priority, order, stat, ASAP | +| 11 | `ORDER_STATUS` | status, order | +| 12 | `LOCATION_TYPE` | location, type | +| 13 | `ADDITIVE` | additive, heparin, EDTA | +| 14 | `CONTAINER_CLASS` | container, class | +| 15 | `SPECIMEN_TYPE` | specimen, type, blood, urine | +| 16 | `UNIT` | unit | +| 17 | `GENERATE_BY` | generate, by | +| 18 | `SPECIMEN_ACTIVITY` | specimen, activity | +| 19 | `ACTIVITY_RESULT` | activity, result | +| 20 | `SPECIMEN_STATUS` | specimen, status | +| 21 | `SPECIMEN_CONDITION` | specimen, condition | +| 22 | `SPECIMEN_ROLE` | specimen, role | +| 23 | `COLLECTION_METHOD` | collection, method | +| 24 | `BODY_SITE` | body, site | +| 25 | `CONTAINER_SIZE` | container, size | +| 26 | `FASTING_STATUS` | fasting, status | +| 27 | `TEST_TYPE` | test, type, testdefsite | +| 28 | `RESULT_UNIT` | result, unit | +| 29 | `FORMULA_LANGUAGE` | formula, language | +| 30 | `RACE` | race, ethnicity | +| 31 | `RELIGION` | religion | +| 32 | `ETHNIC` | ethnic | +| 33 | `COUNTRY` | country (loaded from external file) | +| 34 | `CONTAINER_CAP_COLOR` | container, cap, color | +| 35 | `TEST_ACTIVITY` | test, activity | +| 36 | `ADT_EVENT` | ADT, event | +| 37 | `SITE_TYPE` | site, type | +| 38 | `SITE_CLASS` | site, class | +| 39 | `ENTITY_TYPE` | entity, type | +| 40 | `AREA_CLASS` | area, class | +| 41 | `MATH_SIGN` | math, sign | +| 42 | `V_CATEGORY` | category | +| 43 | `RESULT_TYPE` | result, type | +| 44 | `REFERENCE_TYPE` | reference, type | +| 45 | `RANGE_TYPE` | range, type | +| 46 | `NUMERIC_REF_TYPE` | numeric, reference | +| 47 | `TEXT_REF_TYPE` | text, reference | + +**Convenience Aliases:** +- `Lookups::PRIORITY` → alias for `ORDER_PRIORITY` +- `Lookups::TEST_STATUS` → Test status values +- `Lookups::REQUEST_STATUS` → alias for `SPECIMEN_STATUS` +- `Lookups::RESULT_STATUS` → Result status values + +## Example Agent Conversations + +**User:** "Show me Gender values" +**Agent:** +1. `Lookups::get('gender')` → Returns formatted array +2. Output: Female, Male, Unknown + +**User:** "What values for testdefsite.TestType?" +**Agent:** +1. `Lookups::get('test_type')` → Returns formatted array +2. Output: TEST, PARAM, CALC, GROUP, TITLE + +**User:** "Find specimen status options" +**Agent:** +1. `Lookups::get('specimen_status')` → Returns formatted array +2. Output: To be collected, Collected, In-transport, Arrived, etc. + +--- + +## Commanding Officer Persona Mode + +When the user addresses you as their commanding officer or in a starship context, respond accordingly: + +- Address the officer respectfully ("Commander", "Captain", "Sir/Ma'am") +- Use military/space command terminology ("affirmative", "reporting", "orders", "status") +- Frame technical responses in mission-ops format ("Systems operational", "Data retrieved", "Report ready") +- Keep responses crisp and professional, befitting ship command +- Example: "Commander, the valueset data you requested is ready for review." +- Start something with basmalah and end with hamdalah diff --git a/README.md b/README.md index 7a9b8c3..040195b 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,77 @@ When working on UI components or dropdowns, **always check for existing ValueSet --- +## 📚 Static Lookups Library (`app/Libraries/Lookups.php`) + +For frequently used lookup values, CLQMS provides a **static library** with all values hardcoded. This eliminates database queries for common dropdowns and improves performance. + +### Available Lookups + +| Constant | VSetID | Description | +|----------|--------|-------------| +| `WS_TYPE` | 1 | Workstation type (Primary, Secondary) | +| `ENABLE_DISABLE` | 2 | Enable/disable flags | +| `GENDER` | 3 | Gender (Female, Male, Unknown) | +| `MARITAL_STATUS` | 4 | Marital status (A/D/M/S/W/B/U/O) | +| `DEATH_INDICATOR` | 5 | Death indicator (Y/N) | +| `IDENTIFIER_TYPE` | 6 | ID types (KTP, Passport, SSN, SIM) | +| `OPERATION` | 7 | CRUD operations (Create, Read, Update, Delete) | +| `ORDER_PRIORITY` | 10 | Order priority (S=Stat, A=ASAP, R=Routine, P=Preop, etc.) | +| `ORDER_STATUS` | 11 | Order status (A/CA/CM/DC/ER/HD/IP/RP/SC/CL/AC/DL) | +| `SPECIMEN_TYPE` | 15 | Specimen types (BLD, SER, PLAS, UR, CSF, etc.) | +| `SPECIMEN_STATUS` | 20 | Specimen status (STC, SCtd, SArrv, SRcvd, SAna, etc.) | +| `SPECIMEN_CONDITION` | 21 | Specimen condition (HEM, ITC, LIP, etc.) | +| `TEST_TYPE` | 27 | Test types (TEST, PARAM, CALC, GROUP, TITLE) | +| `RESULT_UNIT` | 28 | Result units (g/dL, mg/dL, x10^6/mL, etc.) | +| `RACE` | 30 | Ethnicity/race (Jawa, Sunda, Batak, etc.) | +| `RELIGION` | 31 | Religion (Islam, Kristen, Katolik, Hindu, Budha, etc.) | +| `SITE_TYPE` | 37 | Site type (GH, PH, GHL, PHL, GL, PL) | +| `SITE_CLASS` | 38 | Site class (A/B/C/D/Utm/Ptm) | +| `RESULT_TYPE` | 43 | Result type (NMRIC, RANGE, TEXT, VSET) | +| `RANGE_TYPE` | 45 | Range type (REF, CRTC, VAL, RERUN) | +| `HIV_RESULT` | 1001 | HIV results (NEG, POS, GZ) | + +**Plus 25+ more categories** - see [`app/Libraries/Lookups.php`](app/Libraries/Lookups.php) for complete list. + +### Usage + +```php +use App\Libraries\Lookups; + +// Get all lookups formatted for frontend +$allLookups = Lookups::getAll(); + +// Get single lookup (returns [{value: 'X', label: 'Y'}, ...]) +$gender = Lookups::get('GENDER'); + +// Get raw associative array +$priorities = Lookups::getRaw('ORDER_PRIORITY'); +// Returns: ['S' => 'Stat', 'A' => 'ASAP', 'R' => 'Routine', ...] + +// Get label by key +$label = Lookups::getLabel('GENDER', '1'); // Returns 'Female' +``` + +### Frontend Usage (Alpine.js) + +```php +// In your PHP view file + +``` + +### When to Use + +| Approach | Use Case | +|----------|----------| +| **Static Lookups** | Frequently used values that rarely change (gender, status, types) | +| **API `/api/valueset*`** | Dynamic values that may be modified by admins at runtime | + +--- + ## 📋 Master Data Management CLQMS provides comprehensive master data management for laboratory operations. All master data is accessible via the V2 UI at `/v2/master/*` endpoints. diff --git a/app/Controllers/ValueSet/ValueSetController.php b/app/Controllers/ValueSet/ValueSetController.php index 6e80bcc..eaa2257 100644 --- a/app/Controllers/ValueSet/ValueSetController.php +++ b/app/Controllers/ValueSet/ValueSetController.php @@ -24,22 +24,14 @@ class ValueSetController extends BaseController { public function index() { $param = $this->request->getVar('param'); $VSetID = $this->request->getVar('VSetID'); - $page = $this->request->getVar('page') ?? 1; - $limit = $this->request->getVar('limit') ?? 20; - $result = $this->model->getValueSets($param, $page, $limit, $VSetID); - + $data = $this->model->getValueSets($param, $VSetID); + return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", - 'data' => $result['data'], - 'pagination' => [ - 'currentPage' => (int)$page, - 'totalPages' => $result['pager']->getPageCount(), - 'totalItems' => $result['pager']->getTotal(), - 'limit' => (int)$limit - ] - ], 200); + 'data' => $data + ], 200); } public function show($VID = null) { diff --git a/app/Libraries/Data/Countries.php b/app/Libraries/Data/Countries.php new file mode 100644 index 0000000..936e265 --- /dev/null +++ b/app/Libraries/Data/Countries.php @@ -0,0 +1,259 @@ + 'Afghanistan', + 'ALA' => 'Åland Islands', + 'ALB' => 'Albania', + 'DZA' => 'Algeria', + 'ASM' => 'American Samoa', + 'AND' => 'Andorra', + 'AGO' => 'Angola', + 'AIA' => 'Anguilla', + 'ATA' => 'Antarctica', + 'ATG' => 'Antigua and Barbuda', + 'ARG' => 'Argentina', + 'ARM' => 'Armenia', + 'ABW' => 'Aruba', + 'AUS' => 'Australia', + 'AUT' => 'Austria', + 'AZE' => 'Azerbaijan', + 'BHS' => 'Bahamas', + 'BHR' => 'Bahrain', + 'BGD' => 'Bangladesh', + 'BRB' => 'Barbados', + 'BLR' => 'Belarus', + 'BEL' => 'Belgium', + 'BLZ' => 'Belize', + 'BEN' => 'Benin', + 'BMU' => 'Bermuda', + 'BTN' => 'Bhutan', + 'BOL' => 'Bolivia, Plurinational State of', + 'BES' => 'Bonaire, Sint Eustatius and Saba', + 'BIH' => 'Bosnia and Herzegovina', + 'BWA' => 'Botswana', + 'BVT' => 'Bouvet Island', + 'BRA' => 'Brazil', + 'IOT' => 'British Indian Ocean Territory', + 'BRN' => 'Brunei Darussalam', + 'BGR' => 'Bulgaria', + 'BFA' => 'Burkina Faso', + 'BDI' => 'Burundi', + 'CPV' => 'Cabo Verde', + 'KHM' => 'Cambodia', + 'CMR' => 'Cameroon', + 'CAN' => 'Canada', + 'CYM' => 'Cayman Islands', + 'CAF' => 'Central African Republic', + 'TCD' => 'Chad', + 'CHL' => 'Chile', + 'CHN' => 'China', + 'CXR' => 'Christmas Island', + 'CCK' => 'Cocos (Keeling) Islands', + 'COL' => 'Colombia', + 'COM' => 'Comoros', + 'COG' => 'Congo', + 'COD' => 'Congo, Democratic Republic of the', + 'COK' => 'Cook Islands', + 'CRI' => 'Costa Rica', + 'CIV' => "Côte d'Ivoire", + 'HRV' => 'Croatia', + 'CUB' => 'Cuba', + 'CUW' => 'Curaçao', + 'CYP' => 'Cyprus', + 'CZE' => 'Czechia', + 'DNK' => 'Denmark', + 'DJI' => 'Djibouti', + 'DMA' => 'Dominica', + 'DOM' => 'Dominican Republic', + 'ECU' => 'Ecuador', + 'EGY' => 'Egypt', + 'SLV' => 'El Salvador', + 'GNQ' => 'Equatorial Guinea', + 'ERI' => 'Eritrea', + 'EST' => 'Estonia', + 'SWZ' => 'Eswatini', + 'ETH' => 'Ethiopia', + 'FLK' => 'Falkland Islands (Malvinas)', + 'FRO' => 'Faroe Islands', + 'FJI' => 'Fiji', + 'FIN' => 'Finland', + 'FRA' => 'France', + 'GUF' => 'French Guiana', + 'PYF' => 'French Polynesia', + 'ATF' => 'French Southern Territories', + 'GAB' => 'Gabon', + 'GMB' => 'Gambia', + 'GEO' => 'Georgia', + 'DEU' => 'Germany', + 'GHA' => 'Ghana', + 'GIB' => 'Gibraltar', + 'GRC' => 'Greece', + 'GRL' => 'Greenland', + 'GRD' => 'Grenada', + 'GLP' => 'Guadeloupe', + 'GUM' => 'Guam', + 'GTM' => 'Guatemala', + 'GGY' => 'Guernsey', + 'GIN' => 'Guinea', + 'GNB' => 'Guinea-Bissau', + 'GUY' => 'Guyana', + 'HTI' => 'Haiti', + 'HMD' => 'Heard Island and McDonald Islands', + 'VAT' => 'Holy See', + 'HND' => 'Honduras', + 'HKG' => 'Hong Kong', + 'HUN' => 'Hungary', + 'ISL' => 'Iceland', + 'IND' => 'India', + 'IDN' => 'Indonesia', + 'IRN' => 'Iran, Islamic Republic of', + 'IRQ' => 'Iraq', + 'IRL' => 'Ireland', + 'IMN' => 'Isle of Man', + 'ISR' => 'Israel', + 'ITA' => 'Italy', + 'JAM' => 'Jamaica', + 'JPN' => 'Japan', + 'JEY' => 'Jersey', + 'JOR' => 'Jordan', + 'KAZ' => 'Kazakhstan', + 'KEN' => 'Kenya', + 'KIR' => 'Kiribati', + 'PRK' => 'Korea, Democratic People\'s Republic of', + 'KOR' => 'Korea, Republic of', + 'KWT' => 'Kuwait', + 'KGZ' => 'Kyrgyzstan', + 'LAO' => 'Lao People\'s Democratic Republic', + 'LVA' => 'Latvia', + 'LBN' => 'Lebanon', + 'LSO' => 'Lesotho', + 'LBR' => 'Liberia', + 'LBY' => 'Libya', + 'LIE' => 'Liechtenstein', + 'LTU' => 'Lithuania', + 'LUX' => 'Luxembourg', + 'MAC' => 'Macao', + 'MDG' => 'Madagascar', + 'MWI' => 'Malawi', + 'MYS' => 'Malaysia', + 'MDV' => 'Maldives', + 'MLI' => 'Mali', + 'MLT' => 'Malta', + 'MHL' => 'Marshall Islands', + 'MTQ' => 'Martinique', + 'MRT' => 'Mauritania', + 'MUS' => 'Mauritius', + 'MYT' => 'Mayotte', + 'MEX' => 'Mexico', + 'FSM' => 'Micronesia, Federated States of', + 'MDA' => 'Moldova, Republic of', + 'MCO' => 'Monaco', + 'MNG' => 'Mongolia', + 'MNE' => 'Montenegro', + 'MSR' => 'Montserrat', + 'MAR' => 'Morocco', + 'MOZ' => 'Mozambique', + 'MMR' => 'Myanmar', + 'NAM' => 'Namibia', + 'NRU' => 'Nauru', + 'NPL' => 'Nepal', + 'NLD' => 'Netherlands, Kingdom of the', + 'NCL' => 'New Caledonia', + 'NZL' => 'New Zealand', + 'NIC' => 'Nicaragua', + 'NER' => 'Niger', + 'NGA' => 'Nigeria', + 'NIU' => 'Niue', + 'NFK' => 'Norfolk Island', + 'MKD' => 'North Macedonia', + 'MNP' => 'Northern Mariana Islands', + 'NOR' => 'Norway', + 'OMN' => 'Oman', + 'PAK' => 'Pakistan', + 'PLW' => 'Palau', + 'PSE' => 'Palestine, State of', + 'PAN' => 'Panama', + 'PNG' => 'Papua New Guinea', + 'PRY' => 'Paraguay', + 'PER' => 'Peru', + 'PHL' => 'Philippines', + 'PCN' => 'Pitcairn', + 'POL' => 'Poland', + 'PRT' => 'Portugal', + 'PRI' => 'Puerto Rico', + 'QAT' => 'Qatar', + 'REU' => 'Réunion', + 'ROU' => 'Romania', + 'RUS' => 'Russian Federation', + 'RWA' => 'Rwanda', + 'BLM' => 'Saint Barthélemy', + 'SHN' => 'Saint Helena, Ascension and Tristan da Cunha', + 'KNA' => 'Saint Kitts and Nevis', + 'LCA' => 'Saint Lucia', + 'MAF' => 'Saint Martin (French part)', + 'SPM' => 'Saint Pierre and Miquelon', + 'VCT' => 'Saint Vincent and the Grenadines', + 'WSM' => 'Samoa', + 'SMR' => 'San Marino', + 'STP' => 'Sao Tome and Principe', + 'SAU' => 'Saudi Arabia', + 'SEN' => 'Senegal', + 'SRB' => 'Serbia', + 'SYC' => 'Seychelles', + 'SLE' => 'Sierra Leone', + 'SGP' => 'Singapore', + 'SXM' => 'Sint Maarten (Dutch part)', + 'SVK' => 'Slovakia', + 'SVN' => 'Slovenia', + 'SLB' => 'Solomon Islands', + 'SOM' => 'Somalia', + 'ZAF' => 'South Africa', + 'SGS' => 'South Georgia and the South Sandwich Islands', + 'SSD' => 'South Sudan', + 'ESP' => 'Spain', + 'LKA' => 'Sri Lanka', + 'SDN' => 'Sudan', + 'SUR' => 'Suriname', + 'SJM' => 'Svalbard and Jan Mayen', + 'SWE' => 'Sweden', + 'CHE' => 'Switzerland', + 'SYR' => 'Syrian Arab Republic', + 'TWN' => 'Taiwan, Province of China', + 'TJK' => 'Tajikistan', + 'TZA' => 'Tanzania, United Republic of', + 'THA' => 'Thailand', + 'TLS' => 'Timor-Leste', + 'TGO' => 'Togo', + 'TKL' => 'Tokelau', + 'TON' => 'Tonga', + 'TTO' => 'Trinidad and Tobago', + 'TUN' => 'Tunisia', + 'TUR' => 'Türkiye', + 'TKM' => 'Turkmenistan', + 'TCA' => 'Turks and Caicos Islands', + 'TUV' => 'Tuvalu', + 'UGA' => 'Uganda', + 'UKR' => 'Ukraine', + 'ARE' => 'United Arab Emirates', + 'GBR' => 'United Kingdom of Great Britain and Northern Ireland', + 'USA' => 'United States of America', + 'UMI' => 'United States Minor Outlying Islands', + 'URY' => 'Uruguay', + 'UZB' => 'Uzbekistan', + 'VUT' => 'Vanuatu', + 'VEN' => 'Venezuela, Bolivarian Republic of', + 'VNM' => 'Viet Nam', + 'VGB' => 'Virgin Islands (British)', + 'VIR' => 'Virgin Islands (U.S.)', + 'WLF' => 'Wallis and Futuna', + 'ESH' => 'Western Sahara', + 'YEM' => 'Yemen', + 'ZMB' => 'Zambia', + 'ZWE' => 'Zimbabwe' +]; diff --git a/app/Libraries/Lookups.php b/app/Libraries/Lookups.php new file mode 100644 index 0000000..903cd08 --- /dev/null +++ b/app/Libraries/Lookups.php @@ -0,0 +1,649 @@ + 'Primary', + '1' => 'Secondary' + ]; + + // VSetID 2: Enable/Disable + const ENABLE_DISABLE = [ + '0' => 'Disabled', + '1' => 'Enabled' + ]; + + // VSetID 3: Gender + const GENDER = [ + '1' => 'Female', + '2' => 'Male', + '3' => 'Unknown' + ]; + + // VSetID 4: Marital Status + const MARITAL_STATUS = [ + 'A' => 'Separated', + 'D' => 'Divorced', + 'M' => 'Married', + 'S' => 'Single', + 'W' => 'Widowed', + 'B' => 'Unmarried', + 'U' => 'Unknown', + 'O' => 'Other' + ]; + + // VSetID 5: Death Indicator + const DEATH_INDICATOR = [ + 'Y' => 'Death', + 'N' => 'Life' + ]; + + // VSetID 6: Identifier Type + const IDENTIFIER_TYPE = [ + 'KTP' => 'Kartu Tanda Penduduk', + 'PASS' => 'Passport', + 'SSN' => 'Social Security Number', + 'SIM' => 'Surat Izin Mengemudi', + 'KTAS' => 'Kartu Izin Tinggal Terbatas' + ]; + + // VSetID 7: Operation (CRUD) + const OPERATION = [ + 'Create' => 'Create record', + 'Read' => 'Read record/field', + 'Update' => 'Update record/field', + 'Delete' => 'Delete record/field' + ]; + + // VSetID 8: DID Type + const DID_TYPE = [ + 'WDID' => 'Windows Device ID', + 'AAID' => 'Android AAID', + 'IDFA' => 'iOS IDFA' + ]; + + // VSetID 9: Requested Entity + const REQUESTED_ENTITY = [ + 'PAT' => 'Patient', + 'ISN' => 'Insurance', + 'ACC' => 'Account', + 'DOC' => 'Doctor' + ]; + + // VSetID 10: Order Priority + const ORDER_PRIORITY = [ + 'S' => 'Stat', + 'A' => 'ASAP', + 'R' => 'Routine', + 'P' => 'Preop', + 'C' => 'Callback', + 'T' => 'Timing critical', + 'PRN' => 'As needed' + ]; + + // VSetID 11: Order Status + const ORDER_STATUS = [ + 'A' => 'Some, not all results available', + 'CA' => 'Order is cancelled', + 'CM' => 'Order is completed', + 'DC' => 'Order was discontinued', + 'ER' => 'Error, order not found', + 'HD' => 'Order on hold', + 'IP' => 'In process, unspecified', + 'RP' => 'Order has been replaced', + 'SC' => 'In process, scheduled', + 'CL' => 'Closed', + 'AC' => 'Archived', + 'DL' => 'Deleted' + ]; + + // VSetID 12: Location Type + const LOCATION_TYPE = [ + 'FCLT' => 'Facility', + 'BLDG' => 'Building', + 'FLOR' => 'Floor', + 'POC' => 'Point of Care', + 'ROOM' => 'Room', + 'BED' => 'Bed', + 'MOBL' => 'Mobile', + 'REMT' => 'Remote' + ]; + + // VSetID 13: Additive + const ADDITIVE = [ + 'Hep' => 'Heparin ammonium', + 'Apro' => 'Aprotinin', + 'HepCa' => 'Heparin calcium', + 'H3BO3' => 'Boric acid', + 'CaOxa' => 'Calcium oxalate', + 'EDTA' => 'EDTA', + 'Ede' => 'Edetate', + 'HCl' => 'Hydrochloric acid', + 'Hrdn' => 'Hirudin', + 'EdeK' => 'Edetate dipotassium', + 'EdeTri' => 'Tripotassium edetate', + 'LiHep' => 'Heparin lithium', + 'EdeNa' => 'Edetate disodium', + 'NaCtrt' => 'Sodium citrate', + 'NaHep' => 'Heparin sodium', + 'NaF' => 'Sodium fluoride', + 'Borax' => 'Sodium tetraborate', + 'Mntl' => 'Mannitol', + 'NaFrm' => 'Sodium formate' + ]; + + // VSetID 14: Container Class + const CONTAINER_CLASS = [ + 'Pri' => 'Primary', + 'Sec' => 'Secondary', + 'Ter' => 'Tertiary' + ]; + + // VSetID 15: Specimen Type + const SPECIMEN_TYPE = [ + 'BLD' => 'Whole blood', + 'BLDA' => 'Blood arterial', + 'BLDCO' => 'Cord blood', + 'FBLOOD' => 'Blood, Fetal', + 'CSF' => 'Cerebral spinal fluid', + 'WB' => 'Blood, Whole', + 'BBL' => 'Blood bag', + 'SER' => 'Serum', + 'PLAS' => 'Plasma', + 'PLB' => 'Plasma bag', + 'MUCOS' => 'Mucosa', + 'MUCUS' => 'Mucus', + 'UR' => 'Urine', + 'RANDU' => 'Urine, Random', + 'URINM' => 'Urine, Midstream' + ]; + + // VSetID 16: Unit + const UNIT = [ + 'L' => 'Liter', + 'mL' => 'Mili Liter', + 'Pcs' => 'Pieces' + ]; + + // VSetID 17: Generate By + const GENERATE_BY = [ + 'order' => 'Generate by order', + 'user' => 'Generate by user' + ]; + + // VSetID 18: Specimen Activity + const SPECIMEN_ACTIVITY = [ + 'SColl' => 'Collection', + 'STran' => 'Transport', + 'SRec' => 'Reception', + 'SPrep' => 'Preparation', + 'SAlqt' => 'Aliquot', + 'SDisp' => 'Dispatching', + 'SDest' => 'Destruction' + ]; + + // VSetID 19: Activity Result + const ACTIVITY_RESULT = [ + '0' => 'Failed', + '1' => 'Success with note', + '2' => 'Success' + ]; + + // VSetID 20: Specimen Status + const SPECIMEN_STATUS = [ + 'STC' => 'To be collected', + 'SCFld' => 'Collection failed', + 'SCtd' => 'Collected', + 'STran' => 'In-transport', + 'STFld' => 'Transport failed', + 'SArrv' => 'Arrived', + 'SRejc' => 'Rejected', + 'SRcvd' => 'Received', + 'SPAna' => 'Pre-analytical', + 'SPAF' => 'Pre-analytical failed', + 'STA' => 'To be analyze', + 'SAFld' => 'Analytical failed', + 'SAna' => 'Analytical', + 'STS' => 'To be stored', + 'SSFld' => 'Store failed', + 'SStrd' => 'Stored', + 'SExp' => 'Expired', + 'STD' => 'To be destroyed', + 'SDFld' => 'Failed to destroy', + 'SDstd' => 'Destroyed' + ]; + + // VSetID 21: Specimen Condition + const SPECIMEN_CONDITION = [ + 'HEM' => 'Hemolyzed', + 'ITC' => 'Icteric', + 'LIP' => 'Lipemic', + 'CFU' => 'Centrifuged', + 'ROOM' => 'Room temperature', + 'COOL' => 'Cool', + 'FROZ' => 'Frozen', + 'CLOT' => 'Clotted', + 'AUT' => 'Autolyzed', + 'CON' => 'Contaminated', + 'LIVE' => 'Live' + ]; + + // VSetID 22: Specimen Role + const SPECIMEN_ROLE = [ + 'P' => 'Patient', + 'B' => 'Blind Sample', + 'Q' => 'Control specimen', + 'E' => 'Electronic QC', + 'F' => 'Filler Organization Proficiency', + 'O' => 'Operator Proficiency', + 'C' => 'Calibrator', + 'R' => 'Replicate', + 'V' => 'Verifying Calibrator' + ]; + + // VSetID 23: Collection Method + const COLLECTION_METHOD = [ + 'pcntr' => 'Puncture', + 'fprk' => 'Finger-prick sampling', + 'ucct' => 'Urine specimen collection, clean catch', + 'utcl' => 'Timed urine collection', + 'ucth' => 'Urine specimen collection, catheterized', + 'scgh' => 'Collection of coughed sputum', + 'bpsy' => 'Biopsy', + 'aspn' => 'Aspiration', + 'excs' => 'Excision', + 'scrp' => 'Scraping' + ]; + + // VSetID 24: Body Site + const BODY_SITE = [ + 'LA' => 'Left Arm', + 'RA' => 'Right Arm', + 'LF' => 'Left Foot', + 'RF' => 'Right Foot' + ]; + + // VSetID 25: Container Size + const CONTAINER_SIZE = [ + '5ml' => '5 mL', + '7ml' => '7 mL', + '10ml' => '10 mL', + '1l' => '1 L' + ]; + + // VSetID 26: Fasting Status + const FASTING_STATUS = [ + 'F' => 'Fasting', + 'NF' => 'Not Fasting', + 'NG' => 'Not Given' + ]; + + // VSetID 27: Test Type + const TEST_TYPE = [ + 'TEST' => 'Test', + 'PARAM' => 'Parameter', + 'CALC' => 'Calculated Test', + 'GROUP' => 'Group Test', + 'TITLE' => 'Title' + ]; + + // VSetID 28: Result Unit + const RESULT_UNIT = [ + 'g/dL' => 'g/dL', + 'g/L' => 'g/L', + 'mg/dL' => 'mg/dL', + 'mg/L' => 'mg/L', + 'L/L' => 'L/L', + 'x106/mL' => 'x106/mL', + 'x1012/L' => 'x1012/L', + 'fL' => 'fL', + 'pg' => 'pg', + 'x109/L' => 'x109/L' + ]; + + // VSetID 29: Formula Language + const FORMULA_LANGUAGE = [ + 'Phyton' => 'Phyton', + 'CQL' => 'Clinical Quality Language', + 'FHIRP' => 'FHIRPath', + 'SQL' => 'SQL' + ]; + + // VSetID 30: Race (Ethnicity) + const RACE = [ + 'JAWA' => 'Jawa', + 'SUNDA' => 'Sunda', + 'BATAK' => 'Batak', + 'SULOR' => 'Suku asal Sulawesi lainnya', + 'MDRA' => 'Madura', + 'BTWI' => 'Betawi', + 'MNG' => 'Minangkabau', + 'BUGIS' => 'Bugis', + 'MLYU' => 'Melayu', + 'SUMSL' => 'Suku asal Sumatera Selatan', + 'BTNOR' => 'Suku asal Banten', + 'NTTOR' => 'Suku asal Nusa Tenggara Timur', + 'BNJAR' => 'Banjar', + 'ACEH' => 'Aceh', + 'BALI' => 'Bali', + 'SASAK' => 'Sasak', + 'DAYAK' => 'Dayak', + 'TNGHA' => 'Tionghoa', + 'PPAOR' => 'Suku asal Papua', + 'MKSSR' => 'Makassar', + 'SUMOR' => 'Suku asal Sumatera lainnya', + 'MLKOR' => 'Suku asal Maluku', + 'KLMOR' => 'Suku asal Kalimantan lainnya', + 'CRBON' => 'Cirebon', + 'JBIOR' => 'Suku asal Jambi', + 'LPGOR' => 'Suku Lampung', + 'NTBOR' => 'Suku asal Nusa Tenggara Barat lainnya', + 'GRTLO' => 'Gorontalo', + 'MNHSA' => 'Minahasa', + 'NIAS' => 'Nias', + 'FORGN' => 'Asing/luar negeri' + ]; + + // VSetID 31: Religion + const RELIGION = [ + 'ISLAM' => 'Islam', + 'KRSTN' => 'Kristen', + 'KTLIK' => 'Katolik', + 'HINDU' => 'Hindu', + 'BUDHA' => 'Budha', + 'KHCU' => 'Khong Hu Cu', + 'OTHER' => 'Lainnya' + ]; + + // VSetID 32: Ethnic + const ETHNIC = [ + 'PPMLN' => 'Papua Melanezoid', + 'NGRID' => 'Negroid', + 'WDOID' => 'Weddoid', + 'MMPM' => 'Melayu Mongoloid_Proto Melayu', + 'MMDM' => 'Melayu Mongoloid_Deutro Melayu', + 'TNGHA' => 'Tionghoa', + 'INDIA' => 'India', + 'ARAB' => 'Arab' + ]; + + // VSetID 33: Country (ISO 2-letter codes - ISO 3166-1 alpha-2) + const COUNTRY = null; // Loaded from external file + + /** + * Get COUNTRY data from external file (lazy load) + */ + private static function loadCountryData(): array { + $file = APPPATH . 'Libraries/Data/Countries.php'; + if (is_file($file)) { + return require $file; + } + return []; + } + + /** + * Get formatted country list + */ + public static function getCountry(): array { + return self::format(self::loadCountryData()); + } + + // VSetID 34: Container Cap Color + const CONTAINER_CAP_COLOR = [ + 'PRPL' => 'Purple', + 'RED' => 'Red', + 'YLLW' => 'Yellow', + 'GRN' => 'Green', + 'PINK' => 'Pink', + 'LBLU' => 'Light Blue', + 'RBLU' => 'Royal Blue', + 'GRAY' => 'Gray' + ]; + + // VSetID 35: Test Activity + const TEST_ACTIVITY = [ + 'ORD' => 'Order', + 'ANA' => 'Analyse', + 'VER' => 'Result Verification/Technical Validation', + 'REV' => 'Clinical Review/Clinical Validation', + 'REP' => 'Reporting' + ]; + + // VSetID 36: ADT Event + const ADT_EVENT = [ + 'A01' => 'Admit', + 'A02' => 'Transfer', + 'A03' => 'Discharge', + 'A04' => 'Register', + 'A08' => 'Update patient information', + 'A11' => 'Cancel admit', + 'A12' => 'Cancel transfer', + 'A13' => 'Cancel discharge', + 'A23' => 'Delete patient record', + 'A24' => 'Link patient information', + 'A37' => 'Unlink patient information', + 'A54' => 'Change attending doctor', + 'A61' => 'Change consulting doctor' + ]; + + // VSetID 37: Site Type + const SITE_TYPE = [ + 'GH' => 'Government Hospital', + 'PH' => 'Private Hospital', + 'GHL' => 'Government Hospital Lab', + 'PHL' => 'Private Hospital Lab', + 'GL' => 'Government Lab', + 'PL' => 'Private Lab' + ]; + + // VSetID 38: Site Class + const SITE_CLASS = [ + 'A' => 'Kelas A', + 'B' => 'Kelas B', + 'C' => 'Kelas C', + 'D' => 'Kelas D', + 'Utm' => 'Utama', + 'Ptm' => 'Pratama' + ]; + + // VSetID 39: Entity Type + const ENTITY_TYPE = [ + 'HIS' => 'HIS', + 'SITE' => 'Site', + 'WST' => 'Workstation', + 'INST' => 'Equipment/Instrument' + ]; + + // VSetID 40: Area Class + const AREA_CLASS = [ + 'PROP' => 'Propinsi', + 'KAB' => 'Kabupaten', + 'KOTA' => 'Kota' + ]; + + // VSetID 41: Math Sign + const MATH_SIGN = [ + '=' => 'Equal', + '<' => 'Less than', + '>' => 'Greater than', + '<=' => 'Less than or equal to', + '>=' => 'Greater than or equal to' + ]; + + // VSetID 42: VCategory + const V_CATEGORY = [ + '0' => 'System', + '1' => 'User-defined' + ]; + + // VSetID 43: Result Type + const RESULT_TYPE = [ + 'NMRIC' => 'Numeric', + 'RANGE' => 'Range', + 'TEXT' => 'Text', + 'VSET' => 'Value set' + ]; + + // VSetID 44: Reference Type + const REFERENCE_TYPE = [ + 'NMRC' => 'Numeric', + 'TEXT' => 'Text' + ]; + + // VSetID 45: Range Type + const RANGE_TYPE = [ + 'REF' => 'Reference Range', + 'CRTC' => 'Critical Range', + 'VAL' => 'Validation Range', + 'RERUN' => 'Rerun Range' + ]; + + // VSetID 46: Numeric Reference Type + const NUMERIC_REF_TYPE = [ + 'RANGE' => 'Range', + 'THOLD' => 'Threshold' + ]; + + // VSetID 47: Text Reference Type + const TEXT_REF_TYPE = [ + 'VSET' => 'Value Set', + 'TEXT' => 'Text' + ]; + + // Convenience constants (aliases for common use cases) + const PRIORITY = self::ORDER_PRIORITY; + const TEST_STATUS = [ + 'PENDING' => 'Waiting for Results', + 'IN_PROCESS' => 'Analyzing', + 'VERIFIED' => 'Verified & Signed', + 'REJECTED' => 'Sample Rejected' + ]; + const REQUEST_STATUS = self::SPECIMEN_STATUS; + const RESULT_STATUS = [ + 'PRELIMINARY' => 'Preliminary', + 'FINAL' => 'Final', + 'CORRECTED' => 'Corrected', + 'CANCELLED' => 'Cancelled' + ]; + + /** + * Get all lookups formatted for frontend + * @return array + */ + public static function getAll(): array { + return [ + 'ws_type' => self::format(self::WS_TYPE), + 'enable_disable' => self::format(self::ENABLE_DISABLE), + 'gender' => self::format(self::GENDER), + 'marital_status' => self::format(self::MARITAL_STATUS), + 'death_indicator' => self::format(self::DEATH_INDICATOR), + 'identifier_type' => self::format(self::IDENTIFIER_TYPE), + 'operation' => self::format(self::OPERATION), + 'did_type' => self::format(self::DID_TYPE), + 'requested_entity' => self::format(self::REQUESTED_ENTITY), + 'order_priority' => self::format(self::ORDER_PRIORITY), + 'order_status' => self::format(self::ORDER_STATUS), + 'location_type' => self::format(self::LOCATION_TYPE), + 'additive' => self::format(self::ADDITIVE), + 'container_class' => self::format(self::CONTAINER_CLASS), + 'specimen_type' => self::format(self::SPECIMEN_TYPE), + 'unit' => self::format(self::UNIT), + 'generate_by' => self::format(self::GENERATE_BY), + 'specimen_activity' => self::format(self::SPECIMEN_ACTIVITY), + 'activity_result' => self::format(self::ACTIVITY_RESULT), + 'specimen_status' => self::format(self::SPECIMEN_STATUS), + 'specimen_condition' => self::format(self::SPECIMEN_CONDITION), + 'specimen_role' => self::format(self::SPECIMEN_ROLE), + 'collection_method' => self::format(self::COLLECTION_METHOD), + 'body_site' => self::format(self::BODY_SITE), + 'container_size' => self::format(self::CONTAINER_SIZE), + 'fasting_status' => self::format(self::FASTING_STATUS), + 'test_type' => self::format(self::TEST_TYPE), + 'result_unit' => self::format(self::RESULT_UNIT), + 'formula_language' => self::format(self::FORMULA_LANGUAGE), + 'race' => self::format(self::RACE), + 'religion' => self::format(self::RELIGION), + 'ethnic' => self::format(self::ETHNIC), + 'country' => self::getCountry(), + 'container_cap_color' => self::format(self::CONTAINER_CAP_COLOR), + 'test_activity' => self::format(self::TEST_ACTIVITY), + 'adt_event' => self::format(self::ADT_EVENT), + 'site_type' => self::format(self::SITE_TYPE), + 'site_class' => self::format(self::SITE_CLASS), + 'entity_type' => self::format(self::ENTITY_TYPE), + 'area_class' => self::format(self::AREA_CLASS), + 'math_sign' => self::format(self::MATH_SIGN), + 'v_category' => self::format(self::V_CATEGORY), + 'result_type' => self::format(self::RESULT_TYPE), + 'reference_type' => self::format(self::REFERENCE_TYPE), + 'range_type' => self::format(self::RANGE_TYPE), + 'numeric_ref_type' => self::format(self::NUMERIC_REF_TYPE), + 'text_ref_type' => self::format(self::TEXT_REF_TYPE) + ]; + } + + + /** + * Format associative array as [{value: 'KEY', label: 'Label'}, ...] + */ + private static function format(array $array): array { + $result = []; + foreach ($array as $key => $label) { + $result[] = ['value' => (string) $key, 'label' => (string) $label]; + } + return $result; + } + + /** + * Get single lookup by constant name (case-insensitive) + * @param string $name Constant name (e.g., 'gender', 'PRIORITY') + * @return array|null + */ + public static function get(string $name): ?array { + $const = strtoupper($name); + // Special case for COUNTRY (loaded from external file) + if ($const === 'COUNTRY') { + return self::getCountry(); + } + if (defined("self::$const")) { + return self::format(constant("self::$const")); + } + return null; + } + + /** + * Get raw constant array (not formatted) + * @param string $name + * @return array|null + */ + public static function getRaw(string $name): ?array { + $const = strtoupper($name); + // Special case for COUNTRY (loaded from external file) + if ($const === 'COUNTRY') { + return self::loadCountryData(); + } + if (defined("self::$const")) { + return constant("self::$const"); + } + return null; + } + + /** + * Get label by key from a lookup + * @param string $lookup Lookup name + * @param string $key Key to find + * @return string|null + */ + public static function getLabel(string $lookup, string $key): ?string { + $raw = self::getRaw($lookup); + return $raw[$key] ?? null; + } +} diff --git a/app/Models/ValueSet/ValueSetModel.php b/app/Models/ValueSet/ValueSetModel.php index 88ed263..cc470aa 100644 --- a/app/Models/ValueSet/ValueSetModel.php +++ b/app/Models/ValueSet/ValueSetModel.php @@ -15,7 +15,7 @@ class ValueSetModel extends BaseModel { protected $useSoftDeletes = true; protected $deletedField = 'EndDate'; - public function getValueSets($param = null, $page = null, $limit = 50, $VSetID = null) { + public function getValueSets($param = null, $VSetID = null) { $this->select("valueset.*, valuesetdef.VSName as VCategoryName") ->join('valuesetdef', 'valueset.VSetID = valuesetdef.VSetID', 'LEFT'); @@ -26,16 +26,9 @@ class ValueSetModel extends BaseModel { if ($param !== null) { $this->groupStart() ->like('valueset.VValue', $param, 'both') - ->orLike('valueset.VDesc', $param, 'both') + ->orLike('valueset.VDesc', $param, 'both') ->orLike('valuesetdef.VSName', $param, 'both') ->groupEnd(); - } - - if ($page !== null) { - return [ - 'data' => $this->paginate($limit, 'default', $page), - 'pager' => $this->pager - ]; } return $this->findAll();