# code_chunks_vec_auxiliary

value00: AGENTS.md
value01:
## Coding Standards

### Language & Formatting
- PHP 8.1+ is the baseline; enable `declare(strict_types=1)` at the top of new files when practical.
- Follow PSR-12 for spacing, line length (~120), and brace placement; prefer 4 spaces and avoid tabs.
- Use short arrays `[]`, and wrap multiline arguments/arrays with one-per-line items.
- Favor expression statements that return early (guard clauses) and keep nested logic shallow.
- Keep methods under ~40 lines when possible; extract private helpers for repeated flows.


value00: AGENTS.md
value01:
### Imports & Structure
- Namespace declarations at the very top followed by grouped `use` statements.
- Import order: Core framework (`CodeIgniter`), then `App\`, then third-party packages (Firebase, Faker, etc.). Keep each group alphabetical.
- No inline `use` statements inside methods.
- Keep `use` statements de-duplicated; rely on IDE or `phpcbf` to reorder.


value00: AGENTS.md
value01:
### Documentation & API Sync
- Whenever a controller or route changes, update `public/paths/<resource>.yaml` and matching `public/components/schemas`. Add tags or schema refs in `public/api-docs.yaml`.
- After editing OpenAPI files, regenerate the bundled docs with `node public/bundle-api-docs.js`. Check `public/api-docs.bundled.yaml` into version control.
- Keep the controller-to-YAML mapping table updated to reflect new resources.


value00: AGENTS.md
value01:
# AGENTS.md - Code Guidelines for CLQMS

> **CLQMS (Clinical Laboratory Quality Management System)** – headless REST API backend built on CodeIgniter 4 with a focus on laboratory workflows, JWT authentication, and synchronized OpenAPI documentation.

---

## Repository Snapshot
- `app/` holds controllers, models, filters, and traits wired through PSR-4 `App\` namespace.
- `tests/` relies on CodeIgniter's testing helpers plus Faker for deterministic fixtures.
- Shared response helpers and ValueSet lookups live under `app/Libraries` and `app/Traits` and should be reused before introducing new helpers.
- Environment values, secrets, and database credentials live in `.env` but are never committed; treat the file as a reference for defaults.

---


value00: AGENTS.md
value01:
### Routing Conventions
- Keep route definitions grouped inside `$routes->group('api/<resource>')` blocks in `app/Config/Routes.php`.
- Prefer nested controllers (e.g., `Patient\PatientController`) for domain partitioning.
- Use RESTful verbs (GET: index/show, POST: create, PATCH: update, DELETE: delete) to keep behavior predictable.
- Document side effects (snapshots, audit logs) directly in the corresponding OpenAPI `paths` file.

### Environment & Secrets
- Use `.env` as the source of truth for database/jwt settings. Do not commit production credentials.
- Sample values are provided in `.env`; copy to `.env.local` or CI secrets with overrides.
- `JWT_SECRET` must be treated as sensitive and rotated via environment updates only.


value00: AGENTS.md
value01:
### Observability & Logging
- Use `log_message('info', ...)` for happy-path checkpoints and `'error'` for catch-all failures.
- Avoid leaking sensitive values (tokens, secrets) in logs; log IDs or hash digests instead.
- Keep `writable/logs` clean by rotating or pruning stale log files with automation outside the repo.

---


value00: AGENTS.md
value01:
### Workflows & Misc
- Use `php spark migrate`/`migrate:rollback` for schema changes.
- For seeding or test fixtures, prefer factories (Faker) seeded in `tests/Support` when available.
- Document major changes in `issues.md` or dedicated feature docs under `docs/` before merging.

### Security & Filters
- Apply the `auth` filter to every protected route, and keep `ApiKey` or other custom filters consolidated under `app/Filters`.
- Sanitize user inputs via `filter_var`, `esc()` helpers, or validated entities before they hit the database.
- Always use parameterized queries/Model `save()` methods to prevent SQL injection, especially with legacy PascalCase columns.
- Respond 401 for missing tokens, 403 when permissions fail, and log sanitized details for ops debugging.


value00: AGENTS.md
value01:
### Legacy Field Naming & ValueSets
- Databases use PascalCase columns such as `PatientID`, `NameFirst`, `CreatedAt`. Keep migration checks aware of these names.
- ValueSet lookups centralize label translation: `Lookups::get('gender')`, `Lookups::getLabel('gender', '1')`, `Lookups::transformLabels($payload, ['Sex' => 'gender'])`.
- Prefer `App\Libraries\Lookups` or `app/Traits/ValueSetTrait` to avoid ad-hoc mappings.

### Nested Data Handling
- For entities that carry related collections (`PatIdt`, `PatCom`, `PatAtt`), extract nested arrays before filtering and validating.
- Use transactions whenever multi-table inserts/updates occur so orphan rows are avoided.
- Guard against empty/null arrays by normalizing to `[]` before iterating.


value00: AGENTS.md
value01:
### Testing & Coverage
- Place feature tests under `tests/Feature`, unit tests under `tests/Unit`.
- Test class names should follow `ClassNameTest`; methods follow `test<Action><Scenario><Result>` (e.g., `testCreatePatientValidationFail`).
- Use `FeatureTestTrait` and `CIUnitTestCase` for API tests; prefer `withBodyFormat('json')->post()` flows.
- Assert status codes: 200 for GET/PATCH, 201 for POST, 400 for validation, 401 for auth, 404 for missing resources, 500 for server errors.
- Run targeted tests during development, full suite before merging.


value00: AGENTS.md
value01:
## Agent Rules Scan
- No `.cursor/rules/*` or `.cursorrules` directory detected; continue without Cursor-specific constraints.
- No `.github/copilot-instructions.md` present; Copilot behaviors revert to general GitHub defaults.

---


value00: AGENTS.md
value01:
## Final Notes for Agents
- This repo has no UI layer; focus exclusively on REST interactions.
- Always pull `public/api-docs.bundled.yaml` in after running `node public/bundle-api-docs.js` so downstream services see the latest contract.
- When in doubt, align with existing controller traits and response helpers to avoid duplicating logic.


value00: AGENTS.md
value01:
### Response & Error Handling
- All responses follow `{ status, message, data }`. `status` values: `success`, `failed`, or `error`.
- Use `$this->respondCreated()`, `$this->respondNoContent()`, or `$this->respond()` with explicit HTTP codes.
- Wrap JWT/external calls in try/catch. Log unexpected exceptions with `log_message('error', $e->getMessage())` before responding with a sanitized failure.
- For validation failures, return HTTP 400 with detailed message; unauthorized access returns 401. Maintain parity with existing tests.


value00: AGENTS.md
value01:
## Build, Lint & Test
All commands run from the repository root.

```bash
# Run the entire PHPUnit suite
./vendor/bin/phpunit

# Target a single test file (fast verification)
./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php

# Run one test case by method
./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php

# Generate scaffolding (model, controller, migration)
php spark make:model <Name>
php spark make:controller <Name>
php spark make:migration <name>

# Database migrations
php spark migrate
php spark migrate:rollback

# After OpenAPI edits
node public/bundle-api-docs.js
```

Use `php spark test --filter <Class>::<method>` when filtering more than one test file is cumbersome.

---


value00: AGENTS.md
value01:
### Database & Transactions
- Use Query Builder or Model methods; enable `use App\Models\BaseModel` which handles UTC conversions.
- Always call `helper('utc')` when manipulating timestamps.
- Wrap multi-table changes in `$this->db->transStart()` / `$this->db->transComplete()` and check `transStatus()` to abort if false.
- Run `checkDbError()` (existing helper) after saves when manual queries are necessary.

### Service Helpers & Libraries
- Encapsulate complex lookups (ValueSet, encryption) inside `app/Libraries` or Traits.
- Reuse `App\Libraries\Lookups` for consistent label/value translations.
- Keep shared logic (e.g., response formatting, JWT decoding) inside Traits and import them via `use`.


value00: AGENTS.md
value01:
### Naming & Types
- Classes, controllers, libraries, and traits: PascalCase (e.g., `PatientImportController`).
- Methods, services, traits: camelCase (`fetchActivePatients`).
- Properties: camelCase for new code; legacy snake_case may persist but avoid new snake_case unless mirroring legacy columns.
- Constants: UPPER_SNAKE_CASE.
- DTOs/array shapes: Use descriptive names (`$patientInput`, `$validatedPayload`).
- Type hints required for method arguments/returns; use union/nullables (e.g., `?string`) instead of doc-only comments.
- Prefer PHPDoc only when type inference fails (complex union or array shapes) but still keep method summaries concise.


value00: AGENTS.md
value01:
### Controller Structure
- Controllers orchestrate request validation, delegates to services/models, and return `ResponseTrait` responses; avoid direct DB queries here.
- Inject models/services via constructor when they are reused. When instantiating on the fly, reference FQCN (`new \App\Models\...`).
- Map HTTP verbs to semantic methods (`index`, `show`, `create`, `update`, `delete`). Keep action methods under 30 lines by delegating heavy lifting to models or libraries.
- Always respond through `$this->respond()` or `$this->respondCreated()` so JSON structure stays consistent.


value00: app/Common.php
value01:
<?php

/**
 * The goal of this file is to allow developers a location
 * where they can overwrite core procedural functions and
 * replace them with their own. This file is loaded during
 * the bootstrap process and is called during the framework's
 * execution.
 *
 * This can be looked at as a `master helper` file that is
 * loaded early on, and may also contain additional functions
 * that you'd like to use throughout your entire application
 *
 * @see: https://codeigniter.com/user_guide/extending/common.html
 */


value00: app/Config/App.php
value01:
    public string $baseURL = '';

    /**
     * Allowed Hostnames in the Site URL other than the hostname in the baseURL.
     * If you want to accept multiple Hostnames, set this.
     *
     * E.g.,
     * When your site URL ($baseURL) is 'http://example.com/', and your site
     * also accepts 'http://media.example.com/' and 'http://accounts.example.com/':
     *     ['media.example.com', 'accounts.example.com']
     *
     * @var list<string>
     */
    public array $allowedHostnames = [];


value00: app/Config/App.php
value01:
    public string $indexPage = '';

    /**
     * --------------------------------------------------------------------------
     * URI PROTOCOL
     * --------------------------------------------------------------------------
     *
     * This item determines which server global should be used to retrieve the
     * URI string. The default setting of 'REQUEST_URI' works for most servers.
     * If your links do not seem to work, try one of the other delicious flavors:
     *
     *  'REQUEST_URI': Uses $_SERVER['REQUEST_URI']
     * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING']
     *    'PATH_INFO': Uses $_SERVER['PATH_INFO']
     *
     * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
     */
    public string $uriProtocol = 'REQUEST_URI';


value00: app/Config/App.php
value01:
    public array $allowedHostnames = [];

    /**
     * --------------------------------------------------------------------------
     * Index File
     * --------------------------------------------------------------------------
     *
     * Typically, this will be your `index.php` file, unless you've renamed it to
     * something else. If you have configured your web server to remove this file
     * from your site URIs, set this variable to an empty string.
     */
    #public string $indexPage = 'index.php';
    public string $indexPage = '';


value00: app/Config/App.php
value01:
     *
     * You need to set a proxy IP address or IP address with subnets and
     * the HTTP header for the client IP address.
     *
     * Here are some examples:
     *     [
     *         '10.0.1.200'     => 'X-Forwarded-For',
     *         '192.168.5.0/24' => 'X-Real-IP',
     *     ]
     *
     * @var array<string, string>
     */
    public array $proxyIPs = [];


value00: app/Config/App.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Reverse Proxy IPs
     * --------------------------------------------------------------------------
     *
     * If your server is behind a reverse proxy, you must whitelist the proxy
     * IP addresses from which CodeIgniter should trust headers such as
     * X-Forwarded-For or Client-IP in order to properly identify
     * the visitor's IP address.
     *
     * You need to set a proxy IP address or IP address with subnets and
     * the HTTP header for the client IP address.


value00: app/Config/App.php
value01:
     * Content Security Policy
     * --------------------------------------------------------------------------
     *
     * Enables the Response's Content Secure Policy to restrict the sources that
     * can be used for images, scripts, CSS files, audio, video, etc. If enabled,
     * the Response object will populate default values for the policy from the
     * `ContentSecurityPolicy.php` file. Controllers can always add to those
     * restrictions at run time.
     *
     * For a better understanding of CSP, see these documents:
     *
     * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/
     * @see http://www.w3.org/TR/CSP/
     */
    public bool $CSPEnabled = false;
}


value00: app/Config/App.php
value01:
    public string $defaultLocale = 'en';

    /**
     * --------------------------------------------------------------------------
     * Negotiate Locale
     * --------------------------------------------------------------------------
     *
     * If true, the current Request object will automatically determine the
     * language to use based on the value of the Accept-Language header.
     *
     * If false, no automatic detection will be performed.
     */
    public bool $negotiateLocale = false;


value00: app/Config/App.php
value01:
    |
    | As a security measure you are STRONGLY encouraged to restrict URLs to
    | as few characters as possible.
    |
    | By default, only these are allowed: `a-z 0-9~%.:_-`
    |
    | Set an empty string to allow all characters -- but only if you are insane.
    |
    | The configured value is actually a regular expression character group
    | and it will be used as: '/\A[<permittedURIChars>]+\z/iu'
    |
    | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
    |
    */


value00: app/Config/App.php
value01:
    /*
    |--------------------------------------------------------------------------
    | Allowed URL Characters
    |--------------------------------------------------------------------------
    |
    | This lets you specify which characters are permitted within your URLs.
    | When someone tries to submit a URL with disallowed characters they will
    | get a warning message.
    |
    | As a security measure you are STRONGLY encouraged to restrict URLs to
    | as few characters as possible.


value00: app/Config/App.php
value01:
    public string $permittedURIChars = 'a-z 0-9~%.:_\-';

    /**
     * --------------------------------------------------------------------------
     * Default Locale
     * --------------------------------------------------------------------------
     *
     * The Locale roughly represents the language and location that your visitor
     * is viewing the site from. It affects the language strings and other
     * strings (like currency markers, numbers, etc), that your program
     * should run under for this request.
     */
    public string $defaultLocale = 'en';


value00: app/Config/App.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Content Security Policy
     * --------------------------------------------------------------------------


value00: app/Config/App.php
value01:
    public array $supportedLocales = ['en'];

    /**
     * --------------------------------------------------------------------------
     * Application Timezone
     * --------------------------------------------------------------------------
     *
     * The default timezone that will be used in your application to display
     * dates with the date helper, and can be retrieved through app_timezone()
     *
     * @see https://www.php.net/manual/en/timezones.php for list of timezones
     *      supported by PHP.
     */
    public string $appTimezone = 'UTC';


value00: app/Config/App.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Base Site URL
     * --------------------------------------------------------------------------
     *
     * URL to your CodeIgniter root. Typically, this will be your base URL,
     * WITH a trailing slash:
     *
     * E.g., http://example.com/
     */
    public string $baseURL = '';


value00: app/Config/App.php
value01:
    public string $appTimezone = 'UTC';

    /**
     * --------------------------------------------------------------------------
     * Default Character Set
     * --------------------------------------------------------------------------
     *
     * This determines which character set is used by default in various methods
     * that require a character set to be provided.
     *
     * @see http://php.net/htmlspecialchars for a list of supported charsets.
     */
    public string $charset = 'UTF-8';


value00: app/Config/App.php
value01:
    public bool $negotiateLocale = false;

    /**
     * --------------------------------------------------------------------------
     * Supported Locales
     * --------------------------------------------------------------------------
     *
     * If $negotiateLocale is true, this array lists the locales supported
     * by the application in descending order of priority. If no match is
     * found, the first locale will be used.
     *
     * IncomingRequest::setLocale() also uses this list.
     *
     * @var list<string>
     */
    public array $supportedLocales = ['en'];


value00: app/Config/App.php
value01:
    public string $charset = 'UTF-8';

    /**
     * --------------------------------------------------------------------------
     * Force Global Secure Requests
     * --------------------------------------------------------------------------
     *
     * If true, this will force every request made to this application to be
     * made via a secure connection (HTTPS). If the incoming request is not
     * secure, the user will be redirected to a secure version of the page
     * and the HTTP Strict Transport Security (HSTS) header will be set.
     */
    public bool $forceGlobalSecureRequests = false;


value00: app/Config/Autoload.php
value01:
    public $classmap = [];

    /**
     * -------------------------------------------------------------------
     * Files
     * -------------------------------------------------------------------
     * The files array provides a list of paths to __non-class__ files
     * that will be autoloaded. This can be useful for bootstrap operations
     * or for loading functions.
     *
     * Prototype:
     *   $files = [
     *       '/path/to/my/file.php',
     *   ];
     *
     * @var list<string>
     */
    public $files = [];


value00: app/Config/Autoload.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\AutoloadConfig;

/**
 * -------------------------------------------------------------------
 * AUTOLOADER CONFIGURATION
 * -------------------------------------------------------------------
 *
 * This file defines the namespaces and class maps so the Autoloader
 * can find the files as needed.
 *
 * NOTE: If you use an identical key in $psr4 or $classmap, then
 *       the values in this file will overwrite the framework's values.
 *
 * NOTE: This class is required prior to Autoloader instantiation,
 *       and does not extend BaseConfig.
 */
class Autoload extends AutoloadConfig
{


value00: app/Config/Autoload.php
value01:
     * their location on the file system. These are used by the autoloader
     * to locate files the first time they have been instantiated.
     *
     * The 'Config' (APPPATH . 'Config') and 'CodeIgniter' (SYSTEMPATH) are
     * already mapped for you.
     *
     * You may change the name of the 'App' namespace if you wish,
     * but this should be done prior to creating any namespaced classes,
     * else you will need to modify all of those classes for this to work.
     *
     * @var array<string, list<string>|string>
     */


value00: app/Config/Autoload.php
value01:
    public $psr4 = [
        APP_NAMESPACE => APPPATH,
    ];

    /**
     * -------------------------------------------------------------------
     * Class Map
     * -------------------------------------------------------------------
     * The class map provides a map of class names and their exact
     * location on the drive. Classes loaded in this manner will have
     * slightly faster performance because they will not have to be
     * searched for within one or more directories as they would if they
     * were being autoloaded through a namespace.
     *
     * Prototype:
     *   $classmap = [
     *       'MyClass'   => '/path/to/class/file.php'
     *   ];
     *
     * @var array<string, string>
     */
    public $classmap = [];


value00: app/Config/Autoload.php
value01:
    /**
     * -------------------------------------------------------------------
     * Namespaces
     * -------------------------------------------------------------------
     * This maps the locations of any namespaces in your application to
     * their location on the file system. These are used by the autoloader
     * to locate files the first time they have been instantiated.


value00: app/Config/Autoload.php
value01:
    public $files = [];

    /**
     * -------------------------------------------------------------------
     * Helpers
     * -------------------------------------------------------------------
     * Prototype:
     *   $helpers = [
     *       'form',
     *   ];
     *
     * @var list<string>
     */
    public $helpers = [];
}


value00: app/Config/Cache.php
value01:
use CodeIgniter\Cache\Handlers\RedisHandler;
use CodeIgniter\Cache\Handlers\WincacheHandler;
use CodeIgniter\Config\BaseConfig;

class Cache extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Primary Handler
     * --------------------------------------------------------------------------
     *
     * The name of the preferred handler that should be used. If for some reason
     * it is not available, the $backupHandler will be used in its place.
     */
    public string $handler = 'file';


value00: app/Config/Cache.php
value01:
     * Web Page Caching: Cache Include Query String
     * --------------------------------------------------------------------------
     *
     * Whether to take the URL query string into consideration when generating
     * output cache files. Valid options are:
     *
     *    false = Disabled
     *    true  = Enabled, take all query parameters into account.
     *            Please be aware that this may result in numerous cache
     *            files generated for the same page over and over again.
     *    ['q'] = Enabled, but only take into account the specified list
     *            of query parameters.
     *
     * @var bool|list<string>
     */
    public $cacheQueryString = false;
}


value00: app/Config/Cache.php
value01:
    /**
     * -------------------------------------------------------------------------
     * Redis settings
     * -------------------------------------------------------------------------
     *
     * Your Redis server can be specified below, if you are using
     * the Redis or Predis drivers.
     *
     * @var array<string, int|string|null>
     */
    public array $redis = [
        'host'     => '127.0.0.1',
        'password' => null,
        'port'     => 6379,
        'timeout'  => 0,
        'database' => 0,
    ];


value00: app/Config/Cache.php
value01:
    public string $reservedCharacters = '{}()/\@:';

    /**
     * --------------------------------------------------------------------------
     * File settings
     * --------------------------------------------------------------------------
     *
     * Your file storage preferences can be specified below, if you are using
     * the File driver.
     *
     * @var array<string, int|string|null>
     */
    public array $file = [
        'storePath' => WRITEPATH . 'cache/',
        'mode'      => 0640,
    ];


value00: app/Config/Cache.php
value01:
<?php

namespace Config;

use CodeIgniter\Cache\CacheInterface;
use CodeIgniter\Cache\Handlers\DummyHandler;
use CodeIgniter\Cache\Handlers\FileHandler;
use CodeIgniter\Cache\Handlers\MemcachedHandler;
use CodeIgniter\Cache\Handlers\PredisHandler;
use CodeIgniter\Cache\Handlers\RedisHandler;
use CodeIgniter\Cache\Handlers\WincacheHandler;
use CodeIgniter\Config\BaseConfig;


value00: app/Config/Cache.php
value01:
    public string $handler = 'file';

    /**
     * --------------------------------------------------------------------------
     * Backup Handler
     * --------------------------------------------------------------------------
     *
     * The name of the handler that will be used in case the first one is
     * unreachable. Often, 'file' is used here since the filesystem is
     * always available, though that's not always practical for the app.
     */
    public string $backupHandler = 'dummy';


value00: app/Config/Cache.php
value01:
    public string $prefix = '';

    /**
     * --------------------------------------------------------------------------
     * Default TTL
     * --------------------------------------------------------------------------
     *
     * The default number of seconds to save items when none is specified.
     *
     * WARNING: This is not used by framework handlers where 60 seconds is
     * hard-coded, but may be useful to projects and modules. This will replace
     * the hard-coded value in a future release.
     */
    public int $ttl = 60;


value00: app/Config/Cache.php
value01:
    public array $file = [
        'storePath' => WRITEPATH . 'cache/',
        'mode'      => 0640,
    ];

    /**
     * -------------------------------------------------------------------------
     * Memcached settings
     * -------------------------------------------------------------------------
     *
     * Your Memcached servers can be specified below, if you are using
     * the Memcached drivers.
     *
     * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached
     *
     * @var array<string, bool|int|string>
     */
    public array $memcached = [
        'host'   => '127.0.0.1',
        'port'   => 11211,
        'weight' => 1,
        'raw'    => false,
    ];


value00: app/Config/Cache.php
value01:
    public int $ttl = 60;

    /**
     * --------------------------------------------------------------------------
     * Reserved Characters
     * --------------------------------------------------------------------------
     *
     * A string of reserved characters that will not be allowed in keys or tags.
     * Strings that violate this restriction will cause handlers to throw.
     * Default: {}()/\@:
     *
     * NOTE: The default set is required for PSR-6 compliance.
     */
    public string $reservedCharacters = '{}()/\@:';


value00: app/Config/Cache.php
value01:
    public string $backupHandler = 'dummy';

    /**
     * --------------------------------------------------------------------------
     * Key Prefix
     * --------------------------------------------------------------------------
     *
     * This string is added to all cache item names to help avoid collisions
     * if you run multiple applications with the same cache engine.
     */
    public string $prefix = '';


value00: app/Config/Cache.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Web Page Caching: Cache Include Query String
     * --------------------------------------------------------------------------


value00: app/Config/Cache.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Available Cache Handlers
     * --------------------------------------------------------------------------
     *
     * This is an array of cache engine alias' and class names. Only engines
     * that are listed here are allowed to be used.
     *
     * @var array<string, class-string<CacheInterface>>
     */
    public array $validHandlers = [
        'dummy'     => DummyHandler::class,
        'file'      => FileHandler::class,
        'memcached' => MemcachedHandler::class,
        'predis'    => PredisHandler::class,
        'redis'     => RedisHandler::class,
        'wincache'  => WincacheHandler::class,
    ];


value00: app/Config/Constants.php
value01:
 | applications.
 |
 | The three main conventions used for determining exit status codes
 | are as follows:
 |
 |    Standard C/C++ Library (stdlibc):
 |       http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
 |       (This link also contains other GNU-specific conventions)
 |    BSD sysexits.h:
 |       http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits
 |    Bash scripting:
 |       http://tldp.org/LDP/abs/html/exitcodes.html
 |
 */


value00: app/Config/Constants.php
value01:
defined('EXIT_SUCCESS')        || define('EXIT_SUCCESS', 0);        // no errors
defined('EXIT_ERROR')          || define('EXIT_ERROR', 1);          // generic error
defined('EXIT_CONFIG')         || define('EXIT_CONFIG', 3);         // configuration error
defined('EXIT_UNKNOWN_FILE')   || define('EXIT_UNKNOWN_FILE', 4);


value00: app/Config/Constants.php
value01:
/*
 | --------------------------------------------------------------------------
 | Exit Status Codes
 | --------------------------------------------------------------------------
 |
 | Used to indicate the conditions under which the script is exit()ing.
 | While there is no universal standard for error codes, there are some
 | broad conventions.  Three such conventions are mentioned below, for
 | those who wish to make use of them.  The CodeIgniter defaults were
 | chosen for the least overlap with these conventions, while still
 | leaving room for others to be defined in future versions and user
 | applications.
 |
 | The three main conventions used for determining exit status codes
 | are as follows:


value00: app/Config/Constants.php
value01:
// configuration error
defined('EXIT_UNKNOWN_FILE')   || define('EXIT_UNKNOWN_FILE', 4);   // file not found
defined('EXIT_UNKNOWN_CLASS')  || define('EXIT_UNKNOWN_CLASS', 5);  // unknown class
defined('EXIT_UNKNOWN_METHOD') || define('EXIT_UNKNOWN_METHOD', 6); // unknown class member
defined('EXIT_USER_INPUT')     || define('EXIT_USER_INPUT', 7);     // invalid user input
defined('EXIT_DATABASE')       || define('EXIT_DATABASE', 8);       // database error
defined('EXIT__AUTO_MIN')      || define('EXIT__AUTO_MIN', 9);      // lowest automatically-assigned error code
defined('EXIT__AUTO_MAX')      || define('EXIT__AUTO_MAX', 125);    // highest automatically-assigned error code


value00: app/Config/Constants.php
value01:
<?php

/*
 | --------------------------------------------------------------------
 | App Namespace
 | --------------------------------------------------------------------
 |
 | This defines the default Namespace that is used throughout
 | CodeIgniter to refer to the Application directory. Change
 | this constant to change the namespace that all application
 | classes should use.
 |
 | NOTE: changing this will require manually modifying the
 | existing namespaces of App\* namespaced-classes.
 */
defined('APP_NAMESPACE') || define('APP_NAMESPACE', 'App');


value00: app/Config/Constants.php
value01:
defined('COMPOSER_PATH') || define('COMPOSER_PATH', ROOTPATH . 'vendor/autoload.php');

/*
 |--------------------------------------------------------------------------
 | Timing Constants
 |--------------------------------------------------------------------------
 |
 | Provide simple ways to work with the myriad of PHP functions that
 | require information to be in seconds.
 */
defined('SECOND') || define('SECOND', 1);
defined('MINUTE') || define('MINUTE', 60);
defined('HOUR')   || define('HOUR', 3600);
defined('DAY')    || define('DAY', 86400);
defined('WEEK')   || define('WEEK', 604800);
defined('MONTH')  || define('MONTH', 2_592_000);
defined('YEAR')   || define('YEAR', 31_536_000);
defined('DECADE') || define('DECADE', 315_360_000);


value00: app/Config/Constants.php
value01:
defined('APP_NAMESPACE') || define('APP_NAMESPACE', 'App');

/*
 | --------------------------------------------------------------------------
 | Composer Path
 | --------------------------------------------------------------------------
 |
 | The path that Composer's autoload file is expected to live. By default,
 | the vendor folder is in the Root directory, but you can customize that here.
 */
defined('COMPOSER_PATH') || define('COMPOSER_PATH', ROOTPATH . 'vendor/autoload.php');


value00: app/Config/ContentSecurityPolicy.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

/**
 * Stores the default settings for the ContentSecurityPolicy, if you
 * choose to use it. The values here will be read in and set as defaults
 * for the site. If needed, they can be overridden on a page-by-page basis.
 *
 * Suggested reference for explanations:
 *
 * @see https://www.html5rocks.com/en/tutorials/security/content-security-policy/
 */
class ContentSecurityPolicy extends BaseConfig
{
    // -------------------------------------------------------------------------


value00: app/Config/ContentSecurityPolicy.php
value01:
    /**
     * Defines the origins from which images can be loaded.
     *
     * @var list<string>|string
     */
    public $imageSrc = 'self';

    /**
     * Restricts the URLs that can appear in a page's `<base>` element.
     *
     * Will default to self if not overridden
     *
     * @var list<string>|string|null
     */
    public $baseURI;

    /**
     * Lists the URLs for workers and embedded frame contents
     *
     * @var list<string>|string
     */
    public $childSrc = 'self';

    /**
     * Limits the origins that you can connect to (via XHR,
     * WebSockets, and EventSource).
     *
     * @var list<string>|string
     */
    public $connectSrc = 'self';


value00: app/Config/ContentSecurityPolicy.php
value01:
    public $connectSrc = 'self';

    /**
     * Specifies the origins that can serve web fonts.
     *
     * @var list<string>|string
     */
    public $fontSrc;

    /**
     * Lists valid endpoints for submission from `<form>` tags.
     *
     * @var list<string>|string
     */
    public $formAction = 'self';

    /**
     * Specifies the sources that can embed the current page.
     * This directive applies to `<frame>`, `<iframe>`, `<embed>`,
     * and `<applet>` tags. This directive can't be used in
     * `<meta>` tags and applies only to non-HTML resources.
     *
     * @var list<string>|string|null
     */
    public $frameAncestors;


value00: app/Config/ContentSecurityPolicy.php
value01:
    public $frameAncestors;

    /**
     * The frame-src directive restricts the URLs which may
     * be loaded into nested browsing contexts.
     *
     * @var list<string>|string|null
     */
    public $frameSrc;

    /**
     * Restricts the origins allowed to deliver video and audio.
     *
     * @var list<string>|string|null
     */
    public $mediaSrc;

    /**
     * Allows control over Flash and other plugins.
     *
     * @var list<string>|string
     */
    public $objectSrc = 'self';

    /**
     * @var list<string>|string|null
     */
    public $manifestSrc;

    /**
     * Limits the kinds of plugins a page may invoke.
     *
     * @var list<string>|string|null
     */


value00: app/Config/ContentSecurityPolicy.php
value01:
{
    // -------------------------------------------------------------------------
    // Broadbrush CSP management
    // -------------------------------------------------------------------------

    /**
     * Default CSP report context
     */
    public bool $reportOnly = false;

    /**
     * Specifies a URL where a browser will send reports
     * when a content security policy is violated.
     */
    public ?string $reportURI = null;

    /**
     * Instructs user agents to rewrite URL schemes, changing
     * HTTP to HTTPS. This directive is for websites with
     * large numbers of old URLs that need to be rewritten.
     */
    public bool $upgradeInsecureRequests = false;

    // -------------------------------------------------------------------------


value00: app/Config/ContentSecurityPolicy.php
value01:
    /**
     * Limits the kinds of plugins a page may invoke.
     *
     * @var list<string>|string|null
     */
    public $pluginTypes;

    /**
     * List of actions allowed.
     *
     * @var list<string>|string|null
     */
    public $sandbox;

    /**
     * Nonce tag for style
     */
    public string $styleNonceTag = '{csp-style-nonce}';

    /**
     * Nonce tag for script
     */
    public string $scriptNonceTag = '{csp-script-nonce}';

    /**
     * Replace nonce tag automatically
     */
    public bool $autoNonce = true;
}


value00: app/Config/ContentSecurityPolicy.php
value01:
    // -------------------------------------------------------------------------
    // Sources allowed
    // NOTE: once you set a policy to 'none', it cannot be further restricted
    // -------------------------------------------------------------------------

    /**
     * Will default to self if not overridden
     *
     * @var list<string>|string|null
     */
    public $defaultSrc;

    /**
     * Lists allowed scripts' URLs.
     *
     * @var list<string>|string
     */
    public $scriptSrc = 'self';

    /**
     * Lists allowed stylesheets' URLs.
     *
     * @var list<string>|string
     */
    public $styleSrc = 'self';

    /**
     * Defines the origins from which images can be loaded.
     *
     * @var list<string>|string
     */


value00: app/Config/Cookie.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use DateTimeInterface;

class Cookie extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Cookie Prefix
     * --------------------------------------------------------------------------
     *
     * Set a cookie name prefix if you need to avoid collisions.
     */
    public string $prefix = '';


value00: app/Config/Cookie.php
value01:
    public string $prefix = '';

    /**
     * --------------------------------------------------------------------------
     * Cookie Expires Timestamp
     * --------------------------------------------------------------------------
     *
     * Default expires timestamp for cookies. Setting this to `0` will mean the
     * cookie will not have the `Expires` attribute and will behave as a session
     * cookie.
     *
     * @var DateTimeInterface|int|string
     */
    public $expires = 0;


value00: app/Config/Cookie.php
value01:
    public string $domain = '';

    /**
     * --------------------------------------------------------------------------
     * Cookie Secure
     * --------------------------------------------------------------------------
     *
     * Cookie will only be set if a secure HTTPS connection exists.
     */
    public bool $secure = false;

    /**
     * --------------------------------------------------------------------------
     * Cookie HTTPOnly
     * --------------------------------------------------------------------------
     *
     * Cookie will only be accessible via HTTP(S) (no JavaScript).
     */
    public bool $httponly = true;


value00: app/Config/Cookie.php
value01:
    public $expires = 0;

    /**
     * --------------------------------------------------------------------------
     * Cookie Path
     * --------------------------------------------------------------------------
     *
     * Typically will be a forward slash.
     */
    public string $path = '/';

    /**
     * --------------------------------------------------------------------------
     * Cookie Domain
     * --------------------------------------------------------------------------
     *
     * Set to `.your-domain.com` for site-wide cookies.
     */
    public string $domain = '';


value00: app/Config/Cookie.php
value01:
     *
     * Configure cookie SameSite setting. Allowed values are:
     * - None
     * - Lax
     * - Strict
     * - ''
     *
     * Alternatively, you can use the constant names:
     * - `Cookie::SAMESITE_NONE`
     * - `Cookie::SAMESITE_LAX`
     * - `Cookie::SAMESITE_STRICT`
     *
     * Defaults to `Lax` for compatibility with modern browsers. Setting `''`
     * (empty string) means default SameSite attribute set by browsers (`Lax`)
     * will be set on cookies. If set to `None`, `$secure` must also be set.
     *
     * @phpstan-var 'None'|'Lax'|'Strict'|''
     */


value00: app/Config/Cookie.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Cookie SameSite
     * --------------------------------------------------------------------------
     *
     * Configure cookie SameSite setting. Allowed values are:
     * - None
     * - Lax
     * - Strict
     * - ''


value00: app/Config/Cookie.php
value01:
    public string $samesite = 'Lax';

    /**
     * --------------------------------------------------------------------------
     * Cookie Raw
     * --------------------------------------------------------------------------
     *
     * This flag allows setting a "raw" cookie, i.e., its name and value are
     * not URL encoded using `rawurlencode()`.
     *
     * If this is set to `true`, cookie names should be compliant of RFC 2616's
     * list of allowed characters.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes
     * @see https://tools.ietf.org/html/rfc2616#section-2.2
     */
    public bool $raw = false;
}


value00: app/Config/Database.php
value01:
    //            'date'     => 'Y-m-d',
    //            'datetime' => 'Y-m-d H:i:s',
    //            'time'     => 'H:i:s',
    //        ],
    //    ];

    //    /**
    //     * Sample database connection for Postgre.
    //     *
    //     * @var array<string, mixed>
    //     */
    //    public array $default = [
    //        'DSN'        => '',
    //        'hostname'   => 'localhost',
    //        'username'   => 'root',
    //        'password'   => 'root',
    //        'database'   => 'ci4',
    //        'schema'     => 'public',
    //        'DBDriver'   => 'Postgre',
    //        'DBPrefix'   => '',
    //        'pConnect'   => false,


value00: app/Config/Database.php
value01:
;

    public function __construct()
    {
        parent::__construct();

        // Ensure that we always set the database group to 'tests' if
        // we are currently running an automated test suite, so that
        // we don't overwrite live data on accident.
        if (ENVIRONMENT === 'testing') {
            if ($this->tests['database'] === $this->default['database']) {
                throw new \RuntimeException('Tests database cannot match the default database.');
            }
            $this->defaultGroup = 'tests';
        }
    }
}


value00: app/Config/Database.php
value01:
    //        'charset'    => 'utf8',
    //        'swapPre'    => '',
    //        'encrypt'    => false,
    //        'failover'   => [],
    //        'port'       => 1433,
    //        'dateFormat' => [
    //            'date'     => 'Y-m-d',
    //            'datetime' => 'Y-m-d H:i:s',
    //            'time'     => 'H:i:s',
    //        ],
    //    ];

    //    /**
    //     * Sample database connection for OCI8.
    //     *
    //     * You may need the following environment variables:
    //     *   NLS_LANG                = 'AMERICAN_AMERICA.UTF8'
    //     *   NLS_DATE_FORMAT         = 'YYYY-MM-DD HH24:MI:SS'
    //     *   NLS_TIMESTAMP_FORMAT    = 'YYYY-MM-DD HH24:MI:SS'
    //     *   NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS'


value00: README.md
value01:
# CLQMS (Clinical Laboratory Quality Management System)

> **A REST API backend for modern clinical laboratory workflows.**

---

## 🤖 For Claude Code

**When working in this repository, prioritize Serena MCP tools for code operations:**

- **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 minimizes tool calls and leverages semantic code understanding for this PHP codebase.


value00: app/Config/Database.php
value01:
[
        'DSN'         => '',
        'hostname'    => 'localhost',
        'username'    => 'root',
        'password'    => 'adminsakti',
        'database'    => 'clqms01_test',
        'DBDriver'    => 'MySQLi',
        'DBPrefix'    => '',  // Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE FOR CI DEVS
        'pConnect'    => false,
        'DBDebug'     => true,
        'charset'     => 'utf8mb4',
        'DBCollat'    => 'utf8mb4_general_ci'


value00: README.md
value01:
## 🛡️ Strategic Pillars

- **Precision & Accuracy:** Strict validation for all laboratory parameters and reference ranges.
- **Scalability:** Optimized for high-volume diagnostic environments.
- **Compliance:** Built-in audit trails and status history for full traceability.
- **Interoperability:** Modular architecture designed for LIS, HIS, and analyzer integrations.

---

## 🛠️ Technical Stack

| Component      | Specification |
| :------------- | :------------ |
| **Language**   | PHP 8.1+ (PSR-compliant) |
| **Framework**  | CodeIgniter 4 (API-only mode) |
| **Security**   | JWT (JSON Web Tokens) Authorization |
| **Database**   | MySQL (Optimized Schema Migration in progress) |
| **API Format** | RESTful JSON |
| **Testing**    | PHPUnit 10.5+ |


---


value00: app/Config/Database.php
value01:
[
        'DSN'          => '',
        'hostname'     => 'localhost',
        'username'     => 'root',
        'password'     => 'adminsakti',
        'database'     => 'clqms01',
        'DBDriver'     => 'MySQLi',
        'DBPrefix'     => '',
        'pConnect'     => false,
        'DBDebug'      => true,
        'charset'      => 'utf8mb4',
        'DBCollat'     => 'utf8mb4_general_ci',
        'swapPre'      => '',
        'encrypt'      => false


value00: app/Config/Database.php
value01:
<?php

namespace Config;

use CodeIgniter\Database\Config;

/**
 * Database Configuration
 */
class Database extends Config
{
    /**
     * The directory that holds the Migrations and Seeds directories.
     */
    public string $filesPath = APPPATH . 'Database' . DIRECTORY_SEPARATOR;

    /**
     * Lets you choose which connection group to use if no other is specified.
     */
    public string $defaultGroup = 'default';

    /**
     * The default database connection.
     *
     * @var array<string, mixed>
     */
    public array $default = [
        'DSN'          => '',
        'hostname'     => 'localhost',
        'username'     => 'root',
        'password'     => 'adminsakti'


value00: app/Config/Database.php
value01:
    //    /**
    //     * Sample database connection for SQLSRV.
    //     *
    //     * @var array<string, mixed>
    //     */
    //    public array $default = [
    //        'DSN'        => '',
    //        'hostname'   => 'localhost',
    //        'username'   => 'root',
    //        'password'   => 'root',
    //        'database'   => 'ci4',
    //        'schema'     => 'dbo',
    //        'DBDriver'   => 'SQLSRV',
    //        'DBPrefix'   => '',
    //        'pConnect'   => false,
    //        'DBDebug'    => true,
    //        'charset'    => 'utf8',
    //        'swapPre'    => '',
    //        'encrypt'    => false,


value00: README.md
value01:
#### Test Response Structure

```json
{
  "status": "success",
  "message": "Data fetched successfully",
  "data": [
    {
      "TestSiteID": 1,
      "TestSiteCode": "CBC",
      "TestSiteName": "Complete Blood Count",
      "TestType": 4,
      "TypeCode": "GROUP",
      "TypeName": "Group Test",
      "SeqScr": 50,
      "VisibleScr": 1,
      "VisibleRpt": 1
    }
  ]
}
```


value00: app/Config/Database.php
value01:
    //    /**
    //     * Sample database connection for SQLite3.
    //     *
    //     * @var array<string, mixed>
    //     */
    //    public array $default = [
    //        'database'    => 'database.db',
    //        'DBDriver'    => 'SQLite3',
    //        'DBPrefix'    => '',
    //        'DBDebug'     => true,
    //        'swapPre'     => '',
    //        'failover'    => [],
    //        'foreignKeys' => true,
    //        'busyTimeout' => 1000,
    //        'synchronous' => null,
    //        'dateFormat'  => [
    //            'date'     => 'Y-m-d',
    //            'datetime' => 'Y-m-d H:i:s',
    //            'time'     => 'H:i:s',


value00: README.md
value01:
#### Patient Management

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `GET` | `/api/patient` | List patients with pagination | Yes |
| `GET` | `/api/patient/{id}` | Get patient details | Yes |
| `POST` | `/api/patient` | Create new patient | Yes |
| `PATCH` | `/api/patient/{id}` | Update patient | Yes |
| `DELETE` | `/api/patient/{id}` | Soft delete patient | Yes |


value00: app/Config/Database.php
value01:
    //        'DBDriver'   => 'Postgre',
    //        'DBPrefix'   => '',
    //        'pConnect'   => false,
    //        'DBDebug'    => true,
    //        'charset'    => 'utf8',
    //        'swapPre'    => '',
    //        'failover'   => [],
    //        'port'       => 5432,
    //        'dateFormat' => [
    //            'date'     => 'Y-m-d',
    //            'datetime' => 'Y-m-d H:i:s',
    //            'time'     => 'H:i:s',
    //        ],
    //    ];

    //    /**
    //     * Sample database connection for SQLSRV.
    //     *
    //     * @var array<string, mixed>


value00: README.md
value01:
#### Result Management

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `GET` | `/api/patresult` | List patient results | Yes |
| `GET` | `/api/patresult/{id}` | Get result details | Yes |
| `POST` | `/api/patresult` | Enter new result | Yes |
| `PATCH` | `/api/patresult/{id}` | Update result | Yes |
| `POST` | `/api/patresult/status` | Verify result (VER/REV/REP) | Yes |


value00: README.md
value01:
### Authentication

Most endpoints require JWT authentication:

**Request Headers:**
```
Authorization: Bearer {jwt_token}
Content-Type: application/json
```

**Login Request Example:**
```bash
POST /api/login
{
  "username": "labuser",
  "password": "password123"
}
```

**Login Response:**
```json
{
  "status": "success",
  "message": "Login successful",
  "data": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
    "expires_in": 3600,
    "user": {
      "id": 1,
      "username": "labuser",
      "name": "Lab User"
    }
  }
}
```

---


value00: README.md
value01:
#### API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/refnum` | List numeric reference ranges |
| `GET` | `/api/refnum/{id}` | Get reference range details |
| `POST` | `/api/refnum` | Create reference range |
| `PATCH` | `/api/refnum` | Update reference range |
| `DELETE` | `/api/refnum` | Soft delete reference range |


value00: app/Config/Database.php
value01:
    //     *   NLS_TIMESTAMP_FORMAT    = 'YYYY-MM-DD HH24:MI:SS'
    //     *   NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS'
    //     *
    //     * @var array<string, mixed>
    //     */
    //    public array $default = [
    //        'DSN'        => 'localhost:1521/XEPDB1',
    //        'username'   => 'root',
    //        'password'   => 'root',
    //        'DBDriver'   => 'OCI8',
    //        'DBPrefix'   => '',
    //        'pConnect'   => false,
    //        'DBDebug'    => true,
    //        'charset'    => 'AL32UTF8',
    //        'swapPre'    => '',
    //        'failover'   => [],
    //        'dateFormat' => [
    //            'date'     => 'Y-m-d',
    //            'datetime' => 'Y-m-d H:i:s',
    //            'time'     => 'H:i:s',


value00: README.md
value01:
| `operation` | CRUD operation types | Create, Read, Update, Delete |
| `site_type` | Healthcare facility types | GH, PH, GHL, PHL, GL, PL |
| `site_class` | Facility classification | A, B, C, D, Utm, Ptm |
| `ws_type` | Workstation types | Primary, Secondary |
| `enable_disable` | Boolean toggle states | Enabled, Disabled |
| `entity_type` | Entity classification | Patient, Provider, Site |
| `requested_entity` | Requestor types | Physician, Nurse, Lab |
| `location_type` | Location categories | OPD, IPD, ER, LAB |
| `area_class` | Geographic classifications | Urban, Rural, Suburban |
| `adt_event` | ADT event types | Admission, Transfer, Discharge |


value00: README.md
value01:
## 📂 Documentation & Specifications

### Key Documents

| Document | Location | Description |
|----------|----------|-------------|
| **PRD** | `PRD.md` | Complete Product Requirements Document (API-focused) |
| **Technical Guide** | `CLAUDE.md` | Architecture, coding standards, common commands |
| **API Overview** | This file | REST API documentation and endpoints |
| **Database Migrations** | `app/Database/Migrations/` | Database schema history |

### API Documentation

All API endpoints follow REST conventions:

**Base URL:** `/api`

**Authentication:** JWT token required for most endpoints (except `/api/login`, `/api/demo/*`)

**Response Format:**
```json
{
  "status": "success|error",
  "message": "Human-readable message",
  "data": { ... }
}
```

---


value00: app/Config/Database.php
value01:
        'charset'      => 'utf8mb4',
        'DBCollat'     => 'utf8mb4_general_ci',
        'swapPre'      => '',
        'encrypt'      => false,
        'compress'     => false,
        'strictOn'     => false,
        'failover'     => [],
        'port'         => 3306,
        'numberNative' => false,
        'foundRows'    => false,
        'dateFormat'   => [
            'date'     => 'Y-m-d',
            'datetime' => 'Y-m-d H:i:s',
            'time'     => 'H:i:s',
        ],
    ];

    //    /**
    //     * Sample database connection for SQLite3.
    //     *
    //     * @var array<string, mixed>


value00: README.md
value01:
#### Common Value Sets

| VSetDefID | Name | Example Values |
|-----------|------|----------------|
| 1 | Priority | STAT (S), ASAP (A), Routine (R), Preop (P) |
| 2 | Enable/Disable | Disabled (0), Enabled (1) |
| 3 | Gender | Female (1), Male (2), Unknown (3) |
| 10 | Order Status | STC, SCtd, SArrv, SRcvd, SAna, etc. |
| 15 | Specimen Type | BLD, SER, PLAS, UR, CSF, etc. |
| 16 | Unit | L, mL, g/dL, mg/dL, etc. |
| 27 | Test Type | TEST, PARAM, CALC, GROUP, TITLE |
| 28 | Result Unit | g/dL, g/L, mg/dL, x10^6/mL, etc. |
| 35 | Test Activity | Order, Analyse, VER, REV, REP |


value00: README.md
value01:
### When to Use

| Approach | Use Case |
|----------|----------|
| **Lookups Library** | Server-side static values that rarely change (gender, status, types) - fast, cached |
| **API `/api/valueset*`** | Dynamic values managed by admins at runtime, or for frontend clients needing lookup data |

### Adding New Lookups

1. Create `app/Libraries/Data/valuesets/{name}.json`:
```json
{
  "name": "example_lookup",
  "description": "Example lookup description",
  "values": [
    {"key": "1", "value": "Option One"},
    {"key": "2", "value": "Option Two"},
    {"key": "3", "value": "Option Three"}
  ]
}
```

2. Access via `Lookups::get('example_lookup')`

---


value00: README.md
value01:
## 🔌 REST API Overview

### API Endpoint Categories

#### Authentication & Authorization

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `POST` | `/api/login` | User login, returns JWT token | No |
| `POST` | `/api/logout` | Invalidate JWT token | Yes |
| `POST` | `/api/refresh` | Refresh JWT token | Yes |


value00: README.md
value01:
### 📊 Database Tables Summary

| Category | Tables | Purpose |
|----------|--------|---------|
| Tests | `testdefsite`, `testdeftech`, `testdefcal`, `testdefgrp`, `testmap` | Test definitions |
| Reference Ranges | `refnum`, `reftxt` | Result validation |
| Value Sets | `valuesetdef`, `valueset` | Configurable options |

---


value00: README.md
value01:
| `result_status` | Result validation status | Preliminary, Final, Corrected |
| `test_type` | Test definition types | TEST, PARAM, CALC, GROUP |
| `test_activity` | Test workflow activities | Order, Analyse, VER, REV |
| `test_status` | Test active status | Active, Inactive, Discontinued |
| `priority` | General priority values | STAT, HIGH, NORMAL, LOW |
| `race` | Ethnicity/race categories | Jawa, Sunda, Batak, etc. |
| `religion` | Religious affiliations | Islam, Kristen, Katolik, Hindu |
| `marital_status` | Marital status | Single, Married, Divorced |
| `death_indicator` | Death status flags | Yes, No |
| `identifier_type` | ID document types | KTP, Passport, SSN, SIM |
| `operation` | CRUD operation types | Create, Read, Update, Delete |


value00: README.md
value01:
#### API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/tests` | List all tests with optional filtering |
| `GET` | `/api/tests/{id}` | Get test details with type-specific data |
| `POST` | `/api/tests` | Create new test definition |
| `PATCH` | `/api/tests` | Update existing test |
| `DELETE` | `/api/tests` | Soft delete test (sets EndDate) |

#### Filtering Parameters

- `TestSiteName` - Search by test name (partial match)
- `TestType` - Filter by test type VID (1-5)
- `VisibleScr` - Filter by screen visibility (0/1)
- `VisibleRpt` - Filter by report visibility (0/1)


value00: README.md
value01:
### Workflow

```
Instrument → tiny-edge → POST /api/edge/result → edgeres table → [Manual/Auto Processing] → patres table
```

**Key Features:**
- **Staging Table:** All results land in `edgeres` first for validation
- **Rerun Handling:** Duplicate `SampleID` + `TestSiteCode` increments `AspCnt` in `patres`
- **Configurable Processing:** Auto or manual processing based on settings
- **Status Tracking:** Full audit trail via `edgestatus` and `edgeack` tables

---


value00: README.md
value01:
### Usage

```php
use App\Libraries\Lookups;

// Get all lookups (loads all JSON files, cached)
$allLookups = Lookups::getAll();

// Get single lookup formatted for dropdowns
$gender = Lookups::get('gender');
// Returns: [{"value":"1","label":"Female"},{"value":"2","label":"Male"},...]

// Get raw data without formatting
$raw = Lookups::getRaw('gender');
// Returns: [{"key":"1","value":"Female"},{"key":"2","value":"Male"},...]

// Get label for a specific key
$label = Lookups::getLabel('gender', '1'); // Returns 'Female'

// Get key/value pairs for select inputs


value00: README.md
value01:
This minimizes tool calls and leverages semantic code understanding for this PHP codebase.

---

CLQMS is a **headless REST API backend** designed to streamline laboratory operations, ensure data integrity, and manage complex diagnostic workflows. Built on a foundation of precision and regulatory compliance, this system provides comprehensive JSON endpoints for laboratory operations.

**Key Characteristic:** This is an **API-only system** with no view layer. Frontend applications (web, mobile, desktop) consume these REST endpoints to build laboratory information systems.

---


value00: app/Config/Database.php
value01:
        'pConnect'    => false,
        'DBDebug'     => true,
        'charset'     => 'utf8mb4',
        'DBCollat'    => 'utf8mb4_general_ci',
        'swapPre'     => '',
        'encrypt'     => false,
        'compress'    => false,
        'strictOn'    => false,
        'failover'    => [],
        'port'        => 3306,
        'foreignKeys' => true,
        'busyTimeout' => 1000,
        'dateFormat'  => [
            'date'     => 'Y-m-d',
            'datetime' => 'Y-m-d H:i:s',
            'time'     => 'H:i:s',
        ],
    ]


value00: README.md
value01:
#### API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/valuesetdef` | List all value set definitions |
| `GET` | `/api/valuesetdef/{id}` | Get valueset with all values |
| `GET` | `/api/valuesetdef/{id}/values` | Get values for specific valueset |
| `POST` | `/api/valuesetdef` | Create new valueset definition |
| `PATCH` | `/api/valuesetdef` | Update valueset definition |
| `DELETE` | `/api/valuesetdef` | Delete valueset definition |


value00: README.md
value01:
### 📜 Usage Notice

**This is an API-only backend system.** There are no views, HTML templates, or server-side rendering components. Frontend applications should consume these REST endpoints to build user interfaces for laboratory operations.

This repository contains proprietary information intended for the 5Panda Team and authorized collaborators.

---
*© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.*


value00: README.md
value01:
$label = Lookups::getLabel('gender', '1'); // Returns 'Female'

// Get key/value pairs for select inputs
$options = Lookups::getOptions('gender');
// Returns: [["key":"1","value":"Female"],...]

// Transform database records with lookup text labels
$patients = [
    ['ID' => 1, 'Sex' => '1', 'Priority' => 'S'],
    ['ID' => 2, 'Sex' => '2', 'Priority' => 'R'],
];
$labeled = Lookups::transformLabels($patients, [
    'Sex' => 'gender',
    'Priority' => 'order_priority'
]);
// Result: [['ID'=>1, 'Sex'=>'1', 'SexText'=>'Female', 'Priority'=>'S', 'PriorityText'=>'Stat'],...]

// Clear cache after modifying valueset data
Lookups::clearCache();
```


value00: README.md
value01:
## 🔌 Edge API - Instrument Integration

The **Edge API** provides endpoints for integrating laboratory instruments via the `tiny-edge` middleware. Results from instruments are staged in the `edgeres` table before processing into the main patient results (`patres`).

### Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/edge/result` | Receive instrument results (stored in `edgeres`) |
| `GET` | `/api/edge/order` | Fetch pending orders for an instrument |
| `POST` | `/api/edge/order/:id/ack` | Acknowledge order delivery to instrument |
| `POST` | `/api/edge/status` | Log instrument status updates |


value00: README.md
value01:
#### Specimen Management

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `GET` | `/api/specimen` | List specimens | Yes |
| `GET` | `/api/specimen/{id}` | Get specimen details | Yes |
| `POST` | `/api/specimen` | Create specimen | Yes |
| `PATCH` | `/api/specimen/{id}` | Update specimen | Yes |
| `POST` | `/api/specimen/status` | Update specimen status | Yes |


value00: README.md
value01:
## 🏛️ Core Architecture & Design

CLQMS is a **headless REST API system** following a clean architecture pattern. The system is designed to be consumed by any frontend client (web, mobile, desktop) through comprehensive JSON endpoints.

**API-First Architecture:**
- **No View Layer:** This system provides REST APIs only - no HTML views, no server-side rendering
- **Frontend Agnostic:** Any client can consume these APIs (React, Vue, Angular, mobile apps, desktop apps)
- **JSON-First:** All requests/responses use JSON format
- **Stateless:** Each API request is independent with JWT authentication


value00: README.md
value01:
| Lookup File | Description | Example Values |
|-------------|-------------|----------------|
| `gender` | Patient gender | Female, Male, Unknown |
| `order_priority` | Order priority levels | Stat, ASAP, Routine, Preop |
| `order_status` | Order lifecycle status | STC, SCtd, SArrv, SRcvd |
| `specimen_type` | Specimen types | BLD, SER, PLAS, UR, CSF |
| `specimen_status` | Specimen status | Ordered, Collected, Received |
| `specimen_condition` | Specimen quality flags | HEM, ITC, LIP, CLOT |
| `specimen_activity` | Specimen workflow events | COLLECT, RECEIVE, REJECT |
| `result_type` | Result data types | NMRIC, RANGE, TEXT, VSET |
| `result_unit` | Common measurement units | g/dL, mg/dL, x10^6/mL |
| `result_status` | Result validation status | Preliminary, Final, Corrected |


value00: README.md
value01:
#### Edge API (Instrument Integration)

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `POST` | `/api/edge/result` | Receive instrument results | API Key |
| `GET` | `/api/edge/order` | Fetch pending orders | API Key |
| `POST` | `/api/edge/order/{id}/ack` | Acknowledge order | API Key |
| `POST` | `/api/edge/status` | Log instrument status | API Key |


value00: README.md
value01:
The system is currently undergoing a strategic **Architectural Redesign** to consolidate legacy structures into a high-performance, maintainable schema. This design focuses on reducing technical debt and improving data consistency across:

- **Unified Test Definitions:** Consolidating technical, calculated, and site-specific test data.
- **Reference Range Centralization:** A unified engine for numeric, threshold, text, and coded results.
- **Ordered Workflow Management:** Precise tracking of orders from collection to verification.

---


value00: app/Config/Database.php
value01:
    //            'date'     => 'Y-m-d',
    //            'datetime' => 'Y-m-d H:i:s',
    //            'time'     => 'H:i:s',
    //        ],
    //    ];

    /**
     * This database connection is used when running PHPUnit database tests.
     * 
     * These values can be overridden in phpunit.xml.dist or .env file using:
     * - database.tests.hostname
     * - database.tests.database
     * - database.tests.username
     * - database.tests.password
     * - database.tests.DBDriver
     *
     * @var array<string, mixed>
     */
    public array $tests = [
        'DSN'         => '',
        'hostname'    => 'localhost',
        'username'    => 'root',
        'password'    => 'adminsakti'


value00: README.md
value01:
| `formula_language` | Formula expression types | Formula, Expression |
| `generate_by` | Generation methods | Auto, Manual, Import |
| `did_type` | Device identification types | Serial, MAC, UUID |
| `activity_result` | Activity outcomes | Success, Fail, Retry |
| `reference_type` | Reference value types | NMRIC, TEXT, LIST |
| `range_type` | Range calculation types | REF, CRTC, VAL, RERUN |
| `numeric_ref_type` | Numeric ref types | Reference, Critical, Valid |
| `text_ref_type` | Text reference types | Normal, Abnormal, Critical |
| `request_status` | Request status | Pending, Approved, Rejected |
| `v_category` | ValueSet categories | Various categories |


value00: README.md
value01:
The Test Definitions module manages all laboratory test configurations including parameters, calculated tests, and test panels.

#### Test Types

| Type Code | Description | Table |
|-----------|-------------|-------|
| `TEST` | Individual laboratory test with technical specs | `testdefsite` + `testdeftech` |
| `PARAM` | Parameter value (non-lab measurement) | `testdefsite` + `testdeftech` |
| `CALC` | Calculated test with formula | `testdefsite` + `testdefcal` |
| `GROUP` | Panel/profile containing multiple tests | `testdefsite` + `testdefgrp` |
| `TITLE` | Section title for report organization | `testdefsite` |


value00: README.md
value01:
### 📑 Value Sets

Value Sets are configurable dropdown options used throughout the system. Each Value Set Definition (VSetDef) contains multiple Value Set Values (ValueSet).

#### Value Set Hierarchy

```
valuesetdef (VSetDefID, VSName, VSDesc)
    └── valueset (VID, VSetID, VValue, VDesc, VOrder, VCategory)
```


value00: README.md
value01:
### API Response Format

All API endpoints return JSON in this format:

**Success Response:**
```json
{
  "status": "success",
  "message": "Operation completed successfully",
  "data": {
    // Response data here
  }
}
```

**Error Response:**
```json
{
  "status": "error",
  "message": "Error description",
  "errors": [
    {
      "field": "field_name",
      "message": "Validation error message"
    }
  ]
}
```


value00: README.md
value01:
## Lookups Library (`app/Libraries/ValueSet.php`)

CLQMS uses a **JSON file-based lookup system** loaded via `App\Libraries\Lookups` class. All lookup data is stored as JSON files in `app/Libraries/Data/valuesets/` for easy maintenance and versioning.

### How It Works

- `Lookups` class extends `ValueSet` which handles caching and file loading
- Each lookup is stored as `app/Libraries/Data/valuesets/{name}.json`
- Lookup names are lowercase with underscores (e.g., `gender.json`, `order_priority.json`)

### Available Lookups

| Lookup File | Description | Example Values |
|-------------|-------------|----------------|


value00: README.md
value01:
#### Value Set Response Structure

```json
{
  "status": "success",
  "data": {
    "VSetDefID": 27,
    "VSName": "Test Type",
    "VSDesc": "testdefsite.TestType",
    "values": [
      { "VID": 1, "VValue": "TEST", "VDesc": "Test", "VOrder": 1 },
      { "VID": 2, "VValue": "PARAM", "VDesc": "Parameter", "VOrder": 2 },
      { "VID": 3, "VValue": "CALC", "VDesc": "Calculated Test", "VOrder": 3 },
      { "VID": 4, "VValue": "GROUP", "VDesc": "Group Test", "VOrder": 4 },
      { "VID": 5, "VValue": "TITLE", "VDesc": "Title", "VOrder": 5 }
    ]
  }
}
```


value00: README.md
value01:
#### Numeric Reference Range Structure

| Field | Description |
|-------|-------------|
| `NumRefType` | Type: REF (Reference), CRTC (Critical), VAL (Validation), RERUN |
| `RangeType` | RANGE or THOLD |
| `Sex` | Gender filter (0=All, 1=Female, 2=Male) |
| `AgeStart` | Minimum age (years) |
| `AgeEnd` | Maximum age (years) |
| `LowSign` | Low boundary sign (=, <, <=) |
| `Low` | Low boundary value |
| `HighSign` | High boundary sign (=, >, >=) |
| `High` | High boundary value |
| `Flag` | Result flag (H, L, A, etc.) |


value00: README.md
value01:
## 📋 Master Data Management

CLQMS provides comprehensive master data management for laboratory operations. All master data is accessible via REST API endpoints.

### 🧪 Laboratory Tests

The Test Definitions module manages all laboratory test configurations including parameters, calculated tests, and test panels.


value00: README.md
value01:
#### Order Management

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `GET` | `/api/ordertest` | List orders | Yes |
| `GET` | `/api/ordertest/{id}` | Get order details | Yes |
| `POST` | `/api/ordertest` | Create order | Yes |
| `PATCH` | `/api/ordertest/{id}` | Update order | Yes |
| `DELETE` | `/api/ordertest/{id}` | Delete order | Yes |
| `POST` | `/api/ordertest/status` | Update order status | Yes |

#### Demo/Test Endpoints (No Auth)

| Method | Endpoint | Description | Auth Required |
|--------|----------|-------------|---------------|
| `POST` | `/api/demo/order` | Create demo order with patient | No |


value00: README.md
value01:
### 📏 Reference Ranges

Reference Ranges define normal and critical values for test results. The system supports multiple reference range types based on patient demographics.

#### Reference Range Types

| Type | Table | Description |
|------|-------|-------------|
| Numeric | `refnum` | Numeric ranges with age/sex criteria |
| Text | `reftxt` | Text-based reference values |


value00: README.md
value01:
| `adt_event` | ADT event types | Admission, Transfer, Discharge |
| `body_site` | Collection sites | Left Arm, Right Arm, Finger |
| `collection_method` | Specimen collection methods | Venipuncture, Fingerstick |
| `container_size` | Tube/container volumes | 3mL, 5mL, 10mL |
| `container_class` | Container types | Vacutainer, Tube, Cup |
| `container_cap_color` | Tube cap colors | Red, Purple, Blue, Green |
| `additive` | Tube additives | EDTA, Heparin, Fluoride |
| `fasting_status` | Fasting requirement flags | Fasting, Non-Fasting |
| `ethnic` | Ethnicity categories | Various regional groups |
| `math_sign` | Mathematical operators | +, -, *, /, =, <, > |
| `formula_language` | Formula expression types | Formula, Expression |


value00: preload.php
value01:
                '/system/Language/',
                '/system/bootstrap.php',
                '/system/rewrite.php',
                '/Views/',
                // Errors occur.
                '/system/ThirdParty/',
            ],
        ],
    ];

    public function __construct()
    {
        $this->loadAutoloader();
    }

    private function loadAutoloader(): void
    {
        $paths = new Paths();
        require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'Boot.php';

        Boot::preload($paths);
    }

    /**
     * Load PHP files.
     */
    public function load(): void


value00: preload.php
value01:
use CodeIgniter\Boot;
use Config\Paths;

/*
 *---------------------------------------------------------------
 * Sample file for Preloading
 *---------------------------------------------------------------
 * See https://www.php.net/manual/en/opcache.preloading.php
 *
 * How to Use:
 *   0. Copy this file to your project root folder.
 *   1. Set the $paths property of the preload class below.
 *   2. Set opcache.preload in php.ini.
 *     php.ini:
 *     opcache.preload=/path/to/preload.php
 */

// Load the paths config file
require __DIR__ . '/app/Config/Paths.php';

// Path to the front controller
define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR);


value00: preload.php
value01:
<?php

/**
 * This file is part of CodeIgniter 4 framework.
 *
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

use CodeIgniter\Boot;
use Config\Paths;


value00: preload.php
value01:
[
                // Not needed if you don't use them.
                '/system/Database/OCI8/',
                '/system/Database/Postgre/',
                '/system/Database/SQLite3/',
                '/system/Database/SQLSRV/',
                // Not needed for web apps.
                '/system/Database/Seeder.php',
                '/system/Test/',
                '/system/CLI/',
                '/system/Commands/',
                '/system/Publisher/',
                '/system/ComposerScripts.php',
                // Not Class/Function files.
                '/system/Config/Routes.php',
                '/system/Language/',
                '/system/bootstrap.php',
                '/system/rewrite.php',
                '/Views/'


value00: preload.php
value01:
// Path to the front controller
define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR);

class preload
{
    /**
     * @var array Paths to preload.
     */
    private array $paths = [
        [
            'include' => __DIR__ . '/vendor/codeigniter4/framework/system', // Change this path if using manual installation
            'exclude' => [
                // Not needed if you don't use them.
                '/system/Database/OCI8/',
                '/system/Database/Postgre/'


value00: preload.php
value01:
    {
        foreach ($this->paths as $path) {
            $directory = new RecursiveDirectoryIterator($path['include']);
            $fullTree  = new RecursiveIteratorIterator($directory);
            $phpFiles  = new RegexIterator(
                $fullTree,
                '/.+((?<!Test)+\.php$)/i',
                RecursiveRegexIterator::GET_MATCH,
            );

            foreach ($phpFiles as $key => $file) {
                foreach ($path['exclude'] as $exclude) {
                    if (str_contains($file[0], $exclude)) {
                        continue 2;
                    }
                }

                require_once $file[0];
                echo 'Loaded: ' . $file[0] . "\n";
            }
        }
    }
}

(new preload())->load();


value00: app/Config/CURLRequest.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class CURLRequest extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * CURLRequest Share Options
     * --------------------------------------------------------------------------
     *
     * Whether share options between requests or not.
     *
     * If true, all the options won't be reset between requests.
     * It may cause an error request with unnecessary headers.
     */
    public bool $shareOptions = false;
}


value00: app/Config/Events.php
value01:
 * the 'on()' method. This accepts any form of callable, including
 * Closures, that will be executed when the event is triggered.
 *
 * Example:
 *      Events::on('create', [$myInstance, 'myMethod']);
 */


value00: app/Config/Events.php
value01:
     * --------------------------------------------------------------------
     * If you delete, they will no longer be collected.
     */
    if (CI_DEBUG && ! is_cli()) {
        Events::on('DBQuery', 'CodeIgniter\Debug\Toolbar\Collectors\Database::collect');
        service('toolbar')->respond();
        // Hot Reload route - for framework use on the hot reloader.
        if (ENVIRONMENT === 'development') {
            service('routes')->get('__hot-reload', static function (): void {
                (new HotReloader())->run();
            });
        }
    }
});


value00: app/Config/Events.php
value01:
Events::on('pre_system', static function (): void {
    if (ENVIRONMENT !== 'testing') {
        if (ini_get('zlib.output_compression')) {
            throw FrameworkException::forEnabledZlibOutputCompression();
        }

        while (ob_get_level() > 0) {
            ob_end_flush();
        }

        ob_start(static fn ($buffer) => $buffer);
    }

    /*
     * --------------------------------------------------------------------
     * Debug Toolbar Listeners.
     * --------------------------------------------------------------------
     * If you delete, they will no longer be collected.
     */


value00: app/Config/Events.php
value01:
<?php

namespace Config;

use CodeIgniter\Events\Events;
use CodeIgniter\Exceptions\FrameworkException;
use CodeIgniter\HotReloader\HotReloader;

/*
 * --------------------------------------------------------------------
 * Application Events
 * --------------------------------------------------------------------
 * Events allow you to tap into the execution of the program without
 * modifying or extending core files. This file provides a central
 * location to define your events, though they can always be added
 * at run-time, also, if needed.
 *
 * You create code that can execute by subscribing to events with
 * the 'on()' method. This accepts any form of callable, including
 * Closures, that will be executed when the event is triggered.
 *


value00: app/Config/DocTypes.php
value01:
<?php

namespace Config;

class DocTypes
{
    /**
     * List of valid document types.
     *
     * @var array<string, string>
     */
    public array $list = [
        'xhtml11'           => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
        'xhtml1-strict'     => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
        'xhtml1-trans'      => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
        'xhtml1-frame'      => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'


value00: app/Config/DocTypes.php
value01:
,
        'xhtml1-frame'      => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
        'xhtml-basic11'     => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
        'html5'             => '<!DOCTYPE html>',
        'html4-strict'      => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
        'html4-trans'       => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'


value00: app/Config/DocTypes.php
value01:
,
        'html4-trans'       => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
        'html4-frame'       => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
        'mathml1'           => '<!DOCTYPE math SYSTEM "http://www.w3.org/Math/DTD/mathml1/mathml.dtd">',
        'mathml2'           => '<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">',
        'svg10'             => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">'


value00: app/Config/DocTypes.php
value01:
,
        'xhtml-rdfa-2'      => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">',
    ];

    /**
     * Whether to remove the solidus (`/`) character for void HTML elements (e.g. `<input>`)
     * for HTML5 compatibility.
     *
     * Set to:
     *    `true` - to be HTML5 compatible
     *    `false` - to be XHTML compatible
     */
    public bool $html5 = true;
}


value00: app/Config/DocTypes.php
value01:
,
        'svg10'             => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">',
        'svg11'             => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
        'svg11-basic'       => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd">',
        'svg11-tiny'        => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">'


value00: app/Config/DocTypes.php
value01:
,
        'svg11-tiny'        => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">',
        'xhtml-math-svg-xh' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">',
        'xhtml-math-svg-sh' => '<!DOCTYPE svg:svg PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">',
        'xhtml-rdfa-1'      => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">',
        'xhtml-rdfa-2'      => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">',
    ]


value00: app/Config/Cors.php
value01:
,

        /**
         * Set methods to allow.
         *
         * The Access-Control-Allow-Methods response header specifies one or more
         * methods allowed when accessing a resource in response to a preflight
         * request.
         *
         * E.g.:
         *   - ['GET', 'POST', 'PUT', 'DELETE']
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
         */
        'allowedMethods' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],

        /**
         * Set how many seconds the results of a preflight request can be cached.
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
         */
        'maxAge' => 7200,
    ];
}


value00: app/Config/Cors.php
value01:
        'allowedOriginsPatterns' => [],

        /**
         * Weather to send the `Access-Control-Allow-Credentials` header.
         *
         * The Access-Control-Allow-Credentials response header tells browsers whether
         * the server allows cross-origin HTTP requests to include credentials.
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
         */
        'supportsCredentials' => true,


value00: app/Config/Cors.php
value01:
[
        /**
         * Origins for the `Access-Control-Allow-Origin` header.
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
         *
         * E.g.:
         *   - ['http://localhost:8080']
         *   - ['https://www.example.com']
         */
        'allowedOrigins' => ['http://localhost:5173', 'https://clqms01.services-summit.my.id'],


value00: app/Config/Cors.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

/**
 * Cross-Origin Resource Sharing (CORS) Configuration
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
 */
class Cors extends BaseConfig
{
    /**
     * The default CORS configuration.
     *
     * @var array{
     *      allowedOrigins: list<string>,
     *      allowedOriginsPatterns: list<string>,
     *      supportsCredentials: bool,
     *      allowedHeaders: list<string>,
     *      exposedHeaders: list<string>,
     *      allowedMethods: list<string>,
     *      maxAge: int,
     *  }
     */
    public array $default = [
        /**
         * Origins for the `Access-Control-Allow-Origin` header.


value00: app/Config/Cors.php
value01:
        'supportsCredentials' => true,

        /**
         * Set headers to allow.
         *
         * The Access-Control-Allow-Headers response header is used in response to
         * a preflight request which includes the Access-Control-Request-Headers to
         * indicate which HTTP headers can be used during the actual request.
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
         */
        'allowedHeaders' => ['Content-Type', 'Authorization', 'X-Requested-With'],


value00: app/Config/Exceptions.php
value01:
{
    /**
     * --------------------------------------------------------------------------
     * LOG EXCEPTIONS?
     * --------------------------------------------------------------------------
     * If true, then exceptions will be logged
     * through Services::Log.
     *
     * Default: true
     */
    public bool $log = true;

    /**
     * --------------------------------------------------------------------------
     * DO NOT LOG STATUS CODES
     * --------------------------------------------------------------------------
     * Any status codes here will NOT be logged if logging is turned on.
     * By default, only 404 (Page Not Found) exceptions are ignored.
     *
     * @var list<int>
     */
    public array $ignoreCodes = [404];


value00: app/Config/Exceptions.php
value01:
    public array $sensitiveDataInTrace = [];

    /**
     * --------------------------------------------------------------------------
     * WHETHER TO THROW AN EXCEPTION ON DEPRECATED ERRORS
     * --------------------------------------------------------------------------
     * If set to `true`, DEPRECATED errors are only logged and no exceptions are
     * thrown. This option also works for user deprecations.
     */
    public bool $logDeprecations = true;


value00: app/Config/Exceptions.php
value01:
    public bool $logDeprecations = true;

    /**
     * --------------------------------------------------------------------------
     * LOG LEVEL THRESHOLD FOR DEPRECATIONS
     * --------------------------------------------------------------------------
     * If `$logDeprecations` is set to `true`, this sets the log level
     * to which the deprecation will be logged. This should be one of the log
     * levels recognized by PSR-3.
     *
     * The related `Config\Logger::$threshold` should be adjusted, if needed,
     * to capture logging the deprecations.
     */
    public string $deprecationLogLevel = LogLevel::WARNING;


value00: app/Config/Cors.php
value01:
        'allowedOrigins' => ['http://localhost:5173', 'https://clqms01.services-summit.my.id'],

        /**
         * Origin regex patterns for the `Access-Control-Allow-Origin` header.
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
         *
         * NOTE: A pattern specified here is part of a regular expression. It will
         *       be actually `#\A<pattern>\z#`.
         *
         * E.g.:
         *   - ['https://\w+\.example\.com']
         */
        'allowedOriginsPatterns' => [],


value00: app/Config/Exceptions.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Debug\ExceptionHandler;
use CodeIgniter\Debug\ExceptionHandlerInterface;
use Psr\Log\LogLevel;
use Throwable;

/**
 * Setup how the exception handler works.
 */
class Exceptions extends BaseConfig


value00: app/Config/Exceptions.php
value01:
    public array $ignoreCodes = [404];

    /**
     * --------------------------------------------------------------------------
     * Error Views Path
     * --------------------------------------------------------------------------
     * This is the path to the directory that contains the 'cli' and 'html'
     * directories that hold the views used to generate errors.
     *
     * Default: APPPATH.'Views/errors'
     */
    public string $errorViewPath = __DIR__ . '/../Views/errors';


value00: app/Config/Cors.php
value01:
        'allowedHeaders' => ['Content-Type', 'Authorization', 'X-Requested-With'],

        /**
         * Set headers to expose.
         *
         * The Access-Control-Expose-Headers response header allows a server to
         * indicate which response headers should be made available to scripts running
         * in the browser, in response to a cross-origin request.
         *
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
         */
        'exposedHeaders' => [],


value00: app/Config/Exceptions.php
value01:
     *
     *      if (in_array($statusCode, [400, 404, 500])) {
     *          return new \App\Libraries\MyExceptionHandler();
     *      }
     *      if ($exception instanceOf PageNotFoundException) {
     *          return new \App\Libraries\MyExceptionHandler();
     *      }
     */
    public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
    {
        return new ExceptionHandler($this);
    }
}


value00: app/Config/Exceptions.php
value01:
    /*
     * DEFINE THE HANDLERS USED
     * --------------------------------------------------------------------------
     * Given the HTTP status code, returns exception handler that
     * should be used to deal with this error. By default, it will run CodeIgniter's
     * default handler and display the error information in the expected format
     * for CLI, HTTP, or AJAX requests, as determined by is_cli() and the expected
     * response format.
     *
     * Custom handlers can be returned if you want to handle one or more specific
     * error codes yourself like:
     *
     *      if (in_array($statusCode, [400, 404, 500])) {
     *          return new \App\Libraries\MyExceptionHandler();


value00: app/Config/Exceptions.php
value01:
    public string $errorViewPath = __DIR__ . '/../Views/errors';

    /**
     * --------------------------------------------------------------------------
     * HIDE FROM DEBUG TRACE
     * --------------------------------------------------------------------------
     * Any data that you would like to hide from the debug trace.
     * In order to specify 2 levels, use "/" to separate.
     * ex. ['server', 'setup/password', 'secret_token']
     *
     * @var list<string>
     */
    public array $sensitiveDataInTrace = [];


value00: app/Config/Feature.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

/**
 * Enable/disable backward compatibility breaking features.
 */
class Feature extends BaseConfig
{
    /**
     * Use improved new auto routing instead of the legacy version.
     */
    public bool $autoRoutesImproved = true;

    /**
     * Use filter execution order in 4.4 or before.
     */
    public bool $oldFilterOrder = false;


value00: app/Config/Feature.php
value01:
    /**
     * Use filter execution order in 4.4 or before.
     */
    public bool $oldFilterOrder = false;

    /**
     * The behavior of `limit(0)` in Query Builder.
     *
     * If true, `limit(0)` returns all records. (the behavior of 4.4.x or before in version 4.x.)
     * If false, `limit(0)` returns no records. (the behavior of 3.1.9 or later in version 3.x.)
     */
    public bool $limitZeroAsAll = true;

    /**
     * Use strict location negotiation.
     *
     * By default, the locale is selected based on a loose comparison of the language code (ISO 639-1)
     * Enabling strict comparison will also consider the region code (ISO 3166-1 alpha-2).
     */
    public bool $strictLocaleNegotiation = false;
}


value00: app/Config/Filters.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\Filters as BaseFilters;
// use CodeIgniter\Filters\Cors;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\ForceHTTPS;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\PageCache;
use CodeIgniter\Filters\PerformanceMetrics;
use CodeIgniter\Filters\SecureHeaders;

class Filters extends BaseFilters
{
    /**
     * Configures aliases for Filter classes to
     * make reading things nicer and simpler.
     *
     * @var array<string, class-string|list<class-string>>
     *
     * [filter_name => classname]
     * or [filter_name => [classname1, classname2, ...]]
     */


value00: app/Config/Filters.php
value01:
    public array $required = [
        'before' => [
            // 'forcehttps', // Force Global Secure Requests - disabled for localhost
            'pagecache',  // Web Page Caching
        ],
        'after' => [
            'pagecache',   // Web Page Caching
            'performance', // Performance Metrics
            'toolbar',     // Debug Toolbar
        ],
    ];

    /**
     * List of filter aliases that are always
     * applied before and after every request.
     *
     * @var array<string, array<string, array<string, string>>>|array<string, list<string>>
     */


value00: app/Config/Filters.php
value01:
    public array $methods = [];

    /**
     * List of filter aliases that should run on any
     * before or after URI patterns.
     *
     * Example:
     * 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
     *
     * @var array<string, array<string, list<string>>>
     */
    public array $filters = [];
}


value00: app/Config/Filters.php
value01:
    public array $globals = [
        'before' => [
            'cors',
            // 'honeypot',
            // 'csrf',
            // 'invalidchars',
        ],
        'after' => [
            // 'honeypot',
            // 'secureheaders',
        ],
    ];

    /**
     * List of filter aliases that works on a
     * particular HTTP method (GET, POST, etc.).
     *
     * Example:
     * 'POST' => ['foo', 'bar']
     *
     * If you use this, you should disable auto-routing because auto-routing
     * permits any HTTP method to access a controller. Accessing the controller
     * with a method you don't expect could bypass the filter.
     *
     * @var array<string, list<string>>
     */
    public array $methods = [];


value00: app/Config/Filters.php
value01:
    /**
     * List of special required filters.
     *
     * The filters listed here are special. They are applied before and after
     * other kinds of filters, and always applied even if a route does not exist.
     *
     * Filters set by default provide framework functionality. If removed,
     * those functions will no longer work.
     *
     * @see https://codeigniter.com/user_guide/incoming/filters.html#provided-filters
     *
     * @var array{before: list<string>, after: list<string>}
     */


value00: app/Config/Filters.php
value01:
    public array $aliases = [
        'csrf'          => CSRF::class,
        'toolbar'       => DebugToolbar::class,
        'honeypot'      => Honeypot::class,
        'invalidchars'  => InvalidChars::class,
        'secureheaders' => SecureHeaders::class,
        // 'cors'          => Cors::class,
        'cors'          => \App\Filters\Cors::class,
        'forcehttps'    => ForceHTTPS::class,
        'pagecache'     => PageCache::class,
        'performance'   => PerformanceMetrics::class,
        'auth'          => \App\Filters\AuthFilter::class,
    ];


value00: app/Config/Format.php
value01:
     *
     * These formats are only checked when the data passed to the respond()
     * method is an array.
     *
     * @var list<string>
     */
    public array $supportedResponseFormats = [
        'application/json',
        'application/xml', // machine-readable XML
        'text/xml', // human-readable XML
    ];


value00: app/Config/Format.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Formatters
     * --------------------------------------------------------------------------
     *
     * Lists the class to use to format responses with of a particular type.
     * For each mime type, list the class that should be used. Formatters
     * can be retrieved through the getFormatter() method.
     *
     * @var array<string, string>
     */
    public array $formatters = [
        'application/json' => JSONFormatter::class,
        'application/xml'  => XMLFormatter::class,
        'text/xml'         => XMLFormatter::class,
    ];


value00: app/Config/Format.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Formatters Options
     * --------------------------------------------------------------------------
     *
     * Additional Options to adjust default formatters behaviour.
     * For each mime type, list the additional options that should be used.
     *
     * @var array<string, int>
     */
    public array $formatterOptions = [
        'application/json' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
        'application/xml'  => 0,
        'text/xml'         => 0,
    ];
}


value00: app/Config/Format.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Format\JSONFormatter;
use CodeIgniter\Format\XMLFormatter;

class Format extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Available Response Formats
     * --------------------------------------------------------------------------
     *
     * When you perform content negotiation with the request, these are the
     * available formats that your application supports. This is currently
     * only used with the API\ResponseTrait. A valid Formatter must exist
     * for the specified format.
     *
     * These formats are only checked when the data passed to the respond()
     * method is an array.
     *


value00: app/Config/Email.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Email extends BaseConfig
{
    public string $fromEmail  = '';
    public string $fromName   = '';
    public string $recipients = '';

    /**
     * The "user agent"
     */
    public string $userAgent = 'CodeIgniter';

    /**
     * The mail sending protocol: mail, sendmail, smtp
     */
    public string $protocol = 'mail';

    /**
     * The server path to Sendmail.
     */
    public string $mailPath = '/usr/sbin/sendmail';

    /**
     * SMTP Server Hostname
     */
    public string $SMTPHost = '';

    /**
     * SMTP Username
     */
    public string $SMTPUser = '';

    /**
     * SMTP Password
     */


value00: app/Config/Email.php
value01:
    public string $mailType = 'text';

    /**
     * Character set (utf-8, iso-8859-1, etc.)
     */
    public string $charset = 'UTF-8';

    /**
     * Whether to validate the email address
     */
    public bool $validate = false;

    /**
     * Email Priority. 1 = highest. 5 = lowest. 3 = normal
     */


value00: app/Config/Email.php
value01:
    /**
     * SMTP Username
     */
    public string $SMTPUser = '';

    /**
     * SMTP Password
     */
    public string $SMTPPass = '';

    /**
     * SMTP Port
     */
    public int $SMTPPort = 25;

    /**
     * SMTP Timeout (in seconds)
     */
    public int $SMTPTimeout = 5;

    /**
     * Enable persistent SMTP connections
     */
    public bool $SMTPKeepAlive = false;


value00: app/Config/Email.php
value01:
    public int $SMTPTimeout = 5;

    /**
     * Enable persistent SMTP connections
     */
    public bool $SMTPKeepAlive = false;

    /**
     * SMTP Encryption.
     *
     * @var string '', 'tls' or 'ssl'. 'tls' will issue a STARTTLS command
     *             to the server. 'ssl' means implicit SSL. Connection on port
     *             465 should set this to ''.
     */
    public string $SMTPCrypto = 'tls';

    /**
     * Enable word-wrap
     */
    public bool $wordWrap = true;

    /**
     * Character count to wrap at
     */
    public int $wrapChars = 76;

    /**
     * Type of mail, either 'text' or 'html'
     */
    public string $mailType = 'text';

    /**
     * Character set (utf-8, iso-8859-1, etc.)
     */


value00: app/Config/Email.php
value01:
    public bool $validate = false;

    /**
     * Email Priority. 1 = highest. 5 = lowest. 3 = normal
     */
    public int $priority = 3;

    /**
     * Newline character. (Use “\r\n” to comply with RFC 822)
     */
    public string $CRLF = "\r\n";

    /**
     * Newline character. (Use “\r\n” to comply with RFC 822)
     */
    public string $newline = "\r\n";

    /**
     * Enable BCC Batch Mode.
     */
    public bool $BCCBatchMode = false;

    /**
     * Number of emails in each BCC batch
     */
    public int $BCCBatchSize = 200;

    /**
     * Enable notify message from server
     */
    public bool $DSN = false;
}


value00: app/Config/Encryption.php
value01:
    public int $blockSize = 16;

    /**
     * --------------------------------------------------------------------------
     * Encryption digest
     * --------------------------------------------------------------------------
     *
     * HMAC digest to use, e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'.
     */
    public string $digest = 'SHA512';

    /**
     * Whether the cipher-text should be raw. If set to false, then it will be base64 encoded.
     * This setting is only used by OpenSSLHandler.
     *
     * Set to false for CI3 Encryption compatibility.
     */
    public bool $rawData = true;


value00: app/Config/Encryption.php
value01:
    public string $driver = 'OpenSSL';

    /**
     * --------------------------------------------------------------------------
     * SodiumHandler's Padding Length in Bytes
     * --------------------------------------------------------------------------
     *
     * This is the number of bytes that will be padded to the plaintext message
     * before it is encrypted. This value should be greater than zero.
     *
     * See the user guide for more information on padding.
     */
    public int $blockSize = 16;


value00: app/Config/Encryption.php
value01:
    public string $key = '';

    /**
     * --------------------------------------------------------------------------
     * Encryption Driver to Use
     * --------------------------------------------------------------------------
     *
     * One of the supported encryption drivers.
     *
     * Available drivers:
     * - OpenSSL
     * - Sodium
     */
    public string $driver = 'OpenSSL';


value00: app/Config/Encryption.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

/**
 * Encryption configuration.
 *
 * These are the settings used for encryption, if you don't pass a parameter
 * array to the encrypter for creation/initialization.
 */
class Encryption extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Encryption Key Starter
     * --------------------------------------------------------------------------
     *
     * If you use the Encryption class you must set an encryption key (seed).
     * You need to ensure it is long enough for the cipher and mode you plan to use.
     * See the user guide for more info.
     */
    public string $key = '';


value00: app/Config/Encryption.php
value01:
    public bool $rawData = true;

    /**
     * Encryption key info.
     * This setting is only used by OpenSSLHandler.
     *
     * Set to 'encryption' for CI3 Encryption compatibility.
     */
    public string $encryptKeyInfo = '';

    /**
     * Authentication key info.
     * This setting is only used by OpenSSLHandler.
     *
     * Set to 'authentication' for CI3 Encryption compatibility.
     */
    public string $authKeyInfo = '';

    /**
     * Cipher to use.
     * This setting is only used by OpenSSLHandler.
     *
     * Set to 'AES-128-CBC' to decrypt encrypted data that encrypted
     * by CI3 Encryption default configuration.
     */
    public string $cipher = 'AES-256-CTR';
}


value00: app/Config/Kint.php
value01:
    public $richObjectPlugins;

    /**
     * @var array<string, class-string<TabPluginInterface>>|null
     */
    public $richTabPlugins;

    /*
    |--------------------------------------------------------------------------
    | CLI Settings
    |--------------------------------------------------------------------------
    */
    public bool $cliColors      = true;
    public bool $cliForceUTF8   = false;
    public bool $cliDetectWidth = true;
    public int $cliMinWidth     = 40;
}


value00: app/Config/Kint.php
value01:
<?php

namespace Config;

use Kint\Parser\ConstructablePluginInterface;
use Kint\Renderer\Rich\TabPluginInterface;
use Kint\Renderer\Rich\ValuePluginInterface;

/**
 * --------------------------------------------------------------------------
 * Kint
 * --------------------------------------------------------------------------
 *
 * We use Kint's `RichRenderer` and `CLIRenderer`. This area contains options
 * that you can set to customize how Kint works for you.
 *
 * @see https://kint-php.github.io/kint/ for details on these settings.
 */
class Kint


value00: app/Config/Kint.php
value01:
{
    /*
    |--------------------------------------------------------------------------
    | Global Settings
    |--------------------------------------------------------------------------
    */

    /**
     * @var list<class-string<ConstructablePluginInterface>|ConstructablePluginInterface>|null
     */
    public $plugins;

    public int $maxDepth           = 6;
    public bool $displayCalledFrom = true;
    public bool $expanded          = false;


value00: app/Config/ForeignCharacters.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\ForeignCharacters as BaseForeignCharacters;

/**
 * @immutable
 */
class ForeignCharacters extends BaseForeignCharacters
{
}


value00: app/Config/Kint.php
value01:
    public int $maxDepth           = 6;
    public bool $displayCalledFrom = true;
    public bool $expanded          = false;

    /*
    |--------------------------------------------------------------------------
    | RichRenderer Settings
    |--------------------------------------------------------------------------
    */
    public string $richTheme = 'aante-light.css';
    public bool $richFolder  = false;

    /**
     * @var array<string, class-string<ValuePluginInterface>>|null
     */
    public $richObjectPlugins;

    /**
     * @var array<string, class-string<TabPluginInterface>>|null
     */


value00: app/Config/Logger.php
value01:
     * threshold determines what gets logged. Any values below or equal to the
     * threshold will be logged.
     *
     * Threshold options are:
     *
     * - 0 = Disables logging, Error logging TURNED OFF
     * - 1 = Emergency Messages - System is unusable
     * - 2 = Alert Messages - Action Must Be Taken Immediately
     * - 3 = Critical Messages - Application component unavailable, unexpected exception.
     * - 4 = Runtime Errors - Don't need immediate action, but should be monitored.
     * - 5 = Warnings - Exceptional occurrences that are not errors.
     * - 6 = Notices - Normal but significant events.
     * - 7 = Info - Interesting events, like user logging in, etc.
     * - 8 = Debug - Detailed debug information.


value00: app/Config/Logger.php
value01:
     * a file on the getServer, a cloud-based service, or even taking actions such
     * as emailing the dev team.
     *
     * Each handler is defined by the class name used for that handler, and it
     * MUST implement the `CodeIgniter\Log\Handlers\HandlerInterface` interface.
     *
     * The value of each key is an array of configuration items that are sent
     * to the constructor of each handler. The only required configuration item
     * is the 'handles' element, which must be an array of integer log levels.
     * This is most easily handled by using the constants defined in the
     * `Psr\Log\LogLevel` class.
     *
     * Handlers are executed in the order defined in this array, starting with
     * the handler on top and continuing down.


value00: app/Config/Logger.php
value01:
[
            // The log levels that this handler will handle.
            'handles' => [
                'critical',
                'alert',
                'emergency',
                'debug',
                'error',
                'info',
                'notice',
                'warning',
            ],

            /*
             * The default filename extension for log files.
             * An extension of 'php' allows for protecting the log files via basic
             * scripting, when they are to be stored under a publicly accessible directory.
             *
             * NOTE: Leaving it blank will default to 'log'.
             */
            'fileExtension' => '',


value00: app/Config/Logger.php
value01:
     * - 7 = Info - Interesting events, like user logging in, etc.
     * - 8 = Debug - Detailed debug information.
     * - 9 = All Messages
     *
     * You can also pass an array with threshold levels to show individual error types
     *
     *     array(1, 2, 3, 8) = Emergency, Alert, Critical, and Debug messages
     *
     * For a live site you'll usually enable Critical or higher (3) to be logged otherwise
     * your log files will fill up very fast.
     *
     * @var int|list<int>
     */


value00: app/Config/Logger.php
value01:
     *
     * Handlers are executed in the order defined in this array, starting with
     * the handler on top and continuing down.
     *
     * @var array<class-string, array<string, int|list<string>|string>>
     */


value00: app/Config/Logger.php
value01:
            'fileExtension' => '',

            /*
             * The file system permissions to be applied on newly created log files.
             *
             * IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal
             * integer notation (i.e. 0700, 0644, etc.)
             */
            'filePermissions' => 0644,

            /*
             * Logging Directory Path
             *
             * By default, logs are written to WRITEPATH . 'logs/'
             * Specify a different destination here, if desired.
             */
            'path' => '',
        ]


value00: app/Config/Logger.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Log Handlers
     * --------------------------------------------------------------------------
     *
     * The logging system supports multiple actions to be taken when something
     * is logged. This is done by allowing for multiple Handlers, special classes
     * designed to write the log to their chosen destinations, whether that is
     * a file on the getServer, a cloud-based service, or even taking actions such
     * as emailing the dev team.


value00: app/Config/Logger.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Log\Handlers\FileHandler;

class Logger extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Error Logging Threshold
     * --------------------------------------------------------------------------
     *
     * You can enable error logging by setting a threshold over zero. The
     * threshold determines what gets logged. Any values below or equal to the
     * threshold will be logged.


value00: app/Config/Logger.php
value01:
    public array $handlers = [
        /*
         * --------------------------------------------------------------------
         * File Handler
         * --------------------------------------------------------------------
         */
        FileHandler::class => [
            // The log levels that this handler will handle.
            'handles' => [
                'critical',
                'alert'


value00: app/Config/Logger.php
value01:
        //                   'error', 'info', 'notice', 'warning'],
        // ],

        /*
         * The ErrorlogHandler writes the logs to PHP's native `error_log()` function.
         * Uncomment this block to use it.
         */
        // 'CodeIgniter\Log\Handlers\ErrorlogHandler' => [
        //     /* The log levels this handler can handle. */
        //     'handles' => ['critical', 'alert', 'emergency', 'debug', 'error', 'info', 'notice', 'warning'],
        //
        //     /*
        //     * The message type where the error should go. Can be 0 or 4, or use the
        //     * class constants: `ErrorlogHandler::TYPE_OS` (0) or `ErrorlogHandler::TYPE_SAPI` (4)
        //     */
        //     'messageType' => 0,
        // ],
    ];
}


value00: app/Config/Logger.php
value01:
    public $threshold = (ENVIRONMENT === 'production') ? 4 : 9;

    /**
     * --------------------------------------------------------------------------
     * Date Format for Logs
     * --------------------------------------------------------------------------
     *
     * Each item that is logged has an associated date. You can use PHP date
     * codes to set your own date formatting
     */
    public string $dateFormat = 'Y-m-d H:i:s';


value00: app/Config/Logger.php
value01:
,

        /*
         * The ChromeLoggerHandler requires the use of the Chrome web browser
         * and the ChromeLogger extension. Uncomment this block to use it.
         */
        // 'CodeIgniter\Log\Handlers\ChromeLoggerHandler' => [
        //     /*
        //      * The log levels that this handler will handle.
        //      */
        //     'handles' => ['critical', 'alert', 'emergency', 'debug',
        //                   'error', 'info', 'notice', 'warning'],


value00: app/Config/Modules.php
value01:
<?php

namespace Config;

use CodeIgniter\Modules\Modules as BaseModules;

/**
 * Modules Configuration.
 *
 * NOTE: This class is required prior to Autoloader instantiation,
 *       and does not extend BaseConfig.
 */
class Modules extends BaseModules
{
    /**
     * --------------------------------------------------------------------------
     * Enable Auto-Discovery?
     * --------------------------------------------------------------------------
     *
     * If true, then auto-discovery will happen across all elements listed in
     * $aliases below. If false, no auto-discovery will happen at all,
     * giving a slight performance boost.
     *
     * @var bool
     */
    public $enabled = true;


value00: app/Config/Modules.php
value01:
    public $composerPackages = [];

    /**
     * --------------------------------------------------------------------------
     * Auto-Discovery Rules
     * --------------------------------------------------------------------------
     *
     * Aliases list of all discovery classes that will be active and used during
     * the current application request.
     *
     * If it is not listed, only the base application elements will be used.
     *
     * @var list<string>
     */
    public $aliases = [
        'events',
        'filters',
        'registrars',
        'routes',
        'services',
    ];
}


value00: app/Config/Modules.php
value01:
    public $discoverInComposer = true;

    /**
     * The Composer package list for Auto-Discovery
     * This setting is optional.
     *
     * E.g.:
     *   [
     *       'only' => [
     *           // List up all packages to auto-discover
     *           'codeigniter4/shield',
     *       ],
     *   ]
     *   or
     *   [
     *       'exclude' => [
     *           // List up packages to exclude.
     *           'pestphp/pest',
     *       ],
     *   ]
     *
     * @var array{only?: list<string>, exclude?: list<string>}
     */
    public $composerPackages = [];


value00: app/Config/Modules.php
value01:
    public $enabled = true;

    /**
     * --------------------------------------------------------------------------
     * Enable Auto-Discovery Within Composer Packages?
     * --------------------------------------------------------------------------
     *
     * If true, then auto-discovery will happen across all namespaces loaded
     * by Composer, as well as the namespaces configured locally.
     *
     * @var bool
     */
    public $discoverInComposer = true;


value00: app/Config/Optimize.php
value01:
class Optimize
{
    /**
     * --------------------------------------------------------------------------
     * Config Caching
     * --------------------------------------------------------------------------
     *
     * @see https://codeigniter.com/user_guide/concepts/factories.html#config-caching
     */
    public bool $configCacheEnabled = false;

    /**
     * --------------------------------------------------------------------------
     * Config Caching
     * --------------------------------------------------------------------------
     *
     * @see https://codeigniter.com/user_guide/concepts/autoloader.html#file-locator-caching
     */
    public bool $locatorCacheEnabled = false;
}


value00: app/Config/Optimize.php
value01:
<?php

namespace Config;

/**
 * Optimization Configuration.
 *
 * NOTE: This class does not extend BaseConfig for performance reasons.
 *       So you cannot replace the property values with Environment Variables.
 */


value00: app/Config/Paths.php
value01:
    public string $appDirectory = __DIR__ . '/..';

    /**
     * ---------------------------------------------------------------
     * WRITABLE DIRECTORY NAME
     * ---------------------------------------------------------------
     *
     * This variable must contain the name of your "writable" directory.
     * The writable directory allows you to group all directories that
     * need write permission to a single place that can be tucked away
     * for maximum security, keeping it out of the app and/or
     * system directories.
     */
    public string $writableDirectory = __DIR__ . '/../../writable';


value00: app/Config/Paths.php
value01:
    public string $writableDirectory = __DIR__ . '/../../writable';

    /**
     * ---------------------------------------------------------------
     * TESTS DIRECTORY NAME
     * ---------------------------------------------------------------
     *
     * This variable must contain the name of your "tests" directory.
     */
    public string $testsDirectory = __DIR__ . '/../../tests';


value00: app/Config/Paths.php
value01:
    public string $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system';

    /**
     * ---------------------------------------------------------------
     * APPLICATION FOLDER NAME
     * ---------------------------------------------------------------
     *
     * If you want this front controller to use a different "app"
     * folder than the default one you can set its name here. The folder
     * can also be renamed or relocated anywhere on your server. If
     * you do, use a full server path.
     *
     * @see http://codeigniter.com/user_guide/general/managing_apps.html
     */
    public string $appDirectory = __DIR__ . '/..';


value00: app/Config/Paths.php
value01:
    public string $testsDirectory = __DIR__ . '/../../tests';

    /**
     * ---------------------------------------------------------------
     * VIEW DIRECTORY NAME
     * ---------------------------------------------------------------
     *
     * This variable must contain the name of the directory that
     * contains the view files used by your application. By
     * default this is in `app/Views`. This value
     * is used when no value is provided to `Services::renderer()`.
     */
    public string $viewDirectory = __DIR__ . '/../Views';
}


value00: app/Config/Paths.php
value01:
<?php

namespace Config;

/**
 * Paths
 *
 * Holds the paths that are used by the system to
 * locate the main directories, app, system, etc.
 *
 * Modifying these allows you to restructure your application,
 * share a system folder between multiple applications, and more.
 *
 * All paths are relative to the project's root folder.
 */
class Paths
{
    /**
     * ---------------------------------------------------------------
     * SYSTEM FOLDER NAME
     * ---------------------------------------------------------------
     *
     * This must contain the name of your "system" folder. Include
     * the path if the folder is not in the same directory as this file.
     */
    public string $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system';


value00: app/Config/Routes.php
value01:
// V2 Auth API Routes (public - no auth required)
$routes->group('v2/auth', function ($routes) {
    $routes->post('login', 'AuthV2Controller::login');
    $routes->post('register', 'AuthV2Controller::register');
    $routes->get('check', 'AuthV2Controller::checkAuth');
    $routes->post('logout', 'AuthV2Controller::logout');
});

// Faker
$routes->get('faker/faker-patient/(:num)', 'faker\FakerPatient::sendMany/$1');


value00: app/Config/Routes.php
value01:
    $routes->group('location', function ($routes) {
        $routes->get('/', 'LocationController::index');
        $routes->get('(:num)', 'LocationController::show/$1');
        $routes->post('/', 'LocationController::create');
        $routes->patch('(:num)', 'LocationController::update/$1');
        $routes->delete('/', 'LocationController::delete');
    });

    // Contact
    $routes->group('contact', function ($routes) {
        $routes->get('/', 'Contact\ContactController::index');
        $routes->get('(:num)', 'Contact\ContactController::show/$1');
        $routes->post('/', 'Contact\ContactController::create');
        $routes->patch('(:num)', 'Contact\ContactController::update/$1');
        $routes->delete('/', 'Contact\ContactController::delete');
    });


value00: app/Config/Routes.php
value01:
$routes->get('/', function () {
    return "Backend Running";
});

$routes->options('(:any)', function () {
    return '';
});

$routes->group('api', ['filter' => 'auth'], function ($routes) {
    $routes->get('dashboard', 'DashboardController::index');
    $routes->get('sample', 'SampleController::index');
    
    // Results CRUD
    $routes->group('result', function ($routes) {
        $routes->get('/', 'ResultController::index');
        $routes->get('(:num)', 'ResultController::show/$1');
        $routes->patch('(:num)', 'ResultController::update/$1');
        $routes->delete('(:num)', 'ResultController::delete/$1');
    });
    
    // Reports
    $routes->get('report/(:num)', 'ReportController::view/$1');
});


value00: app/Config/Routes.php
value01:
    // Result ValueSet
    $routes->group('result', function ($routes) {
        $routes->group('valueset', function ($routes) {
            $routes->get('/', 'Result\ResultValueSetController::index');
            $routes->get('(:num)', 'Result\ResultValueSetController::show/$1');
            $routes->post('/', 'Result\ResultValueSetController::create');
            $routes->put('(:num)', 'Result\ResultValueSetController::update/$1');
            $routes->delete('(:num)', 'Result\ResultValueSetController::delete/$1');
        });
    });

    $routes->post('calc/testsite/(:num)', 'CalculatorController::calculateByTestSite/$1');
    $routes->post('calc/testcode/(:any)', 'CalculatorController::calculateByCodeOrName/$1');

    // Counter


value00: app/Config/Routes.php
value01:
// Faker
$routes->get('faker/faker-patient/(:num)', 'faker\FakerPatient::sendMany/$1');

$routes->group('api', function ($routes) {
    // Auth
    $routes->group('auth', function ($routes) {
        $routes->post('login', 'AuthController::login');
        $routes->post('change_pass', 'AuthController::change_pass');
        $routes->post('register', 'AuthController::register');
        $routes->get('check', 'AuthController::checkAuth');
        $routes->post('logout', 'AuthController::logout');
    });

    // Patient


value00: app/Config/Routes.php
value01:
        // Department
        $routes->group('department', function ($routes) {
            $routes->get('/', 'Organization\DepartmentController::index');
            $routes->get('(:num)', 'Organization\DepartmentController::show/$1');
            $routes->post('/', 'Organization\DepartmentController::create');
            $routes->patch('(:num)', 'Organization\DepartmentController::update/$1');
            $routes->delete('/', 'Organization\DepartmentController::delete');
        });

        // Workstation


value00: app/Config/Routes.php
value01:
    $routes->group('occupation', function ($routes) {
        $routes->get('/', 'Contact\OccupationController::index');
        $routes->get('(:num)', 'Contact\OccupationController::show/$1');
        $routes->post('/', 'Contact\OccupationController::create');
        $routes->patch('(:num)', 'Contact\OccupationController::update/$1');
        //$routes->delete('/', 'Contact\OccupationController::delete');
    });


value00: app/Config/Routes.php
value01:
        // CodingSys
        $routes->group('codingsys', function ($routes) {
            $routes->get('/', 'Organization\CodingSysController::index');
            $routes->get('(:num)', 'Organization\CodingSysController::show/$1');
            $routes->post('/', 'Organization\CodingSysController::create');
            $routes->patch('(:num)', 'Organization\CodingSysController::update/$1');
            $routes->delete('/', 'Organization\CodingSysController::delete');
        });
    }


value00: app/Config/Routes.php
value01:
    $routes->group('medicalspecialty', function ($routes) {
        $routes->get('/', 'Contact\MedicalSpecialtyController::index');
        $routes->get('(:num)', 'Contact\MedicalSpecialtyController::show/$1');
        $routes->post('/', 'Contact\MedicalSpecialtyController::create');
        $routes->patch('(:num)', 'Contact\MedicalSpecialtyController::update/$1');
    });

    // Lib ValueSet (file-based)


value00: app/Config/Routes.php
value01:
);

    // Infrastructure
    $routes->group('equipmentlist', function ($routes) {
        $routes->get('/', 'Infrastructure\EquipmentListController::index');
        $routes->get('(:num)', 'Infrastructure\EquipmentListController::show/$1');
        $routes->post('/', 'Infrastructure\EquipmentListController::create');
        $routes->patch('(:num)', 'Infrastructure\EquipmentListController::update/$1');
        $routes->delete('/', 'Infrastructure\EquipmentListController::delete');
    });

    // Users


value00: app/Config/Routes.php
value01:
        $routes->group('collection', function ($routes) {
            $routes->get('/', 'Specimen\SpecimenCollectionController::index');
            $routes->get('(:num)', 'Specimen\SpecimenCollectionController::show/$1');
            $routes->post('/', 'Specimen\SpecimenCollectionController::create');
            $routes->patch('(:num)', 'Specimen\SpecimenCollectionController::update/$1');
        });

    $routes->get('/', 'Specimen\SpecimenController::index');
    $routes->get('(:num)', 'Specimen\SpecimenController::show/$1');
    $routes->post('/', 'Specimen\SpecimenController::create');
    $routes->patch('(:num)', 'Specimen\SpecimenController::update/$1');
    $routes->delete('(:num)', 'Specimen\SpecimenController::delete/$1');
}


value00: app/Config/Routes.php
value01:
        // Discipline
        $routes->group('discipline', function ($routes) {
            $routes->get('/', 'Organization\DisciplineController::index');
            $routes->get('(:num)', 'Organization\DisciplineController::show/$1');
            $routes->post('/', 'Organization\DisciplineController::create');
            $routes->patch('(:num)', 'Organization\DisciplineController::update/$1');
            $routes->delete('/', 'Organization\DisciplineController::delete');
        });

        // Department


value00: app/Config/Routes.php
value01:
    $routes->post('calc/testcode/(:any)', 'CalculatorController::calculateByCodeOrName/$1');

    // Counter
    $routes->group('counter', function ($routes) {
        $routes->get('/', 'CounterController::index');
        $routes->get('(:num)', 'CounterController::show/$1');
        $routes->post('/', 'CounterController::create');
        $routes->patch('(:num)', 'CounterController::update/$1');
        $routes->delete('/', 'CounterController::delete');
    });

    // AreaGeo
    $routes->group('areageo', function ($routes) {
        $routes->get('/', 'AreaGeoController::index');
        $routes->get('provinces', 'AreaGeoController::getProvinces');
        $routes->get('cities', 'AreaGeoController::getCities');
    });

    // Organization


value00: app/Config/Routes.php
value01:
    // PatVisit
    $routes->group('patvisit', function ($routes) {
        $routes->get('/', 'PatVisitController::index');
        $routes->post('/', 'PatVisitController::create');
        $routes->get('patient/(:num)', 'PatVisitController::showByPatient/$1');
        $routes->get('(:any)', 'PatVisitController::show/$1');
        $routes->delete('/', 'PatVisitController::delete');
        $routes->patch('(:any)', 'PatVisitController::update/$1');
    });


value00: app/Config/Routes.php
value01:
    $routes->group('organization', function ($routes) {
        // Account
        $routes->group('account', function ($routes) {
            $routes->get('/', 'Organization\AccountController::index');
            $routes->get('(:num)', 'Organization\AccountController::show/$1');
            $routes->post('/', 'Organization\AccountController::create');
            $routes->patch('(:num)', 'Organization\AccountController::update/$1');
            $routes->delete('/', 'Organization\AccountController::delete');
        });

        // Site


value00: app/Config/Routes.php
value01:
                $routes->delete('batch', 'Test\TestMapDetailController::batchDelete');
            });
        });
    });

    // Orders
    $routes->group('ordertest', function ($routes) {
        $routes->get('/', 'OrderTestController::index');
        $routes->get('(:any)', 'OrderTestController::show/$1');
        $routes->post('/', 'OrderTestController::create');
        $routes->patch('(:any)', 'OrderTestController::update/$1');
        $routes->delete('/', 'OrderTestController::delete');
        $routes->post('status', 'OrderTestController::updateStatus');
    });

    // Rules


value00: app/Config/Routes.php
value01:
        // Site
        $routes->group('site', function ($routes) {
            $routes->get('/', 'Organization\SiteController::index');
            $routes->get('(:num)', 'Organization\SiteController::show/$1');
            $routes->post('/', 'Organization\SiteController::create');
            $routes->patch('(:num)', 'Organization\SiteController::update/$1');
            $routes->delete('/', 'Organization\SiteController::delete');
        });

        // Discipline


value00: app/Config/Routes.php
value01:
// Edge API - Integration with tiny-edge
    $routes->group('edge', function ($routes) {
        $routes->post('result', 'EdgeController::results');
        $routes->get('order', 'EdgeController::orders');
        $routes->post('order/(:num)/ack', 'EdgeController::ack/$1');
        $routes->post('status', 'EdgeController::status');
    });
});

// Khusus
/*
$routes->get('/api/zones', 'Zones::index');
$routes->get('/api/zones/synchronize', 'Zones::synchronize');
$routes->get('/api/zones/provinces', 'Zones::getProvinces');
$routes->get('/api/zones/cities', 'Zones::getCities');
*/


value00: app/Config/Routes.php
value01:
        // HostComPara
        $routes->group('hostcompara', function ($routes) {
            $routes->get('/', 'Organization\HostComParaController::index');
            $routes->get('(:any)', 'Organization\HostComParaController::show/$1');
            $routes->post('/', 'Organization\HostComParaController::create');
            $routes->patch('(:any)', 'Organization\HostComParaController::update/$1');
            $routes->delete('/', 'Organization\HostComParaController::delete');
        });

        // CodingSys


value00: app/Config/Routes.php
value01:
    // Users
    $routes->group('user', function ($routes) {
        $routes->get('/', 'User\UserController::index');
        $routes->get('(:num)', 'User\UserController::show/$1');
        $routes->post('/', 'User\UserController::create');
        $routes->patch('(:num)', 'User\UserController::update/$1');
        $routes->delete('(:num)', 'User\UserController::delete/$1');
    });

    // Specimen
    $routes->group('specimen', function ($routes) {
        // Container aliases - 'container' and 'containerdef' both point to ContainerDefController


value00: app/Config/Routes.php
value01:
    $routes->group('valueset', function ($routes) {
        $routes->get('/', 'ValueSetController::index');
        $routes->get('(:any)', 'ValueSetController::index/$1');
        $routes->post('refresh', 'ValueSetController::refresh');

        // User ValueSet (database-based)
        $routes->group('user', function ($routes) {
            $routes->group('items', function ($routes) {
                $routes->get('/', 'ValueSetController::items');
                $routes->get('(:num)', 'ValueSetController::showItem/$1');
                $routes->post('/', 'ValueSetController::createItem');
                $routes->put('(:num)', 'ValueSetController::updateItem/$1');
                $routes->delete('(:num)', 'ValueSetController::deleteItem/$1');
            });


value00: app/Config/Routes.php
value01:
<?php

use CodeIgniter\Router\RouteCollection;

/**
 * @var RouteCollection $routes
 */
$routes->get('/', function () {
    return "Backend Running";
});

$routes->options('(:any)', function () {
    return '';
});


value00: app/Config/Routes.php
value01:
        $routes->group('prep', function ($routes) {
            $routes->get('/', 'Specimen\SpecimenPrepController::index');
            $routes->get('(:num)', 'Specimen\SpecimenPrepController::show/$1');
            $routes->post('/', 'Specimen\SpecimenPrepController::create');
            $routes->patch('(:num)', 'Specimen\SpecimenPrepController::update/$1');
        });

        $routes->group('status', function ($routes) {
            $routes->get('/', 'Specimen\SpecimenStatusController::index');
            $routes->get('(:num)', 'Specimen\SpecimenStatusController::show/$1');
            $routes->post('/', 'Specimen\SpecimenStatusController::create');
            $routes->patch('(:num)', 'Specimen\SpecimenStatusController::update/$1');
        });


value00: app/Config/Routes.php
value01:
    // Patient
    $routes->group('patient', function ($routes) {
        $routes->get('/', 'Patient\PatientController::index');
        $routes->post('/', 'Patient\PatientController::create');
        $routes->get('(:num)', 'Patient\PatientController::show/$1');
        $routes->delete('/', 'Patient\PatientController::delete');
        $routes->patch('(:num)', 'Patient\PatientController::update/$1');
        $routes->get('check', 'Patient\PatientController::patientCheck');
    });

    // PatVisit


value00: app/Config/Routes.php
value01:
    $routes->patch('(:num)', 'Specimen\SpecimenController::update/$1');
    $routes->delete('(:num)', 'Specimen\SpecimenController::delete/$1');
});

    // Test 
    $routes->group('test', function ($routes) {
        $routes->get('/', 'Test\TestsController::index');
        $routes->get('(:num)', 'Test\TestsController::show/$1');
        $routes->post('/', 'Test\TestsController::create');
        $routes->patch('(:num)', 'Test\TestsController::update/$1');


value00: app/Config/Routes.php
value01:
        $routes->post('/', 'Test\TestsController::create');
        $routes->patch('(:num)', 'Test\TestsController::update/$1');
        $routes->group('testmap', function ($routes) {
            $routes->get('/', 'Test\TestMapController::index');
            $routes->get('(:num)', 'Test\TestMapController::show/$1');
            $routes->post('/', 'Test\TestMapController::create');
            $routes->patch('(:num)', 'Test\TestMapController::update/$1');
            $routes->delete('/', 'Test\TestMapController::delete');

            // Filter routes
            $routes->get('by-testcode/(:any)', 'Test\TestMapController::showByTestCode/$1');

            // TestMapDetail nested routes
            $routes->group('detail',


value00: app/Config/Routes.php
value01:
        // HostApp
        $routes->group('hostapp', function ($routes) {
            $routes->get('/', 'Organization\HostAppController::index');
            $routes->get('(:any)', 'Organization\HostAppController::show/$1');
            $routes->post('/', 'Organization\HostAppController::create');
            $routes->patch('(:any)', 'Organization\HostAppController::update/$1');
            $routes->delete('/', 'Organization\HostAppController::delete');
        });

        // HostComPara


value00: app/Config/Routes.php
value01:
, function ($routes) {
                $routes->get('/', 'Test\TestMapDetailController::index');
                $routes->get('(:num)', 'Test\TestMapDetailController::show/$1');
                $routes->post('/', 'Test\TestMapDetailController::create');
                $routes->patch('(:num)', 'Test\TestMapDetailController::update/$1');
                $routes->delete('/', 'Test\TestMapDetailController::delete');
                $routes->get('by-testmap/(:num)', 'Test\TestMapDetailController::showByTestMap/$1');
                $routes->post('batch', 'Test\TestMapDetailController::batchCreate');
                $routes->patch('batch', 'Test\TestMapDetailController::batchUpdate');
                $routes->delete('batch', 'Test\TestMapDetailController::batchDelete');
            })


value00: app/Config/Routes.php
value01:
        $routes->group('patvisitadt', function ($routes) {
        $routes->get('visit/(:num)', 'PatVisitController::getADTByVisit/$1');
        $routes->get('(:num)', 'PatVisitController::showADT/$1');
        $routes->post('/', 'PatVisitController::createADT');
        $routes->patch('(:num)', 'PatVisitController::updateADT/$1');
        $routes->delete('/', 'PatVisitController::deleteADT');
    });

    // Master Data

    // Location


value00: app/Config/Routes.php
value01:
        // Workstation
        $routes->group('workstation', function ($routes) {
            $routes->get('/', 'Organization\WorkstationController::index');
            $routes->get('(:num)', 'Organization\WorkstationController::show/$1');
            $routes->post('/', 'Organization\WorkstationController::create');
            $routes->patch('(:num)', 'Organization\WorkstationController::update/$1');
            $routes->delete('/', 'Organization\WorkstationController::delete');
        });

        // HostApp


value00: app/Config/Routes.php
value01:
        $routes->group('container', function ($routes) {
            $routes->get('/', 'Specimen\ContainerDefController::index');
            $routes->get('(:num)', 'Specimen\ContainerDefController::show/$1');
            $routes->post('/', 'Specimen\ContainerDefController::create');
            $routes->patch('(:num)', 'Specimen\ContainerDefController::update/$1');
        });
        $routes->group('containerdef', function ($routes) {
            $routes->get('/', 'Specimen\ContainerDefController::index');
            $routes->get('(:num)', 'Specimen\ContainerDefController::show/$1');
            $routes->post('/', 'Specimen\ContainerDefController::create');
            $routes->patch('(:num)', 'Specimen\ContainerDefController::update/$1');
        });


value00: app/Config/Routes.php
value01:
    $routes->group('rule', function ($routes) {
        $routes->get('/', 'Rule\RuleController::index');
        $routes->get('(:num)', 'Rule\RuleController::show/$1');
        $routes->post('/', 'Rule\RuleController::create');
        $routes->patch('(:num)', 'Rule\RuleController::update/$1');
        $routes->delete('(:num)', 'Rule\RuleController::delete/$1');
        $routes->post('validate', 'Rule\RuleController::validateExpr');
        $routes->post('compile', 'Rule\RuleController::compile');
    });

    // Demo/Test Routes (No Auth)
$routes->group('api/demo', function ($routes) {
    $routes->post('order', 'Test\DemoOrderController::createDemoOrder');
    $routes->get('order', 'Test\DemoOrderController::listDemoOrders');
});

// Edge API - Integration with tiny-edge


value00: app/Config/Routing.php
value01:
namespace Config;

use CodeIgniter\Config\Routing as BaseRouting;

/**
 * Routing configuration
 */
class Routing extends BaseRouting
{
    /**
     * For Defined Routes.
     * An array of files that contain route definitions.
     * Route files are read in order, with the first match
     * found taking precedence.
     *
     * Default: APPPATH . 'Config/Routes.php'
     *
     * @var list<string>
     */
    public array $routeFiles = [
        APPPATH . 'Config/Routes.php',
    ];

    /**
     * For Defined Routes and Auto Routing.
     * The default namespace to use for Controllers when no other
     * namespace has been specified.
     *
     * Default: 'App\Controllers'
     */
    public string $defaultNamespace = 'App\Controllers';


value00: app/Config/Routes.php
value01:
                $routes->delete('(:num)', 'ValueSetController::deleteItem/$1');
            });

            $routes->group('def', function ($routes) {
                $routes->get('/', 'ValueSetDefController::index');
                $routes->get('(:num)', 'ValueSetDefController::show/$1');
                $routes->post('/', 'ValueSetDefController::create');
                $routes->put('(:num)', 'ValueSetDefController::update/$1');
                $routes->delete('(:num)', 'ValueSetDefController::delete/$1');
            });
        });
    });

    // Result ValueSet


value00: app/Config/Routing.php
value01:
    public bool $multipleSegmentsOneParam = false;

    /**
     * For Auto Routing (Improved).
     * Map of URI segments and namespaces.
     *
     * The key is the first URI segment. The value is the controller namespace.
     * E.g.,
     *   [
     *       'blog' => 'Acme\Blog\Controllers',
     *   ]
     *
     * @var array<string, string>
     */
    public array $moduleRoutes = [];

    /**
     * For Auto Routing (Improved).
     * Whether to translate dashes in URIs for controller/method to CamelCase.
     * E.g., blog-controller -> BlogController
     *
     * If you enable this, $translateURIDashes is ignored.
     *
     * Default: false
     */
    public bool $translateUriToCamelCase = true;
}


value00: app/Config/Routing.php
value01:
    public string $defaultNamespace = 'App\Controllers';

    /**
     * For Auto Routing.
     * The default controller to use when no other controller has been
     * specified.
     *
     * Default: 'Home'
     */
    public string $defaultController = 'Home';

    /**
     * For Defined Routes and Auto Routing.
     * The default method to call on the controller when no other
     * method has been set in the route.
     *
     * Default: 'index'
     */
    public string $defaultMethod = 'index';

    /**
     * For Auto Routing.
     * Whether to translate dashes in URIs for controller/method to underscores.
     * Primarily useful when using the auto-routing.
     *
     * Default: false
     */
    public bool $translateURIDashes = false;


value00: app/Config/Honeypot.php
value01:
{
    /**
     * Makes Honeypot visible or not to human
     */
    public bool $hidden = true;

    /**
     * Honeypot Label Content
     */
    public string $label = 'Fill This Field';

    /**
     * Honeypot Field Name
     */
    public string $name = 'honeypot';

    /**
     * Honeypot HTML Template
     */
    public string $template = '<label>{label}</label><input type="text" name="{name}" value="">';

    /**
     * Honeypot container
     *
     * If you enabled CSP, you can remove `style="display:none"`.
     */
    public string $container = '<div style="display:none">{template}</div>';

    /**
     * The id attribute for Honeypot container tag
     *
     * Used when CSP is enabled.
     */
    public string $containerId = 'hpc';
}


value00: app/Config/Routing.php
value01:
<?php

/**
 * This file is part of CodeIgniter 4 framework.
 *
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Config;

use CodeIgniter\Config\Routing as BaseRouting;

/**
 * Routing configuration
 */


value00: app/Config/Generators.php
value01:
     * not to delete them or modify the names. If you will do so, you may
     * end up disrupting the scaffolding process and throw errors.
     *
     * YOU HAVE BEEN WARNED!
     *
     * @var array<string, array<string, string>|string>
     */


value00: app/Config/Routing.php
value01:
    public bool $translateURIDashes = false;

    /**
     * Sets the class/method that should be called if routing doesn't
     * find a match. It can be the controller/method name like: Users::index
     *
     * This setting is passed to the Router class and handled there.
     *
     * If you want to use a closure, you will have to set it in the
     * routes file by calling:
     *
     * $routes->set404Override(function() {
     *    // Do something here
     * });
     *
     * Example:
     *  public $override404 = 'App\Errors::show404';
     */
    public ?string $override404 = null;


value00: app/Config/Honeypot.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Honeypot extends BaseConfig
{
    /**
     * Makes Honeypot visible or not to human
     */
    public bool $hidden = true;


value00: app/Config/Generators.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Generators extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Generator Commands' Views
     * --------------------------------------------------------------------------


value00: app/Config/Generators.php
value01:
    public array $views = [
        'make:cell' => [
            'class' => 'CodeIgniter\Commands\Generators\Views\cell.tpl.php',
            'view'  => 'CodeIgniter\Commands\Generators\Views\cell_view.tpl.php',
        ],
        'make:command'      => 'CodeIgniter\Commands\Generators\Views\command.tpl.php',
        'make:config'       => 'CodeIgniter\Commands\Generators\Views\config.tpl.php',
        'make:controller'   => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php'


value00: app/Config/Generators.php
value01:
     * Generator Commands' Views
     * --------------------------------------------------------------------------
     *
     * This array defines the mapping of generator commands to the view files
     * they are using. If you need to customize them for your own, copy these
     * view files in your own folder and indicate the location here.
     *
     * You will notice that the views have special placeholders enclosed in
     * curly braces `{...}`. These placeholders are used internally by the
     * generator commands in processing replacements, thus you are warned
     * not to delete them or modify the names. If you will do so, you may
     * end up disrupting the scaffolding process and throw errors.


value00: app/Config/Generators.php
value01:
,
        'make:controller'   => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
        'make:entity'       => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php',
        'make:filter'       => 'CodeIgniter\Commands\Generators\Views\filter.tpl.php',
        'make:migration'    => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
        'make:model'        => 'CodeIgniter\Commands\Generators\Views\model.tpl.php',
        'make:seeder'       => 'CodeIgniter\Commands\Generators\Views\seeder.tpl.php',
        'make:validation'   => 'CodeIgniter\Commands\Generators\Views\validation.tpl.php',
        'session:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php',
    ];
}


value00: app/Config/Routing.php
value01:
    /**
     * If TRUE, the system will attempt to match the URI against
     * Controllers by matching each segment against folders/files
     * in APPPATH/Controllers, when a match wasn't found against
     * defined routes.
     *
     * If FALSE, will stop searching and do NO automatic routing.
     */
    public bool $autoRoute = false;

    /**
     * For Defined Routes.
     * If TRUE, will enable the use of the 'prioritize' option
     * when defining routes.
     *
     * Default: false
     */
    public bool $prioritize = false;

    /**
     * For Defined Routes.
     * If TRUE, matched multiple URI segments will be passed as one parameter.
     *
     * Default: false
     */
    public bool $multipleSegmentsOneParam = false;


value00: app/Config/Services.php
value01:
class Services extends BaseService
{
    /*
     * public static function example($getShared = true)
     * {
     *     if ($getShared) {
     *         return static::getSharedInstance('example');
     *     }
     *
     *     return new \CodeIgniter\Example();
     * }
     */
}


value00: app/Config/Services.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseService;

/**
 * Services Configuration file.
 *
 * Services are simply other classes/libraries that the system uses
 * to do its job. This is used by CodeIgniter to allow the core of the
 * framework to be swapped out easily without affecting the usage within
 * the rest of your application.
 *
 * This file holds any application-specific services, or service overrides
 * that you might need. An example has been included with the general
 * method format you should use for your service methods. For more examples,
 * see the core Services file at system/Config/Services.php.
 */


value00: app/Config/Toolbar.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Debug\Toolbar\Collectors\Database;
use CodeIgniter\Debug\Toolbar\Collectors\Events;
use CodeIgniter\Debug\Toolbar\Collectors\Files;
use CodeIgniter\Debug\Toolbar\Collectors\Logs;
use CodeIgniter\Debug\Toolbar\Collectors\Routes;
use CodeIgniter\Debug\Toolbar\Collectors\Timers;


value00: app/Config/Toolbar.php
value01:
    public bool $collectVarData = true;

    /**
     * --------------------------------------------------------------------------
     * Max History
     * --------------------------------------------------------------------------
     *
     * `$maxHistory` sets a limit on the number of past requests that are stored,
     * helping to conserve file space used to store them. You can set it to
     * 0 (zero) to not have any history stored, or -1 for unlimited history.
     */
    public int $maxHistory = 20;


value00: app/Config/Toolbar.php
value01:
    /**
     * --------------------------------------------------------------------------
     * Collect Var Data
     * --------------------------------------------------------------------------
     *
     * If set to false var data from the views will not be collected. Useful to
     * avoid high memory usage when there are lots of data passed to the view.
     */
    public bool $collectVarData = true;


value00: app/Config/Toolbar.php
value01:
use CodeIgniter\Debug\Toolbar\Collectors\Routes;
use CodeIgniter\Debug\Toolbar\Collectors\Timers;
use CodeIgniter\Debug\Toolbar\Collectors\Views;

/**
 * --------------------------------------------------------------------------
 * Debug Toolbar
 * --------------------------------------------------------------------------
 *
 * The Debug Toolbar provides a way to see information about the performance
 * and state of your application during that page display. By default it will
 * NOT be displayed under production environments, and will only display if
 * `CI_DEBUG` is true, since if it's not, there's not much to display anyway.
 */
class Toolbar extends BaseConfig


value00: app/Config/Toolbar.php
value01:
    public int $maxHistory = 20;

    /**
     * --------------------------------------------------------------------------
     * Toolbar Views Path
     * --------------------------------------------------------------------------
     *
     * The full path to the the views that are used by the toolbar.
     * This MUST have a trailing slash.
     */
    public string $viewsPath = SYSTEMPATH . 'Debug/Toolbar/Views/';


value00: app/Config/Toolbar.php
value01:
{
    /**
     * --------------------------------------------------------------------------
     * Toolbar Collectors
     * --------------------------------------------------------------------------
     *
     * List of toolbar collectors that will be called when Debug Toolbar
     * fires up and collects data from.
     *
     * @var list<class-string>
     */
    public array $collectors = [
        Timers::class,
        Database::class,
        Logs::class,
        Views::class,
        // \CodeIgniter\Debug\Toolbar\Collectors\Cache::class,
        Files::class,
        Routes::class,
        Events::class,
    ];


value00: app/Config/Toolbar.php
value01:
    public int $maxQueries = 100;

    /**
     * --------------------------------------------------------------------------
     * Watched Directories
     * --------------------------------------------------------------------------
     *
     * Contains an array of directories that will be watched for changes and
     * used to determine if the hot-reload feature should reload the page or not.
     * We restrict the values to keep performance as high as possible.
     *
     * NOTE: The ROOTPATH will be prepended to all values.
     *
     * @var list<string>
     */
    public array $watchedDirectories = [
        'app',
    ];


value00: app/Config/Toolbar.php
value01:
    public array $watchedDirectories = [
        'app',
    ];

    /**
     * --------------------------------------------------------------------------
     * Watched File Extensions
     * --------------------------------------------------------------------------
     *
     * Contains an array of file extensions that will be watched for changes and
     * used to determine if the hot-reload feature should reload the page or not.
     *
     * @var list<string>
     */
    public array $watchedExtensions = [
        'php', 'css', 'js', 'html', 'svg', 'json', 'env',
    ];
}


value00: app/Config/Toolbar.php
value01:
    public string $viewsPath = SYSTEMPATH . 'Debug/Toolbar/Views/';

    /**
     * --------------------------------------------------------------------------
     * Max Queries
     * --------------------------------------------------------------------------
     *
     * If the Database Collector is enabled, it will log every query that the
     * the system generates so they can be displayed on the toolbar's timeline
     * and in the query log. This can lead to memory issues in some instances
     * with hundreds of queries.
     *
     * `$maxQueries` defines the maximum amount of queries that will be stored.
     */
    public int $maxQueries = 100;


value00: app/Config/UserAgents.php
value01:
class UserAgents extends BaseConfig
{
    /**
     * -------------------------------------------------------------------
     * OS Platforms
     * -------------------------------------------------------------------
     *
     * @var array<string, string>
     */
    public array $platforms = [
        'windows nt 10.0' => 'Windows 10',
        'windows nt 6.3'  => 'Windows 8.1',
        'windows nt 6.2'  => 'Windows 8',
        'windows nt 6.1'  => 'Windows 7',
        'windows nt 6.0'  => 'Windows Vista',
        'windows nt 5.2'  => 'Windows 2003',
        'windows nt 5.1'  => 'Windows XP',
        'windows nt 5.0'  => 'Windows 2000',
        'windows nt 4.0'  => 'Windows NT 4.0',
        'winnt4.0'        => 'Windows NT 4.0'


value00: app/Config/UserAgents.php
value01:
,
        'blackberry'           => 'BlackBerry',
        'cocoon'               => 'O2 Cocoon',
        'blazer'               => 'Treo',
        'lg'                   => 'LG',
        'amoi'                 => 'Amoi',
        'xda'                  => 'XDA',
        'mda'                  => 'MDA',
        'vario'                => 'Vario',
        'htc'                  => 'HTC',
        'samsung'              => 'Samsung',
        'sharp'                => 'Sharp',
        'sie-'                 => 'Siemens',
        'alcatel'              => 'Alcatel',
        'benq'                 => 'BenQ',
        'ipaq'                 => 'HP iPaq',
        'mot-'                 => 'Motorola',
        'playstation portable' => 'PlayStation Portable'


value00: app/Config/UserAgents.php
value01:
,
        'gnu'             => 'GNU/Linux',
        'unix'            => 'Unknown Unix OS',
        'symbian'         => 'Symbian OS',
    ];

    /**
     * -------------------------------------------------------------------
     * Browsers
     * -------------------------------------------------------------------
     *
     * The order of this array should NOT be changed. Many browsers return
     * multiple browser types so we want to identify the subtype first.
     *
     * @var array<string, string>
     */
    public array $browsers = [
        'OPR'    => 'Opera',
        'Flock'  => 'Flock',
        'Edge'   => 'Spartan',
        'Edg'    => 'Edge',
        'Chrome' => 'Chrome'


value00: app/Config/UserAgents.php
value01:
,
        'windows ce' => 'Windows CE',

        // Browsers
        'obigo'         => 'Obigo',
        'netfront'      => 'Netfront Browser',
        'openwave'      => 'Openwave Browser',
        'mobilexplorer' => 'Mobile Explorer',
        'operamini'     => 'Opera Mini',
        'opera mini'    => 'Opera Mini',
        'opera mobi'    => 'Opera Mobile',
        'fennec'        => 'Firefox Mobile',

        // Other
        'digital paths' => 'Digital Paths',
        'avantgo'       => 'AvantGo'


value00: app/Config/UserAgents.php
value01:
,
        'playstation vita'     => 'PlayStation Vita',
        'hiptop'               => 'Danger Hiptop',
        'nec-'                 => 'NEC',
        'panasonic'            => 'Panasonic',
        'philips'              => 'Philips',
        'sagem'                => 'Sagem',
        'sanyo'                => 'Sanyo',
        'spv'                  => 'SPV',
        'zte'                  => 'ZTE',
        'sendo'                => 'Sendo',
        'nintendo dsi'         => 'Nintendo DSi',
        'nintendo ds'          => 'Nintendo DS',
        'nintendo 3ds'         => 'Nintendo 3DS',
        'wii'                  => 'Nintendo Wii'


value00: app/Config/UserAgents.php
value01:
,
        'win95'           => 'Windows 95',
        'windows phone'   => 'Windows Phone',
        'windows'         => 'Unknown Windows OS',
        'android'         => 'Android',
        'blackberry'      => 'BlackBerry',
        'iphone'          => 'iOS',
        'ipad'            => 'iOS',
        'ipod'            => 'iOS',
        'os x'            => 'Mac OS X',
        'ppc mac'         => 'Power PC Mac',
        'freebsd'         => 'FreeBSD',
        'ppc'             => 'Macintosh'


value00: app/Config/UserAgents.php
value01:
,
        'Firebird'          => 'Firebird',
        'Camino'            => 'Camino',
        'Netscape'          => 'Netscape',
        'OmniWeb'           => 'OmniWeb',
        'Safari'            => 'Safari',
        'Mozilla'           => 'Mozilla',
        'Konqueror'         => 'Konqueror',
        'icab'              => 'iCab',
        'Lynx'              => 'Lynx',
        'Links'             => 'Links',
        'hotjava'           => 'HotJava',
        'amaya'             => 'Amaya',
        'IBrowse'           => 'IBrowse',
        'Maxthon'           => 'Maxthon',
        'Ubuntu'            => 'Ubuntu Web Browser',
        'Vivaldi'           => 'Vivaldi',
    ]


value00: app/Config/UserAgents.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

/**
 * -------------------------------------------------------------------
 * User Agents
 * -------------------------------------------------------------------
 *
 * This file contains four arrays of user agent data. It is used by the
 * User Agent Class to help identify browser, platform, robot, and
 * mobile device data. The array keys are used to identify the device
 * and the array values are used to set the actual name of the item.
 */


value00: app/Config/UserAgents.php
value01:
,
        'baiduspider'          => 'Baiduspider',
        'bingbot'              => 'Bing',
        'slurp'                => 'Inktomi Slurp',
        'yahoo'                => 'Yahoo',
        'ask jeeves'           => 'Ask Jeeves',
        'fastcrawler'          => 'FastCrawler',
        'infoseek'             => 'InfoSeek Robot 1.0',
        'lycos'                => 'Lycos',
        'yandex'               => 'YandexBot'


value00: app/Config/UserAgents.php
value01:
,
        'infoseek'             => 'InfoSeek Robot 1.0',
        'lycos'                => 'Lycos',
        'yandex'               => 'YandexBot',
        'mediapartners-google' => 'MediaPartners Google',
        'CRAZYWEBCRAWLER'      => 'Crazy Webcrawler',
        'adsbot-google'        => 'AdsBot Google',
        'feedfetcher-google'   => 'Feedfetcher Google',
        'curious george'       => 'Curious George',
        'ia_archiver'          => 'Alexa Crawler',
        'MJ12bot'              => 'Majestic-12',
        'Uptimebot'            => 'Uptimebot',
    ];
}


value00: app/Config/UserAgents.php
value01:
,
        'Maxthon'           => 'Maxthon',
        'Ubuntu'            => 'Ubuntu Web Browser',
        'Vivaldi'           => 'Vivaldi',
    ];

    /**
     * -------------------------------------------------------------------
     * Mobiles
     * -------------------------------------------------------------------
     *
     * @var array<string, string>
     */
    public array $mobiles = [
        // legacy array, old values commented out
        'mobileexplorer' => 'Mobile Explorer',
        // 'openwave'             => 'Open Wave',
        // 'opera mini'           => 'Opera Mini',
        // 'operamini'            => 'Opera Mini',
        // 'elaine'               => 'Palm',
        'palmsource' => 'Palm'


value00: app/Config/UserAgents.php
value01:
        'nintendo ds'          => 'Nintendo DS',
        'nintendo 3ds'         => 'Nintendo 3DS',
        'wii'                  => 'Nintendo Wii',
        'open web'             => 'Open Web',
        'openweb'              => 'OpenWeb',

        // Operating Systems
        'android'    => 'Android',
        'symbian'    => 'Symbian',
        'SymbianOS'  => 'SymbianOS',
        'elaine'     => 'Palm',
        'series60'   => 'Symbian S60',
        'windows ce' => 'Windows CE',

        // Browsers
        'obigo'         => 'Obigo',
        'netfront'      => 'Netfront Browser'


value00: app/Config/UserAgents.php
value01:
        'OPR'    => 'Opera',
        'Flock'  => 'Flock',
        'Edge'   => 'Spartan',
        'Edg'    => 'Edge',
        'Chrome' => 'Chrome',
        // Opera 10+ always reports Opera/9.80 and appends Version/<real version> to the user agent string
        'Opera.*?Version'   => 'Opera',
        'Opera'             => 'Opera',
        'MSIE'              => 'Internet Explorer',
        'Internet Explorer' => 'Internet Explorer',
        'Trident.* rv'      => 'Internet Explorer',
        'Shiira'            => 'Shiira',
        'Firefox'           => 'Firefox',
        'Chimera'           => 'Chimera',
        'Phoenix'           => 'Phoenix',
        'Firebird'          => 'Firebird',
        'Camino'            => 'Camino',
        'Netscape'          => 'Netscape'


value00: app/Config/UserAgents.php
value01:
,
        'up.browser' => 'Generic Mobile',
        'smartphone' => 'Generic Mobile',
        'cellphone'  => 'Generic Mobile',
    ];

    /**
     * -------------------------------------------------------------------
     * Robots
     * -------------------------------------------------------------------
     *
     * There are hundred of bots but these are the most common.
     *
     * @var array<string, string>
     */
    public array $robots = [
        'googlebot'            => 'Googlebot',
        'msnbot'               => 'MSNBot',
        'baiduspider'          => 'Baiduspider',
        'bingbot'              => 'Bing',
        'slurp'                => 'Inktomi Slurp'


value00: app/Config/UserAgents.php
value01:
        'ipaq'                 => 'HP iPaq',
        'mot-'                 => 'Motorola',
        'playstation portable' => 'PlayStation Portable',
        'playstation 3'        => 'PlayStation 3',
        'playstation vita'     => 'PlayStation Vita',
        'hiptop'               => 'Danger Hiptop',
        'nec-'                 => 'NEC'


value00: app/Config/UserAgents.php
value01:
,
        'nokia'                => 'Nokia',
        'palm'                 => 'Palm',
        'iphone'               => 'Apple iPhone',
        'ipad'                 => 'iPad',
        'ipod'                 => 'Apple iPod Touch',
        'sony'                 => 'Sony Ericsson',
        'ericsson'             => 'Sony Ericsson',
        'blackberry'           => 'BlackBerry',
        'cocoon'               => 'O2 Cocoon',
        'blazer'               => 'Treo'


value00: app/Config/UserAgents.php
value01:
        // 'operamini'            => 'Opera Mini',
        // 'elaine'               => 'Palm',
        'palmsource' => 'Palm',
        // 'digital paths'        => 'Palm',
        // 'avantgo'              => 'Avantgo',
        // 'xiino'                => 'Xiino',
        'palmscape' => 'Palmscape',
        // 'nokia'                => 'Nokia',
        // 'ericsson'             => 'Ericsson',
        // 'blackberry'           => 'BlackBerry',
        // 'motorola'             => 'Motorola'

        // Phones and Manufacturers
        'motorola'             => 'Motorola',
        'nokia'                => 'Nokia',
        'palm'                 => 'Palm',
        'iphone'               => 'Apple iPhone'


value00: app/Config/UserAgents.php
value01:
,
        'windows nt 5.0'  => 'Windows 2000',
        'windows nt 4.0'  => 'Windows NT 4.0',
        'winnt4.0'        => 'Windows NT 4.0',
        'winnt 4.0'       => 'Windows NT',
        'winnt'           => 'Windows NT',
        'windows 98'      => 'Windows 98',
        'win98'           => 'Windows 98',
        'windows 95'      => 'Windows 95',
        'win95'           => 'Windows 95',
        'windows phone'   => 'Windows Phone',
        'windows'         => 'Unknown Windows OS'


value00: app/Config/UserAgents.php
value01:
,
        'ppc mac'         => 'Power PC Mac',
        'freebsd'         => 'FreeBSD',
        'ppc'             => 'Macintosh',
        'linux'           => 'Linux',
        'debian'          => 'Debian',
        'sunos'           => 'Sun Solaris',
        'beos'            => 'BeOS',
        'apachebench'     => 'ApacheBench',
        'aix'             => 'AIX',
        'irix'            => 'Irix',
        'osf'             => 'DEC OSF',
        'hp-ux'           => 'HP-UX',
        'netbsd'          => 'NetBSD',
        'bsdi'            => 'BSDi',
        'openbsd'         => 'OpenBSD',
        'gnu'             => 'GNU/Linux',
        'unix'            => 'Unknown Unix OS',
        'symbian'         => 'Symbian OS',
    ]


value00: app/Config/UserAgents.php
value01:
        'fennec'        => 'Firefox Mobile',

        // Other
        'digital paths' => 'Digital Paths',
        'avantgo'       => 'AvantGo',
        'xiino'         => 'Xiino',
        'novarra'       => 'Novarra Transcoder',
        'vodafone'      => 'Vodafone',
        'docomo'        => 'NTT DoCoMo',
        'o2'            => 'O2',

        // Fallback
        'mobile'     => 'Generic Mobile',
        'wireless'   => 'Generic Mobile',
        'j2me'       => 'Generic Mobile',
        'midp'       => 'Generic Mobile',
        'cldc'       => 'Generic Mobile',
        'up.link'    => 'Generic Mobile',
        'up.browser' => 'Generic Mobile',
        'smartphone' => 'Generic Mobile',
        'cellphone'  => 'Generic Mobile',
    ]


value00: app/Config/View.php
value01:
    public $saveData = true;

    /**
     * Parser Filters map a filter name with any PHP callable. When the
     * Parser prepares a variable for display, it will chain it
     * through the filters in the order defined, inserting any parameters.
     * To prevent potential abuse, all filters MUST be defined here
     * in order for them to be available for use within the Parser.
     *
     * Examples:
     *  { title|esc(js) }
     *  { created_on|date(Y-m-d)|esc(attr) }
     *
     * @var         array<string, string>
     * @phpstan-var array<string, parser_callable_string>
     */
    public $filters = [];


value00: app/Config/View.php
value01:
    /**
     * Parser Plugins provide a way to extend the functionality provided
     * by the core Parser by creating aliases that will be replaced with
     * any callable. Can be single or tag pair.
     *
     * @var         array<string, callable|list<string>|string>
     * @phpstan-var array<string, list<parser_callable_string>|parser_callable_string|parser_callable>
     */
    public $plugins = [];

    /**
     * View Decorators are class methods that will be run in sequence to
     * have a chance to alter the generated output just prior to caching
     * the results.
     *
     * All classes must implement CodeIgniter\View\ViewDecoratorInterface
     *
     * @var list<class-string<ViewDecoratorInterface>>
     */
    public array $decorators = [];
}


value00: app/Config/View.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\View as BaseView;
use CodeIgniter\View\ViewDecoratorInterface;

/**
 * @phpstan-type parser_callable (callable(mixed): mixed)
 * @phpstan-type parser_callable_string (callable(mixed): mixed)&string
 */
class View extends BaseView
{
    /**
     * When false, the view method will clear the data between each
     * call. This keeps your data safe and ensures there is no accidental
     * leaking between calls, so you would need to explicitly pass the data
     * to each view. You might prefer to have the data stick around between
     * calls so that it is available to all views. If that is the case,
     * set $saveData to true.
     *
     * @var bool
     */
    public $saveData = true;


value00: app/Config/Images.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Images\Handlers\GDHandler;
use CodeIgniter\Images\Handlers\ImageMagickHandler;

class Images extends BaseConfig
{
    /**
     * Default handler used if no other handler is specified.
     */
    public string $defaultHandler = 'gd';

    /**
     * The path to the image library.
     * Required for ImageMagick, GraphicsMagick, or NetPBM.
     */
    public string $libraryPath = '/usr/local/bin/convert';

    /**
     * The available handler classes.
     *
     * @var array<string, string>
     */
    public array $handlers = [
        'gd'      => GDHandler::class,
        'imagick' => ImageMagickHandler::class,
    ];
}


value00: app/Config/Boot/development.php
value01:
error_reporting(E_ALL);
ini_set('display_errors', '1');

/*
 |--------------------------------------------------------------------------
 | DEBUG BACKTRACES
 |--------------------------------------------------------------------------
 | If true, this constant will tell the error screens to display debug
 | backtraces along with the other error information. If you would
 | prefer to not see this, set this value to false.
 */
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);


value00: app/Config/Boot/development.php
value01:
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);

/*
 |--------------------------------------------------------------------------
 | DEBUG MODE
 |--------------------------------------------------------------------------
 | Debug mode is an experimental flag that can allow changes throughout
 | the system. This will control whether Kint is loaded, and a few other
 | items. It can always be used within your own application too.
 */
defined('CI_DEBUG') || define('CI_DEBUG', true);


value00: app/Config/Boot/development.php
value01:
<?php

/*
 |--------------------------------------------------------------------------
 | ERROR DISPLAY
 |--------------------------------------------------------------------------
 | In development, we want to show as many errors as possible to help
 | make sure they don't make it to production. And save us hours of
 | painful debugging.
 |
 | If you set 'display_errors' to '1', CI4's detailed error report will show.
 */
error_reporting(E_ALL);
ini_set('display_errors', '1');


value00: app/Config/Mimes.php
value01:
,
        'smi'  => 'application/smil',
        'smil' => 'application/smil',
        'mif'  => 'application/vnd.mif',
        'xls'  => [
            'application/vnd.ms-excel',
            'application/msexcel',
            'application/x-msexcel',
            'application/x-ms-excel',
            'application/x-excel',
            'application/x-dos_ms_excel',
            'application/xls',
            'application/x-xls',
            'application/excel',
            'application/download',
            'application/vnd.ms-office',
            'application/msword',
        ],
        'ppt' => [
            'application/vnd.ms-powerpoint',
            'application/powerpoint',
            'application/vnd.ms-office',
            'application/msword',
        ],


value00: app/Config/Mimes.php
value01:
<?php

namespace Config;

/**
 * This file contains an array of mime types.  It is used by the
 * Upload class to help identify allowed file types.
 *
 * When more than one variation for an extension exist (like jpg, jpeg, etc)
 * the most common one should be first in the array to aid the guess*
 * methods. The same applies when more than one mime-type exists for a
 * single extension.
 *
 * When working with mime types, please make sure you have the ´fileinfo´
 * extension enabled to reliably detect the media types.
 */


value00: app/Config/Mimes.php
value01:
        'dms' => 'application/octet-stream',
        'lha' => 'application/octet-stream',
        'lzh' => 'application/octet-stream',
        'exe' => [
            'application/octet-stream',
            'application/vnd.microsoft.portable-executable',
            'application/x-dosexec',
            'application/x-msdownload',
        ],
        'class' => 'application/octet-stream',
        'psd'   => [
            'application/x-photoshop',
            'image/vnd.adobe.photoshop',
        ],
        'so'  => 'application/octet-stream',
        'sea' => 'application/octet-stream',
        'dll' => 'application/octet-stream'


value00: app/Config/Mimes.php
value01:
        'php3'  => 'application/x-httpd-php',
        'phtml' => 'application/x-httpd-php',
        'phps'  => 'application/x-httpd-php-source',
        'js'    => [
            'application/x-javascript',
            'text/plain',
        ],
        'swf' => 'application/x-shockwave-flash',
        'sit' => 'application/x-stuffit',
        'tar' => 'application/x-tar',
        'tgz' => [
            'application/x-tar',
            'application/x-gzip-compressed',
        ],
        'z'     => 'application/x-compress',
        'xhtml' => 'application/xhtml+xml',
        'xht'   => 'application/xhtml+xml',


value00: app/Config/Mimes.php
value01:
        'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
        'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
        'word' => [
            'application/msword',
            'application/octet-stream',
        ],
        'xl'   => 'application/excel',
        'eml'  => 'message/rfc822',
        'json' => [
            'application/json',
            'text/json',
        ],
        'pem' => [
            'application/x-x509-user-cert',
            'application/x-pem-file',
            'application/octet-stream',
        ],
        'p10' => [
            'application/x-pkcs10',
            'application/pkcs10',
        ],
        'p12' => 'application/x-pkcs12'


value00: app/Config/Mimes.php
value01:
        'z'     => 'application/x-compress',
        'xhtml' => 'application/xhtml+xml',
        'xht'   => 'application/xhtml+xml',
        'zip'   => [
            'application/x-zip',
            'application/zip',
            'application/x-zip-compressed',
            'application/s-compressed',
            'multipart/x-zip',
        ],
        'rar' => [
            'application/vnd.rar',
            'application/x-rar',
            'application/rar',
            'application/x-rar-compressed',
        ],
        'mid'  => 'audio/midi',
        'midi' => 'audio/midi',
        'mpga' => 'audio/mpeg',
        'mp2'  => 'audio/mpeg'


value00: app/Config/Mimes.php
value01:
        'rtf' => 'text/rtf',
        'xml' => [
            'application/xml',
            'text/xml',
            'text/plain',
        ],
        'xsl' => [
            'application/xml',
            'text/xsl',
            'text/xml',
        ],
        'mpeg' => 'video/mpeg',
        'mpg'  => 'video/mpeg',
        'mpe'  => 'video/mpeg',
        'qt'   => 'video/quicktime',
        'mov'  => 'video/quicktime',
        'avi'  => [
            'video/x-msvideo',
            'video/msvideo',
            'video/avi',
            'application/x-troff-msvideo',
        ],
        'movie' => 'video/x-sgi-movie',
        'doc'   => [
            'application/msword',
            'application/vnd.ms-office',
        ]


value00: app/Config/Mimes.php
value01:
        'p10' => [
            'application/x-pkcs10',
            'application/pkcs10',
        ],
        'p12' => 'application/x-pkcs12',
        'p7a' => 'application/x-pkcs7-signature',
        'p7c' => [
            'application/pkcs7-mime',
            'application/x-pkcs7-mime',
        ],
        'p7m' => [
            'application/pkcs7-mime',
            'application/x-pkcs7-mime',
        ],
        'p7r' => 'application/x-pkcs7-certreqresp',
        'p7s' => 'application/pkcs7-signature',
        'crt' => [
            'application/x-x509-ca-cert',
            'application/x-x509-user-cert',
            'application/pkix-cert',
        ],
        'crl' => [
            'application/pkix-crl',
            'application/pkcs-crl',
        ]


value00: app/Config/Mimes.php
value01:
        'rpm'  => 'audio/x-pn-realaudio-plugin',
        'ra'   => 'audio/x-realaudio',
        'rv'   => 'video/vnd.rn-realvideo',
        'wav'  => [
            'audio/x-wav',
            'audio/wave',
            'audio/wav',
        ],
        'bmp' => [
            'image/bmp',
            'image/x-bmp',
            'image/x-bitmap',
            'image/x-xbitmap',
            'image/x-win-bitmap',
            'image/x-windows-bmp',
            'image/ms-bmp',
            'image/x-ms-bmp',
            'application/bmp',
            'application/x-bmp',
            'application/x-win-bitmap',
        ],
        'gif' => 'image/gif',
        'jpg' => [
            'image/jpeg',
            'image/pjpeg',
        ]


value00: app/Config/Mimes.php
value01:
class Mimes
{
    /**
     * Map of extensions to mime types.
     *
     * @var array<string, list<string>|string>
     */
    public static array $mimes = [
        'hqx' => [
            'application/mac-binhex40',
            'application/mac-binhex',
            'application/x-binhex40',
            'application/x-mac-binhex40',
        ],
        'cpt' => 'application/mac-compactpro',
        'csv' => [
            'text/csv',
            'text/x-comma-separated-values'


value00: app/Config/Mimes.php
value01:
        'gif' => 'image/gif',
        'jpg' => [
            'image/jpeg',
            'image/pjpeg',
        ],
        'jpeg' => [
            'image/jpeg',
            'image/pjpeg',
        ],
        'jpe' => [
            'image/jpeg',
            'image/pjpeg',
        ],
        'jp2' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'j2k' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'jpf' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ]


value00: app/Config/Mimes.php
value01:
        'so'  => 'application/octet-stream',
        'sea' => 'application/octet-stream',
        'dll' => 'application/octet-stream',
        'oda' => 'application/oda',
        'pdf' => [
            'application/pdf',
            'application/force-download',
            'application/x-download',
        ],
        'ai' => [
            'application/pdf',
            'application/postscript',
        ],
        'eps'  => 'application/postscript',
        'ps'   => 'application/postscript',
        'smi'  => 'application/smil',
        'smil' => 'application/smil',
        'mif'  => 'application/vnd.mif',


value00: app/Config/Mimes.php
value01:
        'jpf' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'jpg2' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'jpx' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'jpm' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'mj2' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ]


value00: app/Config/Mimes.php
value01:
        'dot' => [
            'application/msword',
            'application/vnd.ms-office',
        ],
        'dotx' => [
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/zip',
            'application/msword',
        ],
        'xlsx' => [
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/zip',
            'application/vnd.ms-excel',
            'application/msword',
            'application/x-zip',
        ],
        'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
        'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12'


value00: app/Config/Mimes.php
value01:
    /**
     * Attempts to determine the best file extension for a given mime type.
     *
     * @param string|null $proposedExtension - default extension (in case there is more than one with the same mime type)
     *
     * @return string|null The extension determined, or null if unable to match.
     */
    public static function guessExtensionFromType(string $type, ?string $proposedExtension = null)
    {
        $type = trim(strtolower($type), '. ');

        $proposedExtension = trim(strtolower($proposedExtension ?? ''));


value00: app/Config/Mimes.php
value01:
        'mid'  => 'audio/midi',
        'midi' => 'audio/midi',
        'mpga' => 'audio/mpeg',
        'mp2'  => 'audio/mpeg',
        'mp3'  => [
            'audio/mpeg',
            'audio/mpg',
            'audio/mpeg3',
            'audio/mp3',
        ],
        'aif' => [
            'audio/x-aiff',
            'audio/aiff',
        ],
        'aiff' => [
            'audio/x-aiff',
            'audio/aiff',
        ],
        'aifc' => 'audio/x-aiff',
        'ram'  => 'audio/x-pn-realaudio',
        'rm'   => 'audio/x-pn-realaudio',
        'rpm'  => 'audio/x-pn-realaudio-plugin',
        'ra'   => 'audio/x-realaudio',
        'rv'   => 'video/vnd.rn-realvideo'


value00: app/Config/Mimes.php
value01:
        'pptx' => [
            'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        ],
        'wbxml' => 'application/wbxml',
        'wmlc'  => 'application/wmlc',
        'dcr'   => 'application/x-director',
        'dir'   => 'application/x-director',
        'dxr'   => 'application/x-director'


value00: app/Config/Mimes.php
value01:
,
        'dcr'   => 'application/x-director',
        'dir'   => 'application/x-director',
        'dxr'   => 'application/x-director',
        'dvi'   => 'application/x-dvi',
        'gtar'  => 'application/x-gtar',
        'gz'    => 'application/x-gzip',
        'gzip'  => 'application/x-gzip',
        'php'   => [
            'application/x-php',
            'application/x-httpd-php',
            'application/php',
            'text/php',
            'text/x-php',
            'application/x-httpd-php-source',
        ],
        'php4'  => 'application/x-httpd-php',
        'php3'  => 'application/x-httpd-php',
        'phtml' => 'application/x-httpd-php',
        'phps'  => 'application/x-httpd-php-source'


value00: app/Config/Mimes.php
value01:
        'ics'  => 'text/calendar',
        'ical' => 'text/calendar',
        'zsh'  => 'text/x-scriptzsh',
        '7zip' => [
            'application/x-compressed',
            'application/x-zip-compressed',
            'application/zip',
            'multipart/x-zip',
        ],
        'cdr' => [
            'application/cdr',
            'application/coreldraw',
            'application/x-cdr',
            'application/x-coreldraw',
            'image/cdr',
            'image/x-cdr',
            'zz-application/zz-winassoc-cdr',
        ],
        'wma' => [
            'audio/x-ms-wma',
            'video/x-ms-asf',
        ],


value00: app/Config/Mimes.php
value01:
        'flac' => 'audio/x-flac',
        'ogg'  => [
            'audio/ogg',
            'video/ogg',
            'application/ogg',
        ],
        'kmz' => [
            'application/vnd.google-earth.kmz',
            'application/zip',
            'application/x-zip',
        ],
        'kml' => [
            'application/vnd.google-earth.kml+xml',
            'application/xml',
            'text/xml',
        ],
        'ics'  => 'text/calendar',
        'ical' => 'text/calendar',
        'zsh'  => 'text/x-scriptzsh',


value00: app/Config/Mimes.php
value01:
,
        'cpt' => 'application/mac-compactpro',
        'csv' => [
            'text/csv',
            'text/x-comma-separated-values',
            'text/comma-separated-values',
            'application/vnd.ms-excel',
            'application/x-csv',
            'text/x-csv',
            'application/csv',
            'application/excel',
            'application/vnd.msexcel',
            'text/plain',
        ],
        'bin' => [
            'application/macbinary',
            'application/mac-binary',
            'application/octet-stream',
            'application/x-binary',
            'application/x-macbinary',
        ],
        'dms' => 'application/octet-stream',
        'lha' => 'application/octet-stream',
        'lzh' => 'application/octet-stream'


value00: app/Config/Mimes.php
value01:
;

    /**
     * Attempts to determine the best mime type for the given file extension.
     *
     * @return string|null The mime type found, or none if unable to determine.
     */
    public static function guessTypeFromExtension(string $extension)
    {
        $extension = trim(strtolower($extension), '. ');

        if (! array_key_exists($extension, static::$mimes)) {
            return null;
        }

        return is_array(static::$mimes[$extension]) ? static::$mimes[$extension][0] : static::$mimes[$extension];
    }


value00: app/Config/Mimes.php
value01:
        'movie' => 'video/x-sgi-movie',
        'doc'   => [
            'application/msword',
            'application/vnd.ms-office',
        ],
        'docx' => [
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/zip',
            'application/msword',
            'application/x-zip',
        ],
        'dot' => [
            'application/msword',
            'application/vnd.ms-office',
        ],


value00: app/Config/Mimes.php
value01:
        'wma' => [
            'audio/x-ms-wma',
            'video/x-ms-asf',
        ],
        'jar' => [
            'application/java-archive',
            'application/x-java-application',
            'application/x-jar',
            'application/x-compressed',
        ],
        'svg' => [
            'image/svg+xml',
            'image/svg',
            'application/xml',
            'text/xml',
        ],
        'vcf' => 'text/x-vcard',
        'srt' => [
            'text/srt',
            'text/plain',
        ],
        'vtt' => [
            'text/vtt',
            'text/plain',
        ],
        'ico' => [
            'image/x-icon',
            'image/x-ico',
            'image/vnd.microsoft.icon',
        ],


value00: app/Config/Mimes.php
value01:
        'ico' => [
            'image/x-icon',
            'image/x-ico',
            'image/vnd.microsoft.icon',
        ],
        'stl' => [
            'application/sla',
            'application/vnd.ms-pki.stl',
            'application/x-navistyle',
            'model/stl',
            'application/octet-stream',
        ],
    ]


value00: app/Config/Mimes.php
value01:
        'tif'  => 'image/tiff',
        'tiff' => 'image/tiff',
        'css'  => [
            'text/css',
            'text/plain',
        ],
        'html' => [
            'text/html',
            'text/plain',
        ],
        'htm' => [
            'text/html',
            'text/plain',
        ],
        'shtml' => [
            'text/html',
            'text/plain',
        ],
        'txt'  => 'text/plain',
        'text' => 'text/plain',
        'log'  => [
            'text/plain',
            'text/x-log',
        ],
        'rtx' => 'text/richtext',
        'rtf' => 'text/rtf',
        'xml' => [
            'application/xml',
            'text/xml',
            'text/plain',
        ]


value00: app/Config/Mimes.php
value01:
        'mp4' => 'video/mp4',
        'm4a' => 'audio/x-m4a',
        'f4v' => [
            'video/mp4',
            'video/x-f4v',
        ],
        'flv'  => 'video/x-flv',
        'webm' => 'video/webm',
        'aac'  => 'audio/x-acc',
        'm4u'  => 'application/vnd.mpegurl',
        'm3u'  => 'text/plain',
        'xspf' => 'application/xspf+xml',
        'vlc'  => 'application/videolan',
        'wmv'  => [
            'video/x-ms-wmv',
            'video/x-ms-asf',
        ],
        'au'   => 'audio/x-au',
        'ac3'  => 'audio/ac3',
        'flac' => 'audio/x-flac',
        'ogg'  => [
            'audio/ogg',
            'video/ogg',
            'application/ogg',
        ]


value00: app/Config/Mimes.php
value01:
        'crl' => [
            'application/pkix-crl',
            'application/pkcs-crl',
        ],
        'der' => 'application/x-x509-ca-cert',
        'kdb' => 'application/octet-stream',
        'pgp' => 'application/pgp',
        'gpg' => 'application/gpg-keys',
        'sst' => 'application/octet-stream',
        'csr' => 'application/octet-stream',
        'rsa' => 'application/x-pkcs7',
        'cer' => [
            'application/pkix-cert',
            'application/x-x509-ca-cert',
        ],
        '3g2' => 'video/3gpp2',
        '3gp' => [
            'video/3gp',
            'video/3gpp',
        ],
        'mp4' => 'video/mp4',
        'm4a' => 'audio/x-m4a',
        'f4v' => [
            'video/mp4',
            'video/x-f4v',
        ]


value00: app/Config/Mimes.php
value01:
        'mj2' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'mjp2' => [
            'image/jp2',
            'video/mj2',
            'image/jpx',
            'image/jpm',
        ],
        'png' => [
            'image/png',
            'image/x-png',
        ],
        'webp' => 'image/webp',
        'tif'  => 'image/tiff',
        'tiff' => 'image/tiff',
        'css'  => [
            'text/css',
            'text/plain',
        ]


value00: app/Config/Mimes.php
value01:
    {
        $type = trim(strtolower($type), '. ');

        $proposedExtension = trim(strtolower($proposedExtension ?? ''));

        if (
            $proposedExtension !== ''
            && array_key_exists($proposedExtension, static::$mimes)
            && in_array($type, (array) static::$mimes[$proposedExtension], true)
        ) {
            // The detected mime type matches with the proposed extension.
            return $proposedExtension;
        }

        // Reverse check the mime type list if no extension was proposed.
        // This search is order sensitive!
        foreach (static::$mimes as $ext => $types) {
            if (in_array($type, (array) $types, true)) {
                return $ext;
            }
        }

        return null;
    }
}


value00: app/Config/Migrations.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Migrations extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Enable/Disable Migrations
     * --------------------------------------------------------------------------
     *
     * Migrations are enabled by default.
     *
     * You should enable migrations whenever you intend to do a schema migration
     * and disable it back when you're done.
     */
    public bool $enabled = true;


value00: app/Config/Migrations.php
value01:
    public bool $enabled = true;

    /**
     * --------------------------------------------------------------------------
     * Migrations Table
     * --------------------------------------------------------------------------
     *
     * This is the name of the table that will store the current migrations state.
     * When migrations runs it will store in a database table which migration
     * files have already been run.
     */
    public string $table = 'migrations';


value00: app/Config/Migrations.php
value01:
    public string $table = 'migrations';

    /**
     * --------------------------------------------------------------------------
     * Timestamp Format
     * --------------------------------------------------------------------------
     *
     * This is the format that will be used when creating new migrations
     * using the CLI command:
     *   > php spark make:migration
     *
     * NOTE: if you set an unsupported format, migration runner will not find
     *       your migration files.
     *
     * Supported formats:
     * - YmdHis_
     * - Y-m-d-His_
     * - Y_m_d_His_
     */
    public string $timestampFormat = 'Y-m-d-His_';
}


value00: app/Controllers/CalculatorController.php
value01:
calculate(): ResponseInterface
  {
    try {
      $data = $this->request->getJSON(true);
      
      if (empty($data['formula'])) {
        return $this->respond([
          'status' => 'failed',
          'message' => 'Formula is required'
        ], 400);
      }

      $result = $this->calculator->calculate(
        $data['formula'],
        $data['variables'] ?? []
      );

      return $this->respond([
        'status' => 'success',
        'data' => [
          'result' => $result,
          'formula' => $data['formula'],
          'variables' => $data['variables'] ?? []
        ]
      ], 200);

    } catch (\Exception $e) {
      return $this->respond([
        'status' => 'failed',
        'message' => $e->getMessage()
      ], 400);
    }
  }


value00: app/Controllers/CalculatorController.php
value01:
  {
    try {
      $data = $this->request->getJSON(true);
      
      if (empty($data['formula'])) {
        return $this->respond([
          'status' => 'failed',
          'message' => 'Formula is required'
        ], 400);
      }

      $validation = $this->calculator->validate($data['formula']);

      return $this->respond([
        'status' => $validation['valid'] ? 'success' : 'failed',
        'data' => [
          'valid' => $validation['valid'],
          'error' => $validation['error'],
          'variables' => $this->calculator->extractVariables($data['formula'])
        ]
      ], 200);

    } catch (\Exception $e) {
      return $this->respond([
        'status' => 'failed',
        'message' => $e->getMessage()
      ], 400);
    }
  }


value00: app/Controllers/CalculatorController.php
value01:
use App\Models\Test\TestDefCalModel;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\ResponseInterface;

class CalculatorController extends Controller
{
  use ResponseTrait;

  protected CalculatorService $calculator;
  protected TestDefCalModel $calcModel;

  public function __construct()
  {
    $this->calculator = new CalculatorService();
    $this->calcModel = new TestDefCalModel();
  }

  /**
   * POST api/calculate
   * Calculate a formula with provided variables
   * 
   * Request: {
   *   "formula": "{result} * {factor} + {gender}",
   *   "variables": {
   *     "result": 100,
   *     "factor": 0.5,
   *     "gender": "female"
   *   }
   * }
   */
  public function calculate(): ResponseInterface


value00: app/Controllers/CalculatorController.php
value01:
  /**
   * POST api/calc/testsite/{testSiteID}
   * Calculate using TestDefCal definition
   * 
   * Request: {
   *   "result": 85,
   *   "gender": "female",
   *   "age": 30
   * }
   */
  public function calculateByTestSite($testSiteID): ResponseInterface
  {
    try {
      $calcDef = $this->calcModel->existsByTestSiteID($testSiteID);
      
      if (!$calcDef) {
        return $this->respond([
          'status' => 'failed',
          'message' => 'No calculation defined for this test site'
        ], 404);
      }

      $testValues = $this->request->getJSON(true);
      $result = $this->calculator->calculateFromDefinition($calcDef, $testValues);


value00: app/Controllers/CalculatorController.php
value01:
  /**
   * POST api/calc/testcode/{codeOrName}
   * Evaluate a configured calculation by its code or name and return only the result map.
   */
  public function calculateByCodeOrName($codeOrName): ResponseInterface
  {
    try {
      $calcDef = $this->calcModel->findActiveByCodeOrName($codeOrName);

      if (!$calcDef || empty($calcDef['FormulaCode'])) {
        return $this->response->setJSON(new \stdClass());
      }

      $input = $this->request->getJSON(true);
      $variables = is_array($input) ? $input : [];

      $result = $this->calculator->calculate($calcDef['FormulaCode'], $variables);

      if ($result === null) {
        return $this->response->setJSON(new \stdClass());
      }

      $responseKey = $calcDef['TestSiteCode'] ?? strtoupper($codeOrName);


value00: app/Controllers/CalculatorController.php
value01:
<?php

namespace App\Controllers;

use App\Traits\ResponseTrait;
use App\Services\CalculatorService;
use App\Models\Test\TestDefCalModel;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\ResponseInterface;


value00: app/Controllers/CalculatorController.php
value01:
  /**
   * POST api/calculate/validate
   * Validate a formula syntax
   * 
   * Request: {
   *   "formula": "{result} * 2 + 5"
   * }
   */
  public function validateFormula(): ResponseInterface


value00: app/Controllers/CalculatorController.php
value01:
      $testValues = $this->request->getJSON(true);
      $result = $this->calculator->calculateFromDefinition($calcDef, $testValues);

      return $this->respond([
        'status' => 'success',
        'data' => [
          'result' => $result,
          'testSiteID' => $testSiteID,
          'formula' => $calcDef['FormulaCode'],
          'variables' => $testValues
        ]
      ], 200);

    } catch (\Exception $e) {
      return $this->respond([
        'status' => 'failed',
        'message' => $e->getMessage()
      ], 400);
    }
  }


value00: app/Controllers/CalculatorController.php
value01:
      $responseKey = $calcDef['TestSiteCode'] ?? strtoupper($codeOrName);

      return $this->response->setJSON([ $responseKey => $result ]);
    } catch (\Exception $e) {
      log_message('error', "Calc lookup failed for {$codeOrName}: " . $e->getMessage());
      return $this->response->setJSON(new \stdClass());
    }
  }
}


value00: app/Controllers/AreaGeoController.php
value01:
    public function getProvinces() {
        $rows = $this->model->getProvinces();
        $transformed = array_map(function($row) {
            return ['value' => $row['AreaGeoID'], 'label' => $row['AreaName']];
        }, $rows);
        if (empty($transformed)) { return $this->respond([ 'status'  => 'success', 'data' => [] ], 200); }
        return $this->respond([ 'status' => 'success', 'data' => $transformed ], 200);
    }


value00: app/Controllers/AreaGeoController.php
value01:
    public function getCities() {
        $filter = [ 'Parent' => $this->request->getVar('ProvinceID') ?? null ];
        $rows = $this->model->getCities($filter);
        $transformed = array_map(function($row) {
            return ['value' => $row['AreaGeoID'], 'label' => $row['AreaName']];
        }, $rows);
        if (empty($transformed)) { return $this->respond([ 'status'  => 'success', 'data' => [] ], 200); }
        return $this->respond([ 'status' => 'success', 'data' => $transformed ], 200);
    }
   
}


value00: app/Controllers/AreaGeoController.php
value01:
	protected $model;

	public function __construct() {	
		$this->model = new AreaGeoModel();
	}

    public function index() {
        try {
            $filters = [
                'AreaGeoID' => $this->request->getVar('AreaGeoID') ?? null,
                'AreaName' => $this->request->getVar('AreaName') ?? null
            ];
            $rows = $this->model->getAreaGeos( $filters );

            if(empty($rows)){return $this->respond(['status'=>'success', 'message'=>"no data found.", 'data'=>$rows], 200);}
            return $this->respond(['status'=>'success', 'message'=>"data fetched successfully", 'data'=>$rows], 200);
        } catch (\Exception $e) {
            return $this->respond([ 'status' => 'error', 'message' => $e->getMessage() ], 200);
        }

    }


value00: app/Controllers/AreaGeoController.php
value01:
<?php
namespace App\Controllers;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\AreaGeoModel;

class AreaGeoController extends BaseController {
	use ResponseTrait;
	
	protected $model;

	public function __construct() {	
		$this->model = new AreaGeoModel();
	}


value00: app/Controllers/AuthController.php
value01:
<?php

namespace App\Controllers;

use App\Traits\ResponseTrait;
use CodeIgniter\Controller;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use CodeIgniter\Cookie\Cookie;


value00: app/Controllers/AuthController.php
value01:
    // ok
    // public function login() {

    //     // Ambil dari JSON Form dan Key .env
    //     $username = $this->request->getVar('username');
    //     $password = $this->request->getVar('password');
    //     $key = getenv('JWT_SECRET');

    //     if (!$username) {
    //         return $this->fail('Username required.', 400);
    //     }

    //     $sql = "SELECT * FROM users WHERE username=" . $this->db->escape($username);
    //     $query = $this->db->query($sql);
    //     $row = $query->getResultArray();

    //     if (!$row) { return $this->fail('User not found.', 401); }
    //     $row = $row[0];
    //     if (!password_verify($password, $row['password'])) {
    //         return $this->fail('Invalid password.', 401);


value00: app/Controllers/AuthController.php
value01:
    //     } catch (Exception $e) {
    //         return $this->fail('Error generating JWT: ' . $e->getMessage(), 500);
    //     }

    //     // Kirim Respon ke HttpOnly yg akan disimpan di browser dan tidak akan dapat diakses oleh siapapun
    //     // $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
    //     $this->response->setCookie([
    //         // 'name'     => 'token',              // nama token
    //         // 'value'    => $jwt,                 // value dari jwt yg sudah di hash
    //         // 'expire'   => 864000,               // 10 hari


value00: app/Controllers/AuthController.php
value01:
        $username = $this->request->getVar('username');
        $password = $this->request->getVar('password');
        $key = getenv('JWT_SECRET');

        if (!$username) {
            return $this->fail('Username required.', 400);
        }

        $sql = "SELECT * FROM users WHERE username=" . $this->db->escape($username);
        $query = $this->db->query($sql);
        $row = $query->getResultArray();

        if (!$row) {
            return $this->fail('User not found.', 401);
        }
        $row = $row[0];
        if (!password_verify($password, $row['password'])) {
            return $this->fail('Invalid password.', 401);
        }

        // Buat JWT payload
        $exp = time() + 864000;


value00: app/Controllers/AuthController.php
value01:
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use CodeIgniter\Cookie\Cookie;

class AuthController extends Controller
{
    use ResponseTrait;

    protected $db;

    // ok
    public function __construct()
    {
        $this->db = \Config\Database::connect();
    }

    // ok
    public function checkAuth()
    {
        $token = $this->request->getCookie('token');
        $key = getenv('JWT_SECRET');

        // Jika token FE tidak ada langsung kabarkan failed
        if (!$token) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'No token found'
            ], 401);
        }

        try {
            // Decode Token dengan Key yg ada di .env


value00: app/Controllers/AuthController.php
value01:
catch (SignatureInvalidException $e) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'Invalid token signature',
                'data' => []
            ], 401);

        } catch (BeforeValidException $e) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'Token not valid yet',
                'data' => []
            ], 401);

        } catch (\Exception $e) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'Invalid token: ' . $e->getMessage(),
                'data' => []
            ], 401);
        }
    }


value00: app/Controllers/AuthController.php
value01:
        $password = $this->request->getJsonVar('password');

        // Validasi Awal Dari BE
        if (empty($username) || empty($password)) {
            return $this->respond([
                'status' => 'failed',
                'code' => 400,
                'message' => 'Username and password are required'
            ], 400); // Gunakan 400 Bad Request
        }

        // Cek Duplikasi Username
        $exists = $this->db->query("SELECT id FROM users WHERE username = ?", [$username])->getRow();
        if ($exists) {
            return $this->respond(['status' => 'failed', 'code' => 409, 'message' => 'Username already exists'], 409);
        }

        $hashedPassword = password_hash($password, PASSWORD_DEFAULT);

        // Mulai transaksi Insert


value00: app/Controllers/AuthController.php
value01:
        $this->response->setCookie([
            'name' => 'token',              // nama token
            'value' => $jwt,                 // value dari jwt yg sudah di hash
            'expire' => 864000,               // 10 hari
            'path' => '/',                  // valid untuk semua path
            'secure' => $isSecure,
            'httponly' => true,                 // dipakai agar cookie berikut tidak dapat diakses oleh javascript
            'samesite' => $isSecure ? Cookie::SAMESITE_NONE : Cookie::SAMESITE_LAX
        ]);

        // Response tanpa token di body
        return $this->respond([
            'status' => 'success',
            'code' => 200,
            'message' => 'Login successful'
        ], 200);
    }


value00: app/Config/Security.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Security extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * CSRF Protection Method
     * --------------------------------------------------------------------------
     *
     * Protection Method for Cross Site Request Forgery protection.
     *
     * @var string 'cookie' or 'session'
     */
    public string $csrfProtection = 'cookie';

    /**
     * --------------------------------------------------------------------------
     * CSRF Token Randomization
     * --------------------------------------------------------------------------
     *
     * Randomize the CSRF Token for added security.
     */


value00: app/Controllers/AuthController.php
value01:
        try {
            // Decode Token dengan Key yg ada di .env
            $decodedPayload = JWT::decode($token, new Key($key, 'HS256'));

            return $this->respond([
                'status' => 'success',
                'message' => 'Authenticated',
                'data' => $decodedPayload
            ], 200);

        } catch (ExpiredException $e) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'Token expired',
                'data' => []
            ], 401);

        }


value00: app/Controllers/AuthController.php
value01:
    //         // 'expire'   => 864000,               // 10 hari
    //         // 'path'     => '/',                  // valid untuk semua path
    //         // 'secure'   => $isSecure,            // true for HTTPS, false for HTTP (localhost)
    //         // 'httponly' => true,                 // dipakai agar cookie berikut tidak dapat diakses oleh javascript
    //         // 'samesite' => $isSecure ? Cookie::SAMESITE_NONE : Cookie::SAMESITE_LAX 
    //     ]);


    //     // Response tanpa token di body
    //     return $this->respond([
    //         'status'  => 'success',
    //         'code' => 200,
    //         'message' => 'Login successful'
    //     ], 200);


value00: app/Config/Security.php
value01:
    public int $expires = 7200;

    /**
     * --------------------------------------------------------------------------
     * CSRF Regenerate
     * --------------------------------------------------------------------------
     *
     * Regenerate CSRF Token on every submission.
     */
    public bool $regenerate = true;

    /**
     * --------------------------------------------------------------------------
     * CSRF Redirect
     * --------------------------------------------------------------------------
     *
     * Redirect to previous page with error on failure.
     *
     * @see https://codeigniter4.github.io/userguide/libraries/security.html#redirection-on-failure
     */
    public bool $redirect = (ENVIRONMENT === 'production');
}


value00: app/Controllers/AuthController.php
value01:
        $this->db->transComplete();

        // Cek status transaksi
        if ($this->db->transStatus() === false) {
            return $this->respond([
                'status' => 'error',
                'code' => 500,
                'message' => 'Failed to create user. Please try again later.'
            ], 500);
        }

        // Respon sukses jika kueri berhasil
        return $this->respond([
            'status' => 'success',
            'code' => 201,
            'message' => 'User ' . $username . ' successfully created.'
        ], 201);

    }


value00: app/Controllers/AuthController.php
value01:
    //     if (!password_verify($password, $row['password'])) {
    //         return $this->fail('Invalid password.', 401);
    //     }

    //     // Buat JWT payload
    //     $exp = time() + 864000;
    //     $payload = [
    //         'userid'   => $row['id'],
    //         'roleid' => $row['role_id'],
    //         'username' => $row['username'],
    //         'exp'      => $exp
    //     ];

    //     try {
    //         // Melakukan Hash terhadap Payload dengan Kunci .env menggunakan Algortima HMAC + SHA-256
    //         $jwt = JWT::encode($payload, $key, 'HS256');
    //     } catch (Exception $e) {
    //         return $this->fail('Error generating JWT: ' . $e->getMessage(), 500);


value00: app/Controllers/AuthController.php
value01:
    //         'status'  => 'success',
    //         'code' => 200,
    //         'message' => 'Login successful'
    //     ], 200);
    // }
    public function login()
    {

        // Ambil dari JSON Form dan Key .env
        $username = $this->request->getVar('username');
        $password = $this->request->getVar('password');


value00: app/Controllers/AuthController.php
value01:
        // Buat JWT payload
        $exp = time() + 864000;
        $payload = [
            'userid' => $row['id'],
            'roleid' => $row['role_id'],
            'username' => $row['username'],
            'exp' => $exp
        ];

        try {
            // Melakukan Hash terhadap Payload dengan Kunci .env menggunakan Algortima HMAC + SHA-256
            $jwt = JWT::encode($payload, $key, 'HS256');
        } catch (\Exception $e) {
            return $this->fail('Error generating JWT: ' . $e->getMessage(), 500);
        }

        // Detect if HTTPS is being used
        $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';

        // Kirim Respon ke HttpOnly yg akan disimpan di browser dan tidak akan dapat diakses oleh siapapun


value00: app/Config/Security.php
value01:
    public bool $tokenRandomize = false;

    /**
     * --------------------------------------------------------------------------
     * CSRF Token Name
     * --------------------------------------------------------------------------
     *
     * Token name for Cross Site Request Forgery protection.
     */
    public string $tokenName = 'csrf_test_name';

    /**
     * --------------------------------------------------------------------------
     * CSRF Header Name
     * --------------------------------------------------------------------------
     *
     * Header name for Cross Site Request Forgery protection.
     */
    public string $headerName = 'X-CSRF-TOKEN';


value00: app/Controllers/AuthController.php
value01:
    // ok
    // public function logout() {
    //     // Definisikan ini pada cookies browser, harus sama dengan cookies login
    //     // $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
    //     return $this->response->setCookie([
    //         'name'     => 'token',
    //         'value'    => '',
    //         'expire'   => time() - 3600,
    //         'path'     => '/',
    //         'secure'   => $isSecure,   
    //         'httponly' => true,
    //         'samesite' => $isSecure ? Cookie::SAMESITE_NONE : Cookie::SAMESITE_LAX

    //     ])->setJSON([
    //         'status'    => 'success',
    //         'code' => 200, 
    //         'message'   => 'Logout successful'
    //     ], 200);
    // }


value00: app/Config/Security.php
value01:
    public string $headerName = 'X-CSRF-TOKEN';

    /**
     * --------------------------------------------------------------------------
     * CSRF Cookie Name
     * --------------------------------------------------------------------------
     *
     * Cookie name for Cross Site Request Forgery protection.
     */
    public string $cookieName = 'csrf_cookie_name';

    /**
     * --------------------------------------------------------------------------
     * CSRF Expires
     * --------------------------------------------------------------------------
     *
     * Expiration time for Cross Site Request Forgery protection cookie.
     *
     * Defaults to two hours (in seconds).
     */
    public int $expires = 7200;


value00: app/Controllers/AuthController.php
value01:
        $hashedPassword = password_hash($password, PASSWORD_DEFAULT);

        // Mulai transaksi Insert
        $this->db->transStart();
        $this->db->query(
            "INSERT INTO users(username, password, role_id) VALUES(?, ?, ?)",
            [$username, $hashedPassword, 1]
        );
        $this->db->transComplete();

        // Cek status transaksi


value00: app/Controllers/AuthController.php
value01:
    public function register()
    {

        $username = strtolower($this->request->getJsonVar('username'));
        $password = $this->request->getJsonVar('password');

        // Validasi Awal Dari BE


value00: app/Config/Pager.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Pager extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Templates
     * --------------------------------------------------------------------------
     *
     * Pagination links are rendered out using views to configure their
     * appearance. This array contains aliases and the view names to
     * use when rendering the links.
     *
     * Within each view, the Pager object will be available as $pager,
     * and the desired group as $pagerGroup;
     *
     * @var array<string, string>
     */


value00: app/Controllers/AuthController.php
value01:
    //         'message' => "Password Changed for $username"
    //     ];
    //     return $this->respond($response);
    // }

    public function coba()
    {

        $token = $this->request->getCookie('token');
        $key = getenv('JWT_SECRET');

        // Decode Token dengan Key yg ada di .env
        $decodedPayload = JWT::decode($token, new Key($key, 'HS256'));

        return $this->respond([
            'status' => 'success',
            'message' => 'Authenticated',
            'data' => $decodedPayload
        ], 200);
    }

}


value00: app/Controllers/AuthController.php
value01:
    // }
    public function logout()
    {
        // Detect if HTTPS is being used
        $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
        
        // Definisikan ini pada cookies browser, harus sama dengan cookies login
        return $this->response->setCookie([
            'name' => 'token',
            'value' => '',
            'expire' => time() - 3600,
            'path' => '/',
            'secure' => $isSecure,
            'httponly' => true,
            'samesite' => $isSecure ? Cookie::SAMESITE_NONE : Cookie::SAMESITE_LAX

        ])->setJSON([
                    'status' => 'success',
                    'code' => 200,
                    'message' => 'Logout successful'
                ], 200);
    }

    // ok


value00: app/Controllers/AuthController.php
value01:
    // public function change_pass() {
    //     $db = \Config\Database::connect();
    //     $username = $this->request->getJsonVar('username');
    //     $password = $this->request->getJsonVar('password');
    //     $password = password_hash($password, PASSWORD_DEFAULT);

    //     $master = $this->request->getJsonVar('master');
    //     $masterkey = getenv('masterkey');

    //     if($master != $masterkey) {
    //         return $this->fail('Invalid master key.', 401);
    //     }

    //     $sql = "update users set password='$password' where username='$username'";
    //     $query = $db->query($sql);
    //     $response = [
    //         'message' => "Password Changed for $username"
    //     ];
    //     return $this->respond($response);
    // }


value00: app/Config/Pager.php
value01:
    public array $templates = [
        'default_full'   => 'CodeIgniter\Pager\Views\default_full',
        'default_simple' => 'CodeIgniter\Pager\Views\default_simple',
        'default_head'   => 'CodeIgniter\Pager\Views\default_head',
    ];

    /**
     * --------------------------------------------------------------------------
     * Items Per Page
     * --------------------------------------------------------------------------
     *
     * The default number of results shown in a single page.
     */
    public int $perPage = 20;
}


value00: app/Controllers/BaseController.php
value01:
    // protected $session;

    /**
     * @return void
     */
    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
    {
        // Do Not Edit This Line
        parent::initController($request, $response, $logger);

        // Preload any models, libraries, etc, here.

        // E.g.: $this->session = service('session');
    }
}


value00: app/Controllers/BaseController.php
value01:
<?php

namespace App\Controllers;

use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;

/**
 * Class BaseController
 *
 * BaseController provides a convenient place for loading components
 * and performing functions that are needed by all your controllers.
 * Extend this class in any new controllers:
 *     class Home extends BaseController
 *
 * For security be sure to declare any new methods as protected or private.
 */
abstract class BaseController extends Controller
{
    /**
     * Instance of the main Request object.
     *
     * @var CLIRequest|IncomingRequest
     */
    protected $request;


value00: app/Controllers/BaseController.php
value01:
{
    /**
     * Instance of the main Request object.
     *
     * @var CLIRequest|IncomingRequest
     */
    protected $request;

    /**
     * An array of helpers to be loaded automatically upon
     * class instantiation. These will be available
     * to all other controllers that extend BaseController.
     *
     * @var list<string>
     */
    protected $helpers = ['json'];

    /**
     * Be sure to declare properties for any property fetch you initialized.
     * The creation of dynamic property is deprecated in PHP 8.2.
     */
    // protected $session;

    /**
     * @return void
     */


value00: app/Config/Publisher.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\Publisher as BasePublisher;

/**
 * Publisher Configuration
 *
 * Defines basic security restrictions for the Publisher class
 * to prevent abuse by injecting malicious files into a project.
 */


value00: app/Config/Publisher.php
value01:
class Publisher extends BasePublisher
{
    /**
     * A list of allowed destinations with a (pseudo-)regex
     * of allowed files for each destination.
     * Attempts to publish to directories not in this list will
     * result in a PublisherException. Files that do no fit the
     * pattern will cause copy/merge to fail.
     *
     * @var array<string, string>
     */
    public $restrictions = [
        ROOTPATH => '*',
        FCPATH   => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
    ];
}


value00: app/Controllers/OrderTestController.php
value01:
<?php
namespace App\Controllers;

use App\Traits\ResponseTrait;
use CodeIgniter\Controller;
use App\Libraries\ValueSet;
use App\Models\OrderTest\OrderTestModel;
use App\Models\Patient\PatientModel;
use App\Models\PatVisit\PatVisitModel;


value00: app/Controllers/OrderTestController.php
value01:
            if ($includeDetails && !empty($rows)) {
                foreach ($rows as &$row) {
                    $row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']);
                    $row['Tests'] = $this->getOrderTests($row['InternalOID']);
                }
            }

            return $this->respond([
                'status' => 'success',
                'message' => 'Data fetched successfully',
                'data' => $rows
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/HomeController.php
value01:
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use CodeIgniter\Cookie\Cookie;

class HomeController extends Controller {
    use ResponseTrait;
    
    public function index() {

        // $token = $this->request->getCookie('token');
        // $key   = getenv('JWT_SECRET');

        // // Decode Token dengan Key yg ada di .env
        // $decodedPayload = JWT::decode($token, new Key($key, 'HS256'));

        // return $this->respond([
        //     'status'  => 'success',
        //     'code'    => 200,
        //     'message' => 'Authenticated',
        //     'data'    => $decodedPayload
        // ], 200);
    }
}


value00: app/Controllers/OrderTestController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);

        if (!$this->validateData($input, $this->rules)) {
            return $this->failValidationErrors($this->validator->getErrors());
        }

        try {
            if (!$this->patientModel->find($input['InternalPID'])) {
                return $this->failValidationErrors(['InternalPID' => 'Patient not found']);
            }

            if (!empty($input['PatVisitID'])) {
                $visit = $this->visitModel->find($input['PatVisitID']);
                if (!$visit) {
                    return $this->failValidationErrors(['PatVisitID' => 'Visit not found']);
                }
            }

            $orderID = $this->model->createOrder($input);


value00: app/Controllers/OrderTestController.php
value01:
        foreach ($tests as &$test) {
            $discipline = [
                'DisciplineID' => $test['DisciplineID'] ?? null,
                'DisciplineCode' => $test['DisciplineCode'] ?? null,
                'DisciplineName' => $test['DisciplineName'] ?? null,
                'SeqScr' => $test['DisciplineSeqScr'] ?? null,
                'SeqRpt' => $test['DisciplineSeqRpt'] ?? null,
            ];

            $test['Discipline'] = $discipline;
            $test['SeqScr'] = $test['TestSeqScr'] ?? null;
            $test['SeqRpt'] = $test['TestSeqRpt'] ?? null;
            $test['DisciplineID'] = $discipline['DisciplineID'];


value00: app/Controllers/OrderTestController.php
value01:
    public function show($orderID = null) {
        try {
            $row = $this->model->getOrder($orderID);
            if (empty($row)) {
                return $this->respond([
                    'status' => 'success',
                    'message' => 'Data not found.',
                    'data' => null
                ], 200);
            }

            $row = ValueSet::transformLabels([$row], [
                'Priority' => 'order_priority',
                'OrderStatus' => 'order_status',
            ])[0];

            // Include specimens and tests
            $row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']);


value00: app/Controllers/OrderTestController.php
value01:
    private function getOrderTests($internalOID) {
        $tests = $this->db->table('patres pr')
            ->select('pr.*, tds.TestSiteCode, tds.TestSiteName, tds.TestType, tds.SeqScr AS TestSeqScr, tds.SeqRpt AS TestSeqRpt, tds.DisciplineID, d.DisciplineCode, d.DisciplineName, d.SeqScr AS DisciplineSeqScr, d.SeqRpt AS DisciplineSeqRpt')
            ->join('testdefsite tds', 'tds.TestSiteID = pr.TestSiteID', 'left')
            ->join('discipline d', 'd.DisciplineID = tds.DisciplineID', 'left')
            ->where('pr.OrderID', $internalOID)
            ->where('pr.DelDate IS NULL')
            ->orderBy('COALESCE(d.SeqScr, 999999) ASC')
            ->orderBy('COALESCE(d.SeqRpt, 999999) ASC')
            ->orderBy('COALESCE(tds.SeqScr, 999999) ASC')
            ->


value00: app/Controllers/OrderTestController.php
value01:
            ->orderBy('COALESCE(d.SeqRpt, 999999) ASC')
            ->orderBy('COALESCE(tds.SeqScr, 999999) ASC')
            ->orderBy('COALESCE(tds.SeqRpt, 999999) ASC')
            ->orderBy('pr.ResultID ASC')
            ->get()
            ->getResultArray();


value00: app/Controllers/OrderTestController.php
value01:
    public function delete() {
        $input = $this->request->getJSON(true);
        $orderID = $input['OrderID'] ?? null;

        if (empty($orderID)) {
            return $this->failValidationErrors(['OrderID' => 'OrderID is required']);
        }

        try {
            $order = $this->model->getOrder($orderID);
            if (!$order) {
                return $this->failNotFound('Order not found');
            }

            $this->model->softDelete($orderID);

            return $this->respondDeleted([
                'status' => 'success',
                'message' => 'Order deleted successfully'
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/OrderTestController.php
value01:
use App\Models\Patient\PatientModel;
use App\Models\PatVisit\PatVisitModel;

class OrderTestController extends Controller {
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $patientModel;
    protected $visitModel;
    protected $rules;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new OrderTestModel();
        $this->patientModel = new PatientModel();
        $this->visitModel = new PatVisitModel();
        $this->rules = [
            'InternalPID' => 'required|is_natural'
        ];
    }

    public function index() {
        $internalPID = $this->request->getVar('InternalPID');
        $includeDetails = $this->request->getVar('include') === 'details';

        try {


value00: app/Controllers/OrderTestController.php
value01:
            $test['SeqRpt'] = $test['TestSeqRpt'] ?? null;
            $test['DisciplineID'] = $discipline['DisciplineID'];

            unset($test['DisciplineCode'], $test['DisciplineName'], $test['DisciplineSeqScr'], $test['DisciplineSeqRpt'], $test['TestSeqScr'], $test['TestSeqRpt']);
        }
        unset($test);

        return $tests;
    }


value00: app/Controllers/OrderTestController.php
value01:
        // Get status for each specimen
        foreach ($specimens as &$specimen) {
            $status = $this->db->table('specimenstatus')
                ->where('SID', $specimen['SID'])
                ->where('EndDate IS NULL')
                ->orderBy('CreateDate', 'DESC')
                ->get()
                ->getRowArray();
            $specimen['Status'] = $status['SpcStatus'] ?? 'PENDING';
        }
        
        return $specimens;
    }


value00: app/Controllers/OrderTestController.php
value01:
    private function getOrderSpecimens($internalOID) {
        $specimens = $this->db->table('specimen s')
            ->select('s.*, cd.ConCode, cd.ConName')
            ->join('containerdef cd', 'cd.ConDefID = s.ConDefID', 'left')
            ->where('s.OrderID', $internalOID)
            ->where('s.EndDate IS NULL')
            ->get()
            ->getResultArray();
        
        // Get status for each specimen


value00: app/Controllers/OrderTestController.php
value01:
            $orderID = $this->model->createOrder($input);
             
            // Fetch complete order details
            $order = $this->model->getOrder($orderID);
            $order['Specimens'] = $this->getOrderSpecimens($order['InternalOID']);
            $order['Tests'] = $this->getOrderTests($order['InternalOID']);

            // Rule engine triggers are fired at the test/result level (test_created, result_updated)

            return $this->respondCreated([
                'status' => 'success',
                'message' => 'Order created successfully',
                'data' => $order
            ], 201);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/OrderTestController.php
value01:
            $updatedOrder = $this->model->getOrder($OrderID);
            $updatedOrder['Specimens'] = $this->getOrderSpecimens($updatedOrder['InternalOID']);
            $updatedOrder['Tests'] = $this->getOrderTests($updatedOrder['InternalOID']);

            return $this->respond([
                'status' => 'success',
                'message' => 'Order updated successfully',
                'data' => $updatedOrder
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/OrderTestController.php
value01:
            if (!$order) {
                return $this->failNotFound('Order not found');
            }

            $updateData = [];
            if (isset($input['Priority'])) $updateData['Priority'] = $input['Priority'];
            if (isset($input['OrderStatus'])) $updateData['OrderStatus'] = $input['OrderStatus'];
            if (isset($input['OrderingProvider'])) $updateData['OrderingProvider'] = $input['OrderingProvider'];
            if (isset($input['DepartmentID'])) $updateData['DepartmentID'] = $input['DepartmentID'];
            if (isset($input['WorkstationID'])) $updateData['WorkstationID'] = $input['WorkstationID'];

            if (!empty($updateData)) {
                $this->model->update($order['InternalOID'], $updateData);
            }


value00: app/Controllers/OrderTestController.php
value01:
    public function updateStatus() {
        $input = $this->request->getJSON(true);

        if (empty($input['OrderID']) || empty($input['OrderStatus'])) {
            return $this->failValidationErrors(['error' => 'OrderID and OrderStatus are required']);
        }

        $validStatuses = ['ORD', 'SCH', 'ANA', 'VER', 'REV', 'REP'];
        if (!in_array($input['OrderStatus'], $validStatuses)) {
            return $this->failValidationErrors(['OrderStatus' => 'Invalid status. Valid: ' . implode(', ', $validStatuses)]);
        }

        try {
            $order = $this->model->getOrder($input['OrderID']);
            if (!$order) {
                return $this->failNotFound('Order not found');
            }


value00: app/Controllers/OrderTestController.php
value01:
            $this->model->updateStatus($input['OrderID'], $input['OrderStatus']);

            $updatedOrder = $this->model->getOrder($input['OrderID']);
            $updatedOrder['Specimens'] = $this->getOrderSpecimens($updatedOrder['InternalOID']);
            $updatedOrder['Tests'] = $this->getOrderTests($updatedOrder['InternalOID']);

            return $this->respond([
                'status' => 'success',
                'message' => 'Order status updated successfully',
                'data' => $updatedOrder
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/OrderTestController.php
value01:
    public function update($OrderID = null) {
        $input = $this->request->getJSON(true);

        if ($OrderID === null || $OrderID === '') {
            return $this->failValidationErrors(['OrderID' => 'OrderID is required']);
        }

        if (isset($input['OrderID']) && (string) $input['OrderID'] !== (string) $OrderID) {
            return $this->failValidationErrors(['OrderID' => 'OrderID in URL does not match body']);
        }

        try {
            $input['OrderID'] = $OrderID;
            $order = $this->model->getOrder($OrderID);
            if (!$order) {
                return $this->failNotFound('Order not found');
            }


value00: app/Controllers/OrderTestController.php
value01:
            $row['Specimens'] = $this->getOrderSpecimens($row['InternalOID']);
            $row['Tests'] = $this->getOrderTests($row['InternalOID']);

            return $this->respond([
                'status' => 'success',
                'message' => 'Data fetched successfully',
                'data' => $row
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/OrderTestController.php
value01:
            if ($internalPID) {
                $rows = $this->model->getOrdersByPatient($internalPID);
            } else {
                $rows = $this->db->table('ordertest')
                    ->where('DelDate', null)
                    ->orderBy('TrnDate', 'DESC')
                    ->get()
                    ->getResultArray();
            }

            $rows = ValueSet::transformLabels($rows, [
                'Priority' => 'order_priority',
                'OrderStatus' => 'order_status',
            ]);


value00: app/Controllers/CounterController.php
value01:
<?php
namespace App\Controllers;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\CounterModel;

class CounterController extends BaseController {
    use ResponseTrait;

    protected $model; 
    public function __construct() {
        $this->model = new CounterModel();
    }

    public function index() {
        $rows = $this->model->findAll();
        
        if (empty($rows)) { 
            return $this->respond([ 'status'  => 'success', 'message' => "No Data.", 'data' => [] ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $rows ], 200);
    }


value00: app/Controllers/CounterController.php
value01:
    public function update($CounterID = null) {
        $input = $this->request->getJSON(true);
        if (!$CounterID || !ctype_digit((string) $CounterID)) {
            return $this->respond(['status' => 'error', 'message' => 'CounterID is required and must be a valid integer'], 400);
        }
        $input['CounterID'] = (int) $CounterID;
        try {
            $this->model->update($input['CounterID'], $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'Data updated successfully', 'data' => $input['CounterID'] ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Config/Session.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\BaseHandler;
use CodeIgniter\Session\Handlers\FileHandler;

class Session extends BaseConfig
{
    /**
     * --------------------------------------------------------------------------
     * Session Driver
     * --------------------------------------------------------------------------
     *
     * The session storage driver to use:
     * - `CodeIgniter\Session\Handlers\FileHandler`
     * - `CodeIgniter\Session\Handlers\DatabaseHandler`
     * - `CodeIgniter\Session\Handlers\MemcachedHandler`
     * - `CodeIgniter\Session\Handlers\RedisHandler`
     *
     * @var class-string<BaseHandler>
     */
    public string $driver = FileHandler::class;


value00: app/Config/Session.php
value01:
    public bool $regenerateDestroy = false;

    /**
     * --------------------------------------------------------------------------
     * Session Database Group
     * --------------------------------------------------------------------------
     *
     * DB Group for the database session.
     */
    public ?string $DBGroup = null;

    /**
     * --------------------------------------------------------------------------
     * Lock Retry Interval (microseconds)
     * --------------------------------------------------------------------------
     *
     * This is used for RedisHandler.
     *
     * Time (microseconds) to wait if lock cannot be acquired.
     * The default is 100,000 microseconds (= 0.1 seconds).
     */


value00: app/Config/Session.php
value01:
    public bool $matchIP = false;

    /**
     * --------------------------------------------------------------------------
     * Session Time to Update
     * --------------------------------------------------------------------------
     *
     * How many seconds between CI regenerating the session ID.
     */
    public int $timeToUpdate = 300;

    /**
     * --------------------------------------------------------------------------
     * Session Regenerate Destroy
     * --------------------------------------------------------------------------
     *
     * Whether to destroy session data associated with the old session ID
     * when auto-regenerating the session ID. When set to FALSE, the data
     * will be later deleted by the garbage collector.
     */


value00: app/Config/Session.php
value01:
    public int $lockRetryInterval = 100_000;

    /**
     * --------------------------------------------------------------------------
     * Lock Max Retries
     * --------------------------------------------------------------------------
     *
     * This is used for RedisHandler.
     *
     * Maximum number of lock acquisition attempts.
     * The default is 300 times. That is lock timeout is about 30 (0.1 * 300)
     * seconds.
     */
    public int $lockMaxRetries = 300;
}


value00: app/Controllers/PagesController.php
value01:
<?php

namespace App\Controllers;

/**
 * PagesController - Serves view pages
 * 
 * This controller only returns views. No business logic.
 * All data is fetched via API calls from the frontend.
 */
class PagesController extends BaseController
{
    // Add page methods here as needed
}


value00: app/Config/Session.php
value01:
    public string $driver = FileHandler::class;

    /**
     * --------------------------------------------------------------------------
     * Session Cookie Name
     * --------------------------------------------------------------------------
     *
     * The session cookie name, must contain only [0-9a-z_-] characters
     */
    public string $cookieName = 'ci_session';

    /**
     * --------------------------------------------------------------------------
     * Session Expiration
     * --------------------------------------------------------------------------
     *
     * The number of SECONDS you want the session to last.
     * Setting to 0 (zero) means expire when the browser is closed.
     */
    public int $expiration = 7200;


value00: app/Config/Session.php
value01:
    public int $expiration = 7200;

    /**
     * --------------------------------------------------------------------------
     * Session Save Path
     * --------------------------------------------------------------------------
     *
     * The location to save sessions to and is driver dependent.
     *
     * For the 'files' driver, it's a path to a writable directory.
     * WARNING: Only absolute paths are supported!
     *
     * For the 'database' driver, it's a table name.
     * Please read up the manual for the format with other session drivers.
     *
     * IMPORTANT: You are REQUIRED to set a valid save path!
     */
    public string $savePath = WRITEPATH . 'session';


value00: app/Controllers/CounterController.php
value01:
    public function delete() {
        $input = $this->request->getJSON(true);
        try {
            $this->model->delete($input['CounterID'], $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'Data deleted successfully', 'data' => $input['CounterID'] ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/CounterController.php
value01:
    public function show($CounterID = null) {
        $row = $this->model->find($CounterID);
        
        if (empty($row)) { 
            return $this->respond([ 'status'  => 'success', 'message' => "No Data.", 'data' => null ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "Data fetched successfully", 'data' => $row ], 200);
    }


value00: app/Config/Session.php
value01:
    public string $savePath = WRITEPATH . 'session';

    /**
     * --------------------------------------------------------------------------
     * Session Match IP
     * --------------------------------------------------------------------------
     *
     * Whether to match the user's IP address when reading the session data.
     *
     * WARNING: If you're using the database driver, don't forget to update
     *          your session table's PRIMARY KEY when changing this setting.
     */
    public bool $matchIP = false;


value00: app/Controllers/CounterController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        try {
            $id = $this->model->insert($input,true);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'Data created successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/EdgeController.php
value01:
<?php

namespace App\Controllers;

use App\Traits\ResponseTrait;
use CodeIgniter\Controller;

class EdgeController extends Controller
{
    use ResponseTrait;

    protected $db;
    protected $edgeResModel;

    public function __construct()
    {
        $this->db = \Config\Database::connect();
        $this->edgeResModel = new \App\Models\EdgeResModel();
    }

    /**
     * POST /api/edge/result
     * Receive results from tiny-edge
     */
    public function results()
    {
        try {
            $input = $this->request->getJSON(true);

            if (empty($input)) {
                return $this->failValidationErrors('Invalid JSON payload');
            }

            // Extract key fields from payload


value00: app/Controllers/EdgeController.php
value01:
    public function orders()
    {
        try {
            $instrumentId = $this->request->getGet('instrument');

            if (!$instrumentId) {
                return $this->failValidationErrors('instrument parameter is required');
            }

            // TODO: Implement order fetching logic
            // For now, return empty array
            return $this->respond([
                'status' => 'success',
                'message' => 'Orders fetched',
                'data' => []
            ]);

        } catch (\Throwable $e) {
            return $this->failServerError('Error fetching orders: ' . $e->getMessage());
        }
    }

    /**
     * POST /api/edge/order/:id/ack
     * Acknowledge order delivery
     */


value00: app/Controllers/EdgeController.php
value01:
            $patientId = $input['patient_id'] ?? null;

            // Store in edgeres table
            $data = [
                'SiteID' => 1, // Default site, can be configured
                'InstrumentID' => $instrumentId,
                'SampleID' => $sampleId,
                'PatientID' => $patientId,
                'Payload' => json_encode($input),
                'Status' => 'pending',
                'AutoProcess' => 0, // Default to manual processing
                'CreateDate' => date('Y-m-d H:i:s')
            ];

            $id = $this->edgeResModel->insert($data);

            if (!$id) {
                return $this->failServerError('Failed to save result');
            }


value00: app/Controllers/EdgeController.php
value01:
    /**
     * POST /api/edge/order/:id/ack
     * Acknowledge order delivery
     */
    public function ack($orderId = null)
    {
        try {
            if (!$orderId) {
                return $this->failValidationErrors('Order ID is required');
            }

            $input = $this->request->getJSON(true);
            $instrumentId = $input['instrument_id'] ?? null;

            // Log acknowledgment


value00: app/Controllers/EdgeController.php
value01:
    /**
     * POST /api/edge/status
     * Log instrument status
     */
    public function status()
    {
        try {
            $input = $this->request->getJSON(true);

            $instrumentId = $input['instrument_id'] ?? null;
            $status = $input['status'] ?? null;
            $lastActivity = $input['last_activity'] ?? null;
            $timestamp = $input['timestamp'] ?? date('Y-m-d H:i:s');

            if (!$instrumentId || !$status) {
                return $this->failValidationErrors('instrument_id and status are required');
            }

            // Store status log


value00: app/Controllers/EdgeController.php
value01:
            // Extract key fields from payload
            $sampleId = $input['sample_id'] ?? null;
            $instrumentId = $input['instrument_id'] ?? null;
            $patientId = $input['patient_id'] ?? null;

            // Store in edgeres table


value00: app/Controllers/EdgeController.php
value01:
            $instrumentId = $input['instrument_id'] ?? null;

            // Log acknowledgment
            $this->db->table('edgeack')->insert([
                'OrderID' => $orderId,
                'InstrumentID' => $instrumentId,
                'AckDate' => date('Y-m-d H:i:s'),
                'CreateDate' => date('Y-m-d H:i:s')
            ]);

            return $this->respond([
                'status' => 'success',
                'message' => 'Order acknowledged',
                'data' => [
                    'order_id' => $orderId
                ]
            ]);

        } catch (\Throwable $e) {
            return $this->failServerError('Error acknowledging order: ' . $e->getMessage());
        }
    }


value00: app/Controllers/EdgeController.php
value01:
            // Store status log
            $this->db->table('edgestatus')->insert([
                'InstrumentID' => $instrumentId,
                'Status' => $status,
                'LastActivity' => $lastActivity,
                'Timestamp' => $timestamp,
                'CreateDate' => date('Y-m-d H:i:s')
            ]);

            return $this->respond([
                'status' => 'success',
                'message' => 'Status logged'
            ]);

        } catch (\Throwable $e) {
            return $this->failServerError('Error logging status: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/EdgeController.php
value01:
            if (!$id) {
                return $this->failServerError('Failed to save result');
            }

            return $this->respondCreated([
                'status' => 'success',
                'message' => 'Result received and queued',
                'data' => [
                    'edge_res_id' => $id,
                    'sample_id' => $sampleId,
                    'instrument_id' => $instrumentId
                ]
            ]);

        } catch (\Throwable $e) {
            return $this->failServerError('Error processing result: ' . $e->getMessage());
        }
    }

    /**
     * GET /api/edge/order
     * Return pending orders for an instrument
     */


value00: app/Config/Boot/production.php
value01:
<?php

/*
 |--------------------------------------------------------------------------
 | ERROR DISPLAY
 |--------------------------------------------------------------------------
 | Don't show ANY in production environments. Instead, let the system catch
 | it and display a generic error message.
 |
 | If you set 'display_errors' to '1', CI4's detailed error report will show.
 */
error_reporting(E_ALL & ~E_DEPRECATED);
// If you want to suppress more types of errors.
// error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
ini_set('display_errors', '0');


value00: app/Config/Boot/production.php
value01:
// error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
ini_set('display_errors', '0');

/*
 |--------------------------------------------------------------------------
 | DEBUG MODE
 |--------------------------------------------------------------------------
 | Debug mode is an experimental flag that can allow changes throughout
 | the system. It's not widely used currently, and may not survive
 | release of the framework.
 */
defined('CI_DEBUG') || define('CI_DEBUG', false);


value00: app/Config/Validation.php
value01:
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Validation\StrictRules\CreditCardRules;
use CodeIgniter\Validation\StrictRules\FileRules;
use CodeIgniter\Validation\StrictRules\FormatRules;


value00: app/Config/Validation.php
value01:
use CodeIgniter\Validation\StrictRules\FileRules;
use CodeIgniter\Validation\StrictRules\FormatRules;
use CodeIgniter\Validation\StrictRules\Rules;

class Validation extends BaseConfig
{
    // --------------------------------------------------------------------
    // Setup
    // --------------------------------------------------------------------

    /**
     * Stores the classes that contain the
     * rules that are available.
     *
     * @var list<string>
     */
    public array $ruleSets = [
        Rules::class,
        FormatRules::class,
        FileRules::class,
        CreditCardRules::class,
    ];

    /**
     * Specifies the views that are used to display the
     * errors.
     *
     * @var array<string, string>
     */


value00: app/Config/Validation.php
value01:
    /**
     * Specifies the views that are used to display the
     * errors.
     *
     * @var array<string, string>
     */
    public array $templates = [
        'list'   => 'CodeIgniter\Validation\Views\list',
        'single' => 'CodeIgniter\Validation\Views\single',
    ];

    // --------------------------------------------------------------------
    // Rules
    // --------------------------------------------------------------------
}


value00: app/Controllers/DashboardController.php
value01:
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use CodeIgniter\Cookie\Cookie;

class DashboardController extends Controller
{
    use ResponseTrait;

    public function index()
    {

        $token = $this->request->getCookie('token');
        $key = getenv('JWT_SECRET');

        // Decode Token dengan Key yg ada di .env
        $decodedPayload = JWT::decode($token, new Key($key, 'HS256'));

        return $this->respond([
            'status' => 'success',
            'code' => 200,
            'message' => 'Authenticated',
            'data' => $decodedPayload
        ], 200);
    }

}


value00: app/Controllers/LocationController.php
value01:
    public function update($LocationID = null) {
        $input = $this->request->getJSON(true);
        if (!$LocationID || !ctype_digit((string) $LocationID)) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'LocationID is required and must be a valid integer',
                'data' => []
            ], 400);
        }
        $input['LocationID'] = (int) $LocationID;


value00: app/Controllers/LocationController.php
value01:
        $input['LocationID'] = (int) $LocationID;
        try {
            if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors( $this->validator->getErrors()); }
            $result = $this->model->saveLocation($input, true);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $result ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/LocationController.php
value01:
<?php
namespace App\Controllers;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\Location\LocationModel;

class LocationController extends BaseController {
    use ResponseTrait;

    protected $model;
    protected $rules;


value00: app/Controllers/LocationController.php
value01:
    public function delete() {
        $input = $this->request->getJSON(true);
        try {
            $LocationID = $input["LocationID"];
            $this->model->deleteLocation($LocationID);
            return $this->respondDeleted([ 'status' => 'success', 'message' => "Location with {$LocationID} deleted successfully." ]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

}


value00: app/Controllers/LocationController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $result = $this->model->saveLocation($input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data created successfully', 'data' => $result ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/LocationController.php
value01:
    use ResponseTrait;

    protected $model;
    protected $rules;

    public function __construct() {
        $this->model = new LocationModel();
        $this->rules = [
            'LocCode' => 'required|max_length[6]',
            'LocFull' => 'required',
        ];
    }

    public function index() {
        $LocName = $this->request->getVar('LocName');
        $LocCode = $this->request->getVar('LocCode');
        $rows = $this->model->getLocations($LocCode,$LocName);
        if (empty($rows)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
    }


value00: app/Controllers/LocationController.php
value01:
    public function show($LocationID = null) {
        $row = $this->model->getLocation($LocationID);
        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
    }


value00: app/Config/Boot/testing.php
value01:
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);

/*
 |--------------------------------------------------------------------------
 | DEBUG MODE
 |--------------------------------------------------------------------------
 | Debug mode is an experimental flag that can allow changes throughout
 | the system. It's not widely used currently, and may not survive
 | release of the framework.
 */
defined('CI_DEBUG') || define('CI_DEBUG', true);


value00: app/Config/Boot/testing.php
value01:
<?php

/*
 * The environment testing is reserved for PHPUnit testing. It has special
 * conditions built into the framework at various places to assist with that.
 * You can’t use it for your development.
 */

/*
 |--------------------------------------------------------------------------
 | ERROR DISPLAY
 |--------------------------------------------------------------------------
 | In development, we want to show as many errors as possible to help
 | make sure they don't make it to production. And save us hours of
 | painful debugging.
 */
error_reporting(E_ALL);
ini_set('display_errors', '1');


value00: app/Controllers/Organization/DepartmentController.php
value01:
<?php
namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;

use App\Models\Organization\DepartmentModel;

class DepartmentController extends BaseController


value00: app/Controllers/Organization/DepartmentController.php
value01:
{
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new DepartmentModel();
    }

    public function index() {
        $filter = [
			'DepartmentCode' => $this->request->getVar('DepartmentCode'),
			'DepartmentName' => $this->request->getVar('DepartmentName'),
		];
        $rows = $this->model->getDepartments($filter);
        
        if (empty($rows)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
    }


value00: app/Controllers/Organization/DepartmentController.php
value01:
    public function show($DepartmentID = null) {
        $row = $this->model->getDepartment($DepartmentID);
        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
    }


value00: app/Controllers/Organization/DepartmentController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        try {
            $id = $this->model->insert($input,true);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data created successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Organization/DepartmentController.php
value01:
    public function update($DepartmentID = null) {
        $input = $this->request->getJSON(true);
        try {
            if (!$DepartmentID || !ctype_digit((string) $DepartmentID)) {
                return $this->failValidationErrors('ID is required.');
            }
            $input['DepartmentID'] = (int) $DepartmentID;
            $id = $input['DepartmentID'];
            $this->model->update($id, $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/DepartmentController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $id = $input["DepartmentID"];
            if (!$id) { return $this->failValidationErrors('ID is required.'); }
            $this->model->delete($id);
            return $this->respondDeleted([ 'status' => 'success', 'message' => "{$id} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Organization/DisciplineController.php
value01:
<?php
namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;

use App\Models\Organization\DisciplineModel;

class DisciplineController extends BaseController {
  use ResponseTrait;

  protected $db;
  protected $model;

  public function __construct() {
    $this->db = \Config\Database::connect();
    $this->model = new DisciplineModel();
  }


value00: app/Controllers/Organization/DisciplineController.php
value01:
  public function __construct() {
    $this->db = \Config\Database::connect();
    $this->model = new DisciplineModel();
  }

  public function index() {
    $filter = [
			'DisciplineCode' => $this->request->getVar('DisciplineCode'),
			'DisciplineName' => $this->request->getVar('DisciplineName'),
		];
		$rows = $this->model->getDisciplines($filter);
    
    if (empty($rows)) {
      return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
    }

    return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
  }


value00: app/Controllers/Organization/DisciplineController.php
value01:
  public function create() {
    $input = $this->request->getJSON(true);
    try {
      $id = $this->model->insert($input,true);
      return $this->respondCreated([ 'status'  => 'success', 'message' => 'data created successfully', 'data' => $id ], 201);
    } catch (\Throwable $e) {
      return $this->failServerError('Something went wrong: ' . $e->getMessage());
    }
  }

  public function update($DisciplineID = null) {
    $input = $this->request->getJSON(true);
    if (!$DisciplineID || !ctype_digit((string) $DisciplineID)) { return $this->failValidationErrors('ID is required.'); }
    $input['DisciplineID'] = (int) $DisciplineID;
    $id = $input['DisciplineID'];


value00: app/Controllers/Organization/DisciplineController.php
value01:
  public function show($DisciplineID = null) {
    $row = $this->model->where('DisciplineID', $DisciplineID)->first();

    if (empty($row)) {
      return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
    }

    return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
  }


value00: app/Controllers/Organization/DisciplineController.php
value01:
    $input['DisciplineID'] = (int) $DisciplineID;
    $id = $input['DisciplineID'];
    $this->model->update($id, $input);
    return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
    /*
    try {
      $id = $input['DisciplineID'];
      $this->model->where('DisciplineID', $id)->update();
      echo $this->model->getLastQuery();
      return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
    } catch (\Throwable $e) {
      return $this->failServerError('Something went wrong: ' . $e->getMessage() );
    }
    */
  }
}


value00: app/Controllers/Organization/DisciplineController.php
value01:
  public function delete() {
    try {
      $input = $this->request->getJSON(true);
      $id = $input["DisciplineID"];
      if (!$id) { return $this->failValidationErrors('ID is required.'); }
      $this->model->delete($id);
      return $this->respondDeleted([ 'status' => 'success', 'message' => "{$id} deleted successfully."]);
    } catch (\Throwable $e) {
      return $this->failServerError('Something went wrong: ' . $e->getMessage());
    }
  }


value00: app/Controllers/Contact/OccupationController.php
value01:
    public function show($OccupationID = null) {
        $model = new OccupationModel();
        $row = $model->find($OccupationID);
        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }
        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data'   => $row ], 200);
    }


value00: app/Controllers/Contact/OccupationController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        try {
            $this->model->insert($input);
            $id = $this->model->getInsertID();
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data created successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            $this->db->transRollback();
            return $this->failServerError('Exception : ' . $e->getMessage());
        }
    }


value00: app/Controllers/Contact/OccupationController.php
value01:
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new OccupationModel();
        $this->rules = [ 'OccCode' => 'required','OccText' => 'required' ];
    }

    public function index() {
        $OccCode = $this->request->getVar('OccCode');
        $OccText = $this->request->getVar('OccText');
        $rows = $this->model->getOccupations($OccCode,$OccText);
        
        if (empty($rows)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data."], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data'   => $rows ], 200);
    }


value00: app/Controllers/Contact/OccupationController.php
value01:
    public function update($OccupationID = null) {
        $input = $this->request->getJSON(true);
        if (!$OccupationID || !ctype_digit((string) $OccupationID)) {
            return $this->respond(['status' => 'error', 'message' => 'OccupationID is required and must be a valid integer'], 400);
        }
        $input['OccupationID'] = (int) $OccupationID;
        try {
            $this->model->update($input['OccupationID'], $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'Data updated successfully', 'data' => $input['OccupationID'] ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Exception : ' . $e->getMessage());
        }
    }

}


value00: app/Controllers/Contact/OccupationController.php
value01:
<?php
namespace App\Controllers\Contact;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\Contact\OccupationModel;

class OccupationController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;


value00: app/Controllers/Organization/HostComParaController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $id = $input['HostAppID'] ?? null;

            if (!$id) {
                return $this->failValidationErrors('HostAppID is required.');
            }

            $this->model->delete($id);
            return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Organization/HostComParaController.php
value01:
<?php

namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\Organization\HostComParaModel;

class HostComParaController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new HostComParaModel();
    }

    public function index() {
        $filter = [
            'HostAppID' => $this->request->getVar('HostAppID'),
            'HostIP' => $this->request->getVar('HostIP'),
        ];

        $builder = $this->model->select('hostcompara.*, hostapp.HostAppName')
            ->join('hostapp', 'hostapp.HostAppID = hostcompara.HostAppID', 'left');


value00: app/Controllers/Organization/HostComParaController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);

        try {
            $id = $this->model->insert($input, true);
            return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    public function update($HostAppID = null) {
        $input = $this->request->getJSON(true);


value00: app/Controllers/Organization/HostComParaController.php
value01:
        if (!empty($filter['HostAppID'])) {
            $builder->where('hostcompara.HostAppID', $filter['HostAppID']);
        }
        if (!empty($filter['HostIP'])) {
            $builder->like('hostcompara.HostIP', $filter['HostIP'], 'both');
        }

        $rows = $builder->findAll();

        if (empty($rows)) {
            return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
        }

        return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
    }


value00: app/Controllers/Organization/HostComParaController.php
value01:
        try {
            if ($HostAppID === null || $HostAppID === '') {
                return $this->failValidationErrors('HostAppID is required.');
            }

            if (isset($input['HostAppID']) && (string) $input['HostAppID'] !== (string) $HostAppID) {
                return $this->failValidationErrors('HostAppID in URL does not match body.');
            }

            $id = $HostAppID;
            $input['HostAppID'] = $id;

            $this->model->update($id, $input);
            return $this->respondCreated(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/HostComParaController.php
value01:
    public function show($HostAppID = null) {
        $row = $this->model->select('hostcompara.*, hostapp.HostAppName')
            ->join('hostapp', 'hostapp.HostAppID = hostcompara.HostAppID', 'left')
            ->where('hostcompara.HostAppID', $HostAppID)
            ->first();

        if (empty($row)) {
            return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
        }

        return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
    }


value00: app/Controllers/Contact/ContactController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $ContactID = $input["ContactID"];
            if (!$ContactID) { return $this->failValidationErrors('ContactID is required.'); }
            $this->model->delete($ContactID);
            return $this->respondDeleted([ 'status' => 'success', 'message' => "Contact with {$ContactID} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Contact/ContactController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $id = $this->model->saveContact($input,true);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data created successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Contact/ContactController.php
value01:
    public function update($ContactID = null) {
        $input = $this->request->getJSON(true);
        if (!$ContactID || !ctype_digit((string) $ContactID)) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'ContactID is required and must be a valid integer',
                'data' => []
            ], 400);
        }
        $input['ContactID'] = (int) $ContactID;
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }


value00: app/Controllers/Contact/ContactController.php
value01:
    public function index() {
        $ContactName = $this->request->getVar('ContactName');
        $Specialty = $this->request->getVar('Specialty');
        $rows = $this->model->getContacts($ContactName, $Specialty);

        if (empty($rows)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
        }

        $rows = ValueSet::transformLabels($rows, [
            'Specialty' => 'specialty',
            'Occupation' => 'occupation',
        ]);

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
    }


value00: app/Controllers/Contact/ContactController.php
value01:
    public function show($ContactID = null) {
        $model = new ContactModel();
        $row = $model->getContactWithDetail($ContactID);

        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }

        $row = ValueSet::transformLabels([$row], [
            'Specialty' => 'specialty',
            'Occupation' => 'occupation',
        ])[0];

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
    }


value00: app/Controllers/Contact/ContactController.php
value01:
<?php
namespace App\Controllers\Contact;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Libraries\ValueSet;
use App\Models\Contact\ContactModel;

class ContactController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new ContactModel();
        $this->rules = [ 'NameFirst' => 'required' ];
    }


value00: app/Controllers/Contact/ContactController.php
value01:
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $this->model->saveContact($input);
            $id = $input['ContactID'];
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/AccountController.php
value01:
<?php
namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;

use App\Models\Organization\AccountModel;

class AccountController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new AccountModel();
    }


value00: app/Controllers/Organization/AccountController.php
value01:
    public function update($AccountID = null) {
        $input = $this->request->getJSON(true);
        if (!$AccountID || !ctype_digit((string) $AccountID)) {
            return $this->failValidationErrors('ID is required.');
        }
        $input['AccountID'] = (int) $AccountID;
        try {
            $id = $input['AccountID'];
            if (!$id) { return $this->failValidationErrors('ID is required.'); }
            $this->model->update($id, $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/SiteController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $id = $input["SiteID"];
            if (!$id) { return $this->failValidationErrors('ID is required.'); }
            $this->model->delete($id);
            return $this->respondDeleted([ 'status' => 'success', 'message' => "{$id} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Organization/SiteController.php
value01:
    public function update($SiteID = null) {
        $input = $this->request->getJSON(true);

        if (!$SiteID || !ctype_digit((string) $SiteID)) { return $this->failValidationErrors('ID is required.'); }
        $input['SiteID'] = (int) $SiteID;
        
        $id = $input['SiteID'];


value00: app/Controllers/Organization/AccountController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $id = $input["AccountID"];
            if (!$id) { return $this->failValidationErrors('ID is required.'); }
            $this->model->delete($id);
            return $this->respondDeleted([ 'status' => 'success', 'message' => "{$id} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Organization/AccountController.php
value01:
    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new AccountModel();
    }

    public function index() {            
			$filter = [
				'Parent' => $this->request->getVar('Parent'),
				'AccountName' => $this->request->getVar('AccountName'),
			];

			$rows = $this->model->getAccounts($filter);
			
			if (empty($rows)) {
				return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
			}

			return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
    }


value00: app/Controllers/Organization/SiteController.php
value01:
    public function show($SiteID = null) {
        //$rows = $this->model->where('SiteID', $SiteID)->findAll();
        $row = $this->model->getSite($SiteID);

        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
    }


value00: app/Controllers/Organization/SiteController.php
value01:
<?php
namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;

use App\Models\Organization\SiteModel;

class SiteController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new SiteModel();
    }


value00: app/Controllers/Organization/AccountController.php
value01:
    public function show($AccountID = null) {
        //$rows = $this->model->where('AccountID', $AccountID)->findAll();
        $row = $this->model->getAccount($AccountID);

        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
    }


value00: app/Controllers/Organization/SiteController.php
value01:
        $id = $input['SiteID'];
        
        if (!empty($input['SiteCode'])) {
            $validation = service('validation');
            $validation->setRules([
                'SiteCode' => 'regex_match[/^[A-Z0-9]{2,6}$/]',
            ]);
            
            if (!$validation->run($input)) {
                return $this->failValidationErrors($validation->getErrors());
            }
        }
        
        try {
            $this->model->update($id, $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/SiteController.php
value01:
    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new SiteModel();
    }

		public function index() {            
			$filter = [
				'SiteCode' => $this->request->getVar('SiteCode'),
				'SiteName' => $this->request->getVar('SiteName'),
			];
			$rows = $this->model->getSites($filter);
			if (empty($rows)) {
				return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
			}
			return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
    }


value00: app/Controllers/Organization/SiteController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        
        $validation = service('validation');
        $validation->setRules([
            'SiteCode' => 'required|regex_match[/^[A-Z0-9]{2,6}$/]',
            'SiteName' => 'required',
        ]);
        
        if (!$validation->run($input)) {
            return $this->failValidationErrors($validation->getErrors());
        }
        
        try {
            $id = $this->model->insert($input,true);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data created successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Contact/MedicalSpecialtyController.php
value01:
    public function update($SpecialtyID = null) {
        $input = $this->request->getJSON(true);
        if (!$SpecialtyID || !ctype_digit((string) $SpecialtyID)) {
            return $this->respond(['status' => 'error', 'message' => 'SpecialtyID is required and must be a valid integer'], 400);
        }
        $input['SpecialtyID'] = (int) $SpecialtyID;
        try {
            $this->model->update($input['SpecialtyID'], $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'Data updated successfully', 'data' => $input['SpecialtyID'] ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Exception : ' . $e->getMessage());
        }
    }

}


value00: app/Controllers/Contact/MedicalSpecialtyController.php
value01:
<?php
namespace App\Controllers\Contact;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\Contact\MedicalSpecialtyModel;

class MedicalSpecialtyController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;


value00: app/Controllers/Contact/MedicalSpecialtyController.php
value01:
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new MedicalSpecialtyModel();
        $this->rules = [ 'SpecialtyText' => 'required' ];
    }

    public function index() {
        $Parent = $this->request->getVar('Parent');
        $SpecialtyText = $this->request->getVar('SpecialtyText');
        $rows = $this->model->getOccupations($Parent,$SpecialtyText);
        
        if (empty($rows)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data."], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data'   => $rows ], 200);
    }


value00: app/Controllers/Contact/MedicalSpecialtyController.php
value01:
    public function show($SpecialtyID = null) {
        $model = new MedicalSpecialtyModel();
        $row = $model->find($SpecialtyID);
        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null], 200);
        }
        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data'   => $row ], 200);
    }


value00: app/Controllers/SampleController.php
value01:
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use CodeIgniter\Cookie\Cookie;

class SampleController extends Controller {
    use ResponseTrait;

    public function index() {

        $token = $this->request->getCookie('token');
        $key   = getenv('JWT_SECRET');

        // Decode Token dengan Key yg ada di .env
        $decodedPayload = JWT::decode($token, new Key($key, 'HS256'));

        return $this->respond([
            'status'  => 'success',
            'code'    => 200,
            'message' => 'Authenticated',
            'data'    => $decodedPayload
        ], 200);
    }
    
}


value00: app/Controllers/Specimen/ContainerDefController.php
value01:
  public function show($ConDefID) {
    try {
      $row = $this->model->getContainer($ConDefID);
      if (empty($row)) {
        return $this->respond([ 'status' => 'success', 'message'=> "data not found", 'data' => null ], 200);
      }

      $row = ValueSet::transformLabels([$row], [
        'ConCategory' => 'container_class',
        'CapColor' => 'container_cap_color',
        'ConSize' => 'container_size',
      ])[0];

      return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data'   => $row ], 200);
    } catch (\Exception $e) {
      return $this->failServerError('Exception : '.$e->getMessage());
    }
  }


value00: app/Controllers/Specimen/ContainerDefController.php
value01:
  public function create() {
    $input = $this->request->getJSON(true);
    if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
    try {
      $ConDefID = $this->model->insert($input);
      return $this->respondCreated([ 'status'  => 'success', 'message' => "data $ConDefID created successfully", 'data' => $ConDefID ]);
    } catch (\Exception $e) {
      return $this->failServerError('Something went wrong: ' . $e->getMessage());
    }
  }


value00: app/Controllers/PatVisitController.php
value01:
			if ($InternalPID) {
				$builder->where('patvisit.InternalPID', $InternalPID);
			}
			if ($PVID) {
				$builder->like('patvisit.PVID', $PVID, 'both');
			}
			if ($PatientID) {
				$builder->like('patient.PatientID', $PatientID, 'both');
			}


value00: app/Controllers/PatVisitController.php
value01:
			$CreateDateFrom = $this->request->getVar('CreateDateFrom');
			$CreateDateTo = $this->request->getVar('CreateDateTo');
			
			$builder = $this->model->select('patvisit.*, patient.NameFirst, patient.NameLast, patient.PatientID, location.LocFull as LastLocation')
				->join('patient', 'patient.InternalPID=patvisit.InternalPID', 'left')
				->join('(SELECT a1.*
					FROM patvisitadt a1
					INNER JOIN (
						SELECT InternalPVID, MAX(PVADTID) AS MaxID
						FROM patvisitadt
						GROUP BY InternalPVID
					) a2 ON a1.InternalPVID = a2.InternalPVID AND a1.PVADTID = a2.MaxID
				) AS latest_patvisitadt', 'latest_patvisitadt.InternalPVID = patvisit.InternalPVID', 'left')
				->join('location', 'location.LocationID = latest_patvisitadt.LocationID', 'left');


value00: app/Controllers/PatVisitController.php
value01:
$modelPVA->select('patvisitadt.*, location.LocFull as LocationName, 
				attDoc.NameFirst as AttDocFirstName, attDoc.NameLast as AttDocLastName,
				refDoc.NameFirst as RefDocFirstName, refDoc.NameLast as RefDocLastName,
				admDoc.NameFirst as AdmDocFirstName, admDoc.NameLast as AdmDocLastName,
				cnsDoc.NameFirst as CnsDocFirstName, cnsDoc.NameLast as CnsDocLastName')
				->join('location', 'location.LocationID = patvisitadt.LocationID', 'left')
				->join('contact attDoc', 'attDoc.ContactID = patvisitadt.AttDoc', 'left')
				->join('contact refDoc', 'refDoc.ContactID = patvisitadt.RefDoc', 'left')
				->join('contact admDoc', 'admDoc.ContactID = patvisitadt.AdmDoc', 'left')
				->join('contact cnsDoc', 'cnsDoc.ContactID = patvisitadt.CnsDoc', 'left')
				->where


value00: app/Controllers/PatVisitController.php
value01:
else {
				return $this->respond(['status' => 'error', 'message' => 'Failed to delete ADT record'], 500);
			}
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}
}


value00: app/Controllers/PatVisitController.php
value01:
	public function getADTByVisit($InternalPVID = null) {
		try {
			if (!$InternalPVID || !is_numeric($InternalPVID)) {
				return $this->respond(['status' => 'error', 'message' => 'Invalid or missing InternalPVID'], 400);
			}

			$modelPVA = new PatVisitADTModel();
			$rows =


value00: app/Controllers/Specimen/ContainerDefController.php
value01:
  public function index() {
    try {
			$filter = [
				'ConCode' => $this->request->getVar('ConCode'),
				'ConName' => $this->request->getVar('ConName')
			];
      $rows = $this->model->getContainers($filter);

      $rows = ValueSet::transformLabels($rows, [
        'ConCategory' => 'container_class',
        'CapColor' => 'container_cap_color',
        'ConSize' => 'container_size',
      ]);

      return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data'   => $rows ], 200);
    } catch (\Exception $e) {
      return $this->failServerError('Exception : '.$e->getMessage());
    }
  }


value00: app/Controllers/PatVisitController.php
value01:
<?php
namespace App\Controllers;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\PatVisit\PatVisitModel;
use App\Models\PatVisit\PatVisitADTModel;
use App\Models\Patient\PatientModel;

class PatVisitController extends BaseController {
	use ResponseTrait;
	
	protected $model;

	public function __construct() {	
		$this->model = new PatVisitModel();
	}

	public function index() {
		try {
			$InternalPID = $this->request->getVar('InternalPID');
			$PVID = $this->request->getVar('PVID');
			$PatientID = $this->request->getVar('PatientID');
			$PatientName = $this->request->getVar('PatientName');
			$CreateDateFrom = $this->request->getVar('CreateDateFrom');
			$CreateDateTo = $this->request->getVar('CreateDateTo');


value00: app/Controllers/PatVisitController.php
value01:
			// Soft delete using EndDate (configured in model)
			$result = $this->model->delete($input["InternalPVID"]);
			
			if ($result) {
				return $this->respond(['status' => 'success', 'message' => 'Data deleted successfully'], 200);
			} else {
				return $this->respond(['status' => 'error', 'message' => 'Failed to delete data'], 500);
			}
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}


value00: app/Controllers/PatVisitController.php
value01:
				->join('contact cnsDoc', 'cnsDoc.ContactID = patvisitadt.CnsDoc', 'left')
				->where('patvisitadt.PVADTID', $PVADTID)
				->where('patvisitadt.DelDate', null)
				->first();

			if (empty($row)) {
				return $this->respond(['status' => 'success', 'message' => 'ADT record not found', 'data' => []], 200);
			}

			return $this->respond(['status' => 'success', 'message' => 'ADT record retrieved', 'data' => $row], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}


value00: app/Controllers/Specimen/ContainerDefController.php
value01:
<?php

namespace App\Controllers\Specimen;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Libraries\ValueSet;
use App\Models\Specimen\ContainerDefModel;

class ContainerDefController extends BaseController {
  use ResponseTrait;

  protected $db;
  protected $model;
  protected $rules;

  public function __construct() {
    $this->db = \Config\Database::connect();
    $this->model = new ContainerDefModel();
    $this->rules = [
      'ConCode' => 'required|max_length[50]',
      'ConName' => 'required|max_length[50]'
    ];
  }


value00: app/Controllers/PatVisitController.php
value01:
	public function showByPatient($InternalPID = null) {
		try {
			$rows = $this->model->showByPatient($InternalPID);
			if($rows == []) { $message = "data not found"; } 
			else { $message = "data found"; }
			return $this->respond(['status' => 'success', 'message'=> $message, 'data' => $rows ], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong '.$e->getMessage());
		}
	}


value00: app/Controllers/PatVisitController.php
value01:
	public function create() {
		$input = $this->request->getJSON(true);
		try {
			// Validate required fields
			if (!isset($input['InternalPID']) || !is_numeric($input['InternalPID'])) {
				return $this->respond(['status' => 'error', 'message' => 'InternalPID is required and must be numeric'], 400);
			}
			
			// Check if patient exists
			$patientModel = new PatientModel();
			$patient = $patientModel->find($input['InternalPID']);
			if (!$patient) {
				return $this->respond(['status' => 'error', 'message' => 'Patient not found'], 404);
			}
			
			$data = $this->model->createPatVisit($input);
			return $this->respond(['status'  => 'success', 'message' => 'Data created successfully', 'data' => $data], 201);


value00: app/Controllers/PatVisitController.php
value01:
				->where('patvisitadt.InternalPVID', $InternalPVID)
				->where('patvisitadt.DelDate', null)
				->orderBy('patvisitadt.CreateDate', 'ASC')
				->findAll();

			if (empty($rows)) {
				return $this->respond(['status' => 'success', 'message' => 'No ADT history found', 'data' => []], 200);
			}

			return $this->respond(['status' => 'success', 'message' => 'ADT history retrieved', 'data' => $rows], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}

	public function showADT($PVADTID = null) {
		try {
			if (!$PVADTID || !is_numeric($PVADTID)) {
				return $this->respond(['status' => 'error', 'message' => 'Invalid or missing PVADTID'], 400);
			}

			$modelPVA = new PatVisitADTModel();
			$row =


value00: app/Controllers/PatVisitController.php
value01:
			return $this->respond(['status'  => 'success', 'message' => 'Data created successfully', 'data' => $data], 201);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}


value00: app/Controllers/PatVisitController.php
value01:
	public function updateADT($PVADTID = null) {
		$input = $this->request->getJSON(true);
		if (!$PVADTID || !is_numeric($PVADTID)) { return $this->respond(['status' => 'error', 'message' => 'Invalid or missing ID'], 400); }
		$input['PVADTID'] = $PVADTID;
		$modelPVA = new PatVisitADTModel();
		try {
			$data = $modelPVA->update($input['PVADTID'], $input);
			return $this->respond(['status'  => 'success', 'message' => 'Data updated successfully', 'data' => $data], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}


value00: app/Controllers/PatVisitController.php
value01:
	public function createADT() {
		$input = $this->request->getJSON(true);
		if (!$input["InternalPVID"] || !is_numeric($input["InternalPVID"])) { return $this->respond(['status' => 'error', 'message' => 'Invalid or missing ID'], 400); }
		$modelPVA = new PatVisitADTModel();
		try {
			$data = $modelPVA->insert($input, true);
			return $this->respond(['status'  => 'success', 'message' => 'Data created successfully', 'data' => $data], 201);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}


value00: app/Controllers/PatVisitController.php
value01:
			return $this->respond(['status' => 'success', 'message' => 'data found', 'data' => $rows], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}

	public function show($PVID = null) {
		try {
			$row = $this->model->show($PVID);
			if (empty($row)) { 
				return $this->respond([ 'status' => 'success', 'message'=> "data not found", 'data' => [] ], 200); 
			} 
			return $this->respond([ 'status' => 'success', 'message'=> "data found", 'data' => $row ], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong '.$e->getMessage());
		}
	}


value00: app/Controllers/Specimen/ContainerDefController.php
value01:
  public function update($ConDefID = null) {
    $input = $this->request->getJSON(true);
    if (!$ConDefID || !ctype_digit((string) $ConDefID)) {
      return $this->failValidationErrors('ConDefID is required.');
    }
    $input['ConDefID'] = (int) $ConDefID;
    if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
    try {
      $ConDefID = $this->model->update($input['ConDefID'], $input);
      return $this->respondCreated([ 'status'  => 'success', 'message' => "data $ConDefID updated successfully" ]);
    } catch (\Exception $e) {
      return $this->failServerError('Something went wrong: ' . $e->getMessage());
    }
  }

}


value00: app/Controllers/PatVisitController.php
value01:
public function deleteADT() {
		$input = $this->request->getJSON(true);
		try {
			if (!isset($input["PVADTID"]) || !is_numeric($input["PVADTID"])) { 
				return $this->respond(['status' => 'error', 'message' => 'Invalid or missing PVADTID'], 400); 
			}
			
			$modelPVA = new PatVisitADTModel();
			$adt = $modelPVA->find($input["PVADTID"]);
			if (!$adt) {
				return $this->respond(['status' => 'error', 'message' => 'ADT record not found'], 404);
			}
			
			$result = $modelPVA->delete($input["PVADTID"]);
			
			if ($result) {
				return $this->respond(['status' => 'success', 'message' => 'ADT record deleted successfully'], 200);
			} else {
				return $this->respond(['status' => 'error', 'message' => 'Failed to delete ADT record'], 500);
			}


value00: app/Controllers/PatVisitController.php
value01:
			if ($PatientID) {
				$builder->like('patient.PatientID', $PatientID, 'both');
			}
			if ($PatientName) {
				$builder->groupStart()
					->like('patient.NameFirst', $PatientName, 'both')
					->orLike('patient.NameLast', $PatientName, 'both')
					->groupEnd();
			}
			if ($CreateDateFrom) {
				$builder->where('patvisit.CreateDate >=', $CreateDateFrom);
			}
			if ($CreateDateTo) {
				$builder->where('patvisit.CreateDate <=', $CreateDateTo);
			}
			
			$rows = $builder->orderBy('patvisit.CreateDate', 'DESC')->findAll();
			
			if (empty($rows)) {
				return $this->respond(['status' => 'success', 'message' => 'data not found', 'data' => []], 200);
			}
			
			return $this->respond(['status' => 'success', 'message' => 'data found', 'data' => $rows], 200);


value00: app/Controllers/PatVisitController.php
value01:
	public function delete() {
		$input = $this->request->getJSON(true);
		try {
			if (!isset($input["InternalPVID"]) || !is_numeric($input["InternalPVID"])) { 
				return $this->respond(['status' => 'error', 'message' => 'Invalid or missing ID'], 400); 
			}
			
			// Check if visit exists
			$visit = $this->model->find($input["InternalPVID"]);
			if (!$visit) {
				return $this->respond(['status' => 'error', 'message' => 'Visit not found'], 404);
			}
			
			// Soft delete using EndDate (configured in model)
			$result = $this->model->delete($input["InternalPVID"]);


value00: app/Controllers/PatVisitController.php
value01:
	public function update($InternalPVID = null) {
		$input = $this->request->getJSON(true);
		if (!$InternalPVID || !is_numeric($InternalPVID)) {
			return $this->respond(['status' => 'error', 'message' => 'Invalid or missing ID'], 400);
		}
		$input['InternalPVID'] = $InternalPVID;
		try {
			// Check if visit exists
			$visit = $this->model->find($input["InternalPVID"]);
			if (!$visit) {
				return $this->respond(['status' => 'error', 'message' => 'Visit not found'], 404);
			}
			
			$data = $this->model->updatePatVisit($input);
			return $this->respond(['status'  => 'success', 'message' => 'Data updated successfully', 'data' => $data], 200);
		} catch (\Exception $e) {
			return $this->failServerError('Something went wrong: ' . $e->getMessage());
		}
	}


value00: app/Controllers/Organization/HostAppController.php
value01:
        try {
            if ($HostAppID === null || $HostAppID === '') {
                return $this->failValidationErrors('HostAppID is required.');
            }

            if (isset($input['HostAppID']) && (string) $input['HostAppID'] !== (string) $HostAppID) {
                return $this->failValidationErrors('HostAppID in URL does not match body.');
            }

            $id = $HostAppID;
            $input['HostAppID'] = $id;
            $this->model->update($id, $input);
            return $this->respondCreated(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/HostAppController.php
value01:
        if (!empty($filter['HostAppID'])) {
            $builder->like('hostapp.HostAppID', $filter['HostAppID'], 'both');
        }
        if (!empty($filter['HostAppName'])) {
            $builder->like('hostapp.HostAppName', $filter['HostAppName'], 'both');
        }

        $rows = $builder->findAll();

        if (empty($rows)) {
            return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
        }

        return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
    }


value00: app/Controllers/Organization/HostAppController.php
value01:
<?php

namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\Organization\HostAppModel;

class HostAppController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new HostAppModel();
    }

    public function index() {
        $filter = [
            'HostAppID' => $this->request->getVar('HostAppID'),
            'HostAppName' => $this->request->getVar('HostAppName'),
        ];

        $builder = $this->model->select('hostapp.*, site.SiteName')
            ->join('site', 'site.SiteID = hostapp.SiteID', 'left');


value00: app/Controllers/Organization/HostAppController.php
value01:
    public function show($HostAppID = null) {
        $row = $this->model->select('hostapp.*, site.SiteName')
            ->join('site', 'site.SiteID = hostapp.SiteID', 'left')
            ->where('hostapp.HostAppID', $HostAppID)
            ->first();

        if (empty($row)) {
            return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
        }

        return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
    }


value00: app/Controllers/Organization/CodingSysController.php
value01:
function index() {
        $filter = [
            'CodingSysAbb' => $this->request->getVar('CodingSysAbb'),
            'FullText' => $this->request->getVar('FullText'),
        ];

        $builder = $this->model;

        if (!empty($filter['CodingSysAbb'])) {
            $builder->like('CodingSysAbb', $filter['CodingSysAbb'], 'both');
        }
        if (!empty($filter['FullText'])) {
            $builder->like('FullText', $filter['FullText'], 'both');
        }

        $rows = $builder->findAll();

        if (empty($rows)) {
            return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
        }

        return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
    }


value00: app/Controllers/Organization/CodingSysController.php
value01:
        try {
            if (!$CodingSysID || !ctype_digit((string) $CodingSysID)) {
                return $this->failValidationErrors('CodingSysID is required.');
            }

            if (isset($input['CodingSysID']) && (string) $input['CodingSysID'] !== (string) $CodingSysID) {
                return $this->failValidationErrors('CodingSysID in URL does not match body.');
            }

            $id = (int) $CodingSysID;
            $input['CodingSysID'] = $id;

            $this->model->update($id, $input);
            return $this->respondCreated(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Organization/CodingSysController.php
value01:
<?php

namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Models\Organization\CodingSysModel;

class CodingSysController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new CodingSysModel();
    }

    public function index()


value00: app/Controllers/Organization/CodingSysController.php
value01:
    public function show($CodingSysID = null) {
        $row = $this->model->where('CodingSysID', $CodingSysID)->first();

        if (empty($row)) {
            return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
        }

        return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
    }


value00: app/Controllers/Organization/CodingSysController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);

        try {
            $id = $this->model->insert($input, true);
            return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }

    public function update($CodingSysID = null) {
        $input = $this->request->getJSON(true);


value00: app/Controllers/Organization/CodingSysController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $id = $input['CodingSysID'] ?? null;

            if (!$id) {
                return $this->failValidationErrors('CodingSysID is required.');
            }

            $this->model->delete($id);
            return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Rule/RuleController.php
value01:
<?php

namespace App\Controllers\Rule;

use App\Controllers\BaseController;
use App\Models\Rule\RuleDefModel;
use App\Models\Test\TestDefSiteModel;
use App\Services\RuleExpressionService;
use App\Traits\ResponseTrait;


value00: app/Controllers/Rule/RuleController.php
value01:
    public function delete($id = null)
    {
        try {
            if (!$id || !is_numeric($id)) {
                return $this->failValidationErrors('RuleID is required');
            }

            $existing = $this->ruleDefModel->where('EndDate', null)->find((int) $id);
            if (!$existing) {
                return $this->respond([
                    'status' => 'failed',
                    'message' => 'Rule not found',
                    'data' => [],
                ], 404);
            }

            $this->ruleDefModel->delete((int) $id);


value00: app/Controllers/Rule/RuleController.php
value01:
use App\Models\Rule\RuleDefModel;
use App\Models\Test\TestDefSiteModel;
use App\Services\RuleExpressionService;
use App\Traits\ResponseTrait;

class RuleController extends BaseController
{
    use ResponseTrait;

    protected RuleDefModel $ruleDefModel;

    public function __construct()
    {
        $this->ruleDefModel = new RuleDefModel();
    }

    public function index()
    {
        try {
            $eventCode = $this->request->getGet('EventCode');
            $testSiteID = $this->request->getGet('TestSiteID');
            $search = $this->request->getGet('search');

            $builder = $this->ruleDefModel->where('ruledef.EndDate', null);


value00: app/Controllers/Rule/RuleController.php
value01:
        try {
            $svc = new RuleExpressionService();
            $compiled = $svc->compile($expr);

            return $this->respond([
                'status' => 'success',
                'data' => [
                    'raw' => $expr,
                    'compiled' => $compiled,
                    'conditionExprCompiled' => json_encode($compiled),
                ],
            ], 200);
        } catch (\Throwable $e) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'Compilation failed',
                'data' => [
                    'error' => $e->getMessage(),
                ],
            ], 400);
        }
    }
}


value00: app/Controllers/Rule/RuleController.php
value01:
    public function update($id = null)
    {
        $input = $this->request->getJSON(true) ?? [];

        if (!$id || !is_numeric($id)) {
            $id = $input['RuleID'] ?? null;
        }
        if (!$id || !is_numeric($id)) {
            return $this->failValidationErrors('RuleID is required');
        }

        $existing = $this->ruleDefModel->where('EndDate', null)->find((int) $id);
        if (!$existing) {
            return $this->respond([
                'status' => 'failed',
                'message' => 'Rule not found',
                'data' => [],
            ], 404);
        }

        $validation = service('validation');


value00: app/Controllers/Rule/RuleController.php
value01:
    public function create()
    {
        $input = $this->request->getJSON(true) ?? [];

        $validation = service('validation');
        $validation->setRules([
            'RuleCode' => 'required|max_length[50]',
            'RuleName' => 'required|max_length[100]',
            'EventCode' => 'required|max_length[50]',
            'TestSiteIDs' => 'required',
            'TestSiteIDs.*' => 'is_natural_no_zero',
            'ConditionExpr' => 'permit_empty|max_length[1000]',
        ]);

        if (!$validation->run($input)) {
            return $this->failValidationErrors($validation->getErrors());
        }

        $testSiteIDs = $input['TestSiteIDs'] ?? [];


value00: app/Controllers/Rule/RuleController.php
value01:
        try {
            $updateData = [];
            foreach (['RuleCode', 'RuleName', 'Description', 'EventCode', 'ConditionExpr', 'ConditionExprCompiled'] as $field) {
                if (array_key_exists($field, $input)) {
                    $updateData[$field] = $input[$field];
                }
            }

            if (!empty($updateData)) {
                $this->ruleDefModel->update((int) $id, $updateData);
            }

            // Update test site mappings if provided
            if (isset($input['TestSiteIDs']) && is_array($input['TestSiteIDs'])) {
                $testSiteIDs = $input['TestSiteIDs'];
                
                // Validate all TestSiteIDs exist
                $testDef = new TestDefSiteModel();


value00: app/Controllers/Rule/RuleController.php
value01:
        $validation = service('validation');
        $validation->setRules([
            'RuleCode' => 'permit_empty|max_length[50]',
            'RuleName' => 'permit_empty|max_length[100]',
            'EventCode' => 'permit_empty|max_length[50]',
            'TestSiteIDs' => 'permit_empty',
            'TestSiteIDs.*' => 'is_natural_no_zero',
            'ConditionExpr' => 'permit_empty|max_length[1000]',
        ]);

        if (!$validation->run($input)) {
            return $this->failValidationErrors($validation->getErrors());
        }

        $db = \Config\Database::connect();
        $db->transStart();


value00: app/Controllers/Rule/RuleController.php
value01:
            if (!$ruleID) {
                throw new \Exception('Failed to create rule');
            }

            // Link rule to test sites
            foreach ($testSiteIDs as $testSiteID) {
                $this->ruleDefModel->linkTest($ruleID, (int) $testSiteID);
            }

            $db->transComplete();
            if ($db->transStatus() === false) {
                throw new \Exception('Transaction failed');
            }


value00: app/Controllers/Rule/RuleController.php
value01:
            if ($db->transStatus() === false) {
                throw new \Exception('Transaction failed');
            }

            return $this->respondCreated([
                'status' => 'success',
                'message' => 'Rule created successfully',
                'data' => ['RuleID' => $ruleID],
            ], 201);
        } catch (\Throwable $e) {
            $db->transRollback();
            log_message('error', 'RuleController::create error: ' . $e->getMessage());
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Organization/WorkstationController.php
value01:
    public function show($WorkstationID = null) {
        $row = $this->model->getWorkstation($WorkstationID);

        if (empty($row)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => null ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
    }


value00: app/Controllers/Rule/RuleController.php
value01:
            $rows = $builder
                ->orderBy('ruledef.RuleID', 'ASC')
                ->findAll();

            return $this->respond([
                'status' => 'success',
                'message' => 'fetch success',
                'data' => $rows,
            ], 200);
        } catch (\Throwable $e) {
            log_message('error', 'RuleController::index error: ' . $e->getMessage());
            return $this->respond([
                'status' => 'failed',
                'message' => 'Failed to fetch rules',
                'data' => [],
            ], 500);
        }
    }


value00: app/Controllers/Rule/RuleController.php
value01:
        try {
            $svc = new RuleExpressionService();
            $result = $svc->evaluate($expr, $context);

            return $this->respond([
                'status' => 'success',
                'data' => [
                    'valid' => true,
                    'result' => $result,
                ],
            ], 200);
        } catch (\Throwable $e) {
            return $this->respond([
                'status' => 'failed',
                'data' => [
                    'valid' => false,
                    'error' => $e->getMessage(),
                ],
            ], 200);
        }
    }


value00: app/Controllers/Rule/RuleController.php
value01:
            $db->transComplete();
            if ($db->transStatus() === false) {
                throw new \Exception('Transaction failed');
            }

            return $this->respond([
                'status' => 'success',
                'message' => 'Rule updated successfully',
                'data' => ['RuleID' => (int) $id],
            ], 200);
        } catch (\Throwable $e) {
            $db->transRollback();
            log_message('error', 'RuleController::update error: ' . $e->getMessage());
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Rule/RuleController.php
value01:
        try {
            $ruleData = [
                'RuleCode' => $input['RuleCode'],
                'RuleName' => $input['RuleName'],
                'Description' => $input['Description'] ?? null,
                'EventCode' => $input['EventCode'],
                'ConditionExpr' => $input['ConditionExpr'] ?? null,
                'ConditionExprCompiled' => $input['ConditionExprCompiled'] ?? null,
            ];

            $ruleID = $this->ruleDefModel->insert($ruleData, true);
            if (!$ruleID) {
                throw new \Exception('Failed to create rule');
            }


value00: app/Controllers/Rule/RuleController.php
value01:
        $testSiteIDs = $input['TestSiteIDs'] ?? [];
        if (!is_array($testSiteIDs) || empty($testSiteIDs)) {
            return $this->failValidationErrors(['TestSiteIDs' => 'At least one TestSiteID is required']);
        }

        // Validate all TestSiteIDs exist
        $testDef = new TestDefSiteModel();
        foreach ($testSiteIDs as $testSiteID) {
            $exists = $testDef->where('EndDate', null)->find((int) $testSiteID);
            if (!$exists) {
                return $this->failValidationErrors(['TestSiteIDs' => "TestSiteID {$testSiteID} not found"]);
            }
        }

        $db = \Config\Database::connect();
        $db->transStart();


value00: app/Controllers/Organization/WorkstationController.php
value01:
{
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new WorkstationModel();
    }

    public function index() {
        $filter = [
			'WorkstationCode' => $this->request->getVar('WorkstationCode'),
			'WorkstationName' => $this->request->getVar('WorkstationName'),
		];
        $rows = $this->model->getWorkstations($filter);
        
        if (empty($rows)) {
            return $this->respond([ 'status'  => 'success', 'message' => "no Data.", 'data' => [] ], 200);
        }

        return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
    }


value00: app/Controllers/Rule/RuleController.php
value01:
    /**
     * Compile DSL expression to engine-compatible structure.
     * Frontend calls this when user clicks "Compile" button.
     */
    public function compile()
    {
        $input = $this->request->getJSON(true) ?? [];
        $expr = $input['expr'] ?? '';

        if (!is_string($expr) || trim($expr) === '') {
            return $this->failValidationErrors(['expr' => 'Expression is required']);
        }

        try {
            $svc = new RuleExpressionService();
            $compiled = $svc->compile($expr);


value00: app/Controllers/Rule/RuleController.php
value01:
                // Validate all TestSiteIDs exist
                $testDef = new TestDefSiteModel();
                foreach ($testSiteIDs as $testSiteID) {
                    $exists = $testDef->where('EndDate', null)->find((int) $testSiteID);
                    if (!$exists) {
                        throw new \Exception("TestSiteID {$testSiteID} not found");
                    }
                }

                // Get current linked tests
                $currentLinks = $this->ruleDefModel->getLinkedTests((int) $id);
                
                // Unlink tests that are no longer in the list


value00: app/Controllers/Rule/RuleController.php
value01:
            $this->ruleDefModel->delete((int) $id);

            return $this->respondDeleted([
                'status' => 'success',
                'message' => 'Rule deleted successfully',
                'data' => ['RuleID' => (int) $id],
            ]);
        } catch (\Throwable $e) {
            log_message('error', 'RuleController::delete error: ' . $e->getMessage());
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Rule/RuleController.php
value01:
            if ($eventCode !== null && $eventCode !== '') {
                $builder->where('ruledef.EventCode', $eventCode);
            }
            if ($search !== null && $search !== '') {
                $builder->like('ruledef.RuleName', $search);
            }

            // Filter by TestSiteID - join with mapping table
            if ($testSiteID !== null && $testSiteID !== '' && is_numeric($testSiteID)) {
                $builder->join('testrule', 'testrule.RuleID = ruledef.RuleID', 'inner');
                $builder->where('testrule.TestSiteID', (int) $testSiteID);
                $builder->where('testrule.EndDate IS NULL');
            }

            $rows = $builder
                ->orderBy('ruledef.RuleID', 'ASC')
                ->findAll();


value00: app/Controllers/Rule/RuleController.php
value01:
    public function validateExpr()
    {
        $input = $this->request->getJSON(true) ?? [];
        $expr = $input['expr'] ?? '';
        $context = $input['context'] ?? [];

        if (!is_string($expr) || trim($expr) === '') {
            return $this->failValidationErrors(['expr' => 'expr is required']);
        }
        if (!is_array($context)) {
            return $this->failValidationErrors(['context' => 'context must be an object']);
        }


value00: app/Controllers/Rule/RuleController.php
value01:
    public function show($id = null)
    {
        try {
            if (!$id || !is_numeric($id)) {
                return $this->failValidationErrors('RuleID is required');
            }

            $rule = $this->ruleDefModel->where('EndDate', null)->find((int) $id);
            if (!$rule) {
                return $this->respond([
                    'status' => 'failed',
                    'message' => 'Rule not found',
                    'data' => [],
                ], 404);
            }

            $linkedTests = $this->ruleDefModel->getLinkedTests((int) $id);

            $rule['linkedTests'] = $linkedTests;


value00: app/Controllers/Rule/RuleController.php
value01:
                // Unlink tests that are no longer in the list
                foreach ($currentLinks as $currentTestSiteID) {
                    if (!in_array($currentTestSiteID, $testSiteIDs)) {
                        $this->ruleDefModel->unlinkTest((int) $id, $currentTestSiteID);
                    }
                }
                
                // Link new tests
                foreach ($testSiteIDs as $testSiteID) {
                    if (!in_array($testSiteID, $currentLinks)) {
                        $this->ruleDefModel->linkTest((int) $id, (int) $testSiteID);
                    }
                }
            }


value00: app/Controllers/Organization/WorkstationController.php
value01:
<?php
namespace App\Controllers\Organization;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;

use App\Models\Organization\WorkstationModel;

class WorkstationController extends BaseController


value00: app/Controllers/Organization/WorkstationController.php
value01:
    public function update($WorkstationID = null) {
        $input = $this->request->getJSON(true);
        try {
            if (!$WorkstationID || !ctype_digit((string) $WorkstationID)) {
                return $this->failValidationErrors('ID is required.');
            }
            $input['WorkstationID'] = (int) $WorkstationID;
            $id = $input['WorkstationID'];
            $this->model->update($id, $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => 'data updated successfully', 'data' => $id ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Rule/RuleController.php
value01:
            $linkedTests = $this->ruleDefModel->getLinkedTests((int) $id);

            $rule['linkedTests'] = $linkedTests;

            return $this->respond([
                'status' => 'success',
                'message' => 'fetch success',
                'data' => $rule,
            ], 200);
        } catch (\Throwable $e) {
            log_message('error', 'RuleController::show error: ' . $e->getMessage());
            return $this->respond([
                'status' => 'failed',
                'message' => 'Failed to fetch rule',
                'data' => [],
            ], 500);
        }
    }


value00: app/Controllers/Organization/WorkstationController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $id = $input["WorkstationID"];
            if (!$id) { return $this->failValidationErrors('ID is required.'); }
            $this->model->delete($id);
            return $this->respondDeleted([ 'status' => 'success', 'message' => "{$id} deleted successfully."]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Specimen/SpecimenController.php
value01:
    public function show($id) {
        try {
            $row = $this->model->where('SID',$id)->first();
            if (empty($row)) {
                return $this->respond([ 'status' => 'success', 'message'=> "data not found", 'data' => null ], 200);
            }

            $row = ValueSet::transformLabels([$row], [
                'SpecimenType' => 'specimen_type',
                'SpecimenStatus' => 'specimen_status',
                'BodySite' => 'body_site',
            ])[0];

            return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data'   => $row ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Exception : '.$e->getMessage());
        }
    }


value00: app/Controllers/Specimen/SpecimenController.php
value01:
            $deleted = $this->model->update($id, [
                'DelDate' => date('Y-m-d H:i:s')
            ]);
            
            if (!$deleted) {
                return $this->respond([
                    'status' => 'failed',
                    'message' => 'Failed to delete specimen',
                    'data' => null
                ], 500);
            }
            
            return $this->respond([
                'status' => 'success',
                'message' => 'Specimen deleted successfully',
                'data' => ['SID' => $id]
            ], 200);
            
        }


value00: app/Controllers/Specimen/SpecimenController.php
value01:
    protected $model;
    protected $rules;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new SpecimenModel();
        $this->rules = [];
    }

    public function index() {
        try {
            $rows = $this->model->findAll();

            $rows = ValueSet::transformLabels($rows, [
                'SpecimenType' => 'specimen_type',
                'SpecimenStatus' => 'specimen_status',
                'BodySite' => 'body_site',
            ]);

            return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data'   => $rows ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Exception : '.$e->getMessage());
        }
    }


value00: app/Controllers/Specimen/SpecimenController.php
value01:
    /**
     * Delete a specimen (soft delete)
     * DELETE /api/specimen/(:num)
     */
    public function delete($id) {
        try {
            // Check if specimen exists
            $specimen = $this->model->where('SID', $id)->first();
            
            if (empty($specimen)) {
                return $this->respond([
                    'status' => 'failed',
                    'message' => 'Specimen not found',
                    'data' => null
                ], 404);
            }
            
            // Perform soft delete (set DelDate)
            $deleted = $this->model->update($id, [
                'DelDate' => date('Y-m-d H:i:s')
            ]);


value00: app/Controllers/Specimen/SpecimenController.php
value01:
<?php

namespace App\Controllers\Specimen;

use App\Traits\ResponseTrait;
use App\Controllers\BaseController;
use App\Libraries\ValueSet;
use App\Models\Specimen\SpecimenModel;

class SpecimenController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;


value00: app/Controllers/Specimen/SpecimenController.php
value01:
    public function update($SID = null) {
        $input = $this->request->getJSON(true);
        if (!$SID || !ctype_digit((string) $SID)) {
            return $this->failValidationErrors('SID is required.');
        }
        $input['SID'] = (int) $SID;
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $id = $this->model->update($input['SID'], $input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => "data $id updated successfully" ]);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Specimen/SpecimenController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $id = $this->model->insert($input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => "data $id created successfully" ]);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Specimen/SpecimenController.php
value01:
catch (\Exception $e) {
            log_message('error', 'SpecimenController::delete error: ' . $e->getMessage());
            return $this->respond([
                'status' => 'failed',
                'message' => 'Failed to delete specimen',
                'data' => null
            ], 500);
        }
    }

}


value00: app/Controllers/ValueSetController.php
value01:
        try {
            $updated = $this->dbModel->update($id, $data);
            if (!$updated) {
                return $this->failValidationErrors($this->dbModel->errors());
            }

            $newRow = $this->dbModel->getValueSet($id);
            return $this->respond([
                'status' => 'success',
                'message' => 'ValueSet item updated',
                'data' => $newRow
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to update: ' . $e->getMessage());
        }
    }


value00: app/Controllers/ValueSetController.php
value01:
            return $this->respond([
                'status' => 'success',
                'data' => $result
            ], 200);
        }

        $data = ValueSet::get($lookupName);
        if (!$data) {
            return $this->respond([
                'status' => 'error',
                'message' => "ValueSet '$lookupName' not found"
            ], 404);
        }

        return $this->respond([
            'status' => 'success',
            'data' => $data
        ], 200);
    }

    public function refresh()
    {
        ValueSet::clearCache();
        return $this->respond([
            'status' => 'success',
            'message' => 'Cache cleared'
        ], 200);
    }


value00: app/Controllers/ValueSetController.php
value01:
        if (!$existing) {
            return $this->failNotFound("ValueSet item not found: $id");
        }

        $data = [];
        if (isset($input['VSetID'])) $data['VSetID'] = $input['VSetID'];
        if (isset($input['VOrder'])) $data['VOrder'] = $input['VOrder'];
        if (isset($input['VValue'])) $data['VValue'] = $input['VValue'];
        if (isset($input['VDesc'])) $data['VDesc'] = $input['VDesc'];
        if (isset($input['SiteID'])) $data['SiteID'] = $input['SiteID'];

        if (empty($data)) {
            return $this->respond([
                'status' => 'success',
                'message' => 'No changes to update',
                'data' => $existing
            ], 200);
        }


value00: app/Controllers/ValueSetController.php
value01:
<?php

namespace App\Controllers;

use App\Libraries\ValueSet;
use App\Models\ValueSet\ValueSetModel;
use App\Traits\ResponseTrait;

class ValueSetController extends \CodeIgniter\Controller
{
    use ResponseTrait;

    protected $dbModel;

    public function __construct()
    {
        $this->dbModel = new ValueSetModel();
    }

    public function index(?string $lookupName = null)
    {
        $search = $this->request->getGet('search') ?? null;
        
        if ($lookupName === null) {
            $all = ValueSet::getAll();
            $result = [];
            foreach ($all as $name => $entry) {


value00: app/Controllers/ValueSetController.php
value01:
            $all = ValueSet::getAll();
            $result = [];
            foreach ($all as $name => $entry) {
                if ($search) {
                    $nameLower = strtolower($name);
                    $labelLower = strtolower($entry['VSName'] ?? '');
                    $searchLower = strtolower($search);
                    if (strpos($nameLower, $searchLower) === false && strpos($labelLower, $searchLower) === false) {
                        continue;
                    }
                }
                $count = count($entry['values'] ?? []);
                $result[] = [
                    'value' => $name,
                    'label' => $entry['VSName'] ?? '',
                    'count' => $count
                ];
            }


value00: app/Controllers/ValueSetController.php
value01:
    public function items()
    {
        $search = $this->request->getGet('search') ?? $this->request->getGet('param') ?? null;
        $VSetID = $this->request->getGet('VSetID') ?? null;

        $rows = $this->dbModel->getValueSets($search, $VSetID);

        return $this->respond([
            'status' => 'success',
            'data' => $rows
        ], 200);
    }

    public function showItem($id = null)
    {
        $row = $this->dbModel->getValueSet($id);
        if (!$row) {
            return $this->failNotFound("ValueSet item not found: $id");
        }

        return $this->respond([
            'status' => 'success',
            'data' => $row
        ], 200);
    }

    public function createItem()


value00: app/Controllers/ValueSetController.php
value01:
    public function updateItem($id = null)
    {
        $input = $this->request->getJSON(true);
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }

        $existing = $this->dbModel->getValueSet($id);
        if (!$existing) {
            return $this->failNotFound("ValueSet item not found: $id");
        }


value00: app/Controllers/ValueSetController.php
value01:
        if ($data['VSetID'] === null) {
            return $this->failValidationErrors(['VSetID is required']);
        }

        try {
            $id = $this->dbModel->insert($data, true);
            if (!$id) {
                return $this->failValidationErrors($this->dbModel->errors());
            }

            $newRow = $this->dbModel->getValueSet($id);
            return $this->respondCreated([
                'status' => 'success',
                'message' => 'ValueSet item created',
                'data' => $newRow
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to create: ' . $e->getMessage());
        }
    }


value00: app/Controllers/ValueSetController.php
value01:
    {
        $input = $this->request->getJSON(true);
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }

        $data = [
            'SiteID' => $input['SiteID'] ?? 1,
            'VSetID' => $input['VSetID'] ?? null,
            'VOrder' => $input['VOrder'] ?? 0,
            'VValue' => $input['VValue'] ?? '',
            'VDesc' => $input['VDesc'] ?? ''
        ];

        if ($data['VSetID'] === null) {
            return $this->failValidationErrors(['VSetID is required']);
        }


value00: app/Controllers/ValueSetController.php
value01:
    public function deleteItem($id = null)
    {
        $existing = $this->dbModel->getValueSet($id);
        if (!$existing) {
            return $this->failNotFound("ValueSet item not found: $id");
        }

        try {
            $this->dbModel->delete($id);
            return $this->respond([
                'status' => 'success',
                'message' => 'ValueSet item deleted'
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to delete: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Patient/PatientController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);

        // Khusus untuk Override PATIDT
        $type = $input['PatIdt']['IdentifierType'] ?? null;
        $identifierRulesMap = [
            'KTP'  => 'required|regex_match[/^[0-9]{16}$/]',            // 16 pas digit numeric
            'PASS' => 'required|regex_match[/^[A-Za-z0-9]{1,9}$/]',     // alphanumeric max 9
            'SSN'  => 'required|regex_match[/^[0-9]{9}$/]',             // numeric, pas 9 digit
            'SIM'  => 'required|regex_match[/^[0-9]{19,20}$/]',         // numeric 19–20 digit
            'KTAS' => 'required|regex_match[/^[0-9]{11}$/]',            // numeric, pas 11 digit
        ];


value00: app/Controllers/Patient/PatientController.php
value01:
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $InternalPID = $this->model->createPatient($input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => "data $InternalPID created successfully" ]);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Patient/PatientController.php
value01:
,
            'PlaceOfBirth'      => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[100]',
            'Citizenship'       => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[100]',

            'Street_1'          => 'permit_empty|regex_match[/^[A-Za-z0-9\'.,\/\- ]+$/]|max_length[255]',
            'Street_2'          => 'permit_empty|regex_match[/^[A-Za-z0-9\'.,\/\- ]+$/]|max_length[255]',
            'Street_3'          => 'permit_empty|regex_match[/^[A-Za-z0-9\'.,\/\- ]+$/]|max_length[255]',

            'EmailAddress1'     => 'permit_empty|valid_email|max_length[100]',
            'EmailAddress2'     => 'permit_empty|valid_email|max_length[100]',
            
            'Birthdate'             => 'required'


value00: app/Controllers/Patient/PatientController.php
value01:
            $this->db->table('patient')->where('InternalPID', $InternalPID)->update(['DelDate' => date('Y-m-d H:i:s')]);

            return $this->respondDeleted([
                'status' => 'success',
                'message' => "Patient ID with {$InternalPID} deleted successfully."
            ]);
 
        } catch (\Exception $e) {
            return $this->failServerError("Internal server error: " . $e->getMessage());
        }
    }

    public function patientCheck() {
        try {
            $PatientID = $this->request->getVar('PatientID');
            $EmailAddress1 = $this->request->getVar('EmailAddress1');

            $tableName = '';
            $searchName = '';


value00: app/Controllers/Patient/PatientController.php
value01:
            if (!$patient) {
                return $this->respond([
                    'status'  => 'success',
                    'message' => "$tableName not found.",
                    'data'    => true,
                ], 200);
            }

            return $this->respond([
                'status'  => 'success',
                'message' => "$tableName already exists.",
                'data'    => false,
            ], 200);


        } catch (\Exception $e) {
            // Error Server Mengembalikan 500
            return $this->failServerError('Something went wrong.'.$e->getMessage());
        }
    }
}


value00: app/Controllers/Patient/PatientController.php
value01:
,
            'Prefix'            => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[10]',
            'Sex'             => 'required',

            'NameFirst'         => 'required|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',
            'NameMiddle'        => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',
            'NameMaiden'        => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',
            'NameLast'          => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|min_length[1]|max_length[60]',

            'Suffix'            => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[10]',
            'PlaceOfBirth'      => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[100]'


value00: app/Controllers/Patient/PatientController.php
value01:
        if ($type === null || $type === '' || !is_string($type)) {
            $identifierRule = 'permit_empty|max_length[255]';
            $this->rules['PatIdt.IdentifierType'] = 'permit_empty';
            $this->rules['PatIdt.Identifier']     = $identifierRule;
        } else {
            $identifierRule = $identifierRulesMap[$type] ?? 'permit_empty|max_length[255]';
            $this->rules['PatIdt.IdentifierType'] = 'required';
            $this->rules['PatIdt.Identifier']     = $identifierRule;
        }

        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }


value00: app/Controllers/Patient/PatientController.php
value01:
,
            'EmailAddress2'     => 'permit_empty|valid_email|max_length[100]',
            
            'Birthdate'             => 'required',
            'PatIdt.IdentifierType' => 'permit_empty',
            'PatIdt.Identifier'     => 'permit_empty|max_length[255]',

            'ZIP'               => 'permit_empty|is_natural|max_length[10]',
            'Phone'             => 'permit_empty|regex_match[/^\\+?[0-9]{8,15}$/]',
            'MobilePhone'       => 'permit_empty|regex_match[/^\\+?[0-9]{8,15}$/]'
        ];
    }


value00: app/Controllers/Patient/PatientController.php
value01:
        if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
        try {
            $InternalPID = $this->model->updatePatient($input);
            return $this->respondCreated([ 'status'  => 'success', 'message' => "data $InternalPID update successfully" ]);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Patient/PatientController.php
value01:
    public function index() {
        $filters = [
            'InternalPID' => $this->request->getVar('InternalPID'),
            'PatientID'   => $this->request->getVar('PatientID'),
            'Name'        => $this->request->getVar('Name'),
            'Birthdate'   => $this->request->getVar('Birthdate'),
        ];

        try {
            $rows = $this->model->getPatients($filters);
            
            $rows = ValueSet::transformLabels($rows, [
                'Sex' => 'sex',
            ]);
            
            return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data'   => $rows ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Exception : '.$e->getMessage());
        }
    }


value00: app/Controllers/Patient/PatientController.php
value01:
            $tableName = '';
            $searchName = '';

            if (!empty($PatientID)){
                $tableName = 'PatientID';
                $searchName = $PatientID;
            } elseif (!empty($EmailAddress1)){
                $tableName = 'EmailAddress1';
                $searchName = $EmailAddress1;
            } else {
                return $this->respond([
                    'status' => 'error',
                    'message' => 'PatientID or EmailAddress1 parameter is required.',
                    'data' => null
                ], 400); 
            }

            $patient = $this->db->table('patient')
                ->where($tableName, $searchName)
                ->get()
                ->getRowArray();


value00: app/Controllers/Patient/PatientController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $InternalPID = $input["InternalPID"];

            // Mencegah Inputan 0, [], null, sql injection


value00: app/Controllers/Patient/PatientController.php
value01:
        // Khusus untuk Override PATIDT
        $type = $input['PatIdt']['IdentifierType'] ?? null;
        $identifierRulesMap = [
            'KTP'  => 'required|regex_match[/^[0-9]{16}$/]',
            'PASS' => 'required|regex_match[/^[A-Za-z0-9]{6,9}$/]',
            'SSN'  => 'required|regex_match[/^[0-9]{3}-[0-9]{2}-[0-9]{4}$/]',
            'SIM'  => 'required|regex_match[/^[A-Za-z0-9]{12,14}$/]',
            'KTAS' => 'required|regex_match[/^[A-Za-z0-9]{12,15}$/]',
        ];


value00: app/Controllers/Patient/PatientController.php
value01:
    public function update($InternalPID = null) {
        $input = $this->request->getJSON(true);

        if (!$InternalPID || !ctype_digit((string) $InternalPID)) {
            return $this->respond([
                'status' => 'error',
                'message' => 'InternalPID is required and must be a valid integer.'
            ], 400);
        }

        $input['InternalPID'] = (int) $InternalPID;

        // Khusus untuk Override PATIDT
        $type = $input['PatIdt']['IdentifierType'] ?? null;


value00: app/Controllers/Patient/PatientController.php
value01:
<?php
namespace App\Controllers\Patient;

use App\Traits\ResponseTrait;
use CodeIgniter\Controller;
use App\Libraries\ValueSet;
use App\Models\Patient\PatientModel;

class PatientController extends Controller {
    use ResponseTrait;

    protected $db;
    protected $model;
    protected $rules;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new PatientModel();
        $this->rules = [
            'PatientID'         => 'required|regex_match[/^[A-Za-z0-9]+$/]|max_length[30]',
            'AlternatePID'      => 'permit_empty|regex_match[/^[A-Za-z0-9]+$/]|max_length[30]',
            'Prefix'            => 'permit_empty|regex_match[/^[A-Za-z\'\. ]+$/]|max_length[10]',


value00: app/Controllers/Patient/PatientController.php
value01:
    public function show($InternalPID = null) {
        try {
            $row = $this->model->getPatient($InternalPID);
            if (empty($row)) { return $this->respond([ 'status'  => 'success', 'message' => "data not found.", 'data' => null ], 200); }
            
            $row = ValueSet::transformLabels([$row], [
                'Sex' => 'sex',
            ])[0];
            
            return $this->respond([ 'status'  => 'success', 'message' => "data fetched successfully", 'data' => $row ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Patient/PatientController.php
value01:
            $InternalPID = $input["InternalPID"];

            // Mencegah Inputan 0, [], null, sql injection
            if (empty($InternalPID) || !ctype_digit((string) $InternalPID)) {
                return $this->respond([
                    'status' => 'error',
                    'message' => "Patient ID must be a valid integer."
                ], 400);
            }

            $patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRow();

            if (!$patient) {
                return $this->failNotFound("Patient ID with {$InternalPID} not found.");
            }

            $this->db->table('patient')->where('InternalPID', $InternalPID)->update(['DelDate' => date('Y-m-d H:i:s')]);


value00: app/Controllers/Test/TestsController.php
value01:
<?php

namespace App\Controllers\Test;

use App\Controllers\BaseController;
use App\Libraries\TestValidationService;
use App\Libraries\ValueSet;
use App\Traits\ResponseTrait;

class TestsController extends BaseController
{
    use ResponseTrait;

    protected $model;
    protected $modelCal;
    protected $modelGrp;
    protected $modelMap;
    protected $modelMapDetail;
    protected $modelRefNum;
    protected $modelRefTxt;
    protected $rules;


value00: app/Controllers/Test/TestsController.php
value01:
            'Method'         => $data['Method'] ?? null,
            'ExpectedTAT'    => $data['ExpectedTAT'] ?? null,
        ];

        $this->model->update($testSiteID, $techData);
    }

    private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID)
    {
        if ($action === 'update') {
            $this->modelRefNum->disableByTestSiteID($testSiteID);
        }

        $this->modelRefNum->batchInsert($testSiteID, $siteID, $ranges);
    }

    private function saveRefTxtRanges($testSiteID, $ranges, $action, $siteID)
    {
        if ($action === 'update') {
            $this->modelRefTxt->disableByTestSiteID($testSiteID);
        }

        $this->modelRefTxt->batchInsert($testSiteID, $siteID, $ranges);
    }


value00: app/Controllers/Test/TestsController.php
value01:
    protected $modelRefTxt;
    protected $rules;

    public function __construct()
    {
        $this->model = new \App\Models\Test\TestDefSiteModel;
        $this->modelCal = new \App\Models\Test\TestDefCalModel;
        $this->modelGrp = new \App\Models\Test\TestDefGrpModel;
        $this->modelMap = new \App\Models\Test\TestMapModel;
        $this->modelMapDetail = new \App\Models\Test\TestMapDetailModel;
        $this->modelRefNum = new \App\Models\RefRange\RefNumModel;
        $this->modelRefTxt = new \App\Models\RefRange\RefTxtModel;

        $this->rules = [
            'TestSiteCode' => 'required',
            'TestSiteName' => 'required',
            'TestType'     => 'required',
            'SiteID'       => 'required',
        ];
    }


value00: app/Controllers/Test/TestsController.php
value01:
        try {
            $testSiteData = [];
            $allowedUpdateFields = [
                'TestSiteCode',
                'TestSiteName',
                'TestType',
                'Description',
                'SeqScr',
                'SeqRpt',
                'IndentLeft',
                'FontStyle',
                'VisibleScr',
                'VisibleRpt',
                'CountStat',
                'StartDate',
            ];

            foreach ($allowedUpdateFields as $field) {
                if (isset($input[$field])) {
                    $testSiteData[$field] = $input[$field];
                }
            }

            if (!empty($testSiteData)) {
                $this->model->update($id, $testSiteData);
            }


value00: app/Controllers/Test/TestsController.php
value01:
    /**
     * Validate that member IDs exist in testdefsite table
     *
     * @param array $memberIDs Array of TestSiteID values to validate
     * @return array ['valid' => bool, 'invalid' => array]
     */


value00: app/Controllers/Test/TestsController.php
value01:
    private function handleDetails($testSiteID, $input, $action)
    {
        $testTypeID = $input['TestType'] ?? null;
        $testSiteCode = null;

        if (!$testTypeID && $action === 'update') {
            $existing = $this->model->find($testSiteID);
            $testTypeID = $existing['TestType'] ?? null;
            $testSiteCode = $existing['TestSiteCode'] ?? null;
        }

        if (!$testTypeID) {
            return;
        }

        $typeCode = $testTypeID;

        $details = $input['details'] ?? $input;
        $details['TestSiteID'] = $testSiteID;
        $details['SiteID'] = $input['SiteID'] ?? 1;


value00: app/Controllers/Test/TestsController.php
value01:
        if (is_array($mappings)) {
            foreach ($mappings as $map) {
                $mapData = [
                    'HostType'   => $map['HostType'] ?? null,
                    'HostID'     => $map['HostID'] ?? null,
                    'ClientType' => $map['ClientType'] ?? null,
                    'ClientID'   => $map['ClientID'] ?? null,
                ];
                $testMapID = $this->modelMap->insert($mapData);

                if ($testMapID && isset($map['details']) && is_array($map['details'])) {
                    foreach ($map['details'] as $detail)


value00: app/Controllers/Test/TestsController.php
value01:
    private function saveCalcDetails($testSiteID, $data, $input, $action)
    {
        $calcData = [
            'TestSiteID'    => $testSiteID,
            'DisciplineID'  => $data['DisciplineID'] ?? null,
            'DepartmentID'  => $data['DepartmentID'] ?? null,
            'FormulaCode'   => $data['FormulaCode'] ?? $data['Formula'] ?? null,
            'ResultType'    => 'NMRIC',
            'RefType'       => $data['RefType'] ?? 'RANGE',
            'Unit1'         => $data['Unit1'] ?? $data['ResultUnit'] ?? null,
            'Factor'        => $data['Factor'] ?? null,
            'Unit2'         => $data['Unit2'] ?? null,
            'Decimal'       => $data['Decimal'] ?? 2,
            'Method'        => $data['Method'] ?? null,
        ];


value00: app/Controllers/Test/TestsController.php
value01:
        switch ($typeCode) {
            case 'CALC':
                $this->saveCalcDetails($testSiteID, $details, $input, $action);

                break;

            case 'GROUP':
                $this->saveGroupDetails($testSiteID, $details, $input, $action);

                break;

            case 'TITLE':
                if (isset($input['testmap']) && is_array($input['testmap'])) {
                    $this->saveTestMap($testSiteID, $testSiteCode, $input['testmap'], $action);
                }

                break;

            case 'TEST':
            case 'PARAM':
            default:
                $this->saveTechDetails($testSiteID, $details, $action, $typeCode);


value00: app/Controllers/Test/TestsController.php
value01:
            $this->handleDetails($id, $input, 'update');

            $db->transComplete();

            if ($db->transStatus() === false) {
                return $this->failServerError('Transaction failed');
            }

            return $this->respond([
                'status'  => 'success',
                'message' => 'Test updated successfully',
                'data'    => ['TestSiteId' => $id],
            ]);
        } catch (\Exception $e) {
            $db->transRollback();

            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/ReportController.php
value01:
use CodeIgniter\Controller;
use App\Models\PatResultModel;
use App\Models\OrderTest\OrderTestModel;
use App\Models\Patient\PatientModel;

class ReportController extends Controller {
    use ResponseTrait;

    protected $resultModel;
    protected $orderModel;
    protected $patientModel;

    public function __construct() {
        $this->resultModel = new PatResultModel();
        $this->orderModel = new OrderTestModel();
        $this->patientModel = new PatientModel();
    }

    /**
     * Generate HTML lab report for an order
     * GET /api/report/{orderID}
     */
    public function view($orderID) {
        try {
            // Get order details
            $order = $this->orderModel->find((int)$orderID);


value00: app/Controllers/Test/TestsController.php
value01:
{
                    foreach ($map['details'] as $detail) {
                        $detailData = [
                            'TestMapID'      => $testMapID,
                            'HostTestCode'   => $detail['HostTestCode'] ?? null,
                            'HostTestName'   => $detail['HostTestName'] ?? null,
                            'ConDefID'       => $detail['ConDefID'] ?? null,
                            'ClientTestCode' => $detail['ClientTestCode'] ?? null,
                            'ClientTestName' => $detail['ClientTestName'] ?? null,
                        ];
                        $this->modelMapDetail->insert($detailData);
                    }
                }
            }
        }
    }
}


value00: app/Controllers/Test/TestsController.php
value01:
    public function delete($id = null)
    {
        $input = $this->request->getJSON(true);

        if (!$id && isset($input['TestSiteID'])) {
            $id = $input['TestSiteID'];
        }
        if (!$id) {
            return $this->failValidationErrors('TestSiteID is required.');
        }

        $existing = $this->model->find($id);
        if (!$existing) {
            return $this->failNotFound('Test not found');
        }

        if (!empty($existing['EndDate'])) {
            return $this->failValidationErrors('Test is already disabled');
        }

        $db = \Config\Database::connect();
        $db->transStart();

        try {
            $now = date('Y-m-d H:i:s');

            $this->model->update($id, ['EndDate' => $now]);


value00: app/Controllers/ValueSetDefController.php
value01:
        try {
            $id = $this->model->insert($data, true);
            if (!$id) {
                return $this->failValidationErrors($this->model->errors());
            }

            $newRow = $this->model->find($id);
            return $this->respondCreated([
                'status' => 'success',
                'message' => 'ValueSet definition created',
                'data' => $newRow
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to create: ' . $e->getMessage());
        }
    }


value00: app/Controllers/ReportController.php
value01:
<?php

namespace App\Controllers;

use App\Traits\ResponseTrait;
use CodeIgniter\Controller;
use App\Models\PatResultModel;
use App\Models\OrderTest\OrderTestModel;
use App\Models\Patient\PatientModel;


value00: app/Controllers/ValueSetDefController.php
value01:
<?php

namespace App\Controllers;

use App\Models\ValueSet\ValueSetDefModel;
use App\Traits\ResponseTrait;

class ValueSetDefController extends \CodeIgniter\Controller
{
    use ResponseTrait;

    protected $model;

    public function __construct()
    {
        $this->model = new ValueSetDefModel();
    }


value00: app/Controllers/Test/TestsController.php
value01:
    public function index()
    {
        $search = $this->request->getGet('search');
        
        $filters = [
            'SiteID' => $this->request->getGet('SiteID'),
            'TestType' => $this->request->getGet('TestType'),
            'VisibleScr' => $this->request->getGet('VisibleScr'),
            'VisibleRpt' => $this->request->getGet('VisibleRpt'),
            'TestSiteName' => $this->request->getGet('TestSiteName'),
            'TestSiteCode' => $this->request->getGet('TestSiteCode'),
            'search' => $search,
        ];

        $rows = $this->model->getTestsWithRelations($filters);


value00: app/Controllers/ReportController.php
value01:
            $results = $this->resultModel->getByOrder((int)$orderID);

            // Prepare data for the view
            $data = [
                'patient' => $patient,
                'order' => $order,
                'results' => $results,
                'generatedAt' => date('Y-m-d H:i:s')
            ];

            // Return HTML view
            return view('reports/lab_report', $data);

        } catch (\Exception $e) {
            log_message('error', 'ReportController::view error: ' . $e->getMessage());
            return $this->respond([
                'status' => 'failed',
                'message' => 'Failed to generate report',
                'data' => []
            ], 500);
        }
    }
}


value00: app/Controllers/ValueSetDefController.php
value01:
    public function delete($id = null)
    {
        $existing = $this->model->find($id);
        if (!$existing) {
            return $this->failNotFound("ValueSet definition not found: $id");
        }

        try {
            $this->model->delete($id);
            return $this->respond([
                'status' => 'success',
                'message' => 'ValueSet definition deleted'
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to delete: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Test/TestsController.php
value01:
        $db = \Config\Database::connect();
        $db->transStart();

        try {
            $testSiteData = [
                'SiteID'      => $input['SiteID'],
                'TestSiteCode'=> $input['TestSiteCode'],
                'TestSiteName'=> $input['TestSiteName'],
                'TestType'    => $input['TestType'],
                'Description' => $input['Description'] ?? null,
                'SeqScr'      => $input['SeqScr'] ?? 0,
                'SeqRpt'      => $input['SeqRpt'] ?? 0,
                'IndentLeft'  => $input['IndentLeft'] ?? 0,
                'FontStyle'   => $input['FontStyle'] ?? null,
                'VisibleScr'  => $input['VisibleScr'] ?? 1,
                'VisibleRpt'  => $input['VisibleRpt'] ?? 1


value00: app/Controllers/Infrastructure/EquipmentListController.php
value01:
    public function show($EID = null) {
        $row = $this->model->getEquipmentList($EID);

        if (empty($row)) {
            return $this->respond([
                'status' => 'success',
                'message' => 'no Data.',
                'data' => null
            ], 200);
        }

        return $this->respond([
            'status' => 'success',
            'message' => 'fetch success',
            'data' => $row
        ], 200);
    }


value00: app/Controllers/Infrastructure/EquipmentListController.php
value01:
    public function create() {
        $input = $this->request->getJSON(true);

        try {
            $EID = $this->model->insert($input, true);
            return $this->respondCreated([
                'status' => 'success',
                'message' => 'data created successfully',
                'data' => $EID
            ], 201);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Test/TestsController.php
value01:
    {
        if ($action === 'update') {
            $this->modelGrp->disableByTestSiteID($testSiteID);
        }

        $members = $data['members'] ?? ($input['Members'] ?? []);
        $memberIDs = [];

        if (is_array($members)) {
            foreach ($members as $m) {
                // Only accept TestSiteID, not Member (which might be SeqScr)
                $memberID = is_array($m) ? ($m['TestSiteID'] ?? null) : $m;
                if ($memberID && is_numeric($memberID)) {
                    $memberIDs[] = (int) $memberID;
                }
            }
        }

        $memberIDs = array_values(array_unique(array_filter($memberIDs)));

        // Validate member IDs before insertion
        $validation = $this->validateMemberIDs($memberIDs);


value00: app/Controllers/Result/ResultValueSetController.php
value01:
<?php

namespace App\Controllers\Result;

use App\Models\ValueSet\ValueSetModel;
use App\Traits\ResponseTrait;

class ResultValueSetController extends \CodeIgniter\Controller
{
    use ResponseTrait;

    protected $dbModel;

    public function __construct()
    {
        $this->dbModel = new ValueSetModel();
    }

    public function index()
    {
        $search = $this->request->getGet('search') ?? $this->request->getGet('param') ?? null;
        $VSetID = $this->request->getGet('VSetID') ?? null;

        $rows = $this->dbModel->getValueSets($search, $VSetID);

        return $this->respond([
            'status' => 'success',
            'data' => $rows
        ], 200);
    }


value00: app/Controllers/Test/TestsController.php
value01:
        if ($action === 'update') {
            $exists = $this->modelCal->existsByTestSiteID($testSiteID);

            if ($exists) {
                $this->modelCal->update($exists['TestCalID'], $calcData);
            } else {
                $this->modelCal->insert($calcData);
            }
        } else {
            $this->modelCal->insert($calcData);
        }

        if ($action === 'update') {
            $this->modelGrp->disableByTestSiteID($testSiteID);
        }

        $memberIDs = $this->resolveCalcMemberIDs($data, $input);

        // Validate member IDs before insertion
        $validation = $this->validateMemberIDs($memberIDs);


value00: app/Controllers/ValueSetDefController.php
value01:
    protected $model;

    public function __construct()
    {
        $this->model = new ValueSetDefModel();
    }

    public function index()
    {
        $search = $this->request->getGet('search') ?? null;
        $limit = (int) ($this->request->getGet('limit') ?? 100);
        $page = (int) ($this->request->getGet('page') ?? 1);
        $offset = ($page - 1) * $limit;

        $rows = $this->model->getValueSetDefs($search);

        $paged = array_slice($rows, $offset, $limit);

        return $this->respond([
            'status' => 'success',
            'data' => $paged,
            'meta' => [
                'total' => count($rows),
                'page' => $page,
                'limit' => $limit
            ]
        ], 200);
    }


value00: app/Controllers/Test/TestsController.php
value01:
        // Validate member IDs before insertion
        $validation = $this->validateMemberIDs($memberIDs);
        if (!$validation['valid']) {
            throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.');
        }

        foreach ($memberIDs as $memberID) {
            $this->modelGrp->insert([
                'TestSiteID' => $testSiteID,
                'Member'     => $memberID,
            ]);
        }
    }


value00: app/Controllers/ValueSetDefController.php
value01:
    public function update($id = null)
    {
        $input = $this->request->getJSON(true);
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }

        $existing = $this->model->find($id);
        if (!$existing) {
            return $this->failNotFound("ValueSet definition not found: $id");
        }


value00: app/Controllers/Test/TestsController.php
value01:
        $rows = $this->model->getTestsWithRelations($filters);

        if (empty($rows)) {
            return $this->respond([
                'status'  => 'success',
                'message' => 'No data.',
                'data'    => [],
            ], 200);
        }

        $rows = ValueSet::transformLabels($rows, [
            'TestType' => 'test_type',
        ]);

        return $this->respond([
            'status'  => 'success',
            'message' => 'Data fetched successfully',
            'data'    => $rows,
        ], 200);
    }


value00: app/Controllers/ValueSetDefController.php
value01:
        if (!$existing) {
            return $this->failNotFound("ValueSet definition not found: $id");
        }

        $data = [];
        if (isset($input['VSName'])) $data['VSName'] = $input['VSName'];
        if (isset($input['VSDesc'])) $data['VSDesc'] = $input['VSDesc'];
        if (isset($input['SiteID'])) $data['SiteID'] = $input['SiteID'];

        if (empty($data)) {
            return $this->respond([
                'status' => 'success',
                'message' => 'No changes to update',
                'data' => $existing
            ], 200);
        }


value00: app/Controllers/Result/ResultValueSetController.php
value01:
    public function delete($id = null)
    {
        $existing = $this->dbModel->getValueSet($id);
        if (!$existing) {
            return $this->failNotFound("ValueSet item not found: $id");
        }

        try {
            $this->dbModel->delete($id);
            return $this->respond([
                'status' => 'success',
                'message' => 'ValueSet item deleted'
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to delete: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Test/TestsController.php
value01:
    private function validateMemberIDs(array $memberIDs): array
    {
        if (empty($memberIDs)) {
            return ['valid' => true, 'invalid' => []];
        }

        $existing = $this->model->whereIn('TestSiteID', $memberIDs)
                                ->where('EndDate IS NULL')
                                ->findAll();

        $existingIDs = array_column($existing, 'TestSiteID');
        $invalidIDs = array_diff($memberIDs, $existingIDs);

        return [
            'valid' => empty($invalidIDs),
            'invalid' => array_values($invalidIDs)
        ];
    }

    private function saveGroupDetails($testSiteID, $data, $input, $action)


value00: app/Controllers/Test/TestsController.php
value01:
                if (in_array($typeCode, ['TEST', 'PARAM']) && isset($details['RefType'])) {
                    $refType = (string) $details['RefType'];
                    $resultType = $details['ResultType'] ?? '';

                    if (TestValidationService::usesRefNum($resultType, $refType) && isset($input['refnum']) && is_array($input['refnum'])) {
                        $this->saveRefNumRanges($testSiteID, $input['refnum'], $action, $input['SiteID'] ?? 1);
                    }

                    if (TestValidationService::usesRefTxt($resultType, $refType) && isset($input['reftxt']) && is_array($input['reftxt'])) {
                        $this->saveRefTxtRanges($testSiteID, $input['reftxt'], $action, $input['SiteID'] ?? 1);
                    }
                }


value00: app/Controllers/Result/ResultValueSetController.php
value01:
        if (isset($input['VValue'])) $data['VValue'] = $input['VValue'];
        if (isset($input['VDesc'])) $data['VDesc'] = $input['VDesc'];
        if (isset($input['SiteID'])) $data['SiteID'] = $input['SiteID'];
        if (isset($input['VCategory'])) $data['VCategory'] = $input['VCategory'];

        if (empty($data)) {
            return $this->respond([
                'status' => 'success',
                'message' => 'No changes to update',
                'data' => $existing
            ], 200);
        }


value00: app/Controllers/Result/ResultValueSetController.php
value01:
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }

        $data = [
            'SiteID' => $input['SiteID'] ?? 1,
            'VSetID' => $input['VSetID'] ?? null,
            'VOrder' => $input['VOrder'] ?? 0,
            'VValue' => $input['VValue'] ?? '',
            'VDesc' => $input['VDesc'] ?? '',
            'VCategory' => $input['VCategory'] ?? null
        ];

        if ($data['VSetID'] === null) {
            return $this->failValidationErrors(['VSetID is required']);
        }


value00: app/Controllers/Infrastructure/EquipmentListController.php
value01:
<?php

namespace App\Controllers\Infrastructure;

use App\Controllers\BaseController;
use App\Traits\ResponseTrait;
use App\Models\Infrastructure\EquipmentListModel;

class EquipmentListController extends BaseController {
    use ResponseTrait;

    protected $db;
    protected $model;

    public function __construct() {
        $this->db = \Config\Database::connect();
        $this->model = new EquipmentListModel();
    }

    public function index() {
        $filter = [
            'IEID' => $this->request->getVar('IEID'),
            'InstrumentName' => $this->request->getVar('InstrumentName')


value00: app/Controllers/ValueSetDefController.php
value01:
        try {
            $updated = $this->model->update($id, $data);
            if (!$updated) {
                return $this->failValidationErrors($this->model->errors());
            }

            $newRow = $this->model->find($id);
            return $this->respond([
                'status' => 'success',
                'message' => 'ValueSet definition updated',
                'data' => $newRow
            ], 200);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to update: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Infrastructure/EquipmentListController.php
value01:
        $filter = [
            'IEID' => $this->request->getVar('IEID'),
            'InstrumentName' => $this->request->getVar('InstrumentName'),
            'DepartmentID' => $this->request->getVar('DepartmentID'),
            'WorkstationID' => $this->request->getVar('WorkstationID'),
            'Enable' => $this->request->getVar('Enable'),
        ];

        $rows = $this->model->getEquipmentLists($filter);


value00: app/Controllers/ValueSetDefController.php
value01:
    public function show($id = null)
    {
        $row = $this->model->find($id);
        if (!$row) {
            return $this->failNotFound("ValueSet definition not found: $id");
        }

        $itemCount = $this->model->db->table('valueset')
            ->select('COUNT(*) as ItemCount')
            ->where('VSetID', $id)
            ->where('EndDate IS NULL')
            ->get()
            ->getRowArray()['ItemCount'] ?? 0;

        $row['ItemCount'] = (int) $itemCount;

        return $this->respond([
            'status' => 'success',
            'data' => $row
        ], 200);
    }

    public function create()


value00: app/Controllers/Result/ResultValueSetController.php
value01:
    public function update($id = null)
    {
        $input = $this->request->getJSON(true);
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }

        $existing = $this->dbModel->getValueSet($id);
        if (!$existing) {
            return $this->failNotFound("ValueSet item not found: $id");
        }

        $data = [];
        if (isset($input['VSetID'])) $data['VSetID'] = $input['VSetID'];
        if (isset($input['VOrder'])) $data['VOrder'] = $input['VOrder'];
        if (isset($input['VValue'])) $data['VValue'] = $input['VValue'];


value00: app/Controllers/Test/TestsController.php
value01:
            $this->model->update($id, ['EndDate' => $now]);

            $testType = $existing['TestType'];
            $typeCode = $testType;

            if (TestValidationService::isCalc($typeCode)) {
                $this->modelCal->disableByTestSiteID($id);
                $this->modelGrp->disableByTestSiteID($id);
            } elseif (TestValidationService::isGroup($typeCode)) {
                $this->modelGrp->disableByTestSiteID($id);
            } elseif (TestValidationService::isTechnicalTest($typeCode)) {
                $this->modelRefNum->disableByTestSiteID($id);
                $this->modelRefTxt->disableByTestSiteID($id);
            }

            // Disable testmap by test code
            $testSiteCode = $existing['TestSiteCode'] ?? null;


value00: app/Controllers/Test/TestsController.php
value01:
            return $this->respond([
                'status'  => 'success',
                'message' => 'Test disabled successfully',
                'data'    => ['TestSiteId' => $id, 'EndDate' => $now],
            ]);
        } catch (\Exception $e) {
            $db->transRollback();

            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Infrastructure/EquipmentListController.php
value01:
    public function delete() {
        try {
            $input = $this->request->getJSON(true);
            $EID = $input['EID'];

            if (!$EID) {
                return $this->failValidationErrors('EID is required.');
            }

            $this->model->delete($EID);
            return $this->respondDeleted([
                'status' => 'success',
                'message' => "{$EID} deleted successfully."
            ]);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }
}


value00: app/Controllers/Result/ResultValueSetController.php
value01:
    public function show($id = null)
    {
        $row = $this->dbModel->getValueSet($id);
        if (!$row) {
            return $this->failNotFound("ValueSet item not found: $id");
        }

        return $this->respond([
            'status' => 'success',
            'data' => $row
        ], 200);
    }

    public function create()
    {
        $input = $this->request->getJSON(true);
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }


value00: app/Controllers/ReportController.php
value01:
            // Get order details
            $order = $this->orderModel->find((int)$orderID);
            
            if (!$order) {
                return $this->respond([
                    'status' => 'failed',
                    'message' => 'Order not found',
                    'data' => []
                ], 404);
            }

            // Get patient details
            $patient = $this->patientModel->find($order['InternalPID']);


value00: app/Controllers/Test/TestsController.php
value01:
    private function resolveCalcMemberIDs(array $data, array $input): array
    {
        $memberIDs = [];

        $rawMembers = $data['members'] ?? ($input['members'] ?? []);
        if (is_array($rawMembers))


value00: app/Controllers/ReportController.php
value01:
            // Get patient details
            $patient = $this->patientModel->find($order['InternalPID']);
            
            if (!$patient) {
                return $this->respond([
                    'status' => 'failed',
                    'message' => 'Patient not found',
                    'data' => []
                ], 404);
            }

            // Get results for this order
            $results = $this->resultModel->getByOrder((int)$orderID);

            // Prepare data for the view


value00: app/Controllers/ValueSetDefController.php
value01:
    {
        $input = $this->request->getJSON(true);
        if (!$input) {
            return $this->failValidationErrors(['Invalid JSON input']);
        }

        $data = [
            'SiteID' => $input['SiteID'] ?? 1,
            'VSName' => $input['VSName'] ?? '',
            'VSDesc' => $input['VSDesc'] ?? ''
        ];


value00: app/Controllers/Test/TestsController.php
value01:
    {
        $memberIDs = [];

        $rawMembers = $data['members'] ?? ($input['members'] ?? []);
        if (is_array($rawMembers)) {
            foreach ($rawMembers as $member) {
                if (is_array($member)) {
                    // Only accept TestSiteID, not Member (which might be SeqScr)
                    $rawID = $member['TestSiteID'] ?? null;
                } else {
                    $rawID = is_numeric($member) ? $member : null;
                }

                if ($rawID !== null && is_numeric($rawID)) {
                    $memberIDs[] = (int) $rawID;
                }
            }
        }

        $memberIDs = array_values(array_unique(array_filter($memberIDs)));

        return $memberIDs;
    }


value00: app/Controllers/Test/TestsController.php
value01:
        $refType = $details['RefType'] ?? $existing['RefType'] ?? '';

        if (TestValidationService::isCalc($testType)) {
            $resultType = 'NMRIC';
            $refType = $refType ?: 'RANGE';
        } elseif (TestValidationService::isGroup($testType) || TestValidationService::isTitle($testType)) {
            $resultType = 'NORES';
            $refType = 'NOREF';
        }

        if ($resultType && $refType) {
            $validation = TestValidationService::validate($testType, $resultType, $refType);
            if (!$validation['valid']) {
                return $this->failValidationErrors(['type_validation' => $validation['error']]);
            }
        }

        $db = \Config\Database::connect();
        $db->transStart();


value00: app/Controllers/Infrastructure/EquipmentListController.php
value01:
    public function update($EID = null) {
        $input = $this->request->getJSON(true);

        try {
            if (!$EID || !ctype_digit((string) $EID)) {
                return $this->failValidationErrors('EID is required.');
            }
            $input['EID'] = (int) $EID;
            $this->model->update($EID, $input);
            return $this->respond([
                'status' => 'success',
                'message' => 'data updated successfully',
                'data' => $EID
            ], 200);
        } catch (\Throwable $e) {
            return $this->failServerError('Something went wrong: ' . $e->getMessage());
        }
    }


value00: app/Controllers/Test/TestsController.php
value01:
    public function show($id = null)
    {
        if (!$id) {
            return $this->failValidationErrors('TestSiteID is required');
        }

        $row = $this->model->getTestById($id);

        if (!$row) {
            return $this->respond([
                'status'  => 'success',
                'message' => 'No data.',
                'data'    => null,
            ], 200);
        }

        $typeCode = $row['TestType'] ?? '';

        if ($typeCode === 'CALC') {
            $row['testdefcal'] = $this->modelCal->getByTestSiteID($id);
            $row['testdefgrp'] = $this->modelGrp->getGroupMembers($id);
        } elseif ($typeCode === 'GROUP') {
            $row['testdefgrp'] = $this->modelGrp->getGroupMembers($id);
        }


value00: app/Controllers/Test/TestsController.php
value01:
        return $this->respond([
            'status'  => 'success',
            'message' => 'Data fetched successfully',
            'data'    => $row,
        ], 200);
    }

    public function create()
    {
        $input = $this->request->getJSON(true);

        if (!$this->validateData($input, $this->rules)) {
            return $this->failValidationErrors($this->validator->getErrors());
        }

        $testType = $input['TestType'] ?? '';
        $details = $input['details'] ?? $input;
        $resultType = $details['ResultType'] ?? '';
        $refType = $details['RefType'] ?? '';


value00: app/Controllers/Test/TestsController.php
value01:
    public function update($id = null)
    {
        $input = $this->request->getJSON(true);

        if (!$id && isset($input['TestSiteID'])) {
            $id = $input['TestSiteID'];
        }
        if (!$id) {
            return $this->failValidationErrors('TestSiteID is required.');
        }

        $existing = $this->model->find($id);
        if (!$existing) {
            return $this->failNotFound('Test not found');
        }

        $testType = $input['TestType'] ?? $existing['TestType'] ?? '';
        $details = $input['details'] ?? $input;
        $resultType = $details['ResultType'] ?? $existing['ResultType'] ?? '';
        $refType = $details['RefType'] ?? $existing['RefType'] ?? '';


