'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; } }