chore(repo): normalize EOL and harden contact patch flow
- handle contact PATCH failures by checking model save result and returning HTTP 400 with the model error message - update ContactDetailModel nested updates to enforce active-detail checks and use model update() with explicit failure propagation - extend contact patch assertions and align test-create variants expectations to status=success for POST responses - refresh composer lock metadata/dependency constraints and include generated docs/data/test files updated during normalization - impact: API contract unchanged except clearer 400 error responses on invalid contact detail updates
This commit is contained in:
parent
7fd3dfddd8
commit
30c4e47304
4
.serena/.gitignore
vendored
4
.serena/.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
/cache
|
/cache
|
||||||
/project.local.yml
|
/project.local.yml
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
Essential commands for CLQMS development (run from repo root on Windows PowerShell):
|
Essential commands for CLQMS development (run from repo root on Windows PowerShell):
|
||||||
|
|
||||||
• `composer install` – install PHP dependencies before running CodeIgniter or tests.
|
• `composer install` – install PHP dependencies before running CodeIgniter or tests.
|
||||||
• `npm install` – sync `package-lock.json` for tooling such as API docs bundler.
|
• `npm install` – sync `package-lock.json` for tooling such as API docs bundler.
|
||||||
• `./vendor/bin/phpunit` – run entire PHPUnit suite (or target files via `--filter`).
|
• `./vendor/bin/phpunit` – run entire PHPUnit suite (or target files via `--filter`).
|
||||||
• `php spark test --filter <Class>::<method>` – focused test run when you know the class/method.
|
• `php spark test --filter <Class>::<method>` – focused test run when you know the class/method.
|
||||||
• `php spark migrate` / `php spark migrate:rollback` – apply or roll back database migrations.
|
• `php spark migrate` / `php spark migrate:rollback` – apply or roll back database migrations.
|
||||||
• `php spark serve` – lightweight dev server for the API while developing locally.
|
• `php spark serve` – lightweight dev server for the API while developing locally.
|
||||||
• `node public/bundle-api-docs.js` – regenerate bundled OpenAPI docs whenever the YAML files change.
|
• `node public/bundle-api-docs.js` – regenerate bundled OpenAPI docs whenever the YAML files change.
|
||||||
• `git status`, `git diff`, `git log --oneline`, `git add <paths>`, `git commit`, `git pull`, `git push` – version control workflow commands.
|
• `git status`, `git diff`, `git log --oneline`, `git add <paths>`, `git commit`, `git pull`, `git push` – version control workflow commands.
|
||||||
• `ls` / `dir` / `Get-ChildItem` – inspect directories in PowerShell; `cd` to move between directories.
|
• `ls` / `dir` / `Get-ChildItem` – inspect directories in PowerShell; `cd` to move between directories.
|
||||||
• `type <file>` or `Get-Content` – view file contents when tools are not convenient.
|
• `type <file>` or `Get-Content` – view file contents when tools are not convenient.
|
||||||
|
|
||||||
Use these commands routinely after code changes, tests, or migrations.
|
Use these commands routinely after code changes, tests, or migrations.
|
||||||
@ -1,10 +1,10 @@
|
|||||||
When a task is completed in CLQMS backend, follow these wrap-up steps:
|
When a task is completed in CLQMS backend, follow these wrap-up steps:
|
||||||
|
|
||||||
1. Run relevant tests (`./vendor/bin/phpunit` or targeted `php spark test --filter ...`).
|
1. Run relevant tests (`./vendor/bin/phpunit` or targeted `php spark test --filter ...`).
|
||||||
2. If migrations changed, run `php spark migrate` / `php spark migrate:rollback` locally and ensure schema updates succeed.
|
2. If migrations changed, run `php spark migrate` / `php spark migrate:rollback` locally and ensure schema updates succeed.
|
||||||
3. After editing OpenAPI documentation (YAML files or controller mappings), regenerate `public/api-docs.bundled.yaml` via `node public/bundle-api-docs.js` and check it into Git.
|
3. After editing OpenAPI documentation (YAML files or controller mappings), regenerate `public/api-docs.bundled.yaml` via `node public/bundle-api-docs.js` and check it into Git.
|
||||||
4. Confirm code adheres to PSR-12/CodeIgniter conventions (strict types, response format, transactions, guard clauses) before committing.
|
4. Confirm code adheres to PSR-12/CodeIgniter conventions (strict types, response format, transactions, guard clauses) before committing.
|
||||||
5. Review `git status/diff` to ensure only intended files are staged; do not commit `.env` or other secret files.
|
5. Review `git status/diff` to ensure only intended files are staged; do not commit `.env` or other secret files.
|
||||||
6. For shared logic changes, double-check lookup JSON cache use and response logging.
|
6. For shared logic changes, double-check lookup JSON cache use and response logging.
|
||||||
|
|
||||||
These steps keep the API consistent, documented, and tested before merging or deploying.
|
These steps keep the API consistent, documented, and tested before merging or deploying.
|
||||||
@ -1,154 +1,154 @@
|
|||||||
# the name by which the project can be referenced within Serena
|
# the name by which the project can be referenced within Serena
|
||||||
project_name: "clqms01-be"
|
project_name: "clqms01-be"
|
||||||
|
|
||||||
|
|
||||||
# list of languages for which language servers are started; choose from:
|
# list of languages for which language servers are started; choose from:
|
||||||
# al bash clojure cpp csharp
|
# al bash clojure cpp csharp
|
||||||
# csharp_omnisharp dart elixir elm erlang
|
# csharp_omnisharp dart elixir elm erlang
|
||||||
# fortran fsharp go groovy haskell
|
# fortran fsharp go groovy haskell
|
||||||
# haxe java julia kotlin lua
|
# haxe java julia kotlin lua
|
||||||
# markdown
|
# markdown
|
||||||
# matlab nix pascal perl php
|
# matlab nix pascal perl php
|
||||||
# php_phpactor powershell python python_jedi r
|
# php_phpactor powershell python python_jedi r
|
||||||
# rego ruby ruby_solargraph rust scala
|
# rego ruby ruby_solargraph rust scala
|
||||||
# swift terraform toml typescript typescript_vts
|
# swift terraform toml typescript typescript_vts
|
||||||
# vue yaml zig
|
# vue yaml zig
|
||||||
# (This list may be outdated. For the current list, see values of Language enum here:
|
# (This list may be outdated. For the current list, see values of Language enum here:
|
||||||
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
|
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
|
||||||
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
|
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
|
||||||
# Note:
|
# Note:
|
||||||
# - For C, use cpp
|
# - For C, use cpp
|
||||||
# - For JavaScript, use typescript
|
# - For JavaScript, use typescript
|
||||||
# - For Free Pascal/Lazarus, use pascal
|
# - For Free Pascal/Lazarus, use pascal
|
||||||
# Special requirements:
|
# Special requirements:
|
||||||
# Some languages require additional setup/installations.
|
# Some languages require additional setup/installations.
|
||||||
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
|
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
|
||||||
# When using multiple languages, the first language server that supports a given file will be used for that file.
|
# When using multiple languages, the first language server that supports a given file will be used for that file.
|
||||||
# The first language is the default language and the respective language server will be used as a fallback.
|
# The first language is the default language and the respective language server will be used as a fallback.
|
||||||
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
|
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
|
||||||
languages:
|
languages:
|
||||||
- php
|
- php
|
||||||
|
|
||||||
# the encoding used by text files in the project
|
# the encoding used by text files in the project
|
||||||
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
|
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
|
||||||
encoding: "utf-8"
|
encoding: "utf-8"
|
||||||
|
|
||||||
# line ending convention to use when writing source files.
|
# line ending convention to use when writing source files.
|
||||||
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
|
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
|
||||||
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
|
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
|
||||||
line_ending:
|
line_ending:
|
||||||
|
|
||||||
# The language backend to use for this project.
|
# The language backend to use for this project.
|
||||||
# If not set, the global setting from serena_config.yml is used.
|
# If not set, the global setting from serena_config.yml is used.
|
||||||
# Valid values: LSP, JetBrains
|
# Valid values: LSP, JetBrains
|
||||||
# Note: the backend is fixed at startup. If a project with a different backend
|
# Note: the backend is fixed at startup. If a project with a different backend
|
||||||
# is activated post-init, an error will be returned.
|
# is activated post-init, an error will be returned.
|
||||||
language_backend:
|
language_backend:
|
||||||
|
|
||||||
# whether to use project's .gitignore files to ignore files
|
# whether to use project's .gitignore files to ignore files
|
||||||
ignore_all_files_in_gitignore: true
|
ignore_all_files_in_gitignore: true
|
||||||
|
|
||||||
# advanced configuration option allowing to configure language server-specific options.
|
# advanced configuration option allowing to configure language server-specific options.
|
||||||
# Maps the language key to the options.
|
# Maps the language key to the options.
|
||||||
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
|
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
|
||||||
# No documentation on options means no options are available.
|
# No documentation on options means no options are available.
|
||||||
ls_specific_settings: {}
|
ls_specific_settings: {}
|
||||||
|
|
||||||
# list of additional paths to ignore in this project.
|
# list of additional paths to ignore in this project.
|
||||||
# Same syntax as gitignore, so you can use * and **.
|
# Same syntax as gitignore, so you can use * and **.
|
||||||
# Note: global ignored_paths from serena_config.yml are also applied additively.
|
# Note: global ignored_paths from serena_config.yml are also applied additively.
|
||||||
ignored_paths: []
|
ignored_paths: []
|
||||||
|
|
||||||
# whether the project is in read-only mode
|
# whether the project is in read-only mode
|
||||||
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||||
# Added on 2025-04-18
|
# Added on 2025-04-18
|
||||||
read_only: false
|
read_only: false
|
||||||
|
|
||||||
# list of tool names to exclude.
|
# list of tool names to exclude.
|
||||||
# This extends the existing exclusions (e.g. from the global configuration)
|
# This extends the existing exclusions (e.g. from the global configuration)
|
||||||
#
|
#
|
||||||
# Below is the complete list of tools for convenience.
|
# Below is the complete list of tools for convenience.
|
||||||
# To make sure you have the latest list of tools, and to view their descriptions,
|
# To make sure you have the latest list of tools, and to view their descriptions,
|
||||||
# execute `uv run scripts/print_tool_overview.py`.
|
# execute `uv run scripts/print_tool_overview.py`.
|
||||||
#
|
#
|
||||||
# * `activate_project`: Activates a project based on the project name or path.
|
# * `activate_project`: Activates a project based on the project name or path.
|
||||||
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
||||||
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
||||||
# * `delete_memory`: Delete a memory file. Should only happen if a user asks for it explicitly,
|
# * `delete_memory`: Delete a memory file. Should only happen if a user asks for it explicitly,
|
||||||
# for example by saying that the information retrieved from a memory file is no longer correct
|
# for example by saying that the information retrieved from a memory file is no longer correct
|
||||||
# or no longer relevant for the project.
|
# or no longer relevant for the project.
|
||||||
# * `edit_memory`: Replaces content matching a regular expression in a memory.
|
# * `edit_memory`: Replaces content matching a regular expression in a memory.
|
||||||
# * `execute_shell_command`: Executes a shell command.
|
# * `execute_shell_command`: Executes a shell command.
|
||||||
# * `find_file`: Finds files in the given relative paths
|
# * `find_file`: Finds files in the given relative paths
|
||||||
# * `find_referencing_symbols`: Finds symbols that reference the given symbol using the language server backend
|
# * `find_referencing_symbols`: Finds symbols that reference the given symbol using the language server backend
|
||||||
# * `find_symbol`: Performs a global (or local) search using the language server backend.
|
# * `find_symbol`: Performs a global (or local) search using the language server backend.
|
||||||
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
||||||
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
||||||
# * `initial_instructions`: Provides instructions Serena usage (i.e. the 'Serena Instructions Manual')
|
# * `initial_instructions`: Provides instructions Serena usage (i.e. the 'Serena Instructions Manual')
|
||||||
# for clients that do not read the initial instructions when the MCP server is connected.
|
# for clients that do not read the initial instructions when the MCP server is connected.
|
||||||
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
||||||
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
||||||
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
||||||
# * `list_memories`: List available memories. Any memory can be read using the `read_memory` tool.
|
# * `list_memories`: List available memories. Any memory can be read using the `read_memory` tool.
|
||||||
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
||||||
# * `read_file`: Reads a file within the project directory.
|
# * `read_file`: Reads a file within the project directory.
|
||||||
# * `read_memory`: Read the content of a memory file. This tool should only be used if the information
|
# * `read_memory`: Read the content of a memory file. This tool should only be used if the information
|
||||||
# is relevant to the current task. You can infer whether the information
|
# is relevant to the current task. You can infer whether the information
|
||||||
# is relevant from the memory file name.
|
# is relevant from the memory file name.
|
||||||
# You should not read the same memory file multiple times in the same conversation.
|
# You should not read the same memory file multiple times in the same conversation.
|
||||||
# * `rename_memory`: Renames or moves a memory. Moving between project and global scope is supported
|
# * `rename_memory`: Renames or moves a memory. Moving between project and global scope is supported
|
||||||
# (e.g., renaming "global/foo" to "bar" moves it from global to project scope).
|
# (e.g., renaming "global/foo" to "bar" moves it from global to project scope).
|
||||||
# * `rename_symbol`: Renames a symbol throughout the codebase using language server refactoring capabilities.
|
# * `rename_symbol`: Renames a symbol throughout the codebase using language server refactoring capabilities.
|
||||||
# For JB, we use a separate tool.
|
# For JB, we use a separate tool.
|
||||||
# * `replace_content`: Replaces content in a file (optionally using regular expressions).
|
# * `replace_content`: Replaces content in a file (optionally using regular expressions).
|
||||||
# * `replace_symbol_body`: Replaces the full definition of a symbol using the language server backend.
|
# * `replace_symbol_body`: Replaces the full definition of a symbol using the language server backend.
|
||||||
# * `safe_delete_symbol`:
|
# * `safe_delete_symbol`:
|
||||||
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
||||||
# * `write_memory`: Write some information (utf-8-encoded) about this project that can be useful for future tasks to a memory in md format.
|
# * `write_memory`: Write some information (utf-8-encoded) about this project that can be useful for future tasks to a memory in md format.
|
||||||
# The memory name should be meaningful.
|
# The memory name should be meaningful.
|
||||||
excluded_tools: []
|
excluded_tools: []
|
||||||
|
|
||||||
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
|
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
|
||||||
# This extends the existing inclusions (e.g. from the global configuration).
|
# This extends the existing inclusions (e.g. from the global configuration).
|
||||||
included_optional_tools: []
|
included_optional_tools: []
|
||||||
|
|
||||||
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
|
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
|
||||||
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
|
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
|
||||||
fixed_tools: []
|
fixed_tools: []
|
||||||
|
|
||||||
# list of mode names to that are always to be included in the set of active modes
|
# list of mode names to that are always to be included in the set of active modes
|
||||||
# The full set of modes to be activated is base_modes + default_modes.
|
# The full set of modes to be activated is base_modes + default_modes.
|
||||||
# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply.
|
# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply.
|
||||||
# Otherwise, this setting overrides the global configuration.
|
# Otherwise, this setting overrides the global configuration.
|
||||||
# Set this to [] to disable base modes for this project.
|
# Set this to [] to disable base modes for this project.
|
||||||
# Set this to a list of mode names to always include the respective modes for this project.
|
# Set this to a list of mode names to always include the respective modes for this project.
|
||||||
base_modes:
|
base_modes:
|
||||||
|
|
||||||
# list of mode names that are to be activated by default.
|
# list of mode names that are to be activated by default.
|
||||||
# The full set of modes to be activated is base_modes + default_modes.
|
# The full set of modes to be activated is base_modes + default_modes.
|
||||||
# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply.
|
# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply.
|
||||||
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
|
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
|
||||||
# This setting can, in turn, be overridden by CLI parameters (--mode).
|
# This setting can, in turn, be overridden by CLI parameters (--mode).
|
||||||
default_modes:
|
default_modes:
|
||||||
|
|
||||||
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||||
# (contrary to the memories, which are loaded on demand).
|
# (contrary to the memories, which are loaded on demand).
|
||||||
initial_prompt: ""
|
initial_prompt: ""
|
||||||
|
|
||||||
# time budget (seconds) per tool call for the retrieval of additional symbol information
|
# time budget (seconds) per tool call for the retrieval of additional symbol information
|
||||||
# such as docstrings or parameter information.
|
# such as docstrings or parameter information.
|
||||||
# This overrides the corresponding setting in the global configuration; see the documentation there.
|
# This overrides the corresponding setting in the global configuration; see the documentation there.
|
||||||
# If null or missing, use the setting from the global configuration.
|
# If null or missing, use the setting from the global configuration.
|
||||||
symbol_info_budget:
|
symbol_info_budget:
|
||||||
|
|
||||||
# list of regex patterns which, when matched, mark a memory entry as read‑only.
|
# list of regex patterns which, when matched, mark a memory entry as read‑only.
|
||||||
# Extends the list from the global configuration, merging the two lists.
|
# Extends the list from the global configuration, merging the two lists.
|
||||||
read_only_memory_patterns: []
|
read_only_memory_patterns: []
|
||||||
|
|
||||||
# list of regex patterns for memories to completely ignore.
|
# list of regex patterns for memories to completely ignore.
|
||||||
# Matching memories will not appear in list_memories or activate_project output
|
# Matching memories will not appear in list_memories or activate_project output
|
||||||
# and cannot be accessed via read_memory or write_memory.
|
# and cannot be accessed via read_memory or write_memory.
|
||||||
# To access ignored memory files, use the read_file tool on the raw file path.
|
# To access ignored memory files, use the read_file tool on the raw file path.
|
||||||
# Extends the list from the global configuration, merging the two lists.
|
# Extends the list from the global configuration, merging the two lists.
|
||||||
# Example: ["_archive/.*", "_episodes/.*"]
|
# Example: ["_archive/.*", "_episodes/.*"]
|
||||||
ignored_memory_patterns: []
|
ignored_memory_patterns: []
|
||||||
|
|||||||
306
AGENTS.md
306
AGENTS.md
@ -1,153 +1,153 @@
|
|||||||
# AGENTS.md - Code Guidelines for CLQMS
|
# 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.
|
> **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
|
## Repository Snapshot
|
||||||
- `app/` holds controllers, models, filters, and traits wired through PSR-4 `App\` namespace.
|
- `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.
|
- `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.
|
- 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.
|
- Environment values, secrets, and database credentials live in `.env` but are never committed; treat the file as a reference for defaults.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Build, Lint & Test
|
## Build, Lint & Test
|
||||||
All commands run from the repository root.
|
All commands run from the repository root.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run the entire PHPUnit suite
|
# Run the entire PHPUnit suite
|
||||||
./vendor/bin/phpunit
|
./vendor/bin/phpunit
|
||||||
|
|
||||||
# Target a single test file (fast verification)
|
# Target a single test file (fast verification)
|
||||||
./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php
|
./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php
|
||||||
|
|
||||||
# Run one test case by method
|
# Run one test case by method
|
||||||
./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php
|
./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php
|
||||||
|
|
||||||
# Generate scaffolding (model, controller, migration)
|
# Generate scaffolding (model, controller, migration)
|
||||||
php spark make:model <Name>
|
php spark make:model <Name>
|
||||||
php spark make:controller <Name>
|
php spark make:controller <Name>
|
||||||
php spark make:migration <name>
|
php spark make:migration <name>
|
||||||
|
|
||||||
# Database migrations
|
# Database migrations
|
||||||
php spark migrate
|
php spark migrate
|
||||||
php spark migrate:rollback
|
php spark migrate:rollback
|
||||||
|
|
||||||
# After OpenAPI edits
|
# After OpenAPI edits
|
||||||
node public/bundle-api-docs.js
|
node public/bundle-api-docs.js
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `php spark test --filter <Class>::<method>` when filtering more than one test file is cumbersome.
|
Use `php spark test --filter <Class>::<method>` when filtering more than one test file is cumbersome.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Agent Rules Scan
|
## Agent Rules Scan
|
||||||
- No `.cursor/rules/*` or `.cursorrules` directory detected; continue without Cursor-specific constraints.
|
- 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.
|
- No `.github/copilot-instructions.md` present; Copilot behaviors revert to general GitHub defaults.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Coding Standards
|
## Coding Standards
|
||||||
|
|
||||||
### Language & Formatting
|
### Language & Formatting
|
||||||
- PHP 8.1+ is the baseline; enable `declare(strict_types=1)` at the top of new files when practical.
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- Keep methods under ~40 lines when possible; extract private helpers for repeated flows.
|
||||||
|
|
||||||
### Naming & Types
|
### Naming & Types
|
||||||
- Classes, controllers, libraries, and traits: PascalCase (e.g., `PatientImportController`).
|
- Classes, controllers, libraries, and traits: PascalCase (e.g., `PatientImportController`).
|
||||||
- Methods, services, traits: camelCase (`fetchActivePatients`).
|
- Methods, services, traits: camelCase (`fetchActivePatients`).
|
||||||
- Properties: camelCase for new code; legacy snake_case may persist but avoid new snake_case unless mirroring legacy columns.
|
- Properties: camelCase for new code; legacy snake_case may persist but avoid new snake_case unless mirroring legacy columns.
|
||||||
- Constants: UPPER_SNAKE_CASE.
|
- Constants: UPPER_SNAKE_CASE.
|
||||||
- DTOs/array shapes: Use descriptive names (`$patientInput`, `$validatedPayload`).
|
- 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.
|
- 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.
|
- Prefer PHPDoc only when type inference fails (complex union or array shapes) but still keep method summaries concise.
|
||||||
|
|
||||||
### Imports & Structure
|
### Imports & Structure
|
||||||
- Namespace declarations at the very top followed by grouped `use` statements.
|
- 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.
|
- Import order: Core framework (`CodeIgniter`), then `App\`, then third-party packages (Firebase, Faker, etc.). Keep each group alphabetical.
|
||||||
- No inline `use` statements inside methods.
|
- No inline `use` statements inside methods.
|
||||||
- Keep `use` statements de-duplicated; rely on IDE or `phpcbf` to reorder.
|
- Keep `use` statements de-duplicated; rely on IDE or `phpcbf` to reorder.
|
||||||
|
|
||||||
### Controller Structure
|
### Controller Structure
|
||||||
- Controllers orchestrate request validation, delegates to services/models, and return `ResponseTrait` responses; avoid direct DB queries here.
|
- 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\...`).
|
- 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.
|
- 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.
|
- Always respond through `$this->respond()` or `$this->respondCreated()` so JSON structure stays consistent.
|
||||||
|
|
||||||
### Response & Error Handling
|
### Response & Error Handling
|
||||||
- All responses follow `{ status, message, data }`. `status` values: `success`, `failed`, or `error`.
|
- All responses follow `{ status, message, data }`. `status` values: `success`, `failed`, or `error`.
|
||||||
- Use `$this->respondCreated()`, `$this->respondNoContent()`, or `$this->respond()` with explicit HTTP codes.
|
- 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.
|
- 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.
|
- For validation failures, return HTTP 400 with detailed message; unauthorized access returns 401. Maintain parity with existing tests.
|
||||||
|
|
||||||
### Database & Transactions
|
### Database & Transactions
|
||||||
- Use Query Builder or Model methods; enable `use App\Models\BaseModel` which handles UTC conversions.
|
- Use Query Builder or Model methods; enable `use App\Models\BaseModel` which handles UTC conversions.
|
||||||
- Always call `helper('utc')` when manipulating timestamps.
|
- 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.
|
- 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.
|
- Run `checkDbError()` (existing helper) after saves when manual queries are necessary.
|
||||||
|
|
||||||
### Service Helpers & Libraries
|
### Service Helpers & Libraries
|
||||||
- Encapsulate complex lookups (ValueSet, encryption) inside `app/Libraries` or Traits.
|
- Encapsulate complex lookups (ValueSet, encryption) inside `app/Libraries` or Traits.
|
||||||
- Reuse `App\Libraries\Lookups` for consistent label/value translations.
|
- 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`.
|
- Keep shared logic (e.g., response formatting, JWT decoding) inside Traits and import them via `use`.
|
||||||
|
|
||||||
### Testing & Coverage
|
### Testing & Coverage
|
||||||
- Place feature tests under `tests/Feature`, unit tests under `tests/Unit`.
|
- 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`).
|
- 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.
|
- 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.
|
- 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.
|
- Run targeted tests during development, full suite before merging.
|
||||||
|
|
||||||
### Documentation & API Sync
|
### 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`.
|
- 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.
|
- 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.
|
- Keep the controller-to-YAML mapping table updated to reflect new resources.
|
||||||
|
|
||||||
### Routing Conventions
|
### Routing Conventions
|
||||||
- Keep route definitions grouped inside `$routes->group('api/<resource>')` blocks in `app/Config/Routes.php`.
|
- 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.
|
- 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.
|
- 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.
|
- Document side effects (snapshots, audit logs) directly in the corresponding OpenAPI `paths` file.
|
||||||
|
|
||||||
### Environment & Secrets
|
### Environment & Secrets
|
||||||
- Use `.env` as the source of truth for database/jwt settings. Do not commit production credentials.
|
- 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.
|
- 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.
|
- `JWT_SECRET` must be treated as sensitive and rotated via environment updates only.
|
||||||
|
|
||||||
### Workflows & Misc
|
### Workflows & Misc
|
||||||
- Use `php spark migrate`/`migrate:rollback` for schema changes.
|
- Use `php spark migrate`/`migrate:rollback` for schema changes.
|
||||||
- For seeding or test fixtures, prefer factories (Faker) seeded in `tests/Support` when available.
|
- 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.
|
- Document major changes in `issues.md` or dedicated feature docs under `docs/` before merging.
|
||||||
|
|
||||||
### Security & Filters
|
### Security & Filters
|
||||||
- Apply the `auth` filter to every protected route, and keep `ApiKey` or other custom filters consolidated under `app/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.
|
- 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.
|
- 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.
|
- Respond 401 for missing tokens, 403 when permissions fail, and log sanitized details for ops debugging.
|
||||||
|
|
||||||
### Legacy Field Naming & ValueSets
|
### Legacy Field Naming & ValueSets
|
||||||
- Databases use PascalCase columns such as `PatientID`, `NameFirst`, `CreatedAt`. Keep migration checks aware of these names.
|
- 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'])`.
|
- 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.
|
- Prefer `App\Libraries\Lookups` or `app/Traits/ValueSetTrait` to avoid ad-hoc mappings.
|
||||||
|
|
||||||
### Nested Data Handling
|
### Nested Data Handling
|
||||||
- For entities that carry related collections (`PatIdt`, `PatCom`, `PatAtt`), extract nested arrays before filtering and validating.
|
- 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.
|
- Use transactions whenever multi-table inserts/updates occur so orphan rows are avoided.
|
||||||
- Guard against empty/null arrays by normalizing to `[]` before iterating.
|
- Guard against empty/null arrays by normalizing to `[]` before iterating.
|
||||||
|
|
||||||
### Observability & Logging
|
### Observability & Logging
|
||||||
- Use `log_message('info', ...)` for happy-path checkpoints and `'error'` for catch-all failures.
|
- 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.
|
- 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.
|
- Keep `writable/logs` clean by rotating or pruning stale log files with automation outside the repo.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Final Notes for Agents
|
## Final Notes for Agents
|
||||||
- This repo has no UI layer; focus exclusively on REST interactions.
|
- 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.
|
- 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.
|
- When in doubt, align with existing controller traits and response helpers to avoid duplicating logic.
|
||||||
- Rely on Serena tools for guided edits, searches, and context summaries (use the available symbolic and search tools before running shell commands).
|
- Rely on Serena tools for guided edits, searches, and context summaries (use the available symbolic and search tools before running shell commands).
|
||||||
|
|||||||
@ -1,60 +1,60 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Controllers\Audit;
|
namespace App\Controllers\Audit;
|
||||||
|
|
||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Services\AuditLogService;
|
use App\Services\AuditLogService;
|
||||||
use App\Traits\ResponseTrait;
|
use App\Traits\ResponseTrait;
|
||||||
use CodeIgniter\HTTP\ResponseInterface;
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class AuditLogController extends BaseController
|
class AuditLogController extends BaseController
|
||||||
{
|
{
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
private AuditLogService $auditLogService;
|
private AuditLogService $auditLogService;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->auditLogService = new AuditLogService();
|
$this->auditLogService = new AuditLogService();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index(): ResponseInterface
|
public function index(): ResponseInterface
|
||||||
{
|
{
|
||||||
$filters = [
|
$filters = [
|
||||||
'table' => $this->request->getGet('table'),
|
'table' => $this->request->getGet('table'),
|
||||||
'rec_id' => $this->request->getGet('rec_id') ?? $this->request->getGet('recId'),
|
'rec_id' => $this->request->getGet('rec_id') ?? $this->request->getGet('recId'),
|
||||||
'event_id' => $this->request->getGet('event_id') ?? $this->request->getGet('eventId'),
|
'event_id' => $this->request->getGet('event_id') ?? $this->request->getGet('eventId'),
|
||||||
'activity_id' => $this->request->getGet('activity_id') ?? $this->request->getGet('activityId'),
|
'activity_id' => $this->request->getGet('activity_id') ?? $this->request->getGet('activityId'),
|
||||||
'from' => $this->request->getGet('from'),
|
'from' => $this->request->getGet('from'),
|
||||||
'to' => $this->request->getGet('to'),
|
'to' => $this->request->getGet('to'),
|
||||||
'search' => $this->request->getGet('search'),
|
'search' => $this->request->getGet('search'),
|
||||||
'page' => $this->request->getGet('page'),
|
'page' => $this->request->getGet('page'),
|
||||||
'perPage' => $this->request->getGet('perPage') ?? $this->request->getGet('per_page'),
|
'perPage' => $this->request->getGet('perPage') ?? $this->request->getGet('per_page'),
|
||||||
];
|
];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$payload = $this->auditLogService->fetchLogs($filters);
|
$payload = $this->auditLogService->fetchLogs($filters);
|
||||||
|
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'message' => 'Audit logs retrieved successfully',
|
'message' => 'Audit logs retrieved successfully',
|
||||||
'data' => $payload,
|
'data' => $payload,
|
||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
'data' => null,
|
'data' => null,
|
||||||
], 400);
|
], 400);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
log_message('error', 'AuditLogController::index error: ' . $e->getMessage());
|
log_message('error', 'AuditLogController::index error: ' . $e->getMessage());
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Unable to retrieve audit logs',
|
'message' => 'Unable to retrieve audit logs',
|
||||||
'data' => null,
|
'data' => null,
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,73 +1,73 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Controllers\Contact;
|
namespace App\Controllers\Contact;
|
||||||
|
|
||||||
use App\Traits\PatchValidationTrait;
|
use App\Traits\PatchValidationTrait;
|
||||||
use App\Traits\ResponseTrait;
|
use App\Traits\ResponseTrait;
|
||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Libraries\ValueSet;
|
use App\Libraries\ValueSet;
|
||||||
use App\Models\Contact\ContactModel;
|
use App\Models\Contact\ContactModel;
|
||||||
|
|
||||||
class ContactController extends BaseController {
|
class ContactController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
use PatchValidationTrait;
|
use PatchValidationTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $model;
|
protected $model;
|
||||||
protected $rules;
|
protected $rules;
|
||||||
protected $patchRules;
|
protected $patchRules;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new ContactModel();
|
$this->model = new ContactModel();
|
||||||
$this->rules = [ 'NameFirst' => 'required' ];
|
$this->rules = [ 'NameFirst' => 'required' ];
|
||||||
$this->patchRules = [ 'NameFirst' => 'permit_empty' ];
|
$this->patchRules = [ 'NameFirst' => 'permit_empty' ];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$ContactName = $this->request->getVar('ContactName');
|
$ContactName = $this->request->getVar('ContactName');
|
||||||
$Specialty = $this->request->getVar('Specialty');
|
$Specialty = $this->request->getVar('Specialty');
|
||||||
$rows = $this->model->getContacts($ContactName, $Specialty);
|
$rows = $this->model->getContacts($ContactName, $Specialty);
|
||||||
|
|
||||||
if (empty($rows)) {
|
if (empty($rows)) {
|
||||||
return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200);
|
return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => [] ], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
$rows = ValueSet::transformLabels($rows, [
|
$rows = ValueSet::transformLabels($rows, [
|
||||||
'Specialty' => 'specialty',
|
'Specialty' => 'specialty',
|
||||||
'Occupation' => 'occupation',
|
'Occupation' => 'occupation',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
|
return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $rows ], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($ContactID = null) {
|
public function show($ContactID = null) {
|
||||||
$model = new ContactModel();
|
$model = new ContactModel();
|
||||||
$row = $model->getContactWithDetail($ContactID);
|
$row = $model->getContactWithDetail($ContactID);
|
||||||
|
|
||||||
if (empty($row)) {
|
if (empty($row)) {
|
||||||
return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => null ], 200);
|
return $this->respond([ 'status' => 'success', 'message' => "no Data.", 'data' => null ], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = ValueSet::transformLabels([$row], [
|
$row = ValueSet::transformLabels([$row], [
|
||||||
'Specialty' => 'specialty',
|
'Specialty' => 'specialty',
|
||||||
'Occupation' => 'occupation',
|
'Occupation' => 'occupation',
|
||||||
])[0];
|
])[0];
|
||||||
|
|
||||||
return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
|
return $this->respond([ 'status' => 'success', 'message'=> "fetch success", 'data' => $row ], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
try {
|
try {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
$ContactID = $input["ContactID"];
|
$ContactID = $input["ContactID"];
|
||||||
if (!$ContactID) { return $this->failValidationErrors('ContactID is required.'); }
|
if (!$ContactID) { return $this->failValidationErrors('ContactID is required.'); }
|
||||||
$this->model->delete($ContactID);
|
$this->model->delete($ContactID);
|
||||||
return $this->respondDeleted([ 'status' => 'success', 'message' => "Contact with {$ContactID} deleted successfully."]);
|
return $this->respondDeleted([ 'status' => 'success', 'message' => "Contact with {$ContactID} deleted successfully."]);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create() {
|
public function create() {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
|
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
|
||||||
@ -87,7 +87,7 @@ class ContactController extends BaseController {
|
|||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($ContactID = null) {
|
public function update($ContactID = null) {
|
||||||
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
||||||
if ($input === null) {
|
if ($input === null) {
|
||||||
@ -115,9 +115,17 @@ class ContactController extends BaseController {
|
|||||||
|
|
||||||
$input['ContactID'] = $id;
|
$input['ContactID'] = $id;
|
||||||
try {
|
try {
|
||||||
$this->model->saveContact($input);
|
$result = $this->model->saveContact($input);
|
||||||
$id = $input['ContactID'];
|
|
||||||
return $this->respond([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $id ], 200);
|
if (($result['status'] ?? 'error') !== 'success') {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'message' => $result['message'] ?? 'Failed to update contact',
|
||||||
|
'data' => []
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respond([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $result ], 200);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,112 +1,112 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Controllers\Organization;
|
namespace App\Controllers\Organization;
|
||||||
|
|
||||||
use App\Traits\PatchValidationTrait;
|
use App\Traits\PatchValidationTrait;
|
||||||
use App\Traits\ResponseTrait;
|
use App\Traits\ResponseTrait;
|
||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Models\Organization\CodingSysModel;
|
use App\Models\Organization\CodingSysModel;
|
||||||
|
|
||||||
class CodingSysController extends BaseController {
|
class CodingSysController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
use PatchValidationTrait;
|
use PatchValidationTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $model;
|
protected $model;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new CodingSysModel();
|
$this->model = new CodingSysModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$filter = [
|
$filter = [
|
||||||
'CodingSysAbb' => $this->request->getVar('CodingSysAbb'),
|
'CodingSysAbb' => $this->request->getVar('CodingSysAbb'),
|
||||||
'FullText' => $this->request->getVar('FullText'),
|
'FullText' => $this->request->getVar('FullText'),
|
||||||
];
|
];
|
||||||
|
|
||||||
$builder = $this->model;
|
$builder = $this->model;
|
||||||
|
|
||||||
if (!empty($filter['CodingSysAbb'])) {
|
if (!empty($filter['CodingSysAbb'])) {
|
||||||
$builder->like('CodingSysAbb', $filter['CodingSysAbb'], 'both');
|
$builder->like('CodingSysAbb', $filter['CodingSysAbb'], 'both');
|
||||||
}
|
}
|
||||||
if (!empty($filter['FullText'])) {
|
if (!empty($filter['FullText'])) {
|
||||||
$builder->like('FullText', $filter['FullText'], 'both');
|
$builder->like('FullText', $filter['FullText'], 'both');
|
||||||
}
|
}
|
||||||
|
|
||||||
$rows = $builder->findAll();
|
$rows = $builder->findAll();
|
||||||
|
|
||||||
if (empty($rows)) {
|
if (empty($rows)) {
|
||||||
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
|
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
|
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($CodingSysID = null) {
|
public function show($CodingSysID = null) {
|
||||||
$row = $this->model->where('CodingSysID', $CodingSysID)->first();
|
$row = $this->model->where('CodingSysID', $CodingSysID)->first();
|
||||||
|
|
||||||
if (empty($row)) {
|
if (empty($row)) {
|
||||||
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
|
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
|
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
try {
|
try {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
$id = $input['CodingSysID'] ?? null;
|
$id = $input['CodingSysID'] ?? null;
|
||||||
|
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
return $this->failValidationErrors('CodingSysID is required.');
|
return $this->failValidationErrors('CodingSysID is required.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->model->delete($id);
|
$this->model->delete($id);
|
||||||
return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
|
return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create() {
|
public function create() {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$id = $this->model->insert($input, true);
|
$id = $this->model->insert($input, true);
|
||||||
return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
|
return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($CodingSysID = null) {
|
public function update($CodingSysID = null) {
|
||||||
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
||||||
if ($input === null) {
|
if ($input === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = $this->requirePatchId($CodingSysID, 'CodingSysID');
|
$id = $this->requirePatchId($CodingSysID, 'CodingSysID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$existing = $this->model->find($id);
|
$existing = $this->model->find($id);
|
||||||
if (!$existing) {
|
if (!$existing) {
|
||||||
return $this->respond(['status' => 'failed', 'message' => 'CodingSys not found', 'data' => []], 404);
|
return $this->respond(['status' => 'failed', 'message' => 'CodingSys not found', 'data' => []], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($input['CodingSysID']) && (string) $input['CodingSysID'] !== (string) $id) {
|
if (isset($input['CodingSysID']) && (string) $input['CodingSysID'] !== (string) $id) {
|
||||||
return $this->failValidationErrors('CodingSysID in URL does not match body.');
|
return $this->failValidationErrors('CodingSysID in URL does not match body.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$input['CodingSysID'] = $id;
|
$input['CodingSysID'] = $id;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->model->update($id, $input);
|
$this->model->update($id, $input);
|
||||||
return $this->respondCreated(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 201);
|
return $this->respondCreated(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 201);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,124 +1,124 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Controllers\Organization;
|
namespace App\Controllers\Organization;
|
||||||
|
|
||||||
use App\Traits\PatchValidationTrait;
|
use App\Traits\PatchValidationTrait;
|
||||||
use App\Traits\ResponseTrait;
|
use App\Traits\ResponseTrait;
|
||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Models\Organization\HostAppModel;
|
use App\Models\Organization\HostAppModel;
|
||||||
|
|
||||||
class HostAppController extends BaseController {
|
class HostAppController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
use PatchValidationTrait;
|
use PatchValidationTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $model;
|
protected $model;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new HostAppModel();
|
$this->model = new HostAppModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$filter = [
|
$filter = [
|
||||||
'HostAppID' => $this->request->getVar('HostAppID'),
|
'HostAppID' => $this->request->getVar('HostAppID'),
|
||||||
'HostAppName' => $this->request->getVar('HostAppName'),
|
'HostAppName' => $this->request->getVar('HostAppName'),
|
||||||
];
|
];
|
||||||
|
|
||||||
$builder = $this->model->select('hostapp.*, site.SiteName')
|
$builder = $this->model->select('hostapp.*, site.SiteName')
|
||||||
->join('site', 'site.SiteID = hostapp.SiteID', 'left');
|
->join('site', 'site.SiteID = hostapp.SiteID', 'left');
|
||||||
|
|
||||||
if (!empty($filter['HostAppID'])) {
|
if (!empty($filter['HostAppID'])) {
|
||||||
if (!ctype_digit((string) $filter['HostAppID'])) {
|
if (!ctype_digit((string) $filter['HostAppID'])) {
|
||||||
return $this->failValidationErrors('HostAppID filter must be a valid integer.');
|
return $this->failValidationErrors('HostAppID filter must be a valid integer.');
|
||||||
}
|
}
|
||||||
$builder->where('hostapp.HostAppID', (int) $filter['HostAppID']);
|
$builder->where('hostapp.HostAppID', (int) $filter['HostAppID']);
|
||||||
}
|
}
|
||||||
if (!empty($filter['HostAppName'])) {
|
if (!empty($filter['HostAppName'])) {
|
||||||
$builder->like('hostapp.HostAppName', $filter['HostAppName'], 'both');
|
$builder->like('hostapp.HostAppName', $filter['HostAppName'], 'both');
|
||||||
}
|
}
|
||||||
|
|
||||||
$rows = $builder->findAll();
|
$rows = $builder->findAll();
|
||||||
|
|
||||||
if (empty($rows)) {
|
if (empty($rows)) {
|
||||||
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
|
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
|
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($HostAppID = null) {
|
public function show($HostAppID = null) {
|
||||||
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = $this->model->select('hostapp.*, site.SiteName')
|
$row = $this->model->select('hostapp.*, site.SiteName')
|
||||||
->join('site', 'site.SiteID = hostapp.SiteID', 'left')
|
->join('site', 'site.SiteID = hostapp.SiteID', 'left')
|
||||||
->where('hostapp.HostAppID', $id)
|
->where('hostapp.HostAppID', $id)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($row)) {
|
if (empty($row)) {
|
||||||
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
|
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
|
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
try {
|
try {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
$id = $this->requirePatchId($input['HostAppID'] ?? null, 'HostAppID');
|
$id = $this->requirePatchId($input['HostAppID'] ?? null, 'HostAppID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->model->delete($id);
|
$this->model->delete($id);
|
||||||
return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
|
return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create() {
|
public function create() {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
unset($input['HostAppID']);
|
unset($input['HostAppID']);
|
||||||
$id = $this->model->insert($input, true);
|
$id = $this->model->insert($input, true);
|
||||||
return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
|
return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($HostAppID = null) {
|
public function update($HostAppID = null) {
|
||||||
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
||||||
if ($input === null) {
|
if ($input === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$existing = $this->model->find($id);
|
$existing = $this->model->find($id);
|
||||||
if (!$existing) {
|
if (!$existing) {
|
||||||
return $this->respond(['status' => 'failed', 'message' => 'HostApp not found', 'data' => []], 404);
|
return $this->respond(['status' => 'failed', 'message' => 'HostApp not found', 'data' => []], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($input['HostAppID'])) {
|
if (isset($input['HostAppID'])) {
|
||||||
if ((string) $input['HostAppID'] !== (string) $id) {
|
if ((string) $input['HostAppID'] !== (string) $id) {
|
||||||
return $this->failValidationErrors('HostAppID in URL does not match body.');
|
return $this->failValidationErrors('HostAppID in URL does not match body.');
|
||||||
}
|
}
|
||||||
unset($input['HostAppID']);
|
unset($input['HostAppID']);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$this->model->update($id, $input);
|
$this->model->update($id, $input);
|
||||||
return $this->respond(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 200);
|
return $this->respond(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 200);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,135 +1,135 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Controllers\Organization;
|
namespace App\Controllers\Organization;
|
||||||
|
|
||||||
use App\Traits\PatchValidationTrait;
|
use App\Traits\PatchValidationTrait;
|
||||||
use App\Traits\ResponseTrait;
|
use App\Traits\ResponseTrait;
|
||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Models\Organization\HostComParaModel;
|
use App\Models\Organization\HostComParaModel;
|
||||||
|
|
||||||
class HostComParaController extends BaseController {
|
class HostComParaController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
use PatchValidationTrait;
|
use PatchValidationTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $model;
|
protected $model;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new HostComParaModel();
|
$this->model = new HostComParaModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$filter = [
|
$filter = [
|
||||||
'HostAppID' => $this->request->getVar('HostAppID'),
|
'HostAppID' => $this->request->getVar('HostAppID'),
|
||||||
'HostIP' => $this->request->getVar('HostIP'),
|
'HostIP' => $this->request->getVar('HostIP'),
|
||||||
];
|
];
|
||||||
|
|
||||||
$builder = $this->model->select('hostcompara.*, hostapp.HostAppName')
|
$builder = $this->model->select('hostcompara.*, hostapp.HostAppName')
|
||||||
->join('hostapp', 'hostapp.HostAppID = hostcompara.HostAppID', 'left');
|
->join('hostapp', 'hostapp.HostAppID = hostcompara.HostAppID', 'left');
|
||||||
|
|
||||||
if (!empty($filter['HostAppID'])) {
|
if (!empty($filter['HostAppID'])) {
|
||||||
if (!ctype_digit((string) $filter['HostAppID'])) {
|
if (!ctype_digit((string) $filter['HostAppID'])) {
|
||||||
return $this->failValidationErrors('HostAppID filter must be a valid integer.');
|
return $this->failValidationErrors('HostAppID filter must be a valid integer.');
|
||||||
}
|
}
|
||||||
$builder->where('hostcompara.HostAppID', (int) $filter['HostAppID']);
|
$builder->where('hostcompara.HostAppID', (int) $filter['HostAppID']);
|
||||||
}
|
}
|
||||||
if (!empty($filter['HostIP'])) {
|
if (!empty($filter['HostIP'])) {
|
||||||
$builder->like('hostcompara.HostIP', $filter['HostIP'], 'both');
|
$builder->like('hostcompara.HostIP', $filter['HostIP'], 'both');
|
||||||
}
|
}
|
||||||
|
|
||||||
$rows = $builder->findAll();
|
$rows = $builder->findAll();
|
||||||
|
|
||||||
if (empty($rows)) {
|
if (empty($rows)) {
|
||||||
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
|
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => []], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
|
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $rows], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($HostAppID = null) {
|
public function show($HostAppID = null) {
|
||||||
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = $this->model->select('hostcompara.*, hostapp.HostAppName')
|
$row = $this->model->select('hostcompara.*, hostapp.HostAppName')
|
||||||
->join('hostapp', 'hostapp.HostAppID = hostcompara.HostAppID', 'left')
|
->join('hostapp', 'hostapp.HostAppID = hostcompara.HostAppID', 'left')
|
||||||
->where('hostcompara.HostAppID', $id)
|
->where('hostcompara.HostAppID', $id)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($row)) {
|
if (empty($row)) {
|
||||||
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
|
return $this->respond(['status' => 'success', 'message' => 'no Data.', 'data' => null], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
|
return $this->respond(['status' => 'success', 'message' => 'fetch success', 'data' => $row], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
try {
|
try {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
$id = $this->requirePatchId($input['HostAppID'] ?? null, 'HostAppID');
|
$id = $this->requirePatchId($input['HostAppID'] ?? null, 'HostAppID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->model->delete($id);
|
$this->model->delete($id);
|
||||||
return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
|
return $this->respondDeleted(['status' => 'success', 'message' => "{$id} deleted successfully."]);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create() {
|
public function create() {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$hostAppId = $input['HostAppID'] ?? null;
|
$hostAppId = $input['HostAppID'] ?? null;
|
||||||
if ($hostAppId === null) {
|
if ($hostAppId === null) {
|
||||||
return $this->failValidationErrors('HostAppID is required.');
|
return $this->failValidationErrors('HostAppID is required.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctype_digit((string) $hostAppId)) {
|
if (!ctype_digit((string) $hostAppId)) {
|
||||||
return $this->failValidationErrors('HostAppID must be a valid integer.');
|
return $this->failValidationErrors('HostAppID must be a valid integer.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$input['HostAppID'] = (int) $hostAppId;
|
$input['HostAppID'] = (int) $hostAppId;
|
||||||
|
|
||||||
$id = $this->model->insert($input, true);
|
$id = $this->model->insert($input, true);
|
||||||
return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
|
return $this->respondCreated(['status' => 'success', 'message' => 'data created successfully', 'data' => $id], 201);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($HostAppID = null) {
|
public function update($HostAppID = null) {
|
||||||
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
$input = $this->requirePatchPayload($this->request->getJSON(true));
|
||||||
if ($input === null) {
|
if ($input === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
$id = $this->requirePatchId($HostAppID, 'HostAppID');
|
||||||
if ($id === null) {
|
if ($id === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$existing = $this->model->find($id);
|
$existing = $this->model->find($id);
|
||||||
if (!$existing) {
|
if (!$existing) {
|
||||||
return $this->respond(['status' => 'failed', 'message' => 'HostComPara not found', 'data' => []], 404);
|
return $this->respond(['status' => 'failed', 'message' => 'HostComPara not found', 'data' => []], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($input['HostAppID'])) {
|
if (isset($input['HostAppID'])) {
|
||||||
if ((string) $input['HostAppID'] !== (string) $id) {
|
if ((string) $input['HostAppID'] !== (string) $id) {
|
||||||
return $this->failValidationErrors('HostAppID in URL does not match body.');
|
return $this->failValidationErrors('HostAppID in URL does not match body.');
|
||||||
}
|
}
|
||||||
unset($input['HostAppID']);
|
unset($input['HostAppID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->model->update($id, $input);
|
$this->model->update($id, $input);
|
||||||
return $this->respond(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 200);
|
return $this->respond(['status' => 'success', 'message' => 'data updated successfully', 'data' => $id], 200);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,306 +1,306 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Controllers\User;
|
namespace App\Controllers\User;
|
||||||
|
|
||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Models\User\UserModel;
|
use App\Models\User\UserModel;
|
||||||
use App\Traits\PatchValidationTrait;
|
use App\Traits\PatchValidationTrait;
|
||||||
use App\Traits\ResponseTrait;
|
use App\Traits\ResponseTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User Management Controller
|
* User Management Controller
|
||||||
* Handles CRUD operations for users
|
* Handles CRUD operations for users
|
||||||
*/
|
*/
|
||||||
class UserController extends BaseController
|
class UserController extends BaseController
|
||||||
{
|
{
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
use PatchValidationTrait;
|
use PatchValidationTrait;
|
||||||
|
|
||||||
protected $model;
|
protected $model;
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new UserModel();
|
$this->model = new UserModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List users with pagination and search
|
* List users with pagination and search
|
||||||
* GET /api/user?page=1&per_page=20&search=term
|
* GET /api/user?page=1&per_page=20&search=term
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$page = (int)($this->request->getGet('page') ?? 1);
|
$page = (int)($this->request->getGet('page') ?? 1);
|
||||||
$perPage = (int)($this->request->getGet('per_page') ?? 20);
|
$perPage = (int)($this->request->getGet('per_page') ?? 20);
|
||||||
$search = $this->request->getGet('search');
|
$search = $this->request->getGet('search');
|
||||||
|
|
||||||
// Build query
|
// Build query
|
||||||
$builder = $this->model->where('DelDate', null);
|
$builder = $this->model->where('DelDate', null);
|
||||||
|
|
||||||
// Apply search if provided
|
// Apply search if provided
|
||||||
if ($search) {
|
if ($search) {
|
||||||
$builder->groupStart()
|
$builder->groupStart()
|
||||||
->like('Username', $search)
|
->like('Username', $search)
|
||||||
->orLike('Email', $search)
|
->orLike('Email', $search)
|
||||||
->orLike('Name', $search)
|
->orLike('Name', $search)
|
||||||
->groupEnd();
|
->groupEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get total count for pagination
|
// Get total count for pagination
|
||||||
$total = $builder->countAllResults(false);
|
$total = $builder->countAllResults(false);
|
||||||
|
|
||||||
// Get paginated results
|
// Get paginated results
|
||||||
$users = $builder
|
$users = $builder
|
||||||
->orderBy('UserID', 'DESC')
|
->orderBy('UserID', 'DESC')
|
||||||
->limit($perPage, ($page - 1) * $perPage)
|
->limit($perPage, ($page - 1) * $perPage)
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'message' => 'Users retrieved successfully',
|
'message' => 'Users retrieved successfully',
|
||||||
'data' => [
|
'data' => [
|
||||||
'users' => $users,
|
'users' => $users,
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'current_page' => $page,
|
'current_page' => $page,
|
||||||
'per_page' => $perPage,
|
'per_page' => $perPage,
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
'total_pages' => ceil($total / $perPage)
|
'total_pages' => ceil($total / $perPage)
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
log_message('error', 'UserController::index error: ' . $e->getMessage());
|
log_message('error', 'UserController::index error: ' . $e->getMessage());
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to retrieve users',
|
'message' => 'Failed to retrieve users',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get single user by ID
|
* Get single user by ID
|
||||||
* GET /api/user/(:num)
|
* GET /api/user/(:num)
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$user = $this->model->where('UserID', $id)
|
$user = $this->model->where('UserID', $id)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'User not found',
|
'message' => 'User not found',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'message' => 'User retrieved successfully',
|
'message' => 'User retrieved successfully',
|
||||||
'data' => $user
|
'data' => $user
|
||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
log_message('error', 'UserController::show error: ' . $e->getMessage());
|
log_message('error', 'UserController::show error: ' . $e->getMessage());
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to retrieve user',
|
'message' => 'Failed to retrieve user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new user
|
* Create new user
|
||||||
* POST /api/user
|
* POST /api/user
|
||||||
*/
|
*/
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$data = $this->request->getJSON(true);
|
$data = $this->request->getJSON(true);
|
||||||
|
|
||||||
// Validation rules
|
// Validation rules
|
||||||
$rules = [
|
$rules = [
|
||||||
'Username' => 'required|min_length[3]|max_length[50]|is_unique[users.Username]',
|
'Username' => 'required|min_length[3]|max_length[50]|is_unique[users.Username]',
|
||||||
'Email' => 'required|valid_email|is_unique[users.Email]',
|
'Email' => 'required|valid_email|is_unique[users.Email]',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$this->validateData($data, $rules)) {
|
if (!$this->validateData($data, $rules)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Validation failed',
|
'message' => 'Validation failed',
|
||||||
'data' => $this->validator->getErrors()
|
'data' => $this->validator->getErrors()
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set default values
|
// Set default values
|
||||||
$data['IsActive'] = $data['IsActive'] ?? true;
|
$data['IsActive'] = $data['IsActive'] ?? true;
|
||||||
$data['CreatedAt'] = date('Y-m-d H:i:s');
|
$data['CreatedAt'] = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
$userId = $this->model->insert($data);
|
$userId = $this->model->insert($data);
|
||||||
|
|
||||||
if (!$userId) {
|
if (!$userId) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to create user',
|
'message' => 'Failed to create user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'message' => 'User created successfully',
|
'message' => 'User created successfully',
|
||||||
'data' => [
|
'data' => [
|
||||||
'UserID' => $userId,
|
'UserID' => $userId,
|
||||||
'Username' => $data['Username'],
|
'Username' => $data['Username'],
|
||||||
'Email' => $data['Email']
|
'Email' => $data['Email']
|
||||||
]
|
]
|
||||||
], 201);
|
], 201);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
log_message('error', 'UserController::create error: ' . $e->getMessage());
|
log_message('error', 'UserController::create error: ' . $e->getMessage());
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to create user',
|
'message' => 'Failed to create user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update existing user
|
* Update existing user
|
||||||
* PATCH /api/user/(:num)
|
* PATCH /api/user/(:num)
|
||||||
*/
|
*/
|
||||||
public function update($id)
|
public function update($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$data = $this->requirePatchPayload($this->request->getJSON(true));
|
$data = $this->requirePatchPayload($this->request->getJSON(true));
|
||||||
if ($data === null) {
|
if ($data === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($id) || !ctype_digit((string) $id)) {
|
if (empty($id) || !ctype_digit((string) $id)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'UserID is required',
|
'message' => 'UserID is required',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['UserID']) && (string) $data['UserID'] !== (string) $id) {
|
if (isset($data['UserID']) && (string) $data['UserID'] !== (string) $id) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'UserID in URL does not match body',
|
'message' => 'UserID in URL does not match body',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$userId = (int) $id;
|
$userId = (int) $id;
|
||||||
|
|
||||||
// Check if user exists
|
// Check if user exists
|
||||||
$user = $this->model->where('UserID', $userId)
|
$user = $this->model->where('UserID', $userId)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'User not found',
|
'message' => 'User not found',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove UserID from data array
|
// Remove UserID from data array
|
||||||
unset($data['UserID']);
|
unset($data['UserID']);
|
||||||
|
|
||||||
// Don't allow updating these fields
|
// Don't allow updating these fields
|
||||||
unset($data['CreatedAt']);
|
unset($data['CreatedAt']);
|
||||||
unset($data['Username']); // Username should not change
|
unset($data['Username']); // Username should not change
|
||||||
|
|
||||||
$data['UpdatedAt'] = date('Y-m-d H:i:s');
|
$data['UpdatedAt'] = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
$updated = $this->model->update($userId, $data);
|
$updated = $this->model->update($userId, $data);
|
||||||
|
|
||||||
if (!$updated) {
|
if (!$updated) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to update user',
|
'message' => 'Failed to update user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'message' => 'User updated successfully',
|
'message' => 'User updated successfully',
|
||||||
'data' => [
|
'data' => [
|
||||||
'UserID' => $userId,
|
'UserID' => $userId,
|
||||||
'updated_fields' => array_keys($data)
|
'updated_fields' => array_keys($data)
|
||||||
]
|
]
|
||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
log_message('error', 'UserController::update error: ' . $e->getMessage());
|
log_message('error', 'UserController::update error: ' . $e->getMessage());
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to update user',
|
'message' => 'Failed to update user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete user (soft delete)
|
* Delete user (soft delete)
|
||||||
* DELETE /api/user/(:num)
|
* DELETE /api/user/(:num)
|
||||||
*/
|
*/
|
||||||
public function delete($id)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Check if user exists
|
// Check if user exists
|
||||||
$user = $this->model->where('UserID', $id)
|
$user = $this->model->where('UserID', $id)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'User not found',
|
'message' => 'User not found',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Soft delete by setting DelDate
|
// Soft delete by setting DelDate
|
||||||
$deleted = $this->model->update($id, [
|
$deleted = $this->model->update($id, [
|
||||||
'DelDate' => date('Y-m-d H:i:s'),
|
'DelDate' => date('Y-m-d H:i:s'),
|
||||||
'IsActive' => false
|
'IsActive' => false
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!$deleted) {
|
if (!$deleted) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to delete user',
|
'message' => 'Failed to delete user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
'message' => 'User deleted successfully',
|
'message' => 'User deleted successfully',
|
||||||
'data' => ['UserID' => $id]
|
'data' => ['UserID' => $id]
|
||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
log_message('error', 'UserController::delete error: ' . $e->getMessage());
|
log_message('error', 'UserController::delete error: ' . $e->getMessage());
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Failed to delete user',
|
'message' => 'Failed to delete user',
|
||||||
'data' => null
|
'data' => null
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,50 +1,50 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Database\Migrations;
|
namespace App\Database\Migrations;
|
||||||
|
|
||||||
use CodeIgniter\Database\Migration;
|
use CodeIgniter\Database\Migration;
|
||||||
|
|
||||||
class CreateHostAppAndCodingSys extends Migration {
|
class CreateHostAppAndCodingSys extends Migration {
|
||||||
public function up() {
|
public function up() {
|
||||||
// Table: hostapp
|
// Table: hostapp
|
||||||
$this->forge->addField([
|
$this->forge->addField([
|
||||||
'HostAppID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
'HostAppID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
||||||
'HostAppName' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => false],
|
'HostAppName' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => false],
|
||||||
'SiteID' => ['type' => 'INT', 'unsigned' => true, 'null' => true],
|
'SiteID' => ['type' => 'INT', 'unsigned' => true, 'null' => true],
|
||||||
'CreateDate' => ['type' => 'DATETIME', 'null' => true],
|
'CreateDate' => ['type' => 'DATETIME', 'null' => true],
|
||||||
'EndDate' => ['type' => 'DATETIME', 'null' => true]
|
'EndDate' => ['type' => 'DATETIME', 'null' => true]
|
||||||
]);
|
]);
|
||||||
$this->forge->addKey('HostAppID', true);
|
$this->forge->addKey('HostAppID', true);
|
||||||
$this->forge->createTable('hostapp');
|
$this->forge->createTable('hostapp');
|
||||||
|
|
||||||
// Table: hostcompara
|
// Table: hostcompara
|
||||||
$this->forge->addField([
|
$this->forge->addField([
|
||||||
'HostAppID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
'HostAppID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
||||||
'HostIP' => ['type' => 'VARCHAR', 'constraint' => 15, 'null' => true],
|
'HostIP' => ['type' => 'VARCHAR', 'constraint' => 15, 'null' => true],
|
||||||
'HostPort' => ['type' => 'VARCHAR', 'constraint' => 6, 'null' => true],
|
'HostPort' => ['type' => 'VARCHAR', 'constraint' => 6, 'null' => true],
|
||||||
'HostPwd' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
'HostPwd' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||||
'CreateDate' => ['type' => 'DATETIME', 'null' => true],
|
'CreateDate' => ['type' => 'DATETIME', 'null' => true],
|
||||||
'EndDate' => ['type' => 'DATETIME', 'null' => true]
|
'EndDate' => ['type' => 'DATETIME', 'null' => true]
|
||||||
]);
|
]);
|
||||||
$this->forge->addKey('HostAppID', true);
|
$this->forge->addKey('HostAppID', true);
|
||||||
$this->forge->createTable('hostcompara');
|
$this->forge->createTable('hostcompara');
|
||||||
|
|
||||||
// Table: codingsys
|
// Table: codingsys
|
||||||
$this->forge->addField([
|
$this->forge->addField([
|
||||||
'CodingSysID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
'CodingSysID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
||||||
'CodingSysAbb' => ['type' => 'VARCHAR', 'constraint' => 6, 'null' => false, 'unique' => true],
|
'CodingSysAbb' => ['type' => 'VARCHAR', 'constraint' => 6, 'null' => false, 'unique' => true],
|
||||||
'FullText' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
'FullText' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||||
'Description' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
'Description' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true],
|
||||||
'CreateDate' => ['type' => 'DATETIME', 'null' => true],
|
'CreateDate' => ['type' => 'DATETIME', 'null' => true],
|
||||||
'EndDate' => ['type' => 'DATETIME', 'null' => true]
|
'EndDate' => ['type' => 'DATETIME', 'null' => true]
|
||||||
]);
|
]);
|
||||||
$this->forge->addKey('CodingSysID', true);
|
$this->forge->addKey('CodingSysID', true);
|
||||||
$this->forge->createTable('codingsys');
|
$this->forge->createTable('codingsys');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down() {
|
public function down() {
|
||||||
$this->forge->dropTable('codingsys');
|
$this->forge->dropTable('codingsys');
|
||||||
$this->forge->dropTable('hostcompara');
|
$this->forge->dropTable('hostcompara');
|
||||||
$this->forge->dropTable('hostapp');
|
$this->forge->dropTable('hostapp');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,137 +1,137 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Database\Migrations;
|
namespace App\Database\Migrations;
|
||||||
|
|
||||||
use CodeIgniter\Database\Migration;
|
use CodeIgniter\Database\Migration;
|
||||||
|
|
||||||
class CreateAuditLogs extends Migration
|
class CreateAuditLogs extends Migration
|
||||||
{
|
{
|
||||||
private array $logTables = [
|
private array $logTables = [
|
||||||
'logpatient' => 'LogPatientID',
|
'logpatient' => 'LogPatientID',
|
||||||
'logorder' => 'LogOrderID',
|
'logorder' => 'LogOrderID',
|
||||||
'logmaster' => 'LogMasterID',
|
'logmaster' => 'LogMasterID',
|
||||||
'logsystem' => 'LogSystemID',
|
'logsystem' => 'LogSystemID',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
foreach ($this->logTables as $table => $pk) {
|
foreach ($this->logTables as $table => $pk) {
|
||||||
$this->createLogTable($table, $pk);
|
$this->createLogTable($table, $pk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
foreach (array_reverse($this->logTables) as $table => $pk) {
|
foreach (array_reverse($this->logTables) as $table => $pk) {
|
||||||
$this->forge->dropTable($table, true);
|
$this->forge->dropTable($table, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createLogTable(string $table, string $primaryKey): void
|
private function createLogTable(string $table, string $primaryKey): void
|
||||||
{
|
{
|
||||||
$fields = [
|
$fields = [
|
||||||
$primaryKey => [
|
$primaryKey => [
|
||||||
'type' => 'BIGINT',
|
'type' => 'BIGINT',
|
||||||
'constraint' => 20,
|
'constraint' => 20,
|
||||||
'unsigned' => true,
|
'unsigned' => true,
|
||||||
'auto_increment' => true,
|
'auto_increment' => true,
|
||||||
],
|
],
|
||||||
'TblName' => [
|
'TblName' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 64,
|
'constraint' => 64,
|
||||||
],
|
],
|
||||||
'RecID' => [
|
'RecID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 64,
|
'constraint' => 64,
|
||||||
],
|
],
|
||||||
'FldName' => [
|
'FldName' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 128,
|
'constraint' => 128,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'FldValuePrev' => [
|
'FldValuePrev' => [
|
||||||
'type' => 'TEXT',
|
'type' => 'TEXT',
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'FldValueNew' => [
|
'FldValueNew' => [
|
||||||
'type' => 'TEXT',
|
'type' => 'TEXT',
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'UserID' => [
|
'UserID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 64,
|
'constraint' => 64,
|
||||||
],
|
],
|
||||||
'SiteID' => [
|
'SiteID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 32,
|
'constraint' => 32,
|
||||||
],
|
],
|
||||||
'DIDType' => [
|
'DIDType' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 32,
|
'constraint' => 32,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'DID' => [
|
'DID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 128,
|
'constraint' => 128,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'MachineID' => [
|
'MachineID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 128,
|
'constraint' => 128,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'SessionID' => [
|
'SessionID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 128,
|
'constraint' => 128,
|
||||||
],
|
],
|
||||||
'AppID' => [
|
'AppID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 64,
|
'constraint' => 64,
|
||||||
],
|
],
|
||||||
'ProcessID' => [
|
'ProcessID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 128,
|
'constraint' => 128,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'WebPageID' => [
|
'WebPageID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 128,
|
'constraint' => 128,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'EventID' => [
|
'EventID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 80,
|
'constraint' => 80,
|
||||||
],
|
],
|
||||||
'ActivityID' => [
|
'ActivityID' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 24,
|
'constraint' => 24,
|
||||||
],
|
],
|
||||||
'Reason' => [
|
'Reason' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 512,
|
'constraint' => 512,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
'LogDate' => [
|
'LogDate' => [
|
||||||
'type' => 'DATETIME',
|
'type' => 'DATETIME',
|
||||||
'constraint' => 3,
|
'constraint' => 3,
|
||||||
],
|
],
|
||||||
'Context' => [
|
'Context' => [
|
||||||
'type' => 'JSON',
|
'type' => 'JSON',
|
||||||
],
|
],
|
||||||
'IpAddress' => [
|
'IpAddress' => [
|
||||||
'type' => 'VARCHAR',
|
'type' => 'VARCHAR',
|
||||||
'constraint' => 45,
|
'constraint' => 45,
|
||||||
'null' => true,
|
'null' => true,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->forge->addField($fields);
|
$this->forge->addField($fields);
|
||||||
$this->forge->addKey($primaryKey, true);
|
$this->forge->addKey($primaryKey, true);
|
||||||
$this->forge->addKey(['LogDate'], false, false, "idx_{$table}_logdate");
|
$this->forge->addKey(['LogDate'], false, false, "idx_{$table}_logdate");
|
||||||
$this->forge->addKey(['RecID', 'LogDate'], false, false, "idx_{$table}_recid_logdate");
|
$this->forge->addKey(['RecID', 'LogDate'], false, false, "idx_{$table}_recid_logdate");
|
||||||
$this->forge->addKey(['UserID', 'LogDate'], false, false, "idx_{$table}_userid_logdate");
|
$this->forge->addKey(['UserID', 'LogDate'], false, false, "idx_{$table}_userid_logdate");
|
||||||
$this->forge->addKey(['EventID', 'LogDate'], false, false, "idx_{$table}_eventid_logdate");
|
$this->forge->addKey(['EventID', 'LogDate'], false, false, "idx_{$table}_eventid_logdate");
|
||||||
$this->forge->addKey(['SiteID', 'LogDate'], false, false, "idx_{$table}_site_logdate");
|
$this->forge->addKey(['SiteID', 'LogDate'], false, false, "idx_{$table}_site_logdate");
|
||||||
$this->forge->createTable($table, true);
|
$this->forge->createTable($table, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,222 +1,222 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Database\Seeds;
|
namespace App\Database\Seeds;
|
||||||
|
|
||||||
use CodeIgniter\Database\Seeder;
|
use CodeIgniter\Database\Seeder;
|
||||||
|
|
||||||
class HostAppCodingSysSeeder extends Seeder
|
class HostAppCodingSysSeeder extends Seeder
|
||||||
{
|
{
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$now = date('Y-m-d H:i:s');
|
$now = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
// Clear existing data first (avoid foreign key constraint issues by ordering)
|
// Clear existing data first (avoid foreign key constraint issues by ordering)
|
||||||
$this->db->table('hostcompara')->emptyTable();
|
$this->db->table('hostcompara')->emptyTable();
|
||||||
$this->db->table('hostapp')->emptyTable();
|
$this->db->table('hostapp')->emptyTable();
|
||||||
$this->db->table('codingsys')->emptyTable();
|
$this->db->table('codingsys')->emptyTable();
|
||||||
|
|
||||||
// HostApp - Host Applications
|
// HostApp - Host Applications
|
||||||
$hostAppData = [
|
$hostAppData = [
|
||||||
[
|
[
|
||||||
'HostAppID' => 1,
|
'HostAppID' => 1,
|
||||||
'HostAppName' => 'Laboratory Information System Main',
|
'HostAppName' => 'Laboratory Information System Main',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 2,
|
'HostAppID' => 2,
|
||||||
'HostAppName' => 'Laboratory Information System Backup',
|
'HostAppName' => 'Laboratory Information System Backup',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 3,
|
'HostAppID' => 3,
|
||||||
'HostAppName' => 'Electronic Medical Record System',
|
'HostAppName' => 'Electronic Medical Record System',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 4,
|
'HostAppID' => 4,
|
||||||
'HostAppName' => 'Picture Archiving System',
|
'HostAppName' => 'Picture Archiving System',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 5,
|
'HostAppID' => 5,
|
||||||
'HostAppName' => 'Billing System',
|
'HostAppName' => 'Billing System',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 6,
|
'HostAppID' => 6,
|
||||||
'HostAppName' => 'Insurance System Integration',
|
'HostAppName' => 'Insurance System Integration',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 7,
|
'HostAppID' => 7,
|
||||||
'HostAppName' => 'Legacy Laboratory System',
|
'HostAppName' => 'Legacy Laboratory System',
|
||||||
'SiteID' => 1,
|
'SiteID' => 1,
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => date('Y-m-d H:i:s', strtotime('-1 year'))
|
'EndDate' => date('Y-m-d H:i:s', strtotime('-1 year'))
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$this->db->table('hostapp')->insertBatch($hostAppData);
|
$this->db->table('hostapp')->insertBatch($hostAppData);
|
||||||
|
|
||||||
// HostComPara - Host Communication Parameters
|
// HostComPara - Host Communication Parameters
|
||||||
$hostComParaData = [
|
$hostComParaData = [
|
||||||
[
|
[
|
||||||
'HostAppID' => 1,
|
'HostAppID' => 1,
|
||||||
'HostIP' => '192.168.1.10',
|
'HostIP' => '192.168.1.10',
|
||||||
'HostPort' => '8080',
|
'HostPort' => '8080',
|
||||||
'HostPwd' => 'lis_main_pass_2024',
|
'HostPwd' => 'lis_main_pass_2024',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 2,
|
'HostAppID' => 2,
|
||||||
'HostIP' => '192.168.1.11',
|
'HostIP' => '192.168.1.11',
|
||||||
'HostPort' => '8081',
|
'HostPort' => '8081',
|
||||||
'HostPwd' => 'lis_backup_pass_2024',
|
'HostPwd' => 'lis_backup_pass_2024',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 3,
|
'HostAppID' => 3,
|
||||||
'HostIP' => '192.168.1.20',
|
'HostIP' => '192.168.1.20',
|
||||||
'HostPort' => '443',
|
'HostPort' => '443',
|
||||||
'HostPwd' => 'emr_secure_2024',
|
'HostPwd' => 'emr_secure_2024',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 4,
|
'HostAppID' => 4,
|
||||||
'HostIP' => '192.168.1.30',
|
'HostIP' => '192.168.1.30',
|
||||||
'HostPort' => '8042',
|
'HostPort' => '8042',
|
||||||
'HostPwd' => 'pacs_dicom_2024',
|
'HostPwd' => 'pacs_dicom_2024',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 5,
|
'HostAppID' => 5,
|
||||||
'HostIP' => '192.168.1.40',
|
'HostIP' => '192.168.1.40',
|
||||||
'HostPort' => '8443',
|
'HostPort' => '8443',
|
||||||
'HostPwd' => 'bill_payment_2024',
|
'HostPwd' => 'bill_payment_2024',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 6,
|
'HostAppID' => 6,
|
||||||
'HostIP' => '192.168.1.50',
|
'HostIP' => '192.168.1.50',
|
||||||
'HostPort' => '443',
|
'HostPort' => '443',
|
||||||
'HostPwd' => 'ins_claim_2024',
|
'HostPwd' => 'ins_claim_2024',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostAppID' => 7,
|
'HostAppID' => 7,
|
||||||
'HostIP' => '192.168.1.99',
|
'HostIP' => '192.168.1.99',
|
||||||
'HostPort' => '8080',
|
'HostPort' => '8080',
|
||||||
'HostPwd' => 'old_legacy_pass',
|
'HostPwd' => 'old_legacy_pass',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => date('Y-m-d H:i:s', strtotime('-1 year'))
|
'EndDate' => date('Y-m-d H:i:s', strtotime('-1 year'))
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$this->db->table('hostcompara')->insertBatch($hostComParaData);
|
$this->db->table('hostcompara')->insertBatch($hostComParaData);
|
||||||
|
|
||||||
// CodingSys - Coding Systems
|
// CodingSys - Coding Systems
|
||||||
$codingSysData = [
|
$codingSysData = [
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'ICD10',
|
'CodingSysAbb' => 'ICD10',
|
||||||
'FullText' => 'International Classification of Diseases 10th Revision',
|
'FullText' => 'International Classification of Diseases 10th Revision',
|
||||||
'Description' => 'Medical diagnosis coding system for diseases and health conditions',
|
'Description' => 'Medical diagnosis coding system for diseases and health conditions',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'ICD10PCS',
|
'CodingSysAbb' => 'ICD10PCS',
|
||||||
'FullText' => 'ICD-10 Procedure Coding System',
|
'FullText' => 'ICD-10 Procedure Coding System',
|
||||||
'Description' => 'Classification system for inpatient hospital procedures',
|
'Description' => 'Classification system for inpatient hospital procedures',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'LOINC',
|
'CodingSysAbb' => 'LOINC',
|
||||||
'FullText' => 'Logical Observation Identifiers Names and Codes',
|
'FullText' => 'Logical Observation Identifiers Names and Codes',
|
||||||
'Description' => 'Standard for identifying medical laboratory observations',
|
'Description' => 'Standard for identifying medical laboratory observations',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'SNOMED',
|
'CodingSysAbb' => 'SNOMED',
|
||||||
'FullText' => 'SNOMED CT',
|
'FullText' => 'SNOMED CT',
|
||||||
'Description' => 'Systematized Nomenclature of Medicine - Clinical Terms',
|
'Description' => 'Systematized Nomenclature of Medicine - Clinical Terms',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'CPT',
|
'CodingSysAbb' => 'CPT',
|
||||||
'FullText' => 'Current Procedural Terminology',
|
'FullText' => 'Current Procedural Terminology',
|
||||||
'Description' => 'Medical code set for medical procedures and services',
|
'Description' => 'Medical code set for medical procedures and services',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'HCPCS',
|
'CodingSysAbb' => 'HCPCS',
|
||||||
'FullText' => 'Healthcare Common Procedure Coding System',
|
'FullText' => 'Healthcare Common Procedure Coding System',
|
||||||
'Description' => 'Medical code set for equipment, supplies, and services',
|
'Description' => 'Medical code set for equipment, supplies, and services',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'RXNORM',
|
'CodingSysAbb' => 'RXNORM',
|
||||||
'FullText' => 'RxNorm',
|
'FullText' => 'RxNorm',
|
||||||
'Description' => 'Normalized naming system for medications',
|
'Description' => 'Normalized naming system for medications',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'NDC',
|
'CodingSysAbb' => 'NDC',
|
||||||
'FullText' => 'National Drug Code',
|
'FullText' => 'National Drug Code',
|
||||||
'Description' => 'Unique identifier for human drugs in the United States',
|
'Description' => 'Unique identifier for human drugs in the United States',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'UCUM',
|
'CodingSysAbb' => 'UCUM',
|
||||||
'FullText' => 'Unified Code for Units of Measure',
|
'FullText' => 'Unified Code for Units of Measure',
|
||||||
'Description' => 'Standard for units of measurement in clinical and scientific contexts',
|
'Description' => 'Standard for units of measurement in clinical and scientific contexts',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'CVX',
|
'CodingSysAbb' => 'CVX',
|
||||||
'FullText' => 'Vaccines Administered',
|
'FullText' => 'Vaccines Administered',
|
||||||
'Description' => 'Vaccine codes for immunization records',
|
'Description' => 'Vaccine codes for immunization records',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => null
|
'EndDate' => null
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'ICD9',
|
'CodingSysAbb' => 'ICD9',
|
||||||
'FullText' => 'International Classification of Diseases 9th Revision',
|
'FullText' => 'International Classification of Diseases 9th Revision',
|
||||||
'Description' => 'Legacy medical diagnosis coding system',
|
'Description' => 'Legacy medical diagnosis coding system',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => date('Y-m-d H:i:s', strtotime('-2 years'))
|
'EndDate' => date('Y-m-d H:i:s', strtotime('-2 years'))
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'CodingSysAbb' => 'ICD9CM',
|
'CodingSysAbb' => 'ICD9CM',
|
||||||
'FullText' => 'ICD-9-CM',
|
'FullText' => 'ICD-9-CM',
|
||||||
'Description' => 'Legacy procedure coding system',
|
'Description' => 'Legacy procedure coding system',
|
||||||
'CreateDate' => $now,
|
'CreateDate' => $now,
|
||||||
'EndDate' => date('Y-m-d H:i:s', strtotime('-2 years'))
|
'EndDate' => date('Y-m-d H:i:s', strtotime('-2 years'))
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$this->db->table('codingsys')->insertBatch($codingSysData);
|
$this->db->table('codingsys')->insertBatch($codingSysData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{"name": "activity_result",
|
{"name": "activity_result",
|
||||||
"VSName": "Activity Result",
|
"VSName": "Activity Result",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "0", "value": "Failed"},
|
{"key": "0", "value": "Failed"},
|
||||||
{"key": "1", "value": "Success with note"},
|
{"key": "1", "value": "Success with note"},
|
||||||
{"key": "2", "value": "Success"}
|
{"key": "2", "value": "Success"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
{"name": "additive",
|
{"name": "additive",
|
||||||
"VSName": "Additive",
|
"VSName": "Additive",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "Hep", "value": "Heparin ammonium"},
|
{"key": "Hep", "value": "Heparin ammonium"},
|
||||||
{"key": "Apro", "value": "Aprotinin"},
|
{"key": "Apro", "value": "Aprotinin"},
|
||||||
{"key": "HepCa", "value": "Heparin calcium"},
|
{"key": "HepCa", "value": "Heparin calcium"},
|
||||||
{"key": "H3BO3", "value": "Boric acid"},
|
{"key": "H3BO3", "value": "Boric acid"},
|
||||||
{"key": "CaOxa", "value": "Calcium oxalate"},
|
{"key": "CaOxa", "value": "Calcium oxalate"},
|
||||||
{"key": "EDTA", "value": "EDTA"},
|
{"key": "EDTA", "value": "EDTA"},
|
||||||
{"key": "Ede", "value": "Edetate"},
|
{"key": "Ede", "value": "Edetate"},
|
||||||
{"key": "HCl", "value": "Hydrochloric acid"},
|
{"key": "HCl", "value": "Hydrochloric acid"},
|
||||||
{"key": "Hrdn", "value": "Hirudin"},
|
{"key": "Hrdn", "value": "Hirudin"},
|
||||||
{"key": "EdeK", "value": "Edetate dipotassium"},
|
{"key": "EdeK", "value": "Edetate dipotassium"},
|
||||||
{"key": "EdeTri", "value": "Tripotassium edetate"},
|
{"key": "EdeTri", "value": "Tripotassium edetate"},
|
||||||
{"key": "LiHep", "value": "Heparin lithium"},
|
{"key": "LiHep", "value": "Heparin lithium"},
|
||||||
{"key": "EdeNa", "value": "Edetate disodium"},
|
{"key": "EdeNa", "value": "Edetate disodium"},
|
||||||
{"key": "NaCtrt", "value": "Sodium citrate"},
|
{"key": "NaCtrt", "value": "Sodium citrate"},
|
||||||
{"key": "NaHep", "value": "Heparin sodium"},
|
{"key": "NaHep", "value": "Heparin sodium"},
|
||||||
{"key": "NaF", "value": "Sodium fluoride"},
|
{"key": "NaF", "value": "Sodium fluoride"},
|
||||||
{"key": "Borax", "value": "Sodium tetraborate"},
|
{"key": "Borax", "value": "Sodium tetraborate"},
|
||||||
{"key": "Mntl", "value": "Mannitol"},
|
{"key": "Mntl", "value": "Mannitol"},
|
||||||
{"key": "NaFrm", "value": "Sodium formate"}
|
{"key": "NaFrm", "value": "Sodium formate"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{"name": "area_class",
|
{"name": "area_class",
|
||||||
"VSName": "Area Class",
|
"VSName": "Area Class",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "PROP", "value": "Propinsi"},
|
{"key": "PROP", "value": "Propinsi"},
|
||||||
{"key": "KAB", "value": "Kabupaten"},
|
{"key": "KAB", "value": "Kabupaten"},
|
||||||
{"key": "KOTA", "value": "Kota"}
|
{"key": "KOTA", "value": "Kota"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{"name": "body_site",
|
{"name": "body_site",
|
||||||
"VSName": "Body Site",
|
"VSName": "Body Site",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "LA", "value": "Left Arm"},
|
{"key": "LA", "value": "Left Arm"},
|
||||||
{"key": "RA", "value": "Right Arm"},
|
{"key": "RA", "value": "Right Arm"},
|
||||||
{"key": "LF", "value": "Left Foot"},
|
{"key": "LF", "value": "Left Foot"},
|
||||||
{"key": "RF", "value": "Right Foot"}
|
{"key": "RF", "value": "Right Foot"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
{"name": "collection_method",
|
{"name": "collection_method",
|
||||||
"VSName": "Collection Method",
|
"VSName": "Collection Method",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "pcntr", "value": "Puncture"},
|
{"key": "pcntr", "value": "Puncture"},
|
||||||
{"key": "fprk", "value": "Finger-prick sampling"},
|
{"key": "fprk", "value": "Finger-prick sampling"},
|
||||||
{"key": "ucct", "value": "Urine specimen collection, clean catch"},
|
{"key": "ucct", "value": "Urine specimen collection, clean catch"},
|
||||||
{"key": "utcl", "value": "Timed urine collection"},
|
{"key": "utcl", "value": "Timed urine collection"},
|
||||||
{"key": "ucth", "value": "Urine specimen collection, catheterized"},
|
{"key": "ucth", "value": "Urine specimen collection, catheterized"},
|
||||||
{"key": "scgh", "value": "Collection of coughed sputum"},
|
{"key": "scgh", "value": "Collection of coughed sputum"},
|
||||||
{"key": "bpsy", "value": "Biopsy"},
|
{"key": "bpsy", "value": "Biopsy"},
|
||||||
{"key": "aspn", "value": "Aspiration"},
|
{"key": "aspn", "value": "Aspiration"},
|
||||||
{"key": "excs", "value": "Excision"},
|
{"key": "excs", "value": "Excision"},
|
||||||
{"key": "scrp", "value": "Scraping"}
|
{"key": "scrp", "value": "Scraping"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
{"name": "container_cap_color",
|
{"name": "container_cap_color",
|
||||||
"VSName": "Container Cap Color",
|
"VSName": "Container Cap Color",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "PRPL", "value": "Purple"},
|
{"key": "PRPL", "value": "Purple"},
|
||||||
{"key": "RED", "value": "Red"},
|
{"key": "RED", "value": "Red"},
|
||||||
{"key": "YLLW", "value": "Yellow"},
|
{"key": "YLLW", "value": "Yellow"},
|
||||||
{"key": "GRN", "value": "Green"},
|
{"key": "GRN", "value": "Green"},
|
||||||
{"key": "PINK", "value": "Pink"},
|
{"key": "PINK", "value": "Pink"},
|
||||||
{"key": "LBLU", "value": "Light Blue"},
|
{"key": "LBLU", "value": "Light Blue"},
|
||||||
{"key": "RBLU", "value": "Royal Blue"},
|
{"key": "RBLU", "value": "Royal Blue"},
|
||||||
{"key": "GRAY", "value": "Gray"}
|
{"key": "GRAY", "value": "Gray"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{"name": "container_class",
|
{"name": "container_class",
|
||||||
"VSName": "Container Class",
|
"VSName": "Container Class",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "Pri", "value": "Primary"},
|
{"key": "Pri", "value": "Primary"},
|
||||||
{"key": "Sec", "value": "Secondary"},
|
{"key": "Sec", "value": "Secondary"},
|
||||||
{"key": "Ter", "value": "Tertiary"}
|
{"key": "Ter", "value": "Tertiary"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{"name": "container_size",
|
{"name": "container_size",
|
||||||
"VSName": "Container Size",
|
"VSName": "Container Size",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "5ml", "value": "5 mL"},
|
{"key": "5ml", "value": "5 mL"},
|
||||||
{"key": "7ml", "value": "7 mL"},
|
{"key": "7ml", "value": "7 mL"},
|
||||||
{"key": "10ml", "value": "10 mL"},
|
{"key": "10ml", "value": "10 mL"},
|
||||||
{"key": "1l", "value": "1 L"}
|
{"key": "1l", "value": "1 L"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,255 +1,255 @@
|
|||||||
{"name": "country",
|
{"name": "country",
|
||||||
"VSName": "Country",
|
"VSName": "Country",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "AFG", "value": "Afghanistan"},
|
{"key": "AFG", "value": "Afghanistan"},
|
||||||
{"key": "ALA", "value": "Åland Islands"},
|
{"key": "ALA", "value": "Åland Islands"},
|
||||||
{"key": "ALB", "value": "Albania"},
|
{"key": "ALB", "value": "Albania"},
|
||||||
{"key": "DZA", "value": "Algeria"},
|
{"key": "DZA", "value": "Algeria"},
|
||||||
{"key": "ASM", "value": "American Samoa"},
|
{"key": "ASM", "value": "American Samoa"},
|
||||||
{"key": "AND", "value": "Andorra"},
|
{"key": "AND", "value": "Andorra"},
|
||||||
{"key": "AGO", "value": "Angola"},
|
{"key": "AGO", "value": "Angola"},
|
||||||
{"key": "AIA", "value": "Anguilla"},
|
{"key": "AIA", "value": "Anguilla"},
|
||||||
{"key": "ATA", "value": "Antarctica"},
|
{"key": "ATA", "value": "Antarctica"},
|
||||||
{"key": "ATG", "value": "Antigua and Barbuda"},
|
{"key": "ATG", "value": "Antigua and Barbuda"},
|
||||||
{"key": "ARG", "value": "Argentina"},
|
{"key": "ARG", "value": "Argentina"},
|
||||||
{"key": "ARM", "value": "Armenia"},
|
{"key": "ARM", "value": "Armenia"},
|
||||||
{"key": "ABW", "value": "Aruba"},
|
{"key": "ABW", "value": "Aruba"},
|
||||||
{"key": "AUS", "value": "Australia"},
|
{"key": "AUS", "value": "Australia"},
|
||||||
{"key": "AUT", "value": "Austria"},
|
{"key": "AUT", "value": "Austria"},
|
||||||
{"key": "AZE", "value": "Azerbaijan"},
|
{"key": "AZE", "value": "Azerbaijan"},
|
||||||
{"key": "BHS", "value": "Bahamas"},
|
{"key": "BHS", "value": "Bahamas"},
|
||||||
{"key": "BHR", "value": "Bahrain"},
|
{"key": "BHR", "value": "Bahrain"},
|
||||||
{"key": "BGD", "value": "Bangladesh"},
|
{"key": "BGD", "value": "Bangladesh"},
|
||||||
{"key": "BRB", "value": "Barbados"},
|
{"key": "BRB", "value": "Barbados"},
|
||||||
{"key": "BLR", "value": "Belarus"},
|
{"key": "BLR", "value": "Belarus"},
|
||||||
{"key": "BEL", "value": "Belgium"},
|
{"key": "BEL", "value": "Belgium"},
|
||||||
{"key": "BLZ", "value": "Belize"},
|
{"key": "BLZ", "value": "Belize"},
|
||||||
{"key": "BEN", "value": "Benin"},
|
{"key": "BEN", "value": "Benin"},
|
||||||
{"key": "BMU", "value": "Bermuda"},
|
{"key": "BMU", "value": "Bermuda"},
|
||||||
{"key": "BTN", "value": "Bhutan"},
|
{"key": "BTN", "value": "Bhutan"},
|
||||||
{"key": "BOL", "value": "Bolivia, Plurinational State of"},
|
{"key": "BOL", "value": "Bolivia, Plurinational State of"},
|
||||||
{"key": "BES", "value": "Bonaire, Sint Eustatius and Saba"},
|
{"key": "BES", "value": "Bonaire, Sint Eustatius and Saba"},
|
||||||
{"key": "BIH", "value": "Bosnia and Herzegovina"},
|
{"key": "BIH", "value": "Bosnia and Herzegovina"},
|
||||||
{"key": "BWA", "value": "Botswana"},
|
{"key": "BWA", "value": "Botswana"},
|
||||||
{"key": "BVT", "value": "Bouvet Island"},
|
{"key": "BVT", "value": "Bouvet Island"},
|
||||||
{"key": "BRA", "value": "Brazil"},
|
{"key": "BRA", "value": "Brazil"},
|
||||||
{"key": "IOT", "value": "British Indian Ocean Territory"},
|
{"key": "IOT", "value": "British Indian Ocean Territory"},
|
||||||
{"key": "BRN", "value": "Brunei Darussalam"},
|
{"key": "BRN", "value": "Brunei Darussalam"},
|
||||||
{"key": "BGR", "value": "Bulgaria"},
|
{"key": "BGR", "value": "Bulgaria"},
|
||||||
{"key": "BFA", "value": "Burkina Faso"},
|
{"key": "BFA", "value": "Burkina Faso"},
|
||||||
{"key": "BDI", "value": "Burundi"},
|
{"key": "BDI", "value": "Burundi"},
|
||||||
{"key": "CPV", "value": "Cabo Verde"},
|
{"key": "CPV", "value": "Cabo Verde"},
|
||||||
{"key": "KHM", "value": "Cambodia"},
|
{"key": "KHM", "value": "Cambodia"},
|
||||||
{"key": "CMR", "value": "Cameroon"},
|
{"key": "CMR", "value": "Cameroon"},
|
||||||
{"key": "CAN", "value": "Canada"},
|
{"key": "CAN", "value": "Canada"},
|
||||||
{"key": "CYM", "value": "Cayman Islands"},
|
{"key": "CYM", "value": "Cayman Islands"},
|
||||||
{"key": "CAF", "value": "Central African Republic"},
|
{"key": "CAF", "value": "Central African Republic"},
|
||||||
{"key": "TCD", "value": "Chad"},
|
{"key": "TCD", "value": "Chad"},
|
||||||
{"key": "CHL", "value": "Chile"},
|
{"key": "CHL", "value": "Chile"},
|
||||||
{"key": "CHN", "value": "China"},
|
{"key": "CHN", "value": "China"},
|
||||||
{"key": "CXR", "value": "Christmas Island"},
|
{"key": "CXR", "value": "Christmas Island"},
|
||||||
{"key": "CCK", "value": "Cocos (Keeling) Islands"},
|
{"key": "CCK", "value": "Cocos (Keeling) Islands"},
|
||||||
{"key": "COL", "value": "Colombia"},
|
{"key": "COL", "value": "Colombia"},
|
||||||
{"key": "COM", "value": "Comoros"},
|
{"key": "COM", "value": "Comoros"},
|
||||||
{"key": "COG", "value": "Congo"},
|
{"key": "COG", "value": "Congo"},
|
||||||
{"key": "COD", "value": "Congo, Democratic Republic of the"},
|
{"key": "COD", "value": "Congo, Democratic Republic of the"},
|
||||||
{"key": "COK", "value": "Cook Islands"},
|
{"key": "COK", "value": "Cook Islands"},
|
||||||
{"key": "CRI", "value": "Costa Rica"},
|
{"key": "CRI", "value": "Costa Rica"},
|
||||||
{"key": "CIV", "value": "Côte d'Ivoire"},
|
{"key": "CIV", "value": "Côte d'Ivoire"},
|
||||||
{"key": "HRV", "value": "Croatia"},
|
{"key": "HRV", "value": "Croatia"},
|
||||||
{"key": "CUB", "value": "Cuba"},
|
{"key": "CUB", "value": "Cuba"},
|
||||||
{"key": "CUW", "value": "Curaçao"},
|
{"key": "CUW", "value": "Curaçao"},
|
||||||
{"key": "CYP", "value": "Cyprus"},
|
{"key": "CYP", "value": "Cyprus"},
|
||||||
{"key": "CZE", "value": "Czechia"},
|
{"key": "CZE", "value": "Czechia"},
|
||||||
{"key": "DNK", "value": "Denmark"},
|
{"key": "DNK", "value": "Denmark"},
|
||||||
{"key": "DJI", "value": "Djibouti"},
|
{"key": "DJI", "value": "Djibouti"},
|
||||||
{"key": "DMA", "value": "Dominica"},
|
{"key": "DMA", "value": "Dominica"},
|
||||||
{"key": "DOM", "value": "Dominican Republic"},
|
{"key": "DOM", "value": "Dominican Republic"},
|
||||||
{"key": "ECU", "value": "Ecuador"},
|
{"key": "ECU", "value": "Ecuador"},
|
||||||
{"key": "EGY", "value": "Egypt"},
|
{"key": "EGY", "value": "Egypt"},
|
||||||
{"key": "SLV", "value": "El Salvador"},
|
{"key": "SLV", "value": "El Salvador"},
|
||||||
{"key": "GNQ", "value": "Equatorial Guinea"},
|
{"key": "GNQ", "value": "Equatorial Guinea"},
|
||||||
{"key": "ERI", "value": "Eritrea"},
|
{"key": "ERI", "value": "Eritrea"},
|
||||||
{"key": "EST", "value": "Estonia"},
|
{"key": "EST", "value": "Estonia"},
|
||||||
{"key": "SWZ", "value": "Eswatini"},
|
{"key": "SWZ", "value": "Eswatini"},
|
||||||
{"key": "ETH", "value": "Ethiopia"},
|
{"key": "ETH", "value": "Ethiopia"},
|
||||||
{"key": "FLK", "value": "Falkland Islands (Malvinas)"},
|
{"key": "FLK", "value": "Falkland Islands (Malvinas)"},
|
||||||
{"key": "FRO", "value": "Faroe Islands"},
|
{"key": "FRO", "value": "Faroe Islands"},
|
||||||
{"key": "FJI", "value": "Fiji"},
|
{"key": "FJI", "value": "Fiji"},
|
||||||
{"key": "FIN", "value": "Finland"},
|
{"key": "FIN", "value": "Finland"},
|
||||||
{"key": "FRA", "value": "France"},
|
{"key": "FRA", "value": "France"},
|
||||||
{"key": "GUF", "value": "French Guiana"},
|
{"key": "GUF", "value": "French Guiana"},
|
||||||
{"key": "PYF", "value": "French Polynesia"},
|
{"key": "PYF", "value": "French Polynesia"},
|
||||||
{"key": "ATF", "value": "French Southern Territories"},
|
{"key": "ATF", "value": "French Southern Territories"},
|
||||||
{"key": "GAB", "value": "Gabon"},
|
{"key": "GAB", "value": "Gabon"},
|
||||||
{"key": "GMB", "value": "Gambia"},
|
{"key": "GMB", "value": "Gambia"},
|
||||||
{"key": "GEO", "value": "Georgia"},
|
{"key": "GEO", "value": "Georgia"},
|
||||||
{"key": "DEU", "value": "Germany"},
|
{"key": "DEU", "value": "Germany"},
|
||||||
{"key": "GHA", "value": "Ghana"},
|
{"key": "GHA", "value": "Ghana"},
|
||||||
{"key": "GIB", "value": "Gibraltar"},
|
{"key": "GIB", "value": "Gibraltar"},
|
||||||
{"key": "GRC", "value": "Greece"},
|
{"key": "GRC", "value": "Greece"},
|
||||||
{"key": "GRL", "value": "Greenland"},
|
{"key": "GRL", "value": "Greenland"},
|
||||||
{"key": "GRD", "value": "Grenada"},
|
{"key": "GRD", "value": "Grenada"},
|
||||||
{"key": "GLP", "value": "Guadeloupe"},
|
{"key": "GLP", "value": "Guadeloupe"},
|
||||||
{"key": "GUM", "value": "Guam"},
|
{"key": "GUM", "value": "Guam"},
|
||||||
{"key": "GTM", "value": "Guatemala"},
|
{"key": "GTM", "value": "Guatemala"},
|
||||||
{"key": "GGY", "value": "Guernsey"},
|
{"key": "GGY", "value": "Guernsey"},
|
||||||
{"key": "GIN", "value": "Guinea"},
|
{"key": "GIN", "value": "Guinea"},
|
||||||
{"key": "GNB", "value": "Guinea-Bissau"},
|
{"key": "GNB", "value": "Guinea-Bissau"},
|
||||||
{"key": "GUY", "value": "Guyana"},
|
{"key": "GUY", "value": "Guyana"},
|
||||||
{"key": "HTI", "value": "Haiti"},
|
{"key": "HTI", "value": "Haiti"},
|
||||||
{"key": "HMD", "value": "Heard Island and McDonald Islands"},
|
{"key": "HMD", "value": "Heard Island and McDonald Islands"},
|
||||||
{"key": "VAT", "value": "Holy See"},
|
{"key": "VAT", "value": "Holy See"},
|
||||||
{"key": "HND", "value": "Honduras"},
|
{"key": "HND", "value": "Honduras"},
|
||||||
{"key": "HKG", "value": "Hong Kong"},
|
{"key": "HKG", "value": "Hong Kong"},
|
||||||
{"key": "HUN", "value": "Hungary"},
|
{"key": "HUN", "value": "Hungary"},
|
||||||
{"key": "ISL", "value": "Iceland"},
|
{"key": "ISL", "value": "Iceland"},
|
||||||
{"key": "IND", "value": "India"},
|
{"key": "IND", "value": "India"},
|
||||||
{"key": "IDN", "value": "Indonesia"},
|
{"key": "IDN", "value": "Indonesia"},
|
||||||
{"key": "IRN", "value": "Iran, Islamic Republic of"},
|
{"key": "IRN", "value": "Iran, Islamic Republic of"},
|
||||||
{"key": "IRQ", "value": "Iraq"},
|
{"key": "IRQ", "value": "Iraq"},
|
||||||
{"key": "IRL", "value": "Ireland"},
|
{"key": "IRL", "value": "Ireland"},
|
||||||
{"key": "IMN", "value": "Isle of Man"},
|
{"key": "IMN", "value": "Isle of Man"},
|
||||||
{"key": "ISR", "value": "Israel"},
|
{"key": "ISR", "value": "Israel"},
|
||||||
{"key": "ITA", "value": "Italy"},
|
{"key": "ITA", "value": "Italy"},
|
||||||
{"key": "JAM", "value": "Jamaica"},
|
{"key": "JAM", "value": "Jamaica"},
|
||||||
{"key": "JPN", "value": "Japan"},
|
{"key": "JPN", "value": "Japan"},
|
||||||
{"key": "JEY", "value": "Jersey"},
|
{"key": "JEY", "value": "Jersey"},
|
||||||
{"key": "JOR", "value": "Jordan"},
|
{"key": "JOR", "value": "Jordan"},
|
||||||
{"key": "KAZ", "value": "Kazakhstan"},
|
{"key": "KAZ", "value": "Kazakhstan"},
|
||||||
{"key": "KEN", "value": "Kenya"},
|
{"key": "KEN", "value": "Kenya"},
|
||||||
{"key": "KIR", "value": "Kiribati"},
|
{"key": "KIR", "value": "Kiribati"},
|
||||||
{"key": "PRK", "value": "Korea, Democratic People's Republic of"},
|
{"key": "PRK", "value": "Korea, Democratic People's Republic of"},
|
||||||
{"key": "KOR", "value": "Korea, Republic of"},
|
{"key": "KOR", "value": "Korea, Republic of"},
|
||||||
{"key": "KWT", "value": "Kuwait"},
|
{"key": "KWT", "value": "Kuwait"},
|
||||||
{"key": "KGZ", "value": "Kyrgyzstan"},
|
{"key": "KGZ", "value": "Kyrgyzstan"},
|
||||||
{"key": "LAO", "value": "Lao People's Democratic Republic"},
|
{"key": "LAO", "value": "Lao People's Democratic Republic"},
|
||||||
{"key": "LVA", "value": "Latvia"},
|
{"key": "LVA", "value": "Latvia"},
|
||||||
{"key": "LBN", "value": "Lebanon"},
|
{"key": "LBN", "value": "Lebanon"},
|
||||||
{"key": "LSO", "value": "Lesotho"},
|
{"key": "LSO", "value": "Lesotho"},
|
||||||
{"key": "LBR", "value": "Liberia"},
|
{"key": "LBR", "value": "Liberia"},
|
||||||
{"key": "LBY", "value": "Libya"},
|
{"key": "LBY", "value": "Libya"},
|
||||||
{"key": "LIE", "value": "Liechtenstein"},
|
{"key": "LIE", "value": "Liechtenstein"},
|
||||||
{"key": "LTU", "value": "Lithuania"},
|
{"key": "LTU", "value": "Lithuania"},
|
||||||
{"key": "LUX", "value": "Luxembourg"},
|
{"key": "LUX", "value": "Luxembourg"},
|
||||||
{"key": "MAC", "value": "Macao"},
|
{"key": "MAC", "value": "Macao"},
|
||||||
{"key": "MDG", "value": "Madagascar"},
|
{"key": "MDG", "value": "Madagascar"},
|
||||||
{"key": "MWI", "value": "Malawi"},
|
{"key": "MWI", "value": "Malawi"},
|
||||||
{"key": "MYS", "value": "Malaysia"},
|
{"key": "MYS", "value": "Malaysia"},
|
||||||
{"key": "MDV", "value": "Maldives"},
|
{"key": "MDV", "value": "Maldives"},
|
||||||
{"key": "MLI", "value": "Mali"},
|
{"key": "MLI", "value": "Mali"},
|
||||||
{"key": "MLT", "value": "Malta"},
|
{"key": "MLT", "value": "Malta"},
|
||||||
{"key": "MHL", "value": "Marshall Islands"},
|
{"key": "MHL", "value": "Marshall Islands"},
|
||||||
{"key": "MTQ", "value": "Martinique"},
|
{"key": "MTQ", "value": "Martinique"},
|
||||||
{"key": "MRT", "value": "Mauritania"},
|
{"key": "MRT", "value": "Mauritania"},
|
||||||
{"key": "MUS", "value": "Mauritius"},
|
{"key": "MUS", "value": "Mauritius"},
|
||||||
{"key": "MYT", "value": "Mayotte"},
|
{"key": "MYT", "value": "Mayotte"},
|
||||||
{"key": "MEX", "value": "Mexico"},
|
{"key": "MEX", "value": "Mexico"},
|
||||||
{"key": "FSM", "value": "Micronesia, Federated States of"},
|
{"key": "FSM", "value": "Micronesia, Federated States of"},
|
||||||
{"key": "MDA", "value": "Moldova, Republic of"},
|
{"key": "MDA", "value": "Moldova, Republic of"},
|
||||||
{"key": "MCO", "value": "Monaco"},
|
{"key": "MCO", "value": "Monaco"},
|
||||||
{"key": "MNG", "value": "Mongolia"},
|
{"key": "MNG", "value": "Mongolia"},
|
||||||
{"key": "MNE", "value": "Montenegro"},
|
{"key": "MNE", "value": "Montenegro"},
|
||||||
{"key": "MSR", "value": "Montserrat"},
|
{"key": "MSR", "value": "Montserrat"},
|
||||||
{"key": "MAR", "value": "Morocco"},
|
{"key": "MAR", "value": "Morocco"},
|
||||||
{"key": "MOZ", "value": "Mozambique"},
|
{"key": "MOZ", "value": "Mozambique"},
|
||||||
{"key": "MMR", "value": "Myanmar"},
|
{"key": "MMR", "value": "Myanmar"},
|
||||||
{"key": "NAM", "value": "Namibia"},
|
{"key": "NAM", "value": "Namibia"},
|
||||||
{"key": "NRU", "value": "Nauru"},
|
{"key": "NRU", "value": "Nauru"},
|
||||||
{"key": "NPL", "value": "Nepal"},
|
{"key": "NPL", "value": "Nepal"},
|
||||||
{"key": "NLD", "value": "Netherlands, Kingdom of the"},
|
{"key": "NLD", "value": "Netherlands, Kingdom of the"},
|
||||||
{"key": "NCL", "value": "New Caledonia"},
|
{"key": "NCL", "value": "New Caledonia"},
|
||||||
{"key": "NZL", "value": "New Zealand"},
|
{"key": "NZL", "value": "New Zealand"},
|
||||||
{"key": "NIC", "value": "Nicaragua"},
|
{"key": "NIC", "value": "Nicaragua"},
|
||||||
{"key": "NER", "value": "Niger"},
|
{"key": "NER", "value": "Niger"},
|
||||||
{"key": "NGA", "value": "Nigeria"},
|
{"key": "NGA", "value": "Nigeria"},
|
||||||
{"key": "NIU", "value": "Niue"},
|
{"key": "NIU", "value": "Niue"},
|
||||||
{"key": "NFK", "value": "Norfolk Island"},
|
{"key": "NFK", "value": "Norfolk Island"},
|
||||||
{"key": "MKD", "value": "North Macedonia"},
|
{"key": "MKD", "value": "North Macedonia"},
|
||||||
{"key": "MNP", "value": "Northern Mariana Islands"},
|
{"key": "MNP", "value": "Northern Mariana Islands"},
|
||||||
{"key": "NOR", "value": "Norway"},
|
{"key": "NOR", "value": "Norway"},
|
||||||
{"key": "OMN", "value": "Oman"},
|
{"key": "OMN", "value": "Oman"},
|
||||||
{"key": "PAK", "value": "Pakistan"},
|
{"key": "PAK", "value": "Pakistan"},
|
||||||
{"key": "PLW", "value": "Palau"},
|
{"key": "PLW", "value": "Palau"},
|
||||||
{"key": "PSE", "value": "Palestine, State of"},
|
{"key": "PSE", "value": "Palestine, State of"},
|
||||||
{"key": "PAN", "value": "Panama"},
|
{"key": "PAN", "value": "Panama"},
|
||||||
{"key": "PNG", "value": "Papua New Guinea"},
|
{"key": "PNG", "value": "Papua New Guinea"},
|
||||||
{"key": "PRY", "value": "Paraguay"},
|
{"key": "PRY", "value": "Paraguay"},
|
||||||
{"key": "PER", "value": "Peru"},
|
{"key": "PER", "value": "Peru"},
|
||||||
{"key": "PHL", "value": "Philippines"},
|
{"key": "PHL", "value": "Philippines"},
|
||||||
{"key": "PCN", "value": "Pitcairn"},
|
{"key": "PCN", "value": "Pitcairn"},
|
||||||
{"key": "POL", "value": "Poland"},
|
{"key": "POL", "value": "Poland"},
|
||||||
{"key": "PRT", "value": "Portugal"},
|
{"key": "PRT", "value": "Portugal"},
|
||||||
{"key": "PRI", "value": "Puerto Rico"},
|
{"key": "PRI", "value": "Puerto Rico"},
|
||||||
{"key": "QAT", "value": "Qatar"},
|
{"key": "QAT", "value": "Qatar"},
|
||||||
{"key": "REU", "value": "Réunion"},
|
{"key": "REU", "value": "Réunion"},
|
||||||
{"key": "ROU", "value": "Romania"},
|
{"key": "ROU", "value": "Romania"},
|
||||||
{"key": "RUS", "value": "Russian Federation"},
|
{"key": "RUS", "value": "Russian Federation"},
|
||||||
{"key": "RWA", "value": "Rwanda"},
|
{"key": "RWA", "value": "Rwanda"},
|
||||||
{"key": "BLM", "value": "Saint Barthélemy"},
|
{"key": "BLM", "value": "Saint Barthélemy"},
|
||||||
{"key": "SHN", "value": "Saint Helena, Ascension and Tristan da Cunha"},
|
{"key": "SHN", "value": "Saint Helena, Ascension and Tristan da Cunha"},
|
||||||
{"key": "KNA", "value": "Saint Kitts and Nevis"},
|
{"key": "KNA", "value": "Saint Kitts and Nevis"},
|
||||||
{"key": "LCA", "value": "Saint Lucia"},
|
{"key": "LCA", "value": "Saint Lucia"},
|
||||||
{"key": "MAF", "value": "Saint Martin (French part)"},
|
{"key": "MAF", "value": "Saint Martin (French part)"},
|
||||||
{"key": "SPM", "value": "Saint Pierre and Miquelon"},
|
{"key": "SPM", "value": "Saint Pierre and Miquelon"},
|
||||||
{"key": "VCT", "value": "Saint Vincent and the Grenadines"},
|
{"key": "VCT", "value": "Saint Vincent and the Grenadines"},
|
||||||
{"key": "WSM", "value": "Samoa"},
|
{"key": "WSM", "value": "Samoa"},
|
||||||
{"key": "SMR", "value": "San Marino"},
|
{"key": "SMR", "value": "San Marino"},
|
||||||
{"key": "STP", "value": "Sao Tome and Principe"},
|
{"key": "STP", "value": "Sao Tome and Principe"},
|
||||||
{"key": "SAU", "value": "Saudi Arabia"},
|
{"key": "SAU", "value": "Saudi Arabia"},
|
||||||
{"key": "SEN", "value": "Senegal"},
|
{"key": "SEN", "value": "Senegal"},
|
||||||
{"key": "SRB", "value": "Serbia"},
|
{"key": "SRB", "value": "Serbia"},
|
||||||
{"key": "SYC", "value": "Seychelles"},
|
{"key": "SYC", "value": "Seychelles"},
|
||||||
{"key": "SLE", "value": "Sierra Leone"},
|
{"key": "SLE", "value": "Sierra Leone"},
|
||||||
{"key": "SGP", "value": "Singapore"},
|
{"key": "SGP", "value": "Singapore"},
|
||||||
{"key": "SXM", "value": "Sint Maarten (Dutch part)"},
|
{"key": "SXM", "value": "Sint Maarten (Dutch part)"},
|
||||||
{"key": "SVK", "value": "Slovakia"},
|
{"key": "SVK", "value": "Slovakia"},
|
||||||
{"key": "SVN", "value": "Slovenia"},
|
{"key": "SVN", "value": "Slovenia"},
|
||||||
{"key": "SLB", "value": "Solomon Islands"},
|
{"key": "SLB", "value": "Solomon Islands"},
|
||||||
{"key": "SOM", "value": "Somalia"},
|
{"key": "SOM", "value": "Somalia"},
|
||||||
{"key": "ZAF", "value": "South Africa"},
|
{"key": "ZAF", "value": "South Africa"},
|
||||||
{"key": "SGS", "value": "South Georgia and the South Sandwich Islands"},
|
{"key": "SGS", "value": "South Georgia and the South Sandwich Islands"},
|
||||||
{"key": "SSD", "value": "South Sudan"},
|
{"key": "SSD", "value": "South Sudan"},
|
||||||
{"key": "ESP", "value": "Spain"},
|
{"key": "ESP", "value": "Spain"},
|
||||||
{"key": "LKA", "value": "Sri Lanka"},
|
{"key": "LKA", "value": "Sri Lanka"},
|
||||||
{"key": "SDN", "value": "Sudan"},
|
{"key": "SDN", "value": "Sudan"},
|
||||||
{"key": "SUR", "value": "Suriname"},
|
{"key": "SUR", "value": "Suriname"},
|
||||||
{"key": "SJM", "value": "Svalbard and Jan Mayen"},
|
{"key": "SJM", "value": "Svalbard and Jan Mayen"},
|
||||||
{"key": "SWE", "value": "Sweden"},
|
{"key": "SWE", "value": "Sweden"},
|
||||||
{"key": "CHE", "value": "Switzerland"},
|
{"key": "CHE", "value": "Switzerland"},
|
||||||
{"key": "SYR", "value": "Syrian Arab Republic"},
|
{"key": "SYR", "value": "Syrian Arab Republic"},
|
||||||
{"key": "TWN", "value": "Taiwan, Province of China"},
|
{"key": "TWN", "value": "Taiwan, Province of China"},
|
||||||
{"key": "TJK", "value": "Tajikistan"},
|
{"key": "TJK", "value": "Tajikistan"},
|
||||||
{"key": "TZA", "value": "Tanzania, United Republic of"},
|
{"key": "TZA", "value": "Tanzania, United Republic of"},
|
||||||
{"key": "THA", "value": "Thailand"},
|
{"key": "THA", "value": "Thailand"},
|
||||||
{"key": "TLS", "value": "Timor-Leste"},
|
{"key": "TLS", "value": "Timor-Leste"},
|
||||||
{"key": "TGO", "value": "Togo"},
|
{"key": "TGO", "value": "Togo"},
|
||||||
{"key": "TKL", "value": "Tokelau"},
|
{"key": "TKL", "value": "Tokelau"},
|
||||||
{"key": "TON", "value": "Tonga"},
|
{"key": "TON", "value": "Tonga"},
|
||||||
{"key": "TTO", "value": "Trinidad and Tobago"},
|
{"key": "TTO", "value": "Trinidad and Tobago"},
|
||||||
{"key": "TUN", "value": "Tunisia"},
|
{"key": "TUN", "value": "Tunisia"},
|
||||||
{"key": "TUR", "value": "Türkiye"},
|
{"key": "TUR", "value": "Türkiye"},
|
||||||
{"key": "TKM", "value": "Turkmenistan"},
|
{"key": "TKM", "value": "Turkmenistan"},
|
||||||
{"key": "TCA", "value": "Turks and Caicos Islands"},
|
{"key": "TCA", "value": "Turks and Caicos Islands"},
|
||||||
{"key": "TUV", "value": "Tuvalu"},
|
{"key": "TUV", "value": "Tuvalu"},
|
||||||
{"key": "UGA", "value": "Uganda"},
|
{"key": "UGA", "value": "Uganda"},
|
||||||
{"key": "UKR", "value": "Ukraine"},
|
{"key": "UKR", "value": "Ukraine"},
|
||||||
{"key": "ARE", "value": "United Arab Emirates"},
|
{"key": "ARE", "value": "United Arab Emirates"},
|
||||||
{"key": "GBR", "value": "United Kingdom of Great Britain and Northern Ireland"},
|
{"key": "GBR", "value": "United Kingdom of Great Britain and Northern Ireland"},
|
||||||
{"key": "USA", "value": "United States of America"},
|
{"key": "USA", "value": "United States of America"},
|
||||||
{"key": "UMI", "value": "United States Minor Outlying Islands"},
|
{"key": "UMI", "value": "United States Minor Outlying Islands"},
|
||||||
{"key": "URY", "value": "Uruguay"},
|
{"key": "URY", "value": "Uruguay"},
|
||||||
{"key": "UZB", "value": "Uzbekistan"},
|
{"key": "UZB", "value": "Uzbekistan"},
|
||||||
{"key": "VUT", "value": "Vanuatu"},
|
{"key": "VUT", "value": "Vanuatu"},
|
||||||
{"key": "VEN", "value": "Venezuela, Bolivarian Republic of"},
|
{"key": "VEN", "value": "Venezuela, Bolivarian Republic of"},
|
||||||
{"key": "VNM", "value": "Viet Nam"},
|
{"key": "VNM", "value": "Viet Nam"},
|
||||||
{"key": "VGB", "value": "Virgin Islands (British)"},
|
{"key": "VGB", "value": "Virgin Islands (British)"},
|
||||||
{"key": "VIR", "value": "Virgin Islands (U.S.)"},
|
{"key": "VIR", "value": "Virgin Islands (U.S.)"},
|
||||||
{"key": "WLF", "value": "Wallis and Futuna"},
|
{"key": "WLF", "value": "Wallis and Futuna"},
|
||||||
{"key": "ESH", "value": "Western Sahara"},
|
{"key": "ESH", "value": "Western Sahara"},
|
||||||
{"key": "YEM", "value": "Yemen"},
|
{"key": "YEM", "value": "Yemen"},
|
||||||
{"key": "ZMB", "value": "Zambia"},
|
{"key": "ZMB", "value": "Zambia"},
|
||||||
{"key": "ZWE", "value": "Zimbabwe"}
|
{"key": "ZWE", "value": "Zimbabwe"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
{"name": "ethnic",
|
{"name": "ethnic",
|
||||||
"VSName": "Ethnic",
|
"VSName": "Ethnic",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "PPMLN", "value": "Papua Melanezoid"},
|
{"key": "PPMLN", "value": "Papua Melanezoid"},
|
||||||
{"key": "NGRID", "value": "Negroid"},
|
{"key": "NGRID", "value": "Negroid"},
|
||||||
{"key": "WDOID", "value": "Weddoid"},
|
{"key": "WDOID", "value": "Weddoid"},
|
||||||
{"key": "MMPM", "value": "Melayu Mongoloid_Proto Melayu"},
|
{"key": "MMPM", "value": "Melayu Mongoloid_Proto Melayu"},
|
||||||
{"key": "MMDM", "value": "Melayu Mongoloid_Deutro Melayu"},
|
{"key": "MMDM", "value": "Melayu Mongoloid_Deutro Melayu"},
|
||||||
{"key": "TNGHA", "value": "Tionghoa"},
|
{"key": "TNGHA", "value": "Tionghoa"},
|
||||||
{"key": "INDIA", "value": "India"},
|
{"key": "INDIA", "value": "India"},
|
||||||
{"key": "ARAB", "value": "Arab"}
|
{"key": "ARAB", "value": "Arab"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,79 +1,79 @@
|
|||||||
{
|
{
|
||||||
"name": "event_id",
|
"name": "event_id",
|
||||||
"VSName": "Audit Event ID",
|
"VSName": "Audit Event ID",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "PATIENT_REGISTERED", "value": "Patient registered"},
|
{"key": "PATIENT_REGISTERED", "value": "Patient registered"},
|
||||||
{"key": "PATIENT_DEMOGRAPHICS_UPDATED", "value": "Patient demographics updated"},
|
{"key": "PATIENT_DEMOGRAPHICS_UPDATED", "value": "Patient demographics updated"},
|
||||||
{"key": "PATIENT_MERGED", "value": "Patient merged"},
|
{"key": "PATIENT_MERGED", "value": "Patient merged"},
|
||||||
{"key": "PATIENT_UNMERGED", "value": "Patient unmerged"},
|
{"key": "PATIENT_UNMERGED", "value": "Patient unmerged"},
|
||||||
{"key": "PATIENT_IDENTIFIER_UPDATED", "value": "Patient identifier updated"},
|
{"key": "PATIENT_IDENTIFIER_UPDATED", "value": "Patient identifier updated"},
|
||||||
{"key": "PATIENT_CONSENT_UPDATED", "value": "Patient consent updated"},
|
{"key": "PATIENT_CONSENT_UPDATED", "value": "Patient consent updated"},
|
||||||
{"key": "PATIENT_INSURANCE_UPDATED", "value": "Patient insurance updated"},
|
{"key": "PATIENT_INSURANCE_UPDATED", "value": "Patient insurance updated"},
|
||||||
{"key": "PATIENT_DELETED", "value": "Patient deleted"},
|
{"key": "PATIENT_DELETED", "value": "Patient deleted"},
|
||||||
{"key": "VISIT_ADMITTED", "value": "Visit admitted"},
|
{"key": "VISIT_ADMITTED", "value": "Visit admitted"},
|
||||||
{"key": "VISIT_TRANSFERRED", "value": "Visit transferred"},
|
{"key": "VISIT_TRANSFERRED", "value": "Visit transferred"},
|
||||||
{"key": "VISIT_DISCHARGED", "value": "Visit discharged"},
|
{"key": "VISIT_DISCHARGED", "value": "Visit discharged"},
|
||||||
{"key": "VISIT_STATUS_UPDATED", "value": "Visit status updated"},
|
{"key": "VISIT_STATUS_UPDATED", "value": "Visit status updated"},
|
||||||
{"key": "ORDER_CREATED", "value": "Order created"},
|
{"key": "ORDER_CREATED", "value": "Order created"},
|
||||||
{"key": "ORDER_CANCELLED", "value": "Order cancelled"},
|
{"key": "ORDER_CANCELLED", "value": "Order cancelled"},
|
||||||
{"key": "ORDER_REOPENED", "value": "Order reopened"},
|
{"key": "ORDER_REOPENED", "value": "Order reopened"},
|
||||||
{"key": "ORDER_TEST_ADDED", "value": "Order test added"},
|
{"key": "ORDER_TEST_ADDED", "value": "Order test added"},
|
||||||
{"key": "ORDER_TEST_REMOVED", "value": "Order test removed"},
|
{"key": "ORDER_TEST_REMOVED", "value": "Order test removed"},
|
||||||
{"key": "SPECIMEN_COLLECTED", "value": "Specimen collected"},
|
{"key": "SPECIMEN_COLLECTED", "value": "Specimen collected"},
|
||||||
{"key": "SPECIMEN_RECEIVED", "value": "Specimen received"},
|
{"key": "SPECIMEN_RECEIVED", "value": "Specimen received"},
|
||||||
{"key": "SPECIMEN_REJECTED", "value": "Specimen rejected"},
|
{"key": "SPECIMEN_REJECTED", "value": "Specimen rejected"},
|
||||||
{"key": "SPECIMEN_ALIQUOTED", "value": "Specimen aliquoted"},
|
{"key": "SPECIMEN_ALIQUOTED", "value": "Specimen aliquoted"},
|
||||||
{"key": "SPECIMEN_DISPOSED", "value": "Specimen disposed"},
|
{"key": "SPECIMEN_DISPOSED", "value": "Specimen disposed"},
|
||||||
{"key": "RESULT_ENTERED", "value": "Result entered"},
|
{"key": "RESULT_ENTERED", "value": "Result entered"},
|
||||||
{"key": "RESULT_UPDATED", "value": "Result updated"},
|
{"key": "RESULT_UPDATED", "value": "Result updated"},
|
||||||
{"key": "RESULT_VERIFIED", "value": "Result verified"},
|
{"key": "RESULT_VERIFIED", "value": "Result verified"},
|
||||||
{"key": "RESULT_AMENDED", "value": "Result amended"},
|
{"key": "RESULT_AMENDED", "value": "Result amended"},
|
||||||
{"key": "RESULT_RELEASED", "value": "Result released"},
|
{"key": "RESULT_RELEASED", "value": "Result released"},
|
||||||
{"key": "RESULT_RETRACTED", "value": "Result retracted"},
|
{"key": "RESULT_RETRACTED", "value": "Result retracted"},
|
||||||
{"key": "RESULT_CORRECTED", "value": "Result corrected"},
|
{"key": "RESULT_CORRECTED", "value": "Result corrected"},
|
||||||
{"key": "QC_RECORDED", "value": "QC recorded"},
|
{"key": "QC_RECORDED", "value": "QC recorded"},
|
||||||
{"key": "QC_FAILED", "value": "QC failed"},
|
{"key": "QC_FAILED", "value": "QC failed"},
|
||||||
{"key": "QC_OVERRIDE_APPLIED", "value": "QC override applied"},
|
{"key": "QC_OVERRIDE_APPLIED", "value": "QC override applied"},
|
||||||
{"key": "VALUESET_ITEM_CREATED", "value": "Value set item created"},
|
{"key": "VALUESET_ITEM_CREATED", "value": "Value set item created"},
|
||||||
{"key": "VALUESET_ITEM_UPDATED", "value": "Value set item updated"},
|
{"key": "VALUESET_ITEM_UPDATED", "value": "Value set item updated"},
|
||||||
{"key": "VALUESET_ITEM_RETIRED", "value": "Value set item retired"},
|
{"key": "VALUESET_ITEM_RETIRED", "value": "Value set item retired"},
|
||||||
{"key": "TEST_DEFINITION_UPDATED", "value": "Test definition updated"},
|
{"key": "TEST_DEFINITION_UPDATED", "value": "Test definition updated"},
|
||||||
{"key": "REFERENCE_RANGE_UPDATED", "value": "Reference range updated"},
|
{"key": "REFERENCE_RANGE_UPDATED", "value": "Reference range updated"},
|
||||||
{"key": "TEST_PANEL_MEMBERSHIP_UPDATED", "value": "Test panel membership updated"},
|
{"key": "TEST_PANEL_MEMBERSHIP_UPDATED", "value": "Test panel membership updated"},
|
||||||
{"key": "ANALYZER_CONFIG_UPDATED", "value": "Analyzer config updated"},
|
{"key": "ANALYZER_CONFIG_UPDATED", "value": "Analyzer config updated"},
|
||||||
{"key": "INTEGRATION_CONFIG_UPDATED", "value": "Integration config updated"},
|
{"key": "INTEGRATION_CONFIG_UPDATED", "value": "Integration config updated"},
|
||||||
{"key": "CODING_SYSTEM_UPDATED", "value": "Coding system updated"},
|
{"key": "CODING_SYSTEM_UPDATED", "value": "Coding system updated"},
|
||||||
{"key": "USER_CREATED", "value": "User created"},
|
{"key": "USER_CREATED", "value": "User created"},
|
||||||
{"key": "USER_DISABLED", "value": "User disabled"},
|
{"key": "USER_DISABLED", "value": "User disabled"},
|
||||||
{"key": "USER_PASSWORD_RESET", "value": "User password reset"},
|
{"key": "USER_PASSWORD_RESET", "value": "User password reset"},
|
||||||
{"key": "USER_ROLE_CHANGED", "value": "User role changed"},
|
{"key": "USER_ROLE_CHANGED", "value": "User role changed"},
|
||||||
{"key": "USER_PERMISSION_CHANGED", "value": "User permission changed"},
|
{"key": "USER_PERMISSION_CHANGED", "value": "User permission changed"},
|
||||||
{"key": "SITE_CREATED", "value": "Site created"},
|
{"key": "SITE_CREATED", "value": "Site created"},
|
||||||
{"key": "SITE_UPDATED", "value": "Site updated"},
|
{"key": "SITE_UPDATED", "value": "Site updated"},
|
||||||
{"key": "WORKSTATION_UPDATED", "value": "Workstation updated"},
|
{"key": "WORKSTATION_UPDATED", "value": "Workstation updated"},
|
||||||
{"key": "AUTH_LOGIN_SUCCESS", "value": "Auth login success"},
|
{"key": "AUTH_LOGIN_SUCCESS", "value": "Auth login success"},
|
||||||
{"key": "AUTH_LOGOUT_SUCCESS", "value": "Auth logout success"},
|
{"key": "AUTH_LOGOUT_SUCCESS", "value": "Auth logout success"},
|
||||||
{"key": "AUTH_LOGIN_FAILED", "value": "Auth login failed"},
|
{"key": "AUTH_LOGIN_FAILED", "value": "Auth login failed"},
|
||||||
{"key": "AUTH_LOCKOUT_TRIGGERED", "value": "Auth lockout triggered"},
|
{"key": "AUTH_LOCKOUT_TRIGGERED", "value": "Auth lockout triggered"},
|
||||||
{"key": "TOKEN_ISSUED", "value": "Token issued"},
|
{"key": "TOKEN_ISSUED", "value": "Token issued"},
|
||||||
{"key": "TOKEN_REFRESHED", "value": "Token refreshed"},
|
{"key": "TOKEN_REFRESHED", "value": "Token refreshed"},
|
||||||
{"key": "TOKEN_REVOKED", "value": "Token revoked"},
|
{"key": "TOKEN_REVOKED", "value": "Token revoked"},
|
||||||
{"key": "AUTHORIZATION_FAILED", "value": "Authorization failed"},
|
{"key": "AUTHORIZATION_FAILED", "value": "Authorization failed"},
|
||||||
{"key": "IMPORT_JOB_STARTED", "value": "Import job started"},
|
{"key": "IMPORT_JOB_STARTED", "value": "Import job started"},
|
||||||
{"key": "IMPORT_JOB_FINISHED", "value": "Import job finished"},
|
{"key": "IMPORT_JOB_FINISHED", "value": "Import job finished"},
|
||||||
{"key": "EXPORT_JOB_STARTED", "value": "Export job started"},
|
{"key": "EXPORT_JOB_STARTED", "value": "Export job started"},
|
||||||
{"key": "EXPORT_JOB_FINISHED", "value": "Export job finished"},
|
{"key": "EXPORT_JOB_FINISHED", "value": "Export job finished"},
|
||||||
{"key": "JOB_STARTED", "value": "Job started"},
|
{"key": "JOB_STARTED", "value": "Job started"},
|
||||||
{"key": "JOB_FINISHED", "value": "Job finished"},
|
{"key": "JOB_FINISHED", "value": "Job finished"},
|
||||||
{"key": "INTEGRATION_SYNC_STARTED", "value": "Integration sync started"},
|
{"key": "INTEGRATION_SYNC_STARTED", "value": "Integration sync started"},
|
||||||
{"key": "INTEGRATION_SYNC_FINISHED", "value": "Integration sync finished"},
|
{"key": "INTEGRATION_SYNC_FINISHED", "value": "Integration sync finished"},
|
||||||
{"key": "AUDIT_WRITE_FAILED", "value": "Audit write failed"},
|
{"key": "AUDIT_WRITE_FAILED", "value": "Audit write failed"},
|
||||||
{"key": "AUDIT_ARCHIVE_EXECUTED", "value": "Audit archive executed"},
|
{"key": "AUDIT_ARCHIVE_EXECUTED", "value": "Audit archive executed"},
|
||||||
{"key": "AUDIT_PURGE_EXECUTED", "value": "Audit purge executed"},
|
{"key": "AUDIT_PURGE_EXECUTED", "value": "Audit purge executed"},
|
||||||
{"key": "AUDIT_CHECKSUM_CREATED", "value": "Audit checksum created"},
|
{"key": "AUDIT_CHECKSUM_CREATED", "value": "Audit checksum created"},
|
||||||
{"key": "AUDIT_CHECKSUM_FAILED", "value": "Audit checksum failed"},
|
{"key": "AUDIT_CHECKSUM_FAILED", "value": "Audit checksum failed"},
|
||||||
{"key": "LEGAL_HOLD_APPLIED", "value": "Legal hold applied"},
|
{"key": "LEGAL_HOLD_APPLIED", "value": "Legal hold applied"},
|
||||||
{"key": "LEGAL_HOLD_RELEASED", "value": "Legal hold released"}
|
{"key": "LEGAL_HOLD_RELEASED", "value": "Legal hold released"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{"name": "fasting_status",
|
{"name": "fasting_status",
|
||||||
"VSName": "Fasting Status",
|
"VSName": "Fasting Status",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "F", "value": "Fasting"},
|
{"key": "F", "value": "Fasting"},
|
||||||
{"key": "NF", "value": "Not Fasting"},
|
{"key": "NF", "value": "Not Fasting"},
|
||||||
{"key": "NG", "value": "Not Given"}
|
{"key": "NG", "value": "Not Given"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{"name": "formula_language",
|
{"name": "formula_language",
|
||||||
"VSName": "Formula Language",
|
"VSName": "Formula Language",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "Phyton", "value": "Phyton"},
|
{"key": "Phyton", "value": "Phyton"},
|
||||||
{"key": "CQL", "value": "Clinical Quality Language"},
|
{"key": "CQL", "value": "Clinical Quality Language"},
|
||||||
{"key": "FHIRP", "value": "FHIRPath"},
|
{"key": "FHIRP", "value": "FHIRPath"},
|
||||||
{"key": "SQL", "value": "SQL"}
|
{"key": "SQL", "value": "SQL"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{"name": "identifier_type",
|
{"name": "identifier_type",
|
||||||
"VSName": "Identifier Type",
|
"VSName": "Identifier Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "KTP", "value": "Kartu Tanda Penduduk"},
|
{"key": "KTP", "value": "Kartu Tanda Penduduk"},
|
||||||
{"key": "PASS", "value": "Passport"},
|
{"key": "PASS", "value": "Passport"},
|
||||||
{"key": "SSN", "value": "Social Security Number"},
|
{"key": "SSN", "value": "Social Security Number"},
|
||||||
{"key": "SIM", "value": "Surat Izin Mengemudi"},
|
{"key": "SIM", "value": "Surat Izin Mengemudi"},
|
||||||
{"key": "KTAS", "value": "Kartu Izin Tinggal Terbatas"}
|
{"key": "KTAS", "value": "Kartu Izin Tinggal Terbatas"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
{"name": "location_type",
|
{"name": "location_type",
|
||||||
"VSName": "Location Type",
|
"VSName": "Location Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "FCLT", "value": "Facility"},
|
{"key": "FCLT", "value": "Facility"},
|
||||||
{"key": "BLDG", "value": "Building"},
|
{"key": "BLDG", "value": "Building"},
|
||||||
{"key": "FLOR", "value": "Floor"},
|
{"key": "FLOR", "value": "Floor"},
|
||||||
{"key": "POC", "value": "Point of Care"},
|
{"key": "POC", "value": "Point of Care"},
|
||||||
{"key": "ROOM", "value": "Room"},
|
{"key": "ROOM", "value": "Room"},
|
||||||
{"key": "BED", "value": "Bed"},
|
{"key": "BED", "value": "Bed"},
|
||||||
{"key": "MOBL", "value": "Mobile"},
|
{"key": "MOBL", "value": "Mobile"},
|
||||||
{"key": "REMT", "value": "Remote"}
|
{"key": "REMT", "value": "Remote"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
{"name": "marital_status",
|
{"name": "marital_status",
|
||||||
"VSName": "Marital Status",
|
"VSName": "Marital Status",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "A", "value": "Separated"},
|
{"key": "A", "value": "Separated"},
|
||||||
{"key": "D", "value": "Divorced"},
|
{"key": "D", "value": "Divorced"},
|
||||||
{"key": "M", "value": "Married"},
|
{"key": "M", "value": "Married"},
|
||||||
{"key": "S", "value": "Single"},
|
{"key": "S", "value": "Single"},
|
||||||
{"key": "W", "value": "Widowed"},
|
{"key": "W", "value": "Widowed"},
|
||||||
{"key": "B", "value": "Unmarried"},
|
{"key": "B", "value": "Unmarried"},
|
||||||
{"key": "U", "value": "Unknown"},
|
{"key": "U", "value": "Unknown"},
|
||||||
{"key": "O", "value": "Other"}
|
{"key": "O", "value": "Other"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{"name": "math_sign",
|
{"name": "math_sign",
|
||||||
"VSName": "Math Sign",
|
"VSName": "Math Sign",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "=", "value": "Equal"},
|
{"key": "=", "value": "Equal"},
|
||||||
{"key": "<", "value": "Less than"},
|
{"key": "<", "value": "Less than"},
|
||||||
{"key": ">", "value": "Greater than"},
|
{"key": ">", "value": "Greater than"},
|
||||||
{"key": "<=", "value": "Less than or equal to"},
|
{"key": "<=", "value": "Less than or equal to"},
|
||||||
{"key": ">=", "value": "Greater than or equal to"}
|
{"key": ">=", "value": "Greater than or equal to"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
{"name": "numeric_ref_type",
|
{"name": "numeric_ref_type",
|
||||||
"VSName": "Numeric Reference Type",
|
"VSName": "Numeric Reference Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "RANGE", "value": "Range"},
|
{"key": "RANGE", "value": "Range"},
|
||||||
{"key": "THOLD", "value": "Threshold"}
|
{"key": "THOLD", "value": "Threshold"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,37 @@
|
|||||||
{"name": "race",
|
{"name": "race",
|
||||||
"VSName": "Race (Ethnicity)",
|
"VSName": "Race (Ethnicity)",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "JAWA", "value": "Jawa"},
|
{"key": "JAWA", "value": "Jawa"},
|
||||||
{"key": "SUNDA", "value": "Sunda"},
|
{"key": "SUNDA", "value": "Sunda"},
|
||||||
{"key": "BATAK", "value": "Batak"},
|
{"key": "BATAK", "value": "Batak"},
|
||||||
{"key": "SULOR", "value": "Suku asal Sulawesi lainnya"},
|
{"key": "SULOR", "value": "Suku asal Sulawesi lainnya"},
|
||||||
{"key": "MDRA", "value": "Madura"},
|
{"key": "MDRA", "value": "Madura"},
|
||||||
{"key": "BTWI", "value": "Betawi"},
|
{"key": "BTWI", "value": "Betawi"},
|
||||||
{"key": "MNG", "value": "Minangkabau"},
|
{"key": "MNG", "value": "Minangkabau"},
|
||||||
{"key": "BUGIS", "value": "Bugis"},
|
{"key": "BUGIS", "value": "Bugis"},
|
||||||
{"key": "MLYU", "value": "Melayu"},
|
{"key": "MLYU", "value": "Melayu"},
|
||||||
{"key": "SUMSL", "value": "Suku asal Sumatera Selatan"},
|
{"key": "SUMSL", "value": "Suku asal Sumatera Selatan"},
|
||||||
{"key": "BTNOR", "value": "Suku asal Banten"},
|
{"key": "BTNOR", "value": "Suku asal Banten"},
|
||||||
{"key": "NTTOR", "value": "Suku asal Nusa Tenggara Timur"},
|
{"key": "NTTOR", "value": "Suku asal Nusa Tenggara Timur"},
|
||||||
{"key": "BNJAR", "value": "Banjar"},
|
{"key": "BNJAR", "value": "Banjar"},
|
||||||
{"key": "ACEH", "value": "Aceh"},
|
{"key": "ACEH", "value": "Aceh"},
|
||||||
{"key": "BALI", "value": "Bali"},
|
{"key": "BALI", "value": "Bali"},
|
||||||
{"key": "SASAK", "value": "Sasak"},
|
{"key": "SASAK", "value": "Sasak"},
|
||||||
{"key": "DAYAK", "value": "Dayak"},
|
{"key": "DAYAK", "value": "Dayak"},
|
||||||
{"key": "TNGHA", "value": "Tionghoa"},
|
{"key": "TNGHA", "value": "Tionghoa"},
|
||||||
{"key": "PPAOR", "value": "Suku asal Papua"},
|
{"key": "PPAOR", "value": "Suku asal Papua"},
|
||||||
{"key": "MKSSR", "value": "Makassar"},
|
{"key": "MKSSR", "value": "Makassar"},
|
||||||
{"key": "SUMOR", "value": "Suku asal Sumatera lainnya"},
|
{"key": "SUMOR", "value": "Suku asal Sumatera lainnya"},
|
||||||
{"key": "MLKOR", "value": "Suku asal Maluku"},
|
{"key": "MLKOR", "value": "Suku asal Maluku"},
|
||||||
{"key": "KLMOR", "value": "Suku asal Kalimantan lainnya"},
|
{"key": "KLMOR", "value": "Suku asal Kalimantan lainnya"},
|
||||||
{"key": "CRBON", "value": "Cirebon"},
|
{"key": "CRBON", "value": "Cirebon"},
|
||||||
{"key": "JBIOR", "value": "Suku asal Jambi"},
|
{"key": "JBIOR", "value": "Suku asal Jambi"},
|
||||||
{"key": "LPGOR", "value": "Suku Lampung"},
|
{"key": "LPGOR", "value": "Suku Lampung"},
|
||||||
{"key": "NTBOR", "value": "Suku asal Nusa Tenggara Barat lainnya"},
|
{"key": "NTBOR", "value": "Suku asal Nusa Tenggara Barat lainnya"},
|
||||||
{"key": "GRTLO", "value": "Gorontalo"},
|
{"key": "GRTLO", "value": "Gorontalo"},
|
||||||
{"key": "MNHSA", "value": "Minahasa"},
|
{"key": "MNHSA", "value": "Minahasa"},
|
||||||
{"key": "NIAS", "value": "Nias"},
|
{"key": "NIAS", "value": "Nias"},
|
||||||
{"key": "FORGN", "value": "Asing/luar negeri"}
|
{"key": "FORGN", "value": "Asing/luar negeri"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{"name": "range_type",
|
{"name": "range_type",
|
||||||
"VSName": "Range Type",
|
"VSName": "Range Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "REF", "value": "Reference Range"},
|
{"key": "REF", "value": "Reference Range"},
|
||||||
{"key": "CRTC", "value": "Critical Range"},
|
{"key": "CRTC", "value": "Critical Range"},
|
||||||
{"key": "VAL", "value": "Validation Range"},
|
{"key": "VAL", "value": "Validation Range"},
|
||||||
{"key": "RERUN", "value": "Rerun Range"}
|
{"key": "RERUN", "value": "Rerun Range"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
{"name": "religion",
|
{"name": "religion",
|
||||||
"VSName": "Religion",
|
"VSName": "Religion",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "ISLAM", "value": "Islam"},
|
{"key": "ISLAM", "value": "Islam"},
|
||||||
{"key": "KRSTN", "value": "Kristen"},
|
{"key": "KRSTN", "value": "Kristen"},
|
||||||
{"key": "KTLIK", "value": "Katolik"},
|
{"key": "KTLIK", "value": "Katolik"},
|
||||||
{"key": "HINDU", "value": "Hindu"},
|
{"key": "HINDU", "value": "Hindu"},
|
||||||
{"key": "BUDHA", "value": "Budha"},
|
{"key": "BUDHA", "value": "Budha"},
|
||||||
{"key": "KHCU", "value": "Khong Hu Cu"},
|
{"key": "KHCU", "value": "Khong Hu Cu"},
|
||||||
{"key": "OTHER", "value": "Lainnya"}
|
{"key": "OTHER", "value": "Lainnya"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
{"name": "request_status",
|
{"name": "request_status",
|
||||||
"VSName": "Request Status",
|
"VSName": "Request Status",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "STC", "value": "To be collected"},
|
{"key": "STC", "value": "To be collected"},
|
||||||
{"key": "SCFld", "value": "Collection failed"},
|
{"key": "SCFld", "value": "Collection failed"},
|
||||||
{"key": "SCtd", "value": "Collected"},
|
{"key": "SCtd", "value": "Collected"},
|
||||||
{"key": "STran", "value": "In-transport"},
|
{"key": "STran", "value": "In-transport"},
|
||||||
{"key": "STFld", "value": "Transport failed"},
|
{"key": "STFld", "value": "Transport failed"},
|
||||||
{"key": "SArrv", "value": "Arrived"},
|
{"key": "SArrv", "value": "Arrived"},
|
||||||
{"key": "SRejc", "value": "Rejected"},
|
{"key": "SRejc", "value": "Rejected"},
|
||||||
{"key": "SRcvd", "value": "Received"},
|
{"key": "SRcvd", "value": "Received"},
|
||||||
{"key": "SPAna", "value": "Pre-analytical"},
|
{"key": "SPAna", "value": "Pre-analytical"},
|
||||||
{"key": "SPAF", "value": "Pre-analytical failed"},
|
{"key": "SPAF", "value": "Pre-analytical failed"},
|
||||||
{"key": "STA", "value": "To be analyze"},
|
{"key": "STA", "value": "To be analyze"},
|
||||||
{"key": "SAFld", "value": "Analytical failed"},
|
{"key": "SAFld", "value": "Analytical failed"},
|
||||||
{"key": "SAna", "value": "Analytical"},
|
{"key": "SAna", "value": "Analytical"},
|
||||||
{"key": "STS", "value": "To be stored"},
|
{"key": "STS", "value": "To be stored"},
|
||||||
{"key": "SSFld", "value": "Store failed"},
|
{"key": "SSFld", "value": "Store failed"},
|
||||||
{"key": "SStrd", "value": "Stored"},
|
{"key": "SStrd", "value": "Stored"},
|
||||||
{"key": "SExp", "value": "Expired"},
|
{"key": "SExp", "value": "Expired"},
|
||||||
{"key": "STD", "value": "To be destroyed"},
|
{"key": "STD", "value": "To be destroyed"},
|
||||||
{"key": "SDFld", "value": "Failed to destroy"},
|
{"key": "SDFld", "value": "Failed to destroy"},
|
||||||
{"key": "SDstd", "value": "Destroyed"}
|
{"key": "SDstd", "value": "Destroyed"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{"name": "result_status",
|
{"name": "result_status",
|
||||||
"VSName": "Result Status",
|
"VSName": "Result Status",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "PRELIMINARY", "value": "Preliminary"},
|
{"key": "PRELIMINARY", "value": "Preliminary"},
|
||||||
{"key": "FINAL", "value": "Final"},
|
{"key": "FINAL", "value": "Final"},
|
||||||
{"key": "CORRECTED", "value": "Corrected"},
|
{"key": "CORRECTED", "value": "Corrected"},
|
||||||
{"key": "CANCELLED", "value": "Cancelled"}
|
{"key": "CANCELLED", "value": "Cancelled"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
{"name": "result_unit",
|
{"name": "result_unit",
|
||||||
"VSName": "Result Unit",
|
"VSName": "Result Unit",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "g/dL", "value": "g/dL"},
|
{"key": "g/dL", "value": "g/dL"},
|
||||||
{"key": "g/L", "value": "g/L"},
|
{"key": "g/L", "value": "g/L"},
|
||||||
{"key": "mg/dL", "value": "mg/dL"},
|
{"key": "mg/dL", "value": "mg/dL"},
|
||||||
{"key": "mg/L", "value": "mg/L"},
|
{"key": "mg/L", "value": "mg/L"},
|
||||||
{"key": "L/L", "value": "L/L"},
|
{"key": "L/L", "value": "L/L"},
|
||||||
{"key": "x106/mL", "value": "x106/mL"},
|
{"key": "x106/mL", "value": "x106/mL"},
|
||||||
{"key": "x1012/L", "value": "x1012/L"},
|
{"key": "x1012/L", "value": "x1012/L"},
|
||||||
{"key": "fL", "value": "fL"},
|
{"key": "fL", "value": "fL"},
|
||||||
{"key": "pg", "value": "pg"},
|
{"key": "pg", "value": "pg"},
|
||||||
{"key": "x109/L", "value": "x109/L"}
|
{"key": "x109/L", "value": "x109/L"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
{"name": "site_class",
|
{"name": "site_class",
|
||||||
"VSName": "Site Class",
|
"VSName": "Site Class",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "A", "value": "Kelas A"},
|
{"key": "A", "value": "Kelas A"},
|
||||||
{"key": "B", "value": "Kelas B"},
|
{"key": "B", "value": "Kelas B"},
|
||||||
{"key": "C", "value": "Kelas C"},
|
{"key": "C", "value": "Kelas C"},
|
||||||
{"key": "D", "value": "Kelas D"},
|
{"key": "D", "value": "Kelas D"},
|
||||||
{"key": "Utm", "value": "Utama"},
|
{"key": "Utm", "value": "Utama"},
|
||||||
{"key": "Ptm", "value": "Pratama"}
|
{"key": "Ptm", "value": "Pratama"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
{"name": "site_type",
|
{"name": "site_type",
|
||||||
"VSName": "Site Type",
|
"VSName": "Site Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "GH", "value": "Government Hospital"},
|
{"key": "GH", "value": "Government Hospital"},
|
||||||
{"key": "PH", "value": "Private Hospital"},
|
{"key": "PH", "value": "Private Hospital"},
|
||||||
{"key": "GHL", "value": "Government Hospital Lab"},
|
{"key": "GHL", "value": "Government Hospital Lab"},
|
||||||
{"key": "PHL", "value": "Private Hospital Lab"},
|
{"key": "PHL", "value": "Private Hospital Lab"},
|
||||||
{"key": "GL", "value": "Government Lab"},
|
{"key": "GL", "value": "Government Lab"},
|
||||||
{"key": "PL", "value": "Private Lab"}
|
{"key": "PL", "value": "Private Lab"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
{"name": "specimen_activity",
|
{"name": "specimen_activity",
|
||||||
"VSName": "Specimen Activity",
|
"VSName": "Specimen Activity",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "SColl", "value": "Collection"},
|
{"key": "SColl", "value": "Collection"},
|
||||||
{"key": "STran", "value": "Transport"},
|
{"key": "STran", "value": "Transport"},
|
||||||
{"key": "SRec", "value": "Reception"},
|
{"key": "SRec", "value": "Reception"},
|
||||||
{"key": "SPrep", "value": "Preparation"},
|
{"key": "SPrep", "value": "Preparation"},
|
||||||
{"key": "SAlqt", "value": "Aliquot"},
|
{"key": "SAlqt", "value": "Aliquot"},
|
||||||
{"key": "SDisp", "value": "Dispatching"},
|
{"key": "SDisp", "value": "Dispatching"},
|
||||||
{"key": "SDest", "value": "Destruction"}
|
{"key": "SDest", "value": "Destruction"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
{"name": "specimen_condition",
|
{"name": "specimen_condition",
|
||||||
"VSName": "Specimen Condition",
|
"VSName": "Specimen Condition",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "HEM", "value": "Hemolyzed"},
|
{"key": "HEM", "value": "Hemolyzed"},
|
||||||
{"key": "ITC", "value": "Icteric"},
|
{"key": "ITC", "value": "Icteric"},
|
||||||
{"key": "LIP", "value": "Lipemic"},
|
{"key": "LIP", "value": "Lipemic"},
|
||||||
{"key": "CFU", "value": "Centrifuged"},
|
{"key": "CFU", "value": "Centrifuged"},
|
||||||
{"key": "ROOM", "value": "Room temperature"},
|
{"key": "ROOM", "value": "Room temperature"},
|
||||||
{"key": "COOL", "value": "Cool"},
|
{"key": "COOL", "value": "Cool"},
|
||||||
{"key": "FROZ", "value": "Frozen"},
|
{"key": "FROZ", "value": "Frozen"},
|
||||||
{"key": "CLOT", "value": "Clotted"},
|
{"key": "CLOT", "value": "Clotted"},
|
||||||
{"key": "AUT", "value": "Autolyzed"},
|
{"key": "AUT", "value": "Autolyzed"},
|
||||||
{"key": "CON", "value": "Contaminated"},
|
{"key": "CON", "value": "Contaminated"},
|
||||||
{"key": "LIVE", "value": "Live"}
|
{"key": "LIVE", "value": "Live"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
{"name": "specimen_role",
|
{"name": "specimen_role",
|
||||||
"VSName": "Specimen Role",
|
"VSName": "Specimen Role",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "P", "value": "Patient"},
|
{"key": "P", "value": "Patient"},
|
||||||
{"key": "B", "value": "Blind Sample"},
|
{"key": "B", "value": "Blind Sample"},
|
||||||
{"key": "Q", "value": "Control specimen"},
|
{"key": "Q", "value": "Control specimen"},
|
||||||
{"key": "E", "value": "Electronic QC"},
|
{"key": "E", "value": "Electronic QC"},
|
||||||
{"key": "F", "value": "Filler Organization Proficiency"},
|
{"key": "F", "value": "Filler Organization Proficiency"},
|
||||||
{"key": "O", "value": "Operator Proficiency"},
|
{"key": "O", "value": "Operator Proficiency"},
|
||||||
{"key": "C", "value": "Calibrator"},
|
{"key": "C", "value": "Calibrator"},
|
||||||
{"key": "R", "value": "Replicate"},
|
{"key": "R", "value": "Replicate"},
|
||||||
{"key": "V", "value": "Verifying Calibrator"}
|
{"key": "V", "value": "Verifying Calibrator"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
{"name": "specimen_status",
|
{"name": "specimen_status",
|
||||||
"VSName": "Specimen Status",
|
"VSName": "Specimen Status",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "STC", "value": "To be collected"},
|
{"key": "STC", "value": "To be collected"},
|
||||||
{"key": "SCFld", "value": "Collection failed"},
|
{"key": "SCFld", "value": "Collection failed"},
|
||||||
{"key": "SCtd", "value": "Collected"},
|
{"key": "SCtd", "value": "Collected"},
|
||||||
{"key": "STran", "value": "In-transport"},
|
{"key": "STran", "value": "In-transport"},
|
||||||
{"key": "STFld", "value": "Transport failed"},
|
{"key": "STFld", "value": "Transport failed"},
|
||||||
{"key": "SArrv", "value": "Arrived"},
|
{"key": "SArrv", "value": "Arrived"},
|
||||||
{"key": "SRejc", "value": "Rejected"},
|
{"key": "SRejc", "value": "Rejected"},
|
||||||
{"key": "SRcvd", "value": "Received"},
|
{"key": "SRcvd", "value": "Received"},
|
||||||
{"key": "SPAna", "value": "Pre-analytical"},
|
{"key": "SPAna", "value": "Pre-analytical"},
|
||||||
{"key": "SPAF", "value": "Pre-analytical failed"},
|
{"key": "SPAF", "value": "Pre-analytical failed"},
|
||||||
{"key": "STA", "value": "To be analyze"},
|
{"key": "STA", "value": "To be analyze"},
|
||||||
{"key": "SAFld", "value": "Analytical failed"},
|
{"key": "SAFld", "value": "Analytical failed"},
|
||||||
{"key": "SAna", "value": "Analytical"},
|
{"key": "SAna", "value": "Analytical"},
|
||||||
{"key": "STS", "value": "To be stored"},
|
{"key": "STS", "value": "To be stored"},
|
||||||
{"key": "SSFld", "value": "Store failed"},
|
{"key": "SSFld", "value": "Store failed"},
|
||||||
{"key": "SStrd", "value": "Stored"},
|
{"key": "SStrd", "value": "Stored"},
|
||||||
{"key": "SExp", "value": "Expired"},
|
{"key": "SExp", "value": "Expired"},
|
||||||
{"key": "STD", "value": "To be destroyed"},
|
{"key": "STD", "value": "To be destroyed"},
|
||||||
{"key": "SDFld", "value": "Failed to destroy"},
|
{"key": "SDFld", "value": "Failed to destroy"},
|
||||||
{"key": "SDstd", "value": "Destroyed"}
|
{"key": "SDstd", "value": "Destroyed"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
{"name": "specimen_type",
|
{"name": "specimen_type",
|
||||||
"VSName": "Specimen Type",
|
"VSName": "Specimen Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "BLD", "value": "Whole blood"},
|
{"key": "BLD", "value": "Whole blood"},
|
||||||
{"key": "BLDA", "value": "Blood arterial"},
|
{"key": "BLDA", "value": "Blood arterial"},
|
||||||
{"key": "BLDCO", "value": "Cord blood"},
|
{"key": "BLDCO", "value": "Cord blood"},
|
||||||
{"key": "FBLOOD", "value": "Blood, Fetal"},
|
{"key": "FBLOOD", "value": "Blood, Fetal"},
|
||||||
{"key": "CSF", "value": "Cerebral spinal fluid"},
|
{"key": "CSF", "value": "Cerebral spinal fluid"},
|
||||||
{"key": "WB", "value": "Blood, Whole"},
|
{"key": "WB", "value": "Blood, Whole"},
|
||||||
{"key": "BBL", "value": "Blood bag"},
|
{"key": "BBL", "value": "Blood bag"},
|
||||||
{"key": "SER", "value": "Serum"},
|
{"key": "SER", "value": "Serum"},
|
||||||
{"key": "PLAS", "value": "Plasma"},
|
{"key": "PLAS", "value": "Plasma"},
|
||||||
{"key": "PLB", "value": "Plasma bag"},
|
{"key": "PLB", "value": "Plasma bag"},
|
||||||
{"key": "MUCOS", "value": "Mucosa"},
|
{"key": "MUCOS", "value": "Mucosa"},
|
||||||
{"key": "MUCUS", "value": "Mucus"},
|
{"key": "MUCUS", "value": "Mucus"},
|
||||||
{"key": "UR", "value": "Urine"},
|
{"key": "UR", "value": "Urine"},
|
||||||
{"key": "RANDU", "value": "Urine, Random"},
|
{"key": "RANDU", "value": "Urine, Random"},
|
||||||
{"key": "URINM", "value": "Urine, Midstream"}
|
{"key": "URINM", "value": "Urine, Midstream"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{"name": "test_activity",
|
{"name": "test_activity",
|
||||||
"VSName": "Test Activity",
|
"VSName": "Test Activity",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "ORD", "value": "Order"},
|
{"key": "ORD", "value": "Order"},
|
||||||
{"key": "ANA", "value": "Analyse"},
|
{"key": "ANA", "value": "Analyse"},
|
||||||
{"key": "VER", "value": "Result Verification/Technical Validation"},
|
{"key": "VER", "value": "Result Verification/Technical Validation"},
|
||||||
{"key": "REV", "value": "Clinical Review/Clinical Validation"},
|
{"key": "REV", "value": "Clinical Review/Clinical Validation"},
|
||||||
{"key": "REP", "value": "Reporting"}
|
{"key": "REP", "value": "Reporting"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{"name": "test_status",
|
{"name": "test_status",
|
||||||
"VSName": "Test Status",
|
"VSName": "Test Status",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "PENDING", "value": "Waiting for Results"},
|
{"key": "PENDING", "value": "Waiting for Results"},
|
||||||
{"key": "IN_PROCESS", "value": "Analyzing"},
|
{"key": "IN_PROCESS", "value": "Analyzing"},
|
||||||
{"key": "VERIFIED", "value": "Verified & Signed"},
|
{"key": "VERIFIED", "value": "Verified & Signed"},
|
||||||
{"key": "REJECTED", "value": "Sample Rejected"}
|
{"key": "REJECTED", "value": "Sample Rejected"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{"name": "test_type",
|
{"name": "test_type",
|
||||||
"VSName": "Test Type",
|
"VSName": "Test Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "TEST", "value": "Test"},
|
{"key": "TEST", "value": "Test"},
|
||||||
{"key": "PARAM", "value": "Parameter"},
|
{"key": "PARAM", "value": "Parameter"},
|
||||||
{"key": "CALC", "value": "Calculated Test"},
|
{"key": "CALC", "value": "Calculated Test"},
|
||||||
{"key": "GROUP", "value": "Group Test"},
|
{"key": "GROUP", "value": "Group Test"},
|
||||||
{"key": "TITLE", "value": "Title"}
|
{"key": "TITLE", "value": "Title"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
{"name": "text_ref_type",
|
{"name": "text_ref_type",
|
||||||
"VSName": "Text Reference Type",
|
"VSName": "Text Reference Type",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "VSET", "value": "Value Set"},
|
{"key": "VSET", "value": "Value Set"},
|
||||||
{"key": "TEXT", "value": "Text"}
|
{"key": "TEXT", "value": "Text"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{"name": "unit",
|
{"name": "unit",
|
||||||
"VSName": "Unit",
|
"VSName": "Unit",
|
||||||
"VCategory": "System",
|
"VCategory": "System",
|
||||||
"values": [
|
"values": [
|
||||||
{"key": "L", "value": "Liter"},
|
{"key": "L", "value": "Liter"},
|
||||||
{"key": "mL", "value": "Mili Liter"},
|
{"key": "mL", "value": "Mili Liter"},
|
||||||
{"key": "Pcs", "value": "Pieces"}
|
{"key": "Pcs", "value": "Pieces"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models\Contact;
|
namespace App\Models\Contact;
|
||||||
|
|
||||||
use App\Models\BaseModel;
|
use App\Models\BaseModel;
|
||||||
|
|
||||||
class ContactDetailModel extends BaseModel {
|
class ContactDetailModel extends BaseModel {
|
||||||
protected $table = 'contactdetail';
|
protected $table = 'contactdetail';
|
||||||
protected $primaryKey = 'ContactDetID';
|
protected $primaryKey = 'ContactDetID';
|
||||||
@ -18,34 +18,34 @@ class ContactDetailModel extends BaseModel {
|
|||||||
public function syncDetails(int $ContactID, array $contactDetails) {
|
public function syncDetails(int $ContactID, array $contactDetails) {
|
||||||
try {
|
try {
|
||||||
$keptSiteIDs = [];
|
$keptSiteIDs = [];
|
||||||
|
|
||||||
foreach ($contactDetails as $detail) {
|
foreach ($contactDetails as $detail) {
|
||||||
if (empty($detail['SiteID'])) {
|
if (empty($detail['SiteID'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$detail['ContactID'] = $ContactID;
|
$detail['ContactID'] = $ContactID;
|
||||||
|
|
||||||
$existing = $this->where('ContactID', $ContactID)
|
$existing = $this->where('ContactID', $ContactID)
|
||||||
->where('SiteID', $detail['SiteID'])
|
->where('SiteID', $detail['SiteID'])
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($existing) {
|
if ($existing) {
|
||||||
$this->update($existing[$this->primaryKey], $detail);
|
$this->update($existing[$this->primaryKey], $detail);
|
||||||
} else {
|
} else {
|
||||||
$this->insert($detail);
|
$this->insert($detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
$keptSiteIDs[] = $detail['SiteID'];
|
$keptSiteIDs[] = $detail['SiteID'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete missing rows
|
// Delete missing rows
|
||||||
if (!empty($keptSiteIDs)) {
|
if (!empty($keptSiteIDs)) {
|
||||||
$this->where('ContactID', $ContactID)
|
$this->where('ContactID', $ContactID)
|
||||||
->whereNotIn('SiteID', $keptSiteIDs)
|
->whereNotIn('SiteID', $keptSiteIDs)
|
||||||
->delete();
|
->delete();
|
||||||
} else {
|
} else {
|
||||||
$this->where('ContactID', $ContactID)->delete();
|
$this->where('ContactID', $ContactID)->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -55,10 +55,10 @@ class ContactDetailModel extends BaseModel {
|
|||||||
];
|
];
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
log_message('error', 'syncDetails error: ' . $e->getMessage());
|
log_message('error', 'syncDetails error: ' . $e->getMessage());
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,6 +113,7 @@ class ContactDetailModel extends BaseModel {
|
|||||||
|
|
||||||
$existing = $this->where('ContactDetID', (int) $detailID)
|
$existing = $this->where('ContactDetID', (int) $detailID)
|
||||||
->where('ContactID', $contactID)
|
->where('ContactID', $contactID)
|
||||||
|
->where('ContactEndDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (empty($existing)) {
|
if (empty($existing)) {
|
||||||
@ -122,13 +123,8 @@ class ContactDetailModel extends BaseModel {
|
|||||||
$updateData = array_intersect_key($detail, array_flip($this->allowedFields));
|
$updateData = array_intersect_key($detail, array_flip($this->allowedFields));
|
||||||
unset($updateData['ContactID']);
|
unset($updateData['ContactID']);
|
||||||
|
|
||||||
if ($updateData !== []) {
|
if ($updateData !== [] && !$this->update((int) $detailID, $updateData)) {
|
||||||
$db = \Config\Database::connect();
|
return false;
|
||||||
$db->table($this->table)
|
|
||||||
->where('ContactDetID', (int) $detailID)
|
|
||||||
->where('ContactID', $contactID)
|
|
||||||
->where('ContactEndDate', null)
|
|
||||||
->update($updateData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models\Organization;
|
namespace App\Models\Organization;
|
||||||
|
|
||||||
use App\Models\BaseModel;
|
use App\Models\BaseModel;
|
||||||
|
|
||||||
class CodingSysModel extends BaseModel {
|
class CodingSysModel extends BaseModel {
|
||||||
protected $table = 'codingsys';
|
protected $table = 'codingsys';
|
||||||
protected $primaryKey = 'CodingSysID';
|
protected $primaryKey = 'CodingSysID';
|
||||||
protected $allowedFields = ['CodingSysAbb', 'FullText', 'Description', 'CreateDate', 'EndDate'];
|
protected $allowedFields = ['CodingSysAbb', 'FullText', 'Description', 'CreateDate', 'EndDate'];
|
||||||
|
|
||||||
protected $useTimestamps = true;
|
protected $useTimestamps = true;
|
||||||
protected $createdField = 'CreateDate';
|
protected $createdField = 'CreateDate';
|
||||||
protected $updatedField = '';
|
protected $updatedField = '';
|
||||||
protected $useSoftDeletes = true;
|
protected $useSoftDeletes = true;
|
||||||
protected $deletedField = 'EndDate';
|
protected $deletedField = 'EndDate';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models\Organization;
|
namespace App\Models\Organization;
|
||||||
|
|
||||||
use App\Models\BaseModel;
|
use App\Models\BaseModel;
|
||||||
|
|
||||||
class HostAppModel extends BaseModel {
|
class HostAppModel extends BaseModel {
|
||||||
protected $table = 'hostapp';
|
protected $table = 'hostapp';
|
||||||
protected $primaryKey = 'HostAppID';
|
protected $primaryKey = 'HostAppID';
|
||||||
protected $allowedFields = ['HostAppName', 'SiteID', 'CreateDate', 'EndDate'];
|
protected $allowedFields = ['HostAppName', 'SiteID', 'CreateDate', 'EndDate'];
|
||||||
|
|
||||||
protected $useTimestamps = true;
|
protected $useTimestamps = true;
|
||||||
protected $createdField = 'CreateDate';
|
protected $createdField = 'CreateDate';
|
||||||
protected $updatedField = '';
|
protected $updatedField = '';
|
||||||
protected $useSoftDeletes = true;
|
protected $useSoftDeletes = true;
|
||||||
protected $deletedField = 'EndDate';
|
protected $deletedField = 'EndDate';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models\Organization;
|
namespace App\Models\Organization;
|
||||||
|
|
||||||
use App\Models\BaseModel;
|
use App\Models\BaseModel;
|
||||||
|
|
||||||
class HostComParaModel extends BaseModel {
|
class HostComParaModel extends BaseModel {
|
||||||
protected $table = 'hostcompara';
|
protected $table = 'hostcompara';
|
||||||
protected $primaryKey = 'HostAppID';
|
protected $primaryKey = 'HostAppID';
|
||||||
protected $allowedFields = ['HostAppID', 'HostIP', 'HostPort', 'HostPwd', 'CreateDate', 'EndDate'];
|
protected $allowedFields = ['HostAppID', 'HostIP', 'HostPort', 'HostPwd', 'CreateDate', 'EndDate'];
|
||||||
|
|
||||||
protected $useTimestamps = true;
|
protected $useTimestamps = true;
|
||||||
protected $createdField = 'CreateDate';
|
protected $createdField = 'CreateDate';
|
||||||
protected $updatedField = '';
|
protected $updatedField = '';
|
||||||
protected $useSoftDeletes = true;
|
protected $useSoftDeletes = true;
|
||||||
protected $deletedField = 'EndDate';
|
protected $deletedField = 'EndDate';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,138 +1,138 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models\User;
|
namespace App\Models\User;
|
||||||
|
|
||||||
use CodeIgniter\Model;
|
use CodeIgniter\Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User Model
|
* User Model
|
||||||
* Handles database operations for users
|
* Handles database operations for users
|
||||||
*/
|
*/
|
||||||
class UserModel extends Model
|
class UserModel extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'users';
|
protected $table = 'users';
|
||||||
protected $primaryKey = 'UserID';
|
protected $primaryKey = 'UserID';
|
||||||
|
|
||||||
// Allow all fields to be mass-assigned
|
// Allow all fields to be mass-assigned
|
||||||
protected $allowedFields = [
|
protected $allowedFields = [
|
||||||
'Username',
|
'Username',
|
||||||
'Email',
|
'Email',
|
||||||
'Name',
|
'Name',
|
||||||
'Role',
|
'Role',
|
||||||
'Department',
|
'Department',
|
||||||
'IsActive',
|
'IsActive',
|
||||||
'CreatedAt',
|
'CreatedAt',
|
||||||
'UpdatedAt',
|
'UpdatedAt',
|
||||||
'DelDate'
|
'DelDate'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Use timestamps (disabled, we handle manually for consistency)
|
// Use timestamps (disabled, we handle manually for consistency)
|
||||||
protected $useTimestamps = false;
|
protected $useTimestamps = false;
|
||||||
|
|
||||||
// Validation rules
|
// Validation rules
|
||||||
protected $validationRules = [
|
protected $validationRules = [
|
||||||
'Username' => 'required|min_length[3]|max_length[50]',
|
'Username' => 'required|min_length[3]|max_length[50]',
|
||||||
'Email' => 'required|valid_email|max_length[100]',
|
'Email' => 'required|valid_email|max_length[100]',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $validationMessages = [
|
protected $validationMessages = [
|
||||||
'Username' => [
|
'Username' => [
|
||||||
'required' => 'Username is required',
|
'required' => 'Username is required',
|
||||||
'min_length' => 'Username must be at least 3 characters',
|
'min_length' => 'Username must be at least 3 characters',
|
||||||
'max_length' => 'Username cannot exceed 50 characters',
|
'max_length' => 'Username cannot exceed 50 characters',
|
||||||
],
|
],
|
||||||
'Email' => [
|
'Email' => [
|
||||||
'required' => 'Email is required',
|
'required' => 'Email is required',
|
||||||
'valid_email' => 'Please provide a valid email address',
|
'valid_email' => 'Please provide a valid email address',
|
||||||
'max_length' => 'Email cannot exceed 100 characters',
|
'max_length' => 'Email cannot exceed 100 characters',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get active users only
|
* Get active users only
|
||||||
*/
|
*/
|
||||||
public function getActive()
|
public function getActive()
|
||||||
{
|
{
|
||||||
return $this->where('DelDate', null)
|
return $this->where('DelDate', null)
|
||||||
->where('IsActive', true)
|
->where('IsActive', true)
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find user by username
|
* Find user by username
|
||||||
*/
|
*/
|
||||||
public function findByUsername($username)
|
public function findByUsername($username)
|
||||||
{
|
{
|
||||||
return $this->where('Username', $username)
|
return $this->where('Username', $username)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->first();
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find user by email
|
* Find user by email
|
||||||
*/
|
*/
|
||||||
public function findByEmail($email)
|
public function findByEmail($email)
|
||||||
{
|
{
|
||||||
return $this->where('Email', $email)
|
return $this->where('Email', $email)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->first();
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search users by name, username, or email
|
* Search users by name, username, or email
|
||||||
*/
|
*/
|
||||||
public function search($term)
|
public function search($term)
|
||||||
{
|
{
|
||||||
return $this->where('DelDate', null)
|
return $this->where('DelDate', null)
|
||||||
->groupStart()
|
->groupStart()
|
||||||
->like('Username', $term)
|
->like('Username', $term)
|
||||||
->orLike('Email', $term)
|
->orLike('Email', $term)
|
||||||
->orLike('Name', $term)
|
->orLike('Name', $term)
|
||||||
->groupEnd()
|
->groupEnd()
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get users by role
|
* Get users by role
|
||||||
*/
|
*/
|
||||||
public function getByRole($role)
|
public function getByRole($role)
|
||||||
{
|
{
|
||||||
return $this->where('Role', $role)
|
return $this->where('Role', $role)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->where('IsActive', true)
|
->where('IsActive', true)
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get users by department
|
* Get users by department
|
||||||
*/
|
*/
|
||||||
public function getByDepartment($department)
|
public function getByDepartment($department)
|
||||||
{
|
{
|
||||||
return $this->where('Department', $department)
|
return $this->where('Department', $department)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->where('IsActive', true)
|
->where('IsActive', true)
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Soft delete user
|
* Soft delete user
|
||||||
*/
|
*/
|
||||||
public function softDelete($id)
|
public function softDelete($id)
|
||||||
{
|
{
|
||||||
return $this->update($id, [
|
return $this->update($id, [
|
||||||
'DelDate' => date('Y-m-d H:i:s'),
|
'DelDate' => date('Y-m-d H:i:s'),
|
||||||
'IsActive' => false
|
'IsActive' => false
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore soft-deleted user
|
* Restore soft-deleted user
|
||||||
*/
|
*/
|
||||||
public function restore($id)
|
public function restore($id)
|
||||||
{
|
{
|
||||||
return $this->update($id, [
|
return $this->update($id, [
|
||||||
'DelDate' => null,
|
'DelDate' => null,
|
||||||
'IsActive' => true
|
'IsActive' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,179 +1,179 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use CodeIgniter\Database\BaseConnection;
|
use CodeIgniter\Database\BaseConnection;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class AuditLogService
|
class AuditLogService
|
||||||
{
|
{
|
||||||
private const TABLE_MAP = [
|
private const TABLE_MAP = [
|
||||||
'logpatient' => 'logpatient',
|
'logpatient' => 'logpatient',
|
||||||
'patient' => 'logpatient',
|
'patient' => 'logpatient',
|
||||||
'visit' => 'logpatient',
|
'visit' => 'logpatient',
|
||||||
'logorder' => 'logorder',
|
'logorder' => 'logorder',
|
||||||
'order' => 'logorder',
|
'order' => 'logorder',
|
||||||
'specimen' => 'logorder',
|
'specimen' => 'logorder',
|
||||||
'result' => 'logorder',
|
'result' => 'logorder',
|
||||||
'logmaster' => 'logmaster',
|
'logmaster' => 'logmaster',
|
||||||
'master' => 'logmaster',
|
'master' => 'logmaster',
|
||||||
'config' => 'logmaster',
|
'config' => 'logmaster',
|
||||||
'valueset' => 'logmaster',
|
'valueset' => 'logmaster',
|
||||||
'logsystem' => 'logsystem',
|
'logsystem' => 'logsystem',
|
||||||
'system' => 'logsystem',
|
'system' => 'logsystem',
|
||||||
'auth' => 'logsystem',
|
'auth' => 'logsystem',
|
||||||
'job' => 'logsystem',
|
'job' => 'logsystem',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const PRIMARY_KEYS = [
|
private const PRIMARY_KEYS = [
|
||||||
'logpatient' => 'LogPatientID',
|
'logpatient' => 'LogPatientID',
|
||||||
'logorder' => 'LogOrderID',
|
'logorder' => 'LogOrderID',
|
||||||
'logmaster' => 'LogMasterID',
|
'logmaster' => 'LogMasterID',
|
||||||
'logsystem' => 'LogSystemID',
|
'logsystem' => 'LogSystemID',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const DEFAULT_PAGE = 1;
|
private const DEFAULT_PAGE = 1;
|
||||||
private const DEFAULT_PER_PAGE = 20;
|
private const DEFAULT_PER_PAGE = 20;
|
||||||
private const MAX_PER_PAGE = 100;
|
private const MAX_PER_PAGE = 100;
|
||||||
|
|
||||||
private static ?BaseConnection $db = null;
|
private static ?BaseConnection $db = null;
|
||||||
|
|
||||||
public function fetchLogs(array $filters): array
|
public function fetchLogs(array $filters): array
|
||||||
{
|
{
|
||||||
$tableKey = $filters['table'] ?? null;
|
$tableKey = $filters['table'] ?? null;
|
||||||
if (empty($tableKey)) {
|
if (empty($tableKey)) {
|
||||||
throw new InvalidArgumentException('table parameter is required');
|
throw new InvalidArgumentException('table parameter is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
$logTable = $this->resolveLogTable($tableKey);
|
$logTable = $this->resolveLogTable($tableKey);
|
||||||
if ($logTable === null) {
|
if ($logTable === null) {
|
||||||
throw new InvalidArgumentException("Unknown audit table: {$tableKey}");
|
throw new InvalidArgumentException("Unknown audit table: {$tableKey}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$builder = $this->getDb()->table($logTable);
|
$builder = $this->getDb()->table($logTable);
|
||||||
|
|
||||||
$this->applyFilters($builder, $filters);
|
$this->applyFilters($builder, $filters);
|
||||||
|
|
||||||
$total = (int) $builder->countAllResults(false);
|
$total = (int) $builder->countAllResults(false);
|
||||||
|
|
||||||
$page = $this->normalizePage($filters['page'] ?? null);
|
$page = $this->normalizePage($filters['page'] ?? null);
|
||||||
$perPage = $this->normalizePerPage($filters['perPage'] ?? $filters['per_page'] ?? null);
|
$perPage = $this->normalizePerPage($filters['perPage'] ?? $filters['per_page'] ?? null);
|
||||||
$offset = ($page - 1) * $perPage;
|
$offset = ($page - 1) * $perPage;
|
||||||
|
|
||||||
$builder->orderBy('LogDate', 'DESC');
|
$builder->orderBy('LogDate', 'DESC');
|
||||||
$builder->orderBy($this->getPrimaryKey($logTable), 'DESC');
|
$builder->orderBy($this->getPrimaryKey($logTable), 'DESC');
|
||||||
|
|
||||||
$rows = $builder
|
$rows = $builder
|
||||||
->limit($perPage, $offset)
|
->limit($perPage, $offset)
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'data' => $rows,
|
'data' => $rows,
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
'perPage' => $perPage,
|
'perPage' => $perPage,
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applyFilters($builder, array $filters): void
|
private function applyFilters($builder, array $filters): void
|
||||||
{
|
{
|
||||||
if (!empty($filters['rec_id'])) {
|
if (!empty($filters['rec_id'])) {
|
||||||
$builder->where('RecID', (string) $filters['rec_id']);
|
$builder->where('RecID', (string) $filters['rec_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($filters['event_id'])) {
|
if (!empty($filters['event_id'])) {
|
||||||
$builder->where('EventID', $this->normalizeCode($filters['event_id']));
|
$builder->where('EventID', $this->normalizeCode($filters['event_id']));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($filters['activity_id'])) {
|
if (!empty($filters['activity_id'])) {
|
||||||
$builder->where('ActivityID', $this->normalizeCode($filters['activity_id']));
|
$builder->where('ActivityID', $this->normalizeCode($filters['activity_id']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->applyDateRange($builder, $filters['from'] ?? null, $filters['to'] ?? null);
|
$this->applyDateRange($builder, $filters['from'] ?? null, $filters['to'] ?? null);
|
||||||
|
|
||||||
if (!empty($filters['search'])) {
|
if (!empty($filters['search'])) {
|
||||||
$search = trim($filters['search']);
|
$search = trim($filters['search']);
|
||||||
if ($search !== '') {
|
if ($search !== '') {
|
||||||
$builder->groupStart();
|
$builder->groupStart();
|
||||||
$builder->like('UserID', $search);
|
$builder->like('UserID', $search);
|
||||||
$builder->orLike('Reason', $search);
|
$builder->orLike('Reason', $search);
|
||||||
$builder->orLike('FldName', $search);
|
$builder->orLike('FldName', $search);
|
||||||
$builder->orLike('FldValuePrev', $search);
|
$builder->orLike('FldValuePrev', $search);
|
||||||
$builder->orLike('FldValueNew', $search);
|
$builder->orLike('FldValueNew', $search);
|
||||||
$builder->orLike('EventID', $search);
|
$builder->orLike('EventID', $search);
|
||||||
$builder->orLike('ActivityID', $search);
|
$builder->orLike('ActivityID', $search);
|
||||||
$builder->groupEnd();
|
$builder->groupEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applyDateRange($builder, ?string $from, ?string $to): void
|
private function applyDateRange($builder, ?string $from, ?string $to): void
|
||||||
{
|
{
|
||||||
if ($from !== null && trim($from) !== '') {
|
if ($from !== null && trim($from) !== '') {
|
||||||
$builder->where('LogDate >=', $this->normalizeDate($from));
|
$builder->where('LogDate >=', $this->normalizeDate($from));
|
||||||
}
|
}
|
||||||
if ($to !== null && trim($to) !== '') {
|
if ($to !== null && trim($to) !== '') {
|
||||||
$builder->where('LogDate <=', $this->normalizeDate($to));
|
$builder->where('LogDate <=', $this->normalizeDate($to));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizeDate(string $value): string
|
private function normalizeDate(string $value): string
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$dt = new DateTime($value, new DateTimeZone('UTC'));
|
$dt = new DateTime($value, new DateTimeZone('UTC'));
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
throw new InvalidArgumentException('Invalid date: ' . $value);
|
throw new InvalidArgumentException('Invalid date: ' . $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $dt->format('Y-m-d H:i:s');
|
return $dt->format('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizeCode(string $value): string
|
private function normalizeCode(string $value): string
|
||||||
{
|
{
|
||||||
return strtoupper(trim($value));
|
return strtoupper(trim($value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizePage($value): int
|
private function normalizePage($value): int
|
||||||
{
|
{
|
||||||
$page = (int) ($value ?? self::DEFAULT_PAGE);
|
$page = (int) ($value ?? self::DEFAULT_PAGE);
|
||||||
return $page < 1 ? self::DEFAULT_PAGE : $page;
|
return $page < 1 ? self::DEFAULT_PAGE : $page;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizePerPage($value): int
|
private function normalizePerPage($value): int
|
||||||
{
|
{
|
||||||
$perPage = (int) ($value ?? self::DEFAULT_PER_PAGE);
|
$perPage = (int) ($value ?? self::DEFAULT_PER_PAGE);
|
||||||
if ($perPage < 1) {
|
if ($perPage < 1) {
|
||||||
return self::DEFAULT_PER_PAGE;
|
return self::DEFAULT_PER_PAGE;
|
||||||
}
|
}
|
||||||
if ($perPage > self::MAX_PER_PAGE) {
|
if ($perPage > self::MAX_PER_PAGE) {
|
||||||
throw new InvalidArgumentException('perPage cannot be greater than ' . self::MAX_PER_PAGE);
|
throw new InvalidArgumentException('perPage cannot be greater than ' . self::MAX_PER_PAGE);
|
||||||
}
|
}
|
||||||
return $perPage;
|
return $perPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveLogTable(?string $key): ?string
|
private function resolveLogTable(?string $key): ?string
|
||||||
{
|
{
|
||||||
if ($key === null) {
|
if ($key === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$lookup = strtolower(trim($key));
|
$lookup = strtolower(trim($key));
|
||||||
return self::TABLE_MAP[$lookup] ?? null;
|
return self::TABLE_MAP[$lookup] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getPrimaryKey(string $table): string
|
private function getPrimaryKey(string $table): string
|
||||||
{
|
{
|
||||||
return self::PRIMARY_KEYS[$table] ?? 'LogID';
|
return self::PRIMARY_KEYS[$table] ?? 'LogID';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getDb(): BaseConnection
|
private function getDb(): BaseConnection
|
||||||
{
|
{
|
||||||
return self::$db ??= \Config\Database::connect();
|
return self::$db ??= \Config\Database::connect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,346 +1,346 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Libraries\ValueSet;
|
use App\Libraries\ValueSet;
|
||||||
use CodeIgniter\Database\BaseConnection;
|
use CodeIgniter\Database\BaseConnection;
|
||||||
use CodeIgniter\HTTP\IncomingRequest;
|
use CodeIgniter\HTTP\IncomingRequest;
|
||||||
use Config\Services;
|
use Config\Services;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
|
|
||||||
class AuditService
|
class AuditService
|
||||||
{
|
{
|
||||||
private const TABLE_MAP = [
|
private const TABLE_MAP = [
|
||||||
'logpatient' => 'logpatient',
|
'logpatient' => 'logpatient',
|
||||||
'patient' => 'logpatient',
|
'patient' => 'logpatient',
|
||||||
'visit' => 'logpatient',
|
'visit' => 'logpatient',
|
||||||
'logorder' => 'logorder',
|
'logorder' => 'logorder',
|
||||||
'order' => 'logorder',
|
'order' => 'logorder',
|
||||||
'specimen' => 'logorder',
|
'specimen' => 'logorder',
|
||||||
'result' => 'logorder',
|
'result' => 'logorder',
|
||||||
'logmaster' => 'logmaster',
|
'logmaster' => 'logmaster',
|
||||||
'master' => 'logmaster',
|
'master' => 'logmaster',
|
||||||
'config' => 'logmaster',
|
'config' => 'logmaster',
|
||||||
'valueset' => 'logmaster',
|
'valueset' => 'logmaster',
|
||||||
'logsystem' => 'logsystem',
|
'logsystem' => 'logsystem',
|
||||||
'system' => 'logsystem',
|
'system' => 'logsystem',
|
||||||
'auth' => 'logsystem',
|
'auth' => 'logsystem',
|
||||||
'job' => 'logsystem',
|
'job' => 'logsystem',
|
||||||
];
|
];
|
||||||
|
|
||||||
private const DEFAULT_APP_ID = 'clqms-api';
|
private const DEFAULT_APP_ID = 'clqms-api';
|
||||||
private const ENTITY_VERSION_DEFAULT = 1;
|
private const ENTITY_VERSION_DEFAULT = 1;
|
||||||
|
|
||||||
private static ?BaseConnection $db = null;
|
private static ?BaseConnection $db = null;
|
||||||
private static $session = null;
|
private static $session = null;
|
||||||
private static ?IncomingRequest $request = null;
|
private static ?IncomingRequest $request = null;
|
||||||
private static ?array $eventIdCache = null;
|
private static ?array $eventIdCache = null;
|
||||||
private static ?string $cachedRequestId = null;
|
private static ?string $cachedRequestId = null;
|
||||||
|
|
||||||
public static function logData(
|
public static function logData(
|
||||||
string $eventId,
|
string $eventId,
|
||||||
string $activityId,
|
string $activityId,
|
||||||
string $entityType,
|
string $entityType,
|
||||||
string $entityId,
|
string $entityId,
|
||||||
string $tableName,
|
string $tableName,
|
||||||
?string $fldName = null,
|
?string $fldName = null,
|
||||||
$previousValue = null,
|
$previousValue = null,
|
||||||
$newValue = null,
|
$newValue = null,
|
||||||
?string $reason = null,
|
?string $reason = null,
|
||||||
?array $context = null,
|
?array $context = null,
|
||||||
array $options = []
|
array $options = []
|
||||||
): void {
|
): void {
|
||||||
$sourceTable = $tableName ?: $entityType;
|
$sourceTable = $tableName ?: $entityType;
|
||||||
$logTable = self::resolveLogTable($sourceTable);
|
$logTable = self::resolveLogTable($sourceTable);
|
||||||
if ($logTable === null) {
|
if ($logTable === null) {
|
||||||
log_message('warning', "AuditService cannot resolve log table for {$sourceTable}");
|
log_message('warning', "AuditService cannot resolve log table for {$sourceTable}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$record = self::buildRecord(
|
$record = self::buildRecord(
|
||||||
$logTable,
|
$logTable,
|
||||||
self::normalizeEventId($eventId),
|
self::normalizeEventId($eventId),
|
||||||
strtoupper($activityId),
|
strtoupper($activityId),
|
||||||
$entityType,
|
$entityType,
|
||||||
$entityId,
|
$entityId,
|
||||||
$sourceTable,
|
$sourceTable,
|
||||||
$fldName,
|
$fldName,
|
||||||
$previousValue,
|
$previousValue,
|
||||||
$newValue,
|
$newValue,
|
||||||
$reason,
|
$reason,
|
||||||
$context,
|
$context,
|
||||||
$options
|
$options
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($record === null) {
|
if ($record === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self::getDb()->table($logTable)->insert($record);
|
self::getDb()->table($logTable)->insert($record);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
log_message('error', "AuditService failed to insert into {$logTable}: {$e->getMessage()}");
|
log_message('error', "AuditService failed to insert into {$logTable}: {$e->getMessage()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function buildRecord(
|
private static function buildRecord(
|
||||||
string $logTable,
|
string $logTable,
|
||||||
string $eventId,
|
string $eventId,
|
||||||
string $activityId,
|
string $activityId,
|
||||||
string $entityType,
|
string $entityType,
|
||||||
string $entityId,
|
string $entityId,
|
||||||
string $tblName,
|
string $tblName,
|
||||||
?string $fldName,
|
?string $fldName,
|
||||||
$previousValue,
|
$previousValue,
|
||||||
$newValue,
|
$newValue,
|
||||||
?string $reason,
|
?string $reason,
|
||||||
?array $context,
|
?array $context,
|
||||||
array $options
|
array $options
|
||||||
): ?array {
|
): ?array {
|
||||||
$contextJson = self::buildContext($context, $options, $entityType);
|
$contextJson = self::buildContext($context, $options, $entityType);
|
||||||
if ($contextJson === null) {
|
if ($contextJson === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'TblName' => $tblName,
|
'TblName' => $tblName,
|
||||||
'RecID' => (string) $entityId,
|
'RecID' => (string) $entityId,
|
||||||
'FldName' => $fldName,
|
'FldName' => $fldName,
|
||||||
'FldValuePrev' => self::serializeValue($previousValue),
|
'FldValuePrev' => self::serializeValue($previousValue),
|
||||||
'FldValueNew' => self::serializeValue($newValue),
|
'FldValueNew' => self::serializeValue($newValue),
|
||||||
'UserID' => self::resolveUserId($options),
|
'UserID' => self::resolveUserId($options),
|
||||||
'SiteID' => self::resolveSiteId($options),
|
'SiteID' => self::resolveSiteId($options),
|
||||||
'DIDType' => $options['did_type'] ?? null,
|
'DIDType' => $options['did_type'] ?? null,
|
||||||
'DID' => $options['did'] ?? null,
|
'DID' => $options['did'] ?? null,
|
||||||
'MachineID' => $options['machine_id'] ?? gethostname(),
|
'MachineID' => $options['machine_id'] ?? gethostname(),
|
||||||
'SessionID' => self::resolveSessionId($options),
|
'SessionID' => self::resolveSessionId($options),
|
||||||
'AppID' => $options['app_id'] ?? self::DEFAULT_APP_ID,
|
'AppID' => $options['app_id'] ?? self::DEFAULT_APP_ID,
|
||||||
'ProcessID' => $options['process_id'] ?? null,
|
'ProcessID' => $options['process_id'] ?? null,
|
||||||
'WebPageID' => $options['web_page_id'] ?? self::resolveRoute($options),
|
'WebPageID' => $options['web_page_id'] ?? self::resolveRoute($options),
|
||||||
'EventID' => $eventId,
|
'EventID' => $eventId,
|
||||||
'ActivityID' => $activityId,
|
'ActivityID' => $activityId,
|
||||||
'Reason' => $reason,
|
'Reason' => $reason,
|
||||||
'LogDate' => self::nowWithMillis(),
|
'LogDate' => self::nowWithMillis(),
|
||||||
'Context' => $contextJson,
|
'Context' => $contextJson,
|
||||||
'IpAddress' => self::resolveIpAddress(),
|
'IpAddress' => self::resolveIpAddress(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function serializeValue($value): ?string
|
private static function serializeValue($value): ?string
|
||||||
{
|
{
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_scalar($value)) {
|
if (is_scalar($value)) {
|
||||||
return (string) $value;
|
return (string) $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
$json = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
return $json !== false ? $json : null;
|
return $json !== false ? $json : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function buildContext(?array $context, array $options, string $entityType): ?string
|
private static function buildContext(?array $context, array $options, string $entityType): ?string
|
||||||
{
|
{
|
||||||
$route = $options['route'] ?? self::resolveRoute($options);
|
$route = $options['route'] ?? self::resolveRoute($options);
|
||||||
$payload = array_merge(
|
$payload = array_merge(
|
||||||
[
|
[
|
||||||
'request_id' => $options['request_id'] ?? self::resolveRequestId(),
|
'request_id' => $options['request_id'] ?? self::resolveRequestId(),
|
||||||
'route' => $route,
|
'route' => $route,
|
||||||
'timestamp_utc' => $options['timestamp_utc'] ?? self::timestampUtc(),
|
'timestamp_utc' => $options['timestamp_utc'] ?? self::timestampUtc(),
|
||||||
'entity_type' => $options['entity_type'] ?? $entityType,
|
'entity_type' => $options['entity_type'] ?? $entityType,
|
||||||
'entity_version' => $options['entity_version'] ?? self::ENTITY_VERSION_DEFAULT,
|
'entity_version' => $options['entity_version'] ?? self::ENTITY_VERSION_DEFAULT,
|
||||||
],
|
],
|
||||||
$context ?? []
|
$context ?? []
|
||||||
);
|
);
|
||||||
|
|
||||||
$json = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
$json = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
return $json !== false ? $json : null;
|
return $json !== false ? $json : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveLogTable(?string $source): ?string
|
private static function resolveLogTable(?string $source): ?string
|
||||||
{
|
{
|
||||||
if ($source === null) {
|
if ($source === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$key = strtolower(trim($source));
|
$key = strtolower(trim($source));
|
||||||
return self::TABLE_MAP[$key] ?? null;
|
return self::TABLE_MAP[$key] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveUserId(array $options): string
|
private static function resolveUserId(array $options): string
|
||||||
{
|
{
|
||||||
return $options['user_id'] ?? self::getSessionValue('user_id') ?? 'SYSTEM';
|
return $options['user_id'] ?? self::getSessionValue('user_id') ?? 'SYSTEM';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveSiteId(array $options): string
|
private static function resolveSiteId(array $options): string
|
||||||
{
|
{
|
||||||
return $options['site_id'] ?? self::getSessionValue('site_id') ?? 'GLOBAL';
|
return $options['site_id'] ?? self::getSessionValue('site_id') ?? 'GLOBAL';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveSessionId(array $options): string
|
private static function resolveSessionId(array $options): string
|
||||||
{
|
{
|
||||||
if (!empty($options['session_id'])) {
|
if (!empty($options['session_id'])) {
|
||||||
return $options['session_id'];
|
return $options['session_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$session = self::getSession();
|
$session = self::getSession();
|
||||||
if ($session !== null && method_exists($session, 'getId')) {
|
if ($session !== null && method_exists($session, 'getId')) {
|
||||||
$id = $session->getId();
|
$id = $session->getId();
|
||||||
if (!empty($id)) {
|
if (!empty($id)) {
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||||
$id = session_id();
|
$id = session_id();
|
||||||
if (!empty($id)) {
|
if (!empty($id)) {
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::generateUniqueId('sess');
|
return self::generateUniqueId('sess');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveRoute(array $options): string
|
private static function resolveRoute(array $options): string
|
||||||
{
|
{
|
||||||
if (!empty($options['route'])) {
|
if (!empty($options['route'])) {
|
||||||
return $options['route'];
|
return $options['route'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = self::getRequest();
|
$request = self::getRequest();
|
||||||
if ($request !== null) {
|
if ($request !== null) {
|
||||||
return trim(sprintf('%s %s', $request->getMethod(), $request->getUri()->getPath()));
|
return trim(sprintf('%s %s', $request->getMethod(), $request->getUri()->getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'cli';
|
return 'cli';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveIpAddress(): ?string
|
private static function resolveIpAddress(): ?string
|
||||||
{
|
{
|
||||||
$request = self::getRequest();
|
$request = self::getRequest();
|
||||||
if ($request !== null) {
|
if ($request !== null) {
|
||||||
return $request->getIPAddress();
|
return $request->getIPAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $_SERVER['REMOTE_ADDR'] ?? null;
|
return $_SERVER['REMOTE_ADDR'] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function normalizeEventId(string $eventId): string
|
private static function normalizeEventId(string $eventId): string
|
||||||
{
|
{
|
||||||
$normalized = strtoupper(trim($eventId));
|
$normalized = strtoupper(trim($eventId));
|
||||||
if (empty($normalized)) {
|
if (empty($normalized)) {
|
||||||
log_message('warning', 'AuditService received empty EventID');
|
log_message('warning', 'AuditService received empty EventID');
|
||||||
return $eventId;
|
return $eventId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self::isKnownEvent($normalized)) {
|
if (!self::isKnownEvent($normalized)) {
|
||||||
log_message('warning', "AuditService unknown EventID: {$normalized}");
|
log_message('warning', "AuditService unknown EventID: {$normalized}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $normalized;
|
return $normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function isKnownEvent(string $eventId): bool
|
private static function isKnownEvent(string $eventId): bool
|
||||||
{
|
{
|
||||||
if (self::$eventIdCache === null) {
|
if (self::$eventIdCache === null) {
|
||||||
$raw = ValueSet::getRaw('event_id') ?? [];
|
$raw = ValueSet::getRaw('event_id') ?? [];
|
||||||
self::$eventIdCache = array_filter(array_map(fn ($item) => $item['key'] ?? null, $raw));
|
self::$eventIdCache = array_filter(array_map(fn ($item) => $item['key'] ?? null, $raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
return in_array($eventId, self::$eventIdCache, true);
|
return in_array($eventId, self::$eventIdCache, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function resolveRequestId(): string
|
private static function resolveRequestId(): string
|
||||||
{
|
{
|
||||||
if (self::$cachedRequestId !== null) {
|
if (self::$cachedRequestId !== null) {
|
||||||
return self::$cachedRequestId;
|
return self::$cachedRequestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = self::getRequest();
|
$request = self::getRequest();
|
||||||
if ($request !== null) {
|
if ($request !== null) {
|
||||||
$value = $request->getHeaderLine('X-Request-ID');
|
$value = $request->getHeaderLine('X-Request-ID');
|
||||||
if (!empty($value)) {
|
if (!empty($value)) {
|
||||||
self::$cachedRequestId = $value;
|
self::$cachedRequestId = $value;
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (['HTTP_X_REQUEST_ID', 'REQUEST_ID'] as $header) {
|
foreach (['HTTP_X_REQUEST_ID', 'REQUEST_ID'] as $header) {
|
||||||
if (!empty($_SERVER[$header])) {
|
if (!empty($_SERVER[$header])) {
|
||||||
self::$cachedRequestId = $_SERVER[$header];
|
self::$cachedRequestId = $_SERVER[$header];
|
||||||
return self::$cachedRequestId;
|
return self::$cachedRequestId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$cachedRequestId = self::generateUniqueId('req');
|
return self::$cachedRequestId = self::generateUniqueId('req');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function nowWithMillis(): string
|
private static function nowWithMillis(): string
|
||||||
{
|
{
|
||||||
$dt = new DateTime('now', new DateTimeZone('UTC'));
|
$dt = new DateTime('now', new DateTimeZone('UTC'));
|
||||||
return $dt->format('Y-m-d H:i:s.v');
|
return $dt->format('Y-m-d H:i:s.v');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function timestampUtc(): string
|
private static function timestampUtc(): string
|
||||||
{
|
{
|
||||||
$dt = new DateTime('now', new DateTimeZone('UTC'));
|
$dt = new DateTime('now', new DateTimeZone('UTC'));
|
||||||
return $dt->format('Y-m-d\TH:i:s.v\Z');
|
return $dt->format('Y-m-d\TH:i:s.v\Z');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getSessionValue(string $key): ?string
|
private static function getSessionValue(string $key): ?string
|
||||||
{
|
{
|
||||||
$session = self::getSession();
|
$session = self::getSession();
|
||||||
if ($session === null) {
|
if ($session === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!method_exists($session, 'get')) {
|
if (!method_exists($session, 'get')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $session->get($key);
|
$value = $session->get($key);
|
||||||
return $value !== null ? (string) $value : null;
|
return $value !== null ? (string) $value : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getSession(): ?object
|
private static function getSession(): ?object
|
||||||
{
|
{
|
||||||
if (self::$session !== null) {
|
if (self::$session !== null) {
|
||||||
return self::$session;
|
return self::$session;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return self::$session = Services::session();
|
return self::$session = Services::session();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return self::$session = null;
|
return self::$session = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getRequest(): ?IncomingRequest
|
private static function getRequest(): ?IncomingRequest
|
||||||
{
|
{
|
||||||
if (self::$request !== null) {
|
if (self::$request !== null) {
|
||||||
return self::$request;
|
return self::$request;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return self::$request = Services::request();
|
return self::$request = Services::request();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return self::$request = null;
|
return self::$request = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getDb(): BaseConnection
|
private static function getDb(): BaseConnection
|
||||||
{
|
{
|
||||||
return self::$db ??= \Config\Database::connect();
|
return self::$db ??= \Config\Database::connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function generateUniqueId(string $prefix): string
|
private static function generateUniqueId(string $prefix): string
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $prefix . '_' . bin2hex(random_bytes(8));
|
return $prefix . '_' . bin2hex(random_bytes(8));
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return uniqid("{$prefix}_", true);
|
return uniqid("{$prefix}_", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,389 +1,389 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Models\Rule\RuleDefModel;
|
use App\Models\Rule\RuleDefModel;
|
||||||
use App\Models\Test\TestDefSiteModel;
|
use App\Models\Test\TestDefSiteModel;
|
||||||
|
|
||||||
class RuleEngineService
|
class RuleEngineService
|
||||||
{
|
{
|
||||||
protected RuleDefModel $ruleDefModel;
|
protected RuleDefModel $ruleDefModel;
|
||||||
protected RuleExpressionService $expr;
|
protected RuleExpressionService $expr;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->ruleDefModel = new RuleDefModel();
|
$this->ruleDefModel = new RuleDefModel();
|
||||||
$this->expr = new RuleExpressionService();
|
$this->expr = new RuleExpressionService();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run rules for an event.
|
* Run rules for an event.
|
||||||
*
|
*
|
||||||
* Expected context keys:
|
* Expected context keys:
|
||||||
* - order: array (must include InternalOID)
|
* - order: array (must include InternalOID)
|
||||||
* - patient: array (optional, includes Sex, Age, etc.)
|
* - patient: array (optional, includes Sex, Age, etc.)
|
||||||
* - tests: array (optional, patres rows)
|
* - tests: array (optional, patres rows)
|
||||||
*
|
*
|
||||||
* @param string $eventCode The event that triggered rule execution
|
* @param string $eventCode The event that triggered rule execution
|
||||||
* @param array $context Context data for rule evaluation
|
* @param array $context Context data for rule evaluation
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function run(string $eventCode, array $context = []): void
|
public function run(string $eventCode, array $context = []): void
|
||||||
{
|
{
|
||||||
$order = $context['order'] ?? null;
|
$order = $context['order'] ?? null;
|
||||||
$testSiteID = $context['testSiteID'] ?? null;
|
$testSiteID = $context['testSiteID'] ?? null;
|
||||||
|
|
||||||
if (is_array($order) && isset($order['TestSiteID']) && $testSiteID === null) {
|
if (is_array($order) && isset($order['TestSiteID']) && $testSiteID === null) {
|
||||||
$testSiteID = is_numeric($order['TestSiteID']) ? (int) $order['TestSiteID'] : null;
|
$testSiteID = is_numeric($order['TestSiteID']) ? (int) $order['TestSiteID'] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rules = $this->ruleDefModel->getActiveByEvent($eventCode, $testSiteID);
|
$rules = $this->ruleDefModel->getActiveByEvent($eventCode, $testSiteID);
|
||||||
if (empty($rules)) {
|
if (empty($rules)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($rules as $rule) {
|
foreach ($rules as $rule) {
|
||||||
$rid = (int) ($rule['RuleID'] ?? 0);
|
$rid = (int) ($rule['RuleID'] ?? 0);
|
||||||
if ($rid === 0) {
|
if ($rid === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Rules must have compiled expressions
|
// Rules must have compiled expressions
|
||||||
$compiled = null;
|
$compiled = null;
|
||||||
if (!empty($rule['ConditionExprCompiled'])) {
|
if (!empty($rule['ConditionExprCompiled'])) {
|
||||||
$compiled = json_decode($rule['ConditionExprCompiled'], true);
|
$compiled = json_decode($rule['ConditionExprCompiled'], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($compiled) || !is_array($compiled)) {
|
if (empty($compiled) || !is_array($compiled)) {
|
||||||
log_message('warning', 'Rule ' . $rid . ' has no compiled expression, skipping');
|
log_message('warning', 'Rule ' . $rid . ' has no compiled expression, skipping');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate condition
|
// Evaluate condition
|
||||||
$conditionExpr = $compiled['conditionExpr'] ?? 'true';
|
$conditionExpr = $compiled['conditionExpr'] ?? 'true';
|
||||||
$matches = $this->evaluateCondition($conditionExpr, $context);
|
$matches = $this->evaluateCondition($conditionExpr, $context);
|
||||||
|
|
||||||
if (!$matches) {
|
if (!$matches) {
|
||||||
// Execute else actions
|
// Execute else actions
|
||||||
$actions = $compiled['else'] ?? [];
|
$actions = $compiled['else'] ?? [];
|
||||||
} else {
|
} else {
|
||||||
// Execute then actions
|
// Execute then actions
|
||||||
$actions = $compiled['then'] ?? [];
|
$actions = $compiled['then'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute all actions
|
// Execute all actions
|
||||||
foreach ($actions as $action) {
|
foreach ($actions as $action) {
|
||||||
$this->executeAction($action, $context);
|
$this->executeAction($action, $context);
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
log_message('error', 'Rule engine error (RuleID=' . $rid . '): ' . $e->getMessage());
|
log_message('error', 'Rule engine error (RuleID=' . $rid . '): ' . $e->getMessage());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate a condition expression
|
* Evaluate a condition expression
|
||||||
* Handles special functions like requested() by querying the database
|
* Handles special functions like requested() by querying the database
|
||||||
*/
|
*/
|
||||||
private function evaluateCondition(string $conditionExpr, array $context): bool
|
private function evaluateCondition(string $conditionExpr, array $context): bool
|
||||||
{
|
{
|
||||||
// Handle requested() function(s) by querying database
|
// Handle requested() function(s) by querying database
|
||||||
$conditionExpr = preg_replace_callback(
|
$conditionExpr = preg_replace_callback(
|
||||||
'/requested\s*\(\s*["\']([^"\']+)["\']\s*\)/i',
|
'/requested\s*\(\s*["\']([^"\']+)["\']\s*\)/i',
|
||||||
function (array $m) use ($context) {
|
function (array $m) use ($context) {
|
||||||
$testCode = $m[1] ?? '';
|
$testCode = $m[1] ?? '';
|
||||||
if ($testCode === '') {
|
if ($testCode === '') {
|
||||||
return 'false';
|
return 'false';
|
||||||
}
|
}
|
||||||
return $this->isTestRequested($testCode, $context) ? 'true' : 'false';
|
return $this->isTestRequested($testCode, $context) ? 'true' : 'false';
|
||||||
},
|
},
|
||||||
$conditionExpr
|
$conditionExpr
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->expr->evaluateBoolean($conditionExpr, $context);
|
return $this->expr->evaluateBoolean($conditionExpr, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a test was requested for the current order
|
* Check if a test was requested for the current order
|
||||||
*/
|
*/
|
||||||
private function isTestRequested(string $testCode, array $context): bool
|
private function isTestRequested(string $testCode, array $context): bool
|
||||||
{
|
{
|
||||||
$order = $context['order'] ?? null;
|
$order = $context['order'] ?? null;
|
||||||
if (!is_array($order) || empty($order['InternalOID'])) {
|
if (!is_array($order) || empty($order['InternalOID'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$internalOID = (int) $order['InternalOID'];
|
$internalOID = (int) $order['InternalOID'];
|
||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
// Query patres to check if test with given code exists
|
// Query patres to check if test with given code exists
|
||||||
$result = $db->table('patres')
|
$result = $db->table('patres')
|
||||||
->select('patres.*, testdefsite.TestSiteCode')
|
->select('patres.*, testdefsite.TestSiteCode')
|
||||||
->join('testdefsite', 'testdefsite.TestSiteID = patres.TestSiteID', 'inner')
|
->join('testdefsite', 'testdefsite.TestSiteID = patres.TestSiteID', 'inner')
|
||||||
->where('patres.OrderID', $internalOID)
|
->where('patres.OrderID', $internalOID)
|
||||||
->where('testdefsite.TestSiteCode', $testCode)
|
->where('testdefsite.TestSiteCode', $testCode)
|
||||||
->where('patres.DelDate', null)
|
->where('patres.DelDate', null)
|
||||||
->where('testdefsite.EndDate', null)
|
->where('testdefsite.EndDate', null)
|
||||||
->get()
|
->get()
|
||||||
->getRow();
|
->getRow();
|
||||||
|
|
||||||
return $result !== null;
|
return $result !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute an action based on its type
|
* Execute an action based on its type
|
||||||
*/
|
*/
|
||||||
protected function executeAction(array $action, array $context): void
|
protected function executeAction(array $action, array $context): void
|
||||||
{
|
{
|
||||||
$type = strtoupper((string) ($action['type'] ?? ''));
|
$type = strtoupper((string) ($action['type'] ?? ''));
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'RESULT_SET':
|
case 'RESULT_SET':
|
||||||
case 'SET_RESULT': // legacy
|
case 'SET_RESULT': // legacy
|
||||||
$this->executeSetResult($action, $context);
|
$this->executeSetResult($action, $context);
|
||||||
break;
|
break;
|
||||||
case 'TEST_INSERT':
|
case 'TEST_INSERT':
|
||||||
case 'INSERT_TEST': // legacy
|
case 'INSERT_TEST': // legacy
|
||||||
$this->executeInsertTest($action, $context);
|
$this->executeInsertTest($action, $context);
|
||||||
break;
|
break;
|
||||||
case 'TEST_DELETE':
|
case 'TEST_DELETE':
|
||||||
$this->executeDeleteTest($action, $context);
|
$this->executeDeleteTest($action, $context);
|
||||||
break;
|
break;
|
||||||
case 'COMMENT_INSERT':
|
case 'COMMENT_INSERT':
|
||||||
case 'ADD_COMMENT': // legacy
|
case 'ADD_COMMENT': // legacy
|
||||||
$this->executeAddComment($action, $context);
|
$this->executeAddComment($action, $context);
|
||||||
break;
|
break;
|
||||||
case 'NO_OP':
|
case 'NO_OP':
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_message('warning', 'Unknown action type: ' . $type);
|
log_message('warning', 'Unknown action type: ' . $type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute SET_RESULT action
|
* Execute SET_RESULT action
|
||||||
*/
|
*/
|
||||||
protected function executeSetResult(array $action, array $context): void
|
protected function executeSetResult(array $action, array $context): void
|
||||||
{
|
{
|
||||||
$order = $context['order'] ?? null;
|
$order = $context['order'] ?? null;
|
||||||
if (!is_array($order) || empty($order['InternalOID'])) {
|
if (!is_array($order) || empty($order['InternalOID'])) {
|
||||||
throw new \Exception('SET_RESULT requires context.order.InternalOID');
|
throw new \Exception('SET_RESULT requires context.order.InternalOID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$internalOID = (int) $order['InternalOID'];
|
$internalOID = (int) $order['InternalOID'];
|
||||||
$testSiteID = $context['testSiteID'] ?? null;
|
$testSiteID = $context['testSiteID'] ?? null;
|
||||||
|
|
||||||
if ($testSiteID === null && isset($order['TestSiteID'])) {
|
if ($testSiteID === null && isset($order['TestSiteID'])) {
|
||||||
$testSiteID = is_numeric($order['TestSiteID']) ? (int) $order['TestSiteID'] : null;
|
$testSiteID = is_numeric($order['TestSiteID']) ? (int) $order['TestSiteID'] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$testCode = $action['testCode'] ?? null;
|
$testCode = $action['testCode'] ?? null;
|
||||||
if ($testCode !== null) {
|
if ($testCode !== null) {
|
||||||
$resolvedId = $this->resolveTestSiteIdByCode($testCode);
|
$resolvedId = $this->resolveTestSiteIdByCode($testCode);
|
||||||
if ($resolvedId === null) {
|
if ($resolvedId === null) {
|
||||||
throw new \Exception('SET_RESULT unknown test code: ' . $testCode);
|
throw new \Exception('SET_RESULT unknown test code: ' . $testCode);
|
||||||
}
|
}
|
||||||
$testSiteID = $resolvedId;
|
$testSiteID = $resolvedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($testSiteID === null) {
|
if ($testSiteID === null) {
|
||||||
throw new \Exception('SET_RESULT requires testSiteID');
|
throw new \Exception('SET_RESULT requires testSiteID');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value
|
// Get the value
|
||||||
if (isset($action['valueExpr']) && is_string($action['valueExpr'])) {
|
if (isset($action['valueExpr']) && is_string($action['valueExpr'])) {
|
||||||
$value = $this->expr->evaluate($action['valueExpr'], $context);
|
$value = $this->expr->evaluate($action['valueExpr'], $context);
|
||||||
} else {
|
} else {
|
||||||
$value = $action['value'] ?? null;
|
$value = $action['value'] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$testSiteCode = $testCode ?? $this->resolveTestSiteCode($testSiteID);
|
$testSiteCode = $testCode ?? $this->resolveTestSiteCode($testSiteID);
|
||||||
|
|
||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
// Check if patres row exists
|
// Check if patres row exists
|
||||||
$patres = $db->table('patres')
|
$patres = $db->table('patres')
|
||||||
->where('OrderID', $internalOID)
|
->where('OrderID', $internalOID)
|
||||||
->where('TestSiteID', $testSiteID)
|
->where('TestSiteID', $testSiteID)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->get()
|
->get()
|
||||||
->getRowArray();
|
->getRowArray();
|
||||||
|
|
||||||
if ($patres) {
|
if ($patres) {
|
||||||
// Update existing result
|
// Update existing result
|
||||||
$ok = $db->table('patres')
|
$ok = $db->table('patres')
|
||||||
->where('OrderID', $internalOID)
|
->where('OrderID', $internalOID)
|
||||||
->where('TestSiteID', $testSiteID)
|
->where('TestSiteID', $testSiteID)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->update(['Result' => $value]);
|
->update(['Result' => $value]);
|
||||||
} else {
|
} else {
|
||||||
// Insert new result row
|
// Insert new result row
|
||||||
$ok = $db->table('patres')->insert([
|
$ok = $db->table('patres')->insert([
|
||||||
'OrderID' => $internalOID,
|
'OrderID' => $internalOID,
|
||||||
'TestSiteID' => $testSiteID,
|
'TestSiteID' => $testSiteID,
|
||||||
'TestSiteCode' => $testSiteCode,
|
'TestSiteCode' => $testSiteCode,
|
||||||
'Result' => $value,
|
'Result' => $value,
|
||||||
'CreateDate' => date('Y-m-d H:i:s'),
|
'CreateDate' => date('Y-m-d H:i:s'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ok === false) {
|
if ($ok === false) {
|
||||||
throw new \Exception('SET_RESULT update/insert failed');
|
throw new \Exception('SET_RESULT update/insert failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute INSERT_TEST action - Insert a new test into patres
|
* Execute INSERT_TEST action - Insert a new test into patres
|
||||||
*/
|
*/
|
||||||
protected function executeInsertTest(array $action, array $context): void
|
protected function executeInsertTest(array $action, array $context): void
|
||||||
{
|
{
|
||||||
$order = $context['order'] ?? null;
|
$order = $context['order'] ?? null;
|
||||||
if (!is_array($order) || empty($order['InternalOID'])) {
|
if (!is_array($order) || empty($order['InternalOID'])) {
|
||||||
throw new \Exception('INSERT_TEST requires context.order.InternalOID');
|
throw new \Exception('INSERT_TEST requires context.order.InternalOID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$internalOID = (int) $order['InternalOID'];
|
$internalOID = (int) $order['InternalOID'];
|
||||||
$testCode = $action['testCode'] ?? null;
|
$testCode = $action['testCode'] ?? null;
|
||||||
|
|
||||||
if (empty($testCode)) {
|
if (empty($testCode)) {
|
||||||
throw new \Exception('INSERT_TEST requires testCode');
|
throw new \Exception('INSERT_TEST requires testCode');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up TestSiteID from TestSiteCode
|
// Look up TestSiteID from TestSiteCode
|
||||||
$testDefSiteModel = new TestDefSiteModel();
|
$testDefSiteModel = new TestDefSiteModel();
|
||||||
$testSite = $testDefSiteModel->where('TestSiteCode', $testCode)
|
$testSite = $testDefSiteModel->where('TestSiteCode', $testCode)
|
||||||
->where('EndDate', null)
|
->where('EndDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$testSite || empty($testSite['TestSiteID'])) {
|
if (!$testSite || empty($testSite['TestSiteID'])) {
|
||||||
throw new \Exception('INSERT_TEST: Test not found with code: ' . $testCode);
|
throw new \Exception('INSERT_TEST: Test not found with code: ' . $testCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
$testSiteID = (int) $testSite['TestSiteID'];
|
$testSiteID = (int) $testSite['TestSiteID'];
|
||||||
|
|
||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
// Check if test already exists (avoid duplicates)
|
// Check if test already exists (avoid duplicates)
|
||||||
$existing = $db->table('patres')
|
$existing = $db->table('patres')
|
||||||
->where('OrderID', $internalOID)
|
->where('OrderID', $internalOID)
|
||||||
->where('TestSiteID', $testSiteID)
|
->where('TestSiteID', $testSiteID)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->get()
|
->get()
|
||||||
->getRow();
|
->getRow();
|
||||||
|
|
||||||
if ($existing) {
|
if ($existing) {
|
||||||
// Test already exists, skip
|
// Test already exists, skip
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert new test row
|
// Insert new test row
|
||||||
$ok = $db->table('patres')->insert([
|
$ok = $db->table('patres')->insert([
|
||||||
'OrderID' => $internalOID,
|
'OrderID' => $internalOID,
|
||||||
'TestSiteID' => $testSiteID,
|
'TestSiteID' => $testSiteID,
|
||||||
'TestSiteCode' => $testCode,
|
'TestSiteCode' => $testCode,
|
||||||
'CreateDate' => date('Y-m-d H:i:s'),
|
'CreateDate' => date('Y-m-d H:i:s'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($ok === false) {
|
if ($ok === false) {
|
||||||
throw new \Exception('INSERT_TEST insert failed');
|
throw new \Exception('INSERT_TEST insert failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute ADD_COMMENT action - Add a comment to the order
|
* Execute ADD_COMMENT action - Add a comment to the order
|
||||||
*/
|
*/
|
||||||
protected function executeAddComment(array $action, array $context): void
|
protected function executeAddComment(array $action, array $context): void
|
||||||
{
|
{
|
||||||
$order = $context['order'] ?? null;
|
$order = $context['order'] ?? null;
|
||||||
if (!is_array($order) || empty($order['InternalOID'])) {
|
if (!is_array($order) || empty($order['InternalOID'])) {
|
||||||
throw new \Exception('ADD_COMMENT requires context.order.InternalOID');
|
throw new \Exception('ADD_COMMENT requires context.order.InternalOID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$internalOID = (int) $order['InternalOID'];
|
$internalOID = (int) $order['InternalOID'];
|
||||||
$comment = $action['comment'] ?? null;
|
$comment = $action['comment'] ?? null;
|
||||||
|
|
||||||
if (empty($comment)) {
|
if (empty($comment)) {
|
||||||
throw new \Exception('ADD_COMMENT requires comment');
|
throw new \Exception('ADD_COMMENT requires comment');
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
// Insert comment into ordercom table
|
// Insert comment into ordercom table
|
||||||
$ok = $db->table('ordercom')->insert([
|
$ok = $db->table('ordercom')->insert([
|
||||||
'InternalOID' => $internalOID,
|
'InternalOID' => $internalOID,
|
||||||
'Comment' => $comment,
|
'Comment' => $comment,
|
||||||
'CreateDate' => date('Y-m-d H:i:s'),
|
'CreateDate' => date('Y-m-d H:i:s'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($ok === false) {
|
if ($ok === false) {
|
||||||
throw new \Exception('ADD_COMMENT insert failed');
|
throw new \Exception('ADD_COMMENT insert failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute TEST_DELETE action - soft delete a test from patres
|
* Execute TEST_DELETE action - soft delete a test from patres
|
||||||
*/
|
*/
|
||||||
protected function executeDeleteTest(array $action, array $context): void
|
protected function executeDeleteTest(array $action, array $context): void
|
||||||
{
|
{
|
||||||
$order = $context['order'] ?? null;
|
$order = $context['order'] ?? null;
|
||||||
if (!is_array($order) || empty($order['InternalOID'])) {
|
if (!is_array($order) || empty($order['InternalOID'])) {
|
||||||
throw new \Exception('TEST_DELETE requires context.order.InternalOID');
|
throw new \Exception('TEST_DELETE requires context.order.InternalOID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$internalOID = (int) $order['InternalOID'];
|
$internalOID = (int) $order['InternalOID'];
|
||||||
$testCode = $action['testCode'] ?? null;
|
$testCode = $action['testCode'] ?? null;
|
||||||
if (empty($testCode)) {
|
if (empty($testCode)) {
|
||||||
throw new \Exception('TEST_DELETE requires testCode');
|
throw new \Exception('TEST_DELETE requires testCode');
|
||||||
}
|
}
|
||||||
|
|
||||||
$testDefSiteModel = new TestDefSiteModel();
|
$testDefSiteModel = new TestDefSiteModel();
|
||||||
$testSite = $testDefSiteModel->where('TestSiteCode', $testCode)
|
$testSite = $testDefSiteModel->where('TestSiteCode', $testCode)
|
||||||
->where('EndDate', null)
|
->where('EndDate', null)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (!$testSite || empty($testSite['TestSiteID'])) {
|
if (!$testSite || empty($testSite['TestSiteID'])) {
|
||||||
// Unknown test code: no-op
|
// Unknown test code: no-op
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$testSiteID = (int) $testSite['TestSiteID'];
|
$testSiteID = (int) $testSite['TestSiteID'];
|
||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
// Soft delete matching patres row(s)
|
// Soft delete matching patres row(s)
|
||||||
$db->table('patres')
|
$db->table('patres')
|
||||||
->where('OrderID', $internalOID)
|
->where('OrderID', $internalOID)
|
||||||
->where('TestSiteID', $testSiteID)
|
->where('TestSiteID', $testSiteID)
|
||||||
->where('DelDate', null)
|
->where('DelDate', null)
|
||||||
->update(['DelDate' => date('Y-m-d H:i:s')]);
|
->update(['DelDate' => date('Y-m-d H:i:s')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveTestSiteCode(int $testSiteID): ?string
|
private function resolveTestSiteCode(int $testSiteID): ?string
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$testDefSiteModel = new TestDefSiteModel();
|
$testDefSiteModel = new TestDefSiteModel();
|
||||||
$row = $testDefSiteModel->where('TestSiteID', $testSiteID)->where('EndDate', null)->first();
|
$row = $testDefSiteModel->where('TestSiteID', $testSiteID)->where('EndDate', null)->first();
|
||||||
return $row['TestSiteCode'] ?? null;
|
return $row['TestSiteCode'] ?? null;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveTestSiteIdByCode(string $testSiteCode): ?int
|
private function resolveTestSiteIdByCode(string $testSiteCode): ?int
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$testDefSiteModel = new TestDefSiteModel();
|
$testDefSiteModel = new TestDefSiteModel();
|
||||||
$row = $testDefSiteModel->where('TestSiteCode', $testSiteCode)->where('EndDate', null)->first();
|
$row = $testDefSiteModel->where('TestSiteCode', $testSiteCode)->where('EndDate', null)->first();
|
||||||
if (empty($row['TestSiteID'])) {
|
if (empty($row['TestSiteID'])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int) $row['TestSiteID'];
|
return (int) $row['TestSiteID'];
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Traits;
|
namespace App\Traits;
|
||||||
|
|
||||||
trait PatchValidationTrait {
|
trait PatchValidationTrait {
|
||||||
protected function requirePatchId(mixed $id, string $label = 'ID'): ?int {
|
protected function requirePatchId(mixed $id, string $label = 'ID'): ?int {
|
||||||
if ($id === null || $id === '' || !ctype_digit((string) $id)) {
|
if ($id === null || $id === '' || !ctype_digit((string) $id)) {
|
||||||
$this->failValidationErrors("{$label} is required and must be a valid integer.");
|
$this->failValidationErrors("{$label} is required and must be a valid integer.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (int) $id;
|
return (int) $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function requirePatchPayload(mixed $payload): ?array {
|
protected function requirePatchPayload(mixed $payload): ?array {
|
||||||
if (!is_array($payload) || empty($payload)) {
|
if (!is_array($payload) || empty($payload)) {
|
||||||
$this->failValidationErrors('No data provided for update.');
|
$this->failValidationErrors('No data provided for update.');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return $payload;
|
return $payload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
69
composer.lock
generated
69
composer.lock
generated
@ -88,12 +88,12 @@
|
|||||||
"version": "v7.0.5",
|
"version": "v7.0.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/firebase/php-jwt.git",
|
"url": "https://github.com/googleapis/php-jwt.git",
|
||||||
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380"
|
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
"url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
||||||
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
"reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
@ -142,8 +142,8 @@
|
|||||||
"php"
|
"php"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
"issues": "https://github.com/googleapis/php-jwt/issues",
|
||||||
"source": "https://github.com/firebase/php-jwt/tree/v7.0.5"
|
"source": "https://github.com/googleapis/php-jwt/tree/v7.0.5"
|
||||||
},
|
},
|
||||||
"time": "2026-04-01T20:38:03+00:00"
|
"time": "2026-04-01T20:38:03+00:00"
|
||||||
},
|
},
|
||||||
@ -362,30 +362,34 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache",
|
"name": "symfony/cache",
|
||||||
"version": "v8.0.8",
|
"version": "v7.4.8",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/cache.git",
|
"url": "https://github.com/symfony/cache.git",
|
||||||
"reference": "8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78"
|
"reference": "467464da294734b0fb17e853e5712abc8470f819"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/cache/zipball/8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78",
|
"url": "https://api.github.com/repos/symfony/cache/zipball/467464da294734b0fb17e853e5712abc8470f819",
|
||||||
"reference": "8abf3ccbeae9d3071b81a3ae7ee11b209f9e1e78",
|
"reference": "467464da294734b0fb17e853e5712abc8470f819",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.4",
|
"php": ">=8.2",
|
||||||
"psr/cache": "^2.0|^3.0",
|
"psr/cache": "^2.0|^3.0",
|
||||||
"psr/log": "^1.1|^2|^3",
|
"psr/log": "^1.1|^2|^3",
|
||||||
"symfony/cache-contracts": "^3.6",
|
"symfony/cache-contracts": "^3.6",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
"symfony/service-contracts": "^2.5|^3",
|
"symfony/service-contracts": "^2.5|^3",
|
||||||
"symfony/var-exporter": "^7.4|^8.0"
|
"symfony/var-exporter": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"doctrine/dbal": "<4.3",
|
"doctrine/dbal": "<3.6",
|
||||||
"ext-redis": "<6.1",
|
"ext-redis": "<6.1",
|
||||||
"ext-relay": "<0.12.1"
|
"ext-relay": "<0.12.1",
|
||||||
|
"symfony/dependency-injection": "<6.4",
|
||||||
|
"symfony/http-kernel": "<6.4",
|
||||||
|
"symfony/var-dumper": "<6.4"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
"psr/cache-implementation": "2.0|3.0",
|
"psr/cache-implementation": "2.0|3.0",
|
||||||
@ -394,16 +398,16 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"cache/integration-tests": "dev-master",
|
"cache/integration-tests": "dev-master",
|
||||||
"doctrine/dbal": "^4.3",
|
"doctrine/dbal": "^3.6|^4",
|
||||||
"predis/predis": "^1.1|^2.0",
|
"predis/predis": "^1.1|^2.0",
|
||||||
"psr/simple-cache": "^1.0|^2.0|^3.0",
|
"psr/simple-cache": "^1.0|^2.0|^3.0",
|
||||||
"symfony/clock": "^7.4|^8.0",
|
"symfony/clock": "^6.4|^7.0|^8.0",
|
||||||
"symfony/config": "^7.4|^8.0",
|
"symfony/config": "^6.4|^7.0|^8.0",
|
||||||
"symfony/dependency-injection": "^7.4|^8.0",
|
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||||
"symfony/filesystem": "^7.4|^8.0",
|
"symfony/filesystem": "^6.4|^7.0|^8.0",
|
||||||
"symfony/http-kernel": "^7.4|^8.0",
|
"symfony/http-kernel": "^6.4|^7.0|^8.0",
|
||||||
"symfony/messenger": "^7.4|^8.0",
|
"symfony/messenger": "^6.4|^7.0|^8.0",
|
||||||
"symfony/var-dumper": "^7.4|^8.0"
|
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -438,7 +442,7 @@
|
|||||||
"psr6"
|
"psr6"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/cache/tree/v8.0.8"
|
"source": "https://github.com/symfony/cache/tree/v7.4.8"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -458,7 +462,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-03-30T15:18:51+00:00"
|
"time": "2026-03-30T15:15:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache-contracts",
|
"name": "symfony/cache-contracts",
|
||||||
@ -760,25 +764,26 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-exporter",
|
"name": "symfony/var-exporter",
|
||||||
"version": "v8.0.8",
|
"version": "v7.4.8",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-exporter.git",
|
"url": "https://github.com/symfony/var-exporter.git",
|
||||||
"reference": "15776bb07a91b089037da89f8832fa41d5fa6ec6"
|
"reference": "398907e89a2a56fe426f7955c6fa943ec0c77225"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/15776bb07a91b089037da89f8832fa41d5fa6ec6",
|
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/398907e89a2a56fe426f7955c6fa943ec0c77225",
|
||||||
"reference": "15776bb07a91b089037da89f8832fa41d5fa6ec6",
|
"reference": "398907e89a2a56fe426f7955c6fa943ec0c77225",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.4"
|
"php": ">=8.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/property-access": "^7.4|^8.0",
|
"symfony/property-access": "^6.4|^7.0|^8.0",
|
||||||
"symfony/serializer": "^7.4|^8.0",
|
"symfony/serializer": "^6.4|^7.0|^8.0",
|
||||||
"symfony/var-dumper": "^7.4|^8.0"
|
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -816,7 +821,7 @@
|
|||||||
"serialize"
|
"serialize"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/var-exporter/tree/v8.0.8"
|
"source": "https://github.com/symfony/var-exporter/tree/v7.4.8"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -836,7 +841,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-03-30T15:14:47+00:00"
|
"time": "2026-03-24T13:12:05+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
|||||||
12
package-lock.json
generated
12
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "clqms01-be",
|
"name": "clqms01-be",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {}
|
"packages": {}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,107 +1,107 @@
|
|||||||
AuditLogEntry:
|
AuditLogEntry:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
LogPatientID:
|
LogPatientID:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
nullable: true
|
||||||
LogOrderID:
|
LogOrderID:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
nullable: true
|
||||||
LogMasterID:
|
LogMasterID:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
nullable: true
|
||||||
LogSystemID:
|
LogSystemID:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
nullable: true
|
||||||
TblName:
|
TblName:
|
||||||
type: string
|
type: string
|
||||||
RecID:
|
RecID:
|
||||||
type: string
|
type: string
|
||||||
FldName:
|
FldName:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
FldValuePrev:
|
FldValuePrev:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
FldValueNew:
|
FldValueNew:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
UserID:
|
UserID:
|
||||||
type: string
|
type: string
|
||||||
SiteID:
|
SiteID:
|
||||||
type: string
|
type: string
|
||||||
DIDType:
|
DIDType:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
DID:
|
DID:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
MachineID:
|
MachineID:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
SessionID:
|
SessionID:
|
||||||
type: string
|
type: string
|
||||||
AppID:
|
AppID:
|
||||||
type: string
|
type: string
|
||||||
ProcessID:
|
ProcessID:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
WebPageID:
|
WebPageID:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
EventID:
|
EventID:
|
||||||
type: string
|
type: string
|
||||||
ActivityID:
|
ActivityID:
|
||||||
type: string
|
type: string
|
||||||
Reason:
|
Reason:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
LogDate:
|
LogDate:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
Context:
|
Context:
|
||||||
type: string
|
type: string
|
||||||
IpAddress:
|
IpAddress:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
|
||||||
AuditLogListResponse:
|
AuditLogListResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/AuditLogEntry'
|
$ref: '#/AuditLogEntry'
|
||||||
pagination:
|
pagination:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
page:
|
page:
|
||||||
type: integer
|
type: integer
|
||||||
perPage:
|
perPage:
|
||||||
type: integer
|
type: integer
|
||||||
total:
|
total:
|
||||||
type: integer
|
type: integer
|
||||||
required: [page, perPage, total]
|
required: [page, perPage, total]
|
||||||
required: [data, pagination]
|
required: [data, pagination]
|
||||||
|
|
||||||
AuditLogsEnvelope:
|
AuditLogsEnvelope:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
data:
|
data:
|
||||||
$ref: '#/AuditLogListResponse'
|
$ref: '#/AuditLogListResponse'
|
||||||
required: [status, message, data]
|
required: [status, message, data]
|
||||||
|
|
||||||
AuditLogsErrorResponse:
|
AuditLogsErrorResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
data:
|
data:
|
||||||
nullable: true
|
nullable: true
|
||||||
required: [status, message, data]
|
required: [status, message, data]
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
User:
|
User:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
UserID:
|
UserID:
|
||||||
type: integer
|
type: integer
|
||||||
description: Unique user identifier
|
description: Unique user identifier
|
||||||
Username:
|
Username:
|
||||||
type: string
|
type: string
|
||||||
description: Unique login username
|
description: Unique login username
|
||||||
Email:
|
Email:
|
||||||
type: string
|
type: string
|
||||||
format: email
|
format: email
|
||||||
description: User email address
|
description: User email address
|
||||||
Name:
|
Name:
|
||||||
type: string
|
type: string
|
||||||
description: Full name of the user
|
description: Full name of the user
|
||||||
Role:
|
Role:
|
||||||
type: string
|
type: string
|
||||||
description: User role (admin, technician, doctor, etc.)
|
description: User role (admin, technician, doctor, etc.)
|
||||||
Department:
|
Department:
|
||||||
type: string
|
type: string
|
||||||
description: Department name
|
description: Department name
|
||||||
IsActive:
|
IsActive:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: Whether the user account is active
|
description: Whether the user account is active
|
||||||
CreatedAt:
|
CreatedAt:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: Creation timestamp
|
description: Creation timestamp
|
||||||
UpdatedAt:
|
UpdatedAt:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: Last update timestamp
|
description: Last update timestamp
|
||||||
DelDate:
|
DelDate:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
nullable: true
|
nullable: true
|
||||||
description: Soft delete timestamp (null if active)
|
description: Soft delete timestamp (null if active)
|
||||||
|
|
||||||
UserCreate:
|
UserCreate:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- Username
|
- Username
|
||||||
- Email
|
- Email
|
||||||
properties:
|
properties:
|
||||||
Username:
|
Username:
|
||||||
type: string
|
type: string
|
||||||
minLength: 3
|
minLength: 3
|
||||||
maxLength: 50
|
maxLength: 50
|
||||||
description: Unique login username
|
description: Unique login username
|
||||||
Email:
|
Email:
|
||||||
type: string
|
type: string
|
||||||
format: email
|
format: email
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
description: User email address
|
description: User email address
|
||||||
Name:
|
Name:
|
||||||
type: string
|
type: string
|
||||||
description: Full name of the user
|
description: Full name of the user
|
||||||
Role:
|
Role:
|
||||||
type: string
|
type: string
|
||||||
description: User role
|
description: User role
|
||||||
Department:
|
Department:
|
||||||
type: string
|
type: string
|
||||||
description: Department name
|
description: Department name
|
||||||
IsActive:
|
IsActive:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
description: Whether the user account is active
|
description: Whether the user account is active
|
||||||
|
|
||||||
UserUpdate:
|
UserUpdate:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- UserID
|
- UserID
|
||||||
properties:
|
properties:
|
||||||
UserID:
|
UserID:
|
||||||
type: integer
|
type: integer
|
||||||
description: User ID to update
|
description: User ID to update
|
||||||
Email:
|
Email:
|
||||||
type: string
|
type: string
|
||||||
format: email
|
format: email
|
||||||
description: User email address
|
description: User email address
|
||||||
Name:
|
Name:
|
||||||
type: string
|
type: string
|
||||||
description: Full name of the user
|
description: Full name of the user
|
||||||
Role:
|
Role:
|
||||||
type: string
|
type: string
|
||||||
description: User role
|
description: User role
|
||||||
Department:
|
Department:
|
||||||
type: string
|
type: string
|
||||||
description: Department name
|
description: Department name
|
||||||
IsActive:
|
IsActive:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: Whether the user account is active
|
description: Whether the user account is active
|
||||||
|
|
||||||
UserListResponse:
|
UserListResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: success
|
example: success
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: Users retrieved successfully
|
example: Users retrieved successfully
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
users:
|
users:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/User'
|
$ref: '#/User'
|
||||||
pagination:
|
pagination:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
current_page:
|
current_page:
|
||||||
type: integer
|
type: integer
|
||||||
per_page:
|
per_page:
|
||||||
type: integer
|
type: integer
|
||||||
total:
|
total:
|
||||||
type: integer
|
type: integer
|
||||||
total_pages:
|
total_pages:
|
||||||
type: integer
|
type: integer
|
||||||
@ -1,76 +1,76 @@
|
|||||||
/api/audit-logs:
|
/api/audit-logs:
|
||||||
get:
|
get:
|
||||||
tags: [Audit]
|
tags: [Audit]
|
||||||
summary: Retrieve audit log entries for a table
|
summary: Retrieve audit log entries for a table
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: table
|
- name: table
|
||||||
in: query
|
in: query
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Table alias for the audit data (logpatient, logorder, logmaster, logsystem)
|
description: Table alias for the audit data (logpatient, logorder, logmaster, logsystem)
|
||||||
- name: rec_id
|
- name: rec_id
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Primary record identifier (RecID) to filter audit rows
|
description: Primary record identifier (RecID) to filter audit rows
|
||||||
- name: event_id
|
- name: event_id
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Canonical EventID (case insensitive)
|
description: Canonical EventID (case insensitive)
|
||||||
- name: activity_id
|
- name: activity_id
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Canonical ActivityID (case insensitive)
|
description: Canonical ActivityID (case insensitive)
|
||||||
- name: from
|
- name: from
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: Lower bound for LogDate inclusive
|
description: Lower bound for LogDate inclusive
|
||||||
- name: to
|
- name: to
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
description: Upper bound for LogDate inclusive
|
description: Upper bound for LogDate inclusive
|
||||||
- name: search
|
- name: search
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Search term that matches user, reason, field names, or values
|
description: Search term that matches user, reason, field names, or values
|
||||||
- name: page
|
- name: page
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
default: 1
|
default: 1
|
||||||
description: Page number
|
description: Page number
|
||||||
- name: perPage
|
- name: perPage
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
default: 20
|
default: 20
|
||||||
description: Items per page (max 100)
|
description: Items per page (max 100)
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Audit log results
|
description: Audit log results
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '../components/schemas/audit-logs.yaml#/AuditLogsEnvelope'
|
$ref: '../components/schemas/audit-logs.yaml#/AuditLogsEnvelope'
|
||||||
'400':
|
'400':
|
||||||
description: Validation failure (missing table or invalid filters)
|
description: Validation failure (missing table or invalid filters)
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '../components/schemas/audit-logs.yaml#/AuditLogsErrorResponse'
|
$ref: '../components/schemas/audit-logs.yaml#/AuditLogsErrorResponse'
|
||||||
'500':
|
'500':
|
||||||
description: Internal error when retrieving audit logs
|
description: Internal error when retrieving audit logs
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '../components/schemas/audit-logs.yaml#/AuditLogsErrorResponse'
|
$ref: '../components/schemas/audit-logs.yaml#/AuditLogsErrorResponse'
|
||||||
|
|||||||
@ -1,112 +1,112 @@
|
|||||||
/api/calc/testcode/{codeOrName}:
|
/api/calc/testcode/{codeOrName}:
|
||||||
post:
|
post:
|
||||||
tags: [Calculation]
|
tags: [Calculation]
|
||||||
summary: Evaluate a configured calculation by test code or name and return the raw result map.
|
summary: Evaluate a configured calculation by test code or name and return the raw result map.
|
||||||
security: []
|
security: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: codeOrName
|
- name: codeOrName
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: TestSiteCode or TestSiteName of the calculated test (case-insensitive).
|
description: TestSiteCode or TestSiteName of the calculated test (case-insensitive).
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
description: Key-value pairs where keys match member tests used in the formula.
|
description: Key-value pairs where keys match member tests used in the formula.
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: number
|
type: number
|
||||||
example:
|
example:
|
||||||
TBIL: 5
|
TBIL: 5
|
||||||
DBIL: 3
|
DBIL: 3
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Returns a single key/value pair with the canonical TestSiteCode or an empty object when the calculation is incomplete or missing.
|
description: Returns a single key/value pair with the canonical TestSiteCode or an empty object when the calculation is incomplete or missing.
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
examples:
|
examples:
|
||||||
success:
|
success:
|
||||||
value:
|
value:
|
||||||
IBIL: 2.0
|
IBIL: 2.0
|
||||||
incomplete:
|
incomplete:
|
||||||
value: {}
|
value: {}
|
||||||
|
|
||||||
/api/calc/testsite/{testSiteID}:
|
/api/calc/testsite/{testSiteID}:
|
||||||
post:
|
post:
|
||||||
tags: [Calculation]
|
tags: [Calculation]
|
||||||
summary: Evaluate a calculation defined for a test site and return a structured result.
|
summary: Evaluate a calculation defined for a test site and return a structured result.
|
||||||
security: []
|
security: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: testSiteID
|
- name: testSiteID
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
description: Identifier for the test site whose definition should be evaluated.
|
description: Identifier for the test site whose definition should be evaluated.
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
description: Variable assignments required by the test site formula.
|
description: Variable assignments required by the test site formula.
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: number
|
type: number
|
||||||
example:
|
example:
|
||||||
result: 85
|
result: 85
|
||||||
gender: "female"
|
gender: "female"
|
||||||
age: 30
|
age: 30
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Returns the calculated result, testSiteID, formula code, and echoed variables.
|
description: Returns the calculated result, testSiteID, formula code, and echoed variables.
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: success
|
example: success
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
result:
|
result:
|
||||||
type: number
|
type: number
|
||||||
testSiteID:
|
testSiteID:
|
||||||
type: integer
|
type: integer
|
||||||
formula:
|
formula:
|
||||||
type: string
|
type: string
|
||||||
variables:
|
variables:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: number
|
type: number
|
||||||
examples:
|
examples:
|
||||||
success:
|
success:
|
||||||
value:
|
value:
|
||||||
status: success
|
status: success
|
||||||
data:
|
data:
|
||||||
result: 92.4
|
result: 92.4
|
||||||
testSiteID: 123
|
testSiteID: 123
|
||||||
formula: "{result} * {factor} + {age}"
|
formula: "{result} * {factor} + {age}"
|
||||||
variables:
|
variables:
|
||||||
result: 85
|
result: 85
|
||||||
gender: female
|
gender: female
|
||||||
age: 30
|
age: 30
|
||||||
'404':
|
'404':
|
||||||
description: No calculation defined for the requested test site.
|
description: No calculation defined for the requested test site.
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: failed
|
example: failed
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: No calculation defined for this test site
|
example: No calculation defined for this test site
|
||||||
|
|||||||
@ -1,220 +1,220 @@
|
|||||||
/api/user:
|
/api/user:
|
||||||
get:
|
get:
|
||||||
tags: [User]
|
tags: [User]
|
||||||
summary: List users with pagination and search
|
summary: List users with pagination and search
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: page
|
- name: page
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
default: 1
|
default: 1
|
||||||
description: Page number
|
description: Page number
|
||||||
- name: per_page
|
- name: per_page
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
default: 20
|
default: 20
|
||||||
description: Items per page
|
description: Items per page
|
||||||
- name: search
|
- name: search
|
||||||
in: query
|
in: query
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Search term for username, email, or name
|
description: Search term for username, email, or name
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: List of users with pagination
|
description: List of users with pagination
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: success
|
example: success
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: Users retrieved successfully
|
example: Users retrieved successfully
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
users:
|
users:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '../components/schemas/user.yaml#/User'
|
$ref: '../components/schemas/user.yaml#/User'
|
||||||
pagination:
|
pagination:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
current_page:
|
current_page:
|
||||||
type: integer
|
type: integer
|
||||||
per_page:
|
per_page:
|
||||||
type: integer
|
type: integer
|
||||||
total:
|
total:
|
||||||
type: integer
|
type: integer
|
||||||
total_pages:
|
total_pages:
|
||||||
type: integer
|
type: integer
|
||||||
'500':
|
'500':
|
||||||
description: Server error
|
description: Server error
|
||||||
|
|
||||||
post:
|
post:
|
||||||
tags: [User]
|
tags: [User]
|
||||||
summary: Create new user
|
summary: Create new user
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '../components/schemas/user.yaml#/UserCreate'
|
$ref: '../components/schemas/user.yaml#/UserCreate'
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: User created successfully
|
description: User created successfully
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: success
|
example: success
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: User created successfully
|
example: User created successfully
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
UserID:
|
UserID:
|
||||||
type: integer
|
type: integer
|
||||||
Username:
|
Username:
|
||||||
type: string
|
type: string
|
||||||
Email:
|
Email:
|
||||||
type: string
|
type: string
|
||||||
'400':
|
'400':
|
||||||
description: Validation failed
|
description: Validation failed
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: failed
|
example: failed
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: Validation failed
|
example: Validation failed
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
'500':
|
'500':
|
||||||
description: Server error
|
description: Server error
|
||||||
|
|
||||||
|
|
||||||
/api/user/{id}:
|
/api/user/{id}:
|
||||||
get:
|
get:
|
||||||
tags: [User]
|
tags: [User]
|
||||||
summary: Get user by ID
|
summary: Get user by ID
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: id
|
- name: id
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
description: User ID
|
description: User ID
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: User details
|
description: User details
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '../components/schemas/user.yaml#/User'
|
$ref: '../components/schemas/user.yaml#/User'
|
||||||
'404':
|
'404':
|
||||||
description: User not found
|
description: User not found
|
||||||
'500':
|
'500':
|
||||||
description: Server error
|
description: Server error
|
||||||
|
|
||||||
patch:
|
patch:
|
||||||
tags: [User]
|
tags: [User]
|
||||||
summary: Update existing user
|
summary: Update existing user
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: id
|
- name: id
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
description: User ID
|
description: User ID
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '../components/schemas/user.yaml#/UserUpdate'
|
$ref: '../components/schemas/user.yaml#/UserUpdate'
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: User updated successfully
|
description: User updated successfully
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: success
|
example: success
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: User updated successfully
|
example: User updated successfully
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
UserID:
|
UserID:
|
||||||
type: integer
|
type: integer
|
||||||
updated_fields:
|
updated_fields:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
'400':
|
'400':
|
||||||
description: UserID is required
|
description: UserID is required
|
||||||
'404':
|
'404':
|
||||||
description: User not found
|
description: User not found
|
||||||
'500':
|
'500':
|
||||||
description: Server error
|
description: Server error
|
||||||
|
|
||||||
delete:
|
delete:
|
||||||
tags: [User]
|
tags: [User]
|
||||||
summary: Delete user (soft delete)
|
summary: Delete user (soft delete)
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: id
|
- name: id
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
description: User ID
|
description: User ID
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: User deleted successfully
|
description: User deleted successfully
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
example: success
|
example: success
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: User deleted successfully
|
example: User deleted successfully
|
||||||
data:
|
data:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
UserID:
|
UserID:
|
||||||
type: integer
|
type: integer
|
||||||
'404':
|
'404':
|
||||||
description: User not found
|
description: User not found
|
||||||
'500':
|
'500':
|
||||||
description: Server error
|
description: Server error
|
||||||
|
|||||||
@ -1,62 +1,62 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Support\Traits;
|
namespace Tests\Support\Traits;
|
||||||
|
|
||||||
use App\Models\Patient\PatientModel;
|
use App\Models\Patient\PatientModel;
|
||||||
use Faker\Factory;
|
use Faker\Factory;
|
||||||
|
|
||||||
trait CreatesPatients
|
trait CreatesPatients
|
||||||
{
|
{
|
||||||
protected function createTestPatient(array $overrides = []): int
|
protected function createTestPatient(array $overrides = []): int
|
||||||
{
|
{
|
||||||
$faker = Factory::create('id_ID');
|
$faker = Factory::create('id_ID');
|
||||||
$patientPayload = array_merge([
|
$patientPayload = array_merge([
|
||||||
'PatientID' => 'PAT' . $faker->numerify('##########'),
|
'PatientID' => 'PAT' . $faker->numerify('##########'),
|
||||||
'AlternatePID' => 'ALT' . $faker->numerify('##########'),
|
'AlternatePID' => 'ALT' . $faker->numerify('##########'),
|
||||||
'Prefix' => $faker->title,
|
'Prefix' => $faker->title,
|
||||||
'NameFirst' => 'Test',
|
'NameFirst' => 'Test',
|
||||||
'NameMiddle' => $faker->firstName,
|
'NameMiddle' => $faker->firstName,
|
||||||
'NameLast' => 'Patient',
|
'NameLast' => 'Patient',
|
||||||
'Suffix' => 'S.Kom',
|
'Suffix' => 'S.Kom',
|
||||||
'Sex' => (string) $faker->numberBetween(5, 6),
|
'Sex' => (string) $faker->numberBetween(5, 6),
|
||||||
'PlaceOfBirth' => $faker->city,
|
'PlaceOfBirth' => $faker->city,
|
||||||
'Birthdate' => $faker->date('Y-m-d'),
|
'Birthdate' => $faker->date('Y-m-d'),
|
||||||
'ZIP' => $faker->postcode,
|
'ZIP' => $faker->postcode,
|
||||||
'Street_1' => $faker->streetAddress,
|
'Street_1' => $faker->streetAddress,
|
||||||
'City' => $faker->city,
|
'City' => $faker->city,
|
||||||
'Province' => $faker->state,
|
'Province' => $faker->state,
|
||||||
'EmailAddress1' => 'test.' . $faker->unique()->userName . '@example.com',
|
'EmailAddress1' => 'test.' . $faker->unique()->userName . '@example.com',
|
||||||
'Phone' => $faker->numerify('08##########'),
|
'Phone' => $faker->numerify('08##########'),
|
||||||
'MobilePhone' => $faker->numerify('08##########'),
|
'MobilePhone' => $faker->numerify('08##########'),
|
||||||
'Race' => (string) $faker->numberBetween(175, 205),
|
'Race' => (string) $faker->numberBetween(175, 205),
|
||||||
'Country' => (string) $faker->numberBetween(221, 469),
|
'Country' => (string) $faker->numberBetween(221, 469),
|
||||||
'MaritalStatus' => (string) $faker->numberBetween(8, 15),
|
'MaritalStatus' => (string) $faker->numberBetween(8, 15),
|
||||||
'Religion' => (string) $faker->numberBetween(206, 212),
|
'Religion' => (string) $faker->numberBetween(206, 212),
|
||||||
'Ethnic' => (string) $faker->numberBetween(213, 220),
|
'Ethnic' => (string) $faker->numberBetween(213, 220),
|
||||||
'Citizenship' => 'WNI',
|
'Citizenship' => 'WNI',
|
||||||
'isDead' => (string) $faker->numberBetween(0, 1),
|
'isDead' => (string) $faker->numberBetween(0, 1),
|
||||||
'PatIdt' => [
|
'PatIdt' => [
|
||||||
'IdentifierType' => 'ID',
|
'IdentifierType' => 'ID',
|
||||||
'Identifier' => $faker->numerify('################')
|
'Identifier' => $faker->numerify('################')
|
||||||
],
|
],
|
||||||
'PatAtt' => [
|
'PatAtt' => [
|
||||||
[ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ]
|
[ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ]
|
||||||
],
|
],
|
||||||
'PatCom' => $faker->sentence,
|
'PatCom' => $faker->sentence,
|
||||||
], $overrides);
|
], $overrides);
|
||||||
|
|
||||||
if ($patientPayload['isDead'] === '1') {
|
if ($patientPayload['isDead'] === '1') {
|
||||||
$patientPayload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
|
$patientPayload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
|
||||||
} else {
|
} else {
|
||||||
$patientPayload['DeathDateTime'] = null;
|
$patientPayload['DeathDateTime'] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$patientModel = new PatientModel();
|
$patientModel = new PatientModel();
|
||||||
$internalPID = $patientModel->createPatient($patientPayload);
|
$internalPID = $patientModel->createPatient($patientPayload);
|
||||||
if (!$internalPID) {
|
if (!$internalPID) {
|
||||||
throw new \RuntimeException('Failed to insert test patient');
|
throw new \RuntimeException('Failed to insert test patient');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $internalPID;
|
return $internalPID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,117 +1,117 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Audit;
|
namespace Tests\Feature\Audit;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class AuditLogTest extends CIUnitTestCase
|
class AuditLogTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
private $testRecId = 'TEST-REC-123';
|
private $testRecId = 'TEST-REC-123';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->db->table('logpatient')->insert([
|
$this->db->table('logpatient')->insert([
|
||||||
'TblName' => 'patient',
|
'TblName' => 'patient',
|
||||||
'RecID' => $this->testRecId,
|
'RecID' => $this->testRecId,
|
||||||
'UserID' => 'USR_TEST',
|
'UserID' => 'USR_TEST',
|
||||||
'SiteID' => 'SITE01',
|
'SiteID' => 'SITE01',
|
||||||
'SessionID' => 'sess_test',
|
'SessionID' => 'sess_test',
|
||||||
'AppID' => 'clqms-api',
|
'AppID' => 'clqms-api',
|
||||||
'EventID' => 'PATIENT_REGISTERED',
|
'EventID' => 'PATIENT_REGISTERED',
|
||||||
'ActivityID' => 'CREATE',
|
'ActivityID' => 'CREATE',
|
||||||
'LogDate' => '2026-03-25 12:00:00',
|
'LogDate' => '2026-03-25 12:00:00',
|
||||||
'Context' => json_encode([
|
'Context' => json_encode([
|
||||||
'request_id' => 'req-test-1',
|
'request_id' => 'req-test-1',
|
||||||
'route' => 'POST /api/patient',
|
'route' => 'POST /api/patient',
|
||||||
'timestamp_utc' => '2026-03-25T12:00:00.000Z',
|
'timestamp_utc' => '2026-03-25T12:00:00.000Z',
|
||||||
'entity_type' => 'patient',
|
'entity_type' => 'patient',
|
||||||
'entity_version' => 1,
|
'entity_version' => 1,
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function tearDown(): void
|
protected function tearDown(): void
|
||||||
{
|
{
|
||||||
$this->db->table('logpatient')->where('RecID', $this->testRecId)->delete();
|
$this->db->table('logpatient')->where('RecID', $this->testRecId)->delete();
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTableIsRequired()
|
public function testTableIsRequired()
|
||||||
{
|
{
|
||||||
$result = $this->getWithAuth('api/audit-logs');
|
$result = $this->getWithAuth('api/audit-logs');
|
||||||
|
|
||||||
$result->assertStatus(400);
|
$result->assertStatus(400);
|
||||||
$result->assertJSONFragment([
|
$result->assertJSONFragment([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'table parameter is required',
|
'message' => 'table parameter is required',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUnknownTableReturnsValidationError()
|
public function testUnknownTableReturnsValidationError()
|
||||||
{
|
{
|
||||||
$result = $this->getWithAuth('api/audit-logs?table=unknown');
|
$result = $this->getWithAuth('api/audit-logs?table=unknown');
|
||||||
|
|
||||||
$result->assertStatus(400);
|
$result->assertStatus(400);
|
||||||
$result->assertJSONFragment([
|
$result->assertJSONFragment([
|
||||||
'status' => 'failed',
|
'status' => 'failed',
|
||||||
'message' => 'Unknown audit table: unknown',
|
'message' => 'Unknown audit table: unknown',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAuditLogsFilterByRecId()
|
public function testAuditLogsFilterByRecId()
|
||||||
{
|
{
|
||||||
$result = $this->getWithAuth('api/audit-logs?table=logpatient&rec_id=' . $this->testRecId);
|
$result = $this->getWithAuth('api/audit-logs?table=logpatient&rec_id=' . $this->testRecId);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$result->assertJSONFragment([
|
$result->assertJSONFragment([
|
||||||
'status' => 'success',
|
'status' => 'success',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$payload = json_decode($result->getJSON(), true);
|
$payload = json_decode($result->getJSON(), true);
|
||||||
$this->assertCount(1, $payload['data']['data']);
|
$this->assertCount(1, $payload['data']['data']);
|
||||||
$this->assertEquals($this->testRecId, $payload['data']['data'][0]['RecID']);
|
$this->assertEquals($this->testRecId, $payload['data']['data'][0]['RecID']);
|
||||||
|
|
||||||
$pagination = $payload['data']['pagination'];
|
$pagination = $payload['data']['pagination'];
|
||||||
$this->assertSame(1, $pagination['page']);
|
$this->assertSame(1, $pagination['page']);
|
||||||
$this->assertSame(20, $pagination['perPage']);
|
$this->assertSame(20, $pagination['perPage']);
|
||||||
$this->assertSame(1, $pagination['total']);
|
$this->assertSame(1, $pagination['total']);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getWithAuth(string $uri)
|
private function getWithAuth(string $uri)
|
||||||
{
|
{
|
||||||
$_COOKIE['token'] = $this->buildToken();
|
$_COOKIE['token'] = $this->buildToken();
|
||||||
|
|
||||||
$response = $this->get($uri);
|
$response = $this->get($uri);
|
||||||
|
|
||||||
unset($_COOKIE['token']);
|
unset($_COOKIE['token']);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildToken(): string
|
private function buildToken(): string
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
'sub' => 'audit-test',
|
'sub' => 'audit-test',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return JWT::encode($payload, $this->resolveSecret(), 'HS256');
|
return JWT::encode($payload, $this->resolveSecret(), 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveSecret(): string
|
private function resolveSecret(): string
|
||||||
{
|
{
|
||||||
$secret = getenv('JWT_SECRET');
|
$secret = getenv('JWT_SECRET');
|
||||||
if ($secret === false) {
|
if ($secret === false) {
|
||||||
return 'tests-secret';
|
return 'tests-secret';
|
||||||
}
|
}
|
||||||
return trim($secret, "'\"");
|
return trim($secret, "'\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -156,6 +156,7 @@ class ContactPatchTest extends CIUnitTestCase
|
|||||||
[
|
[
|
||||||
'ContactDetID' => $keepDetail['ContactDetID'],
|
'ContactDetID' => $keepDetail['ContactDetID'],
|
||||||
'JobTitle' => 'Senior Doctor',
|
'JobTitle' => 'Senior Doctor',
|
||||||
|
'ContactStartDate' => '2026-04-16T07:22:44.000Z',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'created' => [
|
'created' => [
|
||||||
@ -182,8 +183,19 @@ class ContactPatchTest extends CIUnitTestCase
|
|||||||
$this->assertCount(2, $afterData['Details']);
|
$this->assertCount(2, $afterData['Details']);
|
||||||
$detailIds = array_column($afterData['Details'], 'ContactDetID');
|
$detailIds = array_column($afterData['Details'], 'ContactDetID');
|
||||||
$this->assertContains($keepDetail['ContactDetID'], $detailIds);
|
$this->assertContains($keepDetail['ContactDetID'], $detailIds);
|
||||||
|
$this->assertNotContains($deleteDetail['ContactDetID'], $detailIds);
|
||||||
|
|
||||||
$updatedDetails = array_values(array_filter($afterData['Details'], static fn ($row) => $row['ContactDetID'] === $keepDetail['ContactDetID']));
|
$updatedDetails = array_values(array_filter(
|
||||||
|
$afterData['Details'],
|
||||||
|
static fn ($row) => $row['ContactDetID'] === $keepDetail['ContactDetID']
|
||||||
|
));
|
||||||
$this->assertNotEmpty($updatedDetails);
|
$this->assertNotEmpty($updatedDetails);
|
||||||
|
$this->assertSame('Senior Doctor', $updatedDetails[0]['JobTitle']);
|
||||||
|
|
||||||
|
$createdDetails = array_values(array_filter(
|
||||||
|
$afterData['Details'],
|
||||||
|
static fn ($row) => (string) $row['SiteID'] === '3'
|
||||||
|
));
|
||||||
|
$this->assertNotEmpty($createdDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,144 +1,144 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Location;
|
namespace Tests\Feature\Location;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class LocationPatchTest extends CIUnitTestCase
|
class LocationPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/location';
|
protected string $endpoint = 'api/location';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createLocation(array $data = []): array
|
private function createLocation(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'LocCode' => 'LC' . substr(uniqid(), -4),
|
'LocCode' => 'LC' . substr(uniqid(), -4),
|
||||||
'LocFull' => 'Test Location ' . uniqid(),
|
'LocFull' => 'Test Location ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
$locationId = $decoded['data']['LocationID'];
|
$locationId = $decoded['data']['LocationID'];
|
||||||
$show = $this->withHeaders($this->authHeaders())
|
$show = $this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$locationId}");
|
->call('get', "{$this->endpoint}/{$locationId}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
return $showData;
|
return $showData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateLocationSuccess()
|
public function testPartialUpdateLocationSuccess()
|
||||||
{
|
{
|
||||||
$location = $this->createLocation();
|
$location = $this->createLocation();
|
||||||
$id = $location['LocationID'];
|
$id = $location['LocationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['LocFull' => 'Updated Location']);
|
->call('patch', "{$this->endpoint}/{$id}", ['LocFull' => 'Updated Location']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Location', $showData['LocFull']);
|
$this->assertEquals('Updated Location', $showData['LocFull']);
|
||||||
$this->assertEquals($location['LocCode'], $showData['LocCode']);
|
$this->assertEquals($location['LocCode'], $showData['LocCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateLocationNotFound()
|
public function testPartialUpdateLocationNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['LocFull' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['LocFull' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateLocationInvalidId()
|
public function testPartialUpdateLocationInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['LocFull' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['LocFull' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateLocationEmptyPayload()
|
public function testPartialUpdateLocationEmptyPayload()
|
||||||
{
|
{
|
||||||
$location = $this->createLocation();
|
$location = $this->createLocation();
|
||||||
$id = $location['LocationID'];
|
$id = $location['LocationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateLocationSingleField()
|
public function testPartialUpdateLocationSingleField()
|
||||||
{
|
{
|
||||||
$location = $this->createLocation();
|
$location = $this->createLocation();
|
||||||
$id = $location['LocationID'];
|
$id = $location['LocationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['LocCode' => 'LC' . substr(uniqid(), -4)]);
|
->call('patch', "{$this->endpoint}/{$id}", ['LocCode' => 'LC' . substr(uniqid(), -4)]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($location['LocCode'], $showData['LocCode']);
|
$this->assertNotEquals($location['LocCode'], $showData['LocCode']);
|
||||||
$this->assertEquals($location['LocFull'], $showData['LocFull']);
|
$this->assertEquals($location['LocFull'], $showData['LocFull']);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateLocationAddressField()
|
public function testPartialUpdateLocationAddressField()
|
||||||
{
|
{
|
||||||
$location = $this->createLocation();
|
$location = $this->createLocation();
|
||||||
$id = $location['LocationID'];
|
$id = $location['LocationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['Street1' => '123 Market St']);
|
->call('patch', "{$this->endpoint}/{$id}", ['Street1' => '123 Market St']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('123 Market St', $showData['Street1']);
|
$this->assertEquals('123 Market St', $showData['Street1']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,301 +1,301 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class MasterDataPatchTest extends CIUnitTestCase
|
class MasterDataPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createResource(string $endpoint, array $payload)
|
private function createResource(string $endpoint, array $payload)
|
||||||
{
|
{
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBody(json_encode($payload))
|
->withBody(json_encode($payload))
|
||||||
->call('post', $endpoint);
|
->call('post', $endpoint);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
$this->assertEquals('success', $decoded['status']);
|
$this->assertEquals('success', $decoded['status']);
|
||||||
|
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetchFirstRecord(string $endpoint, string $idKey): array
|
private function fetchFirstRecord(string $endpoint, string $idKey): array
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$response = $this->withHeaders($this->authHeaders())->call('get', $endpoint);
|
$response = $this->withHeaders($this->authHeaders())->call('get', $endpoint);
|
||||||
} catch (PageNotFoundException $e) {
|
} catch (PageNotFoundException $e) {
|
||||||
$this->markTestSkipped("{$endpoint} GET not available: {$e->getMessage()}");
|
$this->markTestSkipped("{$endpoint} GET not available: {$e->getMessage()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
$rows = $decoded['data'] ?? [];
|
$rows = $decoded['data'] ?? [];
|
||||||
|
|
||||||
if (empty($rows)) {
|
if (empty($rows)) {
|
||||||
$this->markTestSkipped("No data available at {$endpoint}");
|
$this->markTestSkipped("No data available at {$endpoint}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$record = $rows[0];
|
$record = $rows[0];
|
||||||
$this->assertArrayHasKey($idKey, $record);
|
$this->assertArrayHasKey($idKey, $record);
|
||||||
|
|
||||||
return $record;
|
return $record;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetchResource(string $endpoint, $id): array
|
private function fetchResource(string $endpoint, $id): array
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->call('get', "$endpoint/{$id}");
|
->call('get', "$endpoint/{$id}");
|
||||||
} catch (PageNotFoundException $e) {
|
} catch (PageNotFoundException $e) {
|
||||||
$this->markTestSkipped("{$endpoint}/{$id} GET not available: {$e->getMessage()}");
|
$this->markTestSkipped("{$endpoint}/{$id} GET not available: {$e->getMessage()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOccupation()
|
public function testPartialUpdateOccupation()
|
||||||
{
|
{
|
||||||
$occCode = 'PATCH_OCC_' . uniqid();
|
$occCode = 'PATCH_OCC_' . uniqid();
|
||||||
$id = $this->createResource('api/occupation', [
|
$id = $this->createResource('api/occupation', [
|
||||||
'OccCode' => $occCode,
|
'OccCode' => $occCode,
|
||||||
'OccText' => 'Original text',
|
'OccText' => 'Original text',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$originalData = $this->fetchResource('api/occupation', $id);
|
$originalData = $this->fetchResource('api/occupation', $id);
|
||||||
$originalCode = $originalData['OccCode'];
|
$originalCode = $originalData['OccCode'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/occupation/{$id}", ['OccText' => 'Patched occupation']);
|
->call('patch', "api/occupation/{$id}", ['OccText' => 'Patched occupation']);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$showData = $this->fetchResource('api/occupation', $id);
|
$showData = $this->fetchResource('api/occupation', $id);
|
||||||
|
|
||||||
$this->assertEquals('Patched occupation', $showData['OccText']);
|
$this->assertEquals('Patched occupation', $showData['OccText']);
|
||||||
$this->assertEquals($originalCode, $showData['OccCode']);
|
$this->assertEquals($originalCode, $showData['OccCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateMedicalSpecialty()
|
public function testPartialUpdateMedicalSpecialty()
|
||||||
{
|
{
|
||||||
$text = 'Specialty ' . uniqid();
|
$text = 'Specialty ' . uniqid();
|
||||||
$id = $this->createResource('api/medicalspecialty', ['SpecialtyText' => $text]);
|
$id = $this->createResource('api/medicalspecialty', ['SpecialtyText' => $text]);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/medicalspecialty/{$id}", ['SpecialtyText' => 'Updated specialty']);
|
->call('patch', "api/medicalspecialty/{$id}", ['SpecialtyText' => 'Updated specialty']);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "api/medicalspecialty/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "api/medicalspecialty/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated specialty', $showData['SpecialtyText']);
|
$this->assertEquals('Updated specialty', $showData['SpecialtyText']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCounter()
|
public function testPartialUpdateCounter()
|
||||||
{
|
{
|
||||||
$initial = 'Counter ' . uniqid();
|
$initial = 'Counter ' . uniqid();
|
||||||
$id = $this->createResource('api/counter', [
|
$id = $this->createResource('api/counter', [
|
||||||
'CounterName' => $initial,
|
'CounterName' => $initial,
|
||||||
'CounterValue' => 1,
|
'CounterValue' => 1,
|
||||||
'CounterStart' => 1,
|
'CounterStart' => 1,
|
||||||
'CounterEnd' => 10,
|
'CounterEnd' => 10,
|
||||||
'CounterReset' => 1,
|
'CounterReset' => 1,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/counter/{$id}", ['CounterName' => 'Updated counter']);
|
->call('patch', "api/counter/{$id}", ['CounterName' => 'Updated counter']);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "api/counter/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "api/counter/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated counter', $showData['CounterName']);
|
$this->assertEquals('Updated counter', $showData['CounterName']);
|
||||||
$this->assertEquals(1, (int) $showData['CounterValue']);
|
$this->assertEquals(1, (int) $showData['CounterValue']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOrganizationAccount()
|
public function testPartialUpdateOrganizationAccount()
|
||||||
{
|
{
|
||||||
$name = 'Account ' . uniqid();
|
$name = 'Account ' . uniqid();
|
||||||
$id = $this->createResource('api/organization/account', ['AccountName' => $name]);
|
$id = $this->createResource('api/organization/account', ['AccountName' => $name]);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/organization/account/{$id}", ['AccountName' => 'Updated account']);
|
->call('patch', "api/organization/account/{$id}", ['AccountName' => 'Updated account']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/account/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/account/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated account', $showData['AccountName']);
|
$this->assertEquals('Updated account', $showData['AccountName']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDiscipline()
|
public function testPartialUpdateDiscipline()
|
||||||
{
|
{
|
||||||
$code = 'DIS_' . strtoupper(bin2hex(random_bytes(2)));
|
$code = 'DIS_' . strtoupper(bin2hex(random_bytes(2)));
|
||||||
$name = 'Discipline ' . uniqid();
|
$name = 'Discipline ' . uniqid();
|
||||||
$id = $this->createResource('api/organization/discipline', [
|
$id = $this->createResource('api/organization/discipline', [
|
||||||
'DisciplineCode' => $code,
|
'DisciplineCode' => $code,
|
||||||
'DisciplineName' => $name,
|
'DisciplineName' => $name,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/organization/discipline/{$id}", ['DisciplineName' => 'Discipline Updated']);
|
->call('patch', "api/organization/discipline/{$id}", ['DisciplineName' => 'Discipline Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/discipline/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/discipline/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Discipline Updated', $showData['DisciplineName']);
|
$this->assertEquals('Discipline Updated', $showData['DisciplineName']);
|
||||||
$this->assertEquals($code, $showData['DisciplineCode']);
|
$this->assertEquals($code, $showData['DisciplineCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCodingSystem()
|
public function testPartialUpdateCodingSystem()
|
||||||
{
|
{
|
||||||
$abbr = 'CS' . strtoupper(bin2hex(random_bytes(2)));
|
$abbr = 'CS' . strtoupper(bin2hex(random_bytes(2)));
|
||||||
$full = 'Full text ' . uniqid();
|
$full = 'Full text ' . uniqid();
|
||||||
$id = $this->createResource('api/organization/codingsys', [
|
$id = $this->createResource('api/organization/codingsys', [
|
||||||
'CodingSysAbb' => $abbr,
|
'CodingSysAbb' => $abbr,
|
||||||
'FullText' => $full,
|
'FullText' => $full,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/organization/codingsys/{$id}", ['FullText' => 'Updated full text']);
|
->call('patch', "api/organization/codingsys/{$id}", ['FullText' => 'Updated full text']);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/codingsys/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/codingsys/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated full text', $showData['FullText']);
|
$this->assertEquals('Updated full text', $showData['FullText']);
|
||||||
$this->assertEquals($abbr, $showData['CodingSysAbb']);
|
$this->assertEquals($abbr, $showData['CodingSysAbb']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenContainer()
|
public function testPartialUpdateSpecimenContainer()
|
||||||
{
|
{
|
||||||
$record = $this->fetchFirstRecord('api/specimen/container', 'ConDefID');
|
$record = $this->fetchFirstRecord('api/specimen/container', 'ConDefID');
|
||||||
$id = $record['ConDefID'];
|
$id = $record['ConDefID'];
|
||||||
$newName = 'Patch Container ' . uniqid();
|
$newName = 'Patch Container ' . uniqid();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/specimen/container/{$id}", ['ConName' => $newName]);
|
->call('patch', "api/specimen/container/{$id}", ['ConName' => $newName]);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$showData = $this->fetchResource('api/specimen/container', $id);
|
$showData = $this->fetchResource('api/specimen/container', $id);
|
||||||
|
|
||||||
$this->assertEquals($newName, $showData['ConName']);
|
$this->assertEquals($newName, $showData['ConName']);
|
||||||
$this->assertEquals($record['ConCode'] ?? null, $showData['ConCode'] ?? null);
|
$this->assertEquals($record['ConCode'] ?? null, $showData['ConCode'] ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenPrep()
|
public function testPartialUpdateSpecimenPrep()
|
||||||
{
|
{
|
||||||
$record = $this->fetchFirstRecord('api/specimen/prep', 'SpcPrpID');
|
$record = $this->fetchFirstRecord('api/specimen/prep', 'SpcPrpID');
|
||||||
$id = $record['SpcPrpID'];
|
$id = $record['SpcPrpID'];
|
||||||
$newDesc = 'Partial Prep ' . uniqid();
|
$newDesc = 'Partial Prep ' . uniqid();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/specimen/prep/{$id}", ['Description' => $newDesc]);
|
->call('patch', "api/specimen/prep/{$id}", ['Description' => $newDesc]);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$showData = $this->fetchResource('api/specimen/prep', $id);
|
$showData = $this->fetchResource('api/specimen/prep', $id);
|
||||||
|
|
||||||
$this->assertEquals($newDesc, $showData['Description']);
|
$this->assertEquals($newDesc, $showData['Description']);
|
||||||
$this->assertEquals($record['SpcStaID'] ?? null, $showData['SpcStaID'] ?? null);
|
$this->assertEquals($record['SpcStaID'] ?? null, $showData['SpcStaID'] ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenStatus()
|
public function testPartialUpdateSpecimenStatus()
|
||||||
{
|
{
|
||||||
$record = $this->fetchFirstRecord('api/specimen/status', 'SpcStaID');
|
$record = $this->fetchFirstRecord('api/specimen/status', 'SpcStaID');
|
||||||
$id = $record['SpcStaID'];
|
$id = $record['SpcStaID'];
|
||||||
$newStatus = 'UpdatedStatus';
|
$newStatus = 'UpdatedStatus';
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/specimen/status/{$id}", ['SpcStatus' => $newStatus]);
|
->call('patch', "api/specimen/status/{$id}", ['SpcStatus' => $newStatus]);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$showData = $this->fetchResource('api/specimen/status', $id);
|
$showData = $this->fetchResource('api/specimen/status', $id);
|
||||||
|
|
||||||
$this->assertEquals($newStatus, $showData['SpcStatus']);
|
$this->assertEquals($newStatus, $showData['SpcStatus']);
|
||||||
$this->assertEquals($record['OrderID'] ?? null, $showData['OrderID'] ?? null);
|
$this->assertEquals($record['OrderID'] ?? null, $showData['OrderID'] ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenCollection()
|
public function testPartialUpdateSpecimenCollection()
|
||||||
{
|
{
|
||||||
$record = $this->fetchFirstRecord('api/specimen/collection', 'SpcColID');
|
$record = $this->fetchFirstRecord('api/specimen/collection', 'SpcColID');
|
||||||
$id = $record['SpcColID'];
|
$id = $record['SpcColID'];
|
||||||
$newBodySite = 'BodySite ' . uniqid();
|
$newBodySite = 'BodySite ' . uniqid();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/specimen/collection/{$id}", ['BodySite' => $newBodySite]);
|
->call('patch', "api/specimen/collection/{$id}", ['BodySite' => $newBodySite]);
|
||||||
|
|
||||||
$patch->assertStatus(201);
|
$patch->assertStatus(201);
|
||||||
$showData = $this->fetchResource('api/specimen/collection', $id);
|
$showData = $this->fetchResource('api/specimen/collection', $id);
|
||||||
|
|
||||||
$this->assertEquals($newBodySite, $showData['BodySite']);
|
$this->assertEquals($newBodySite, $showData['BodySite']);
|
||||||
$this->assertEquals($record['SpRole'] ?? null, $showData['SpRole'] ?? null);
|
$this->assertEquals($record['SpRole'] ?? null, $showData['SpRole'] ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateEquipmentList()
|
public function testPartialUpdateEquipmentList()
|
||||||
{
|
{
|
||||||
$record = $this->fetchFirstRecord('api/equipmentlist', 'EID');
|
$record = $this->fetchFirstRecord('api/equipmentlist', 'EID');
|
||||||
$id = $record['EID'];
|
$id = $record['EID'];
|
||||||
$newName = 'Equipment ' . uniqid();
|
$newName = 'Equipment ' . uniqid();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "api/equipmentlist/{$id}", ['InstrumentName' => $newName]);
|
->call('patch', "api/equipmentlist/{$id}", ['InstrumentName' => $newName]);
|
||||||
|
|
||||||
$patch->assertStatus(200, 'Equipment patch should return 200');
|
$patch->assertStatus(200, 'Equipment patch should return 200');
|
||||||
$showData = $this->fetchResource('api/equipmentlist', $id);
|
$showData = $this->fetchResource('api/equipmentlist', $id);
|
||||||
|
|
||||||
$this->assertEquals($newName, $showData['InstrumentName']);
|
$this->assertEquals($newName, $showData['InstrumentName']);
|
||||||
$this->assertEquals($record['DepartmentID'] ?? null, $showData['DepartmentID'] ?? null);
|
$this->assertEquals($record['DepartmentID'] ?? null, $showData['DepartmentID'] ?? null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\OrderTest;
|
namespace Tests\Feature\OrderTest;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class OrderTestPatchTest extends CIUnitTestCase
|
class OrderTestPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/ordertest';
|
protected string $endpoint = 'api/ordertest';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createOrderTest(array $data = []): array
|
private function createOrderTest(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'OrderCode' => 'ORD_' . uniqid(),
|
'OrderCode' => 'ORD_' . uniqid(),
|
||||||
'OrderName' => 'Test Order ' . uniqid(),
|
'OrderName' => 'Test Order ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOrderTestSuccess()
|
public function testPartialUpdateOrderTestSuccess()
|
||||||
{
|
{
|
||||||
$order = $this->createOrderTest();
|
$order = $this->createOrderTest();
|
||||||
$id = $order['OrderID'];
|
$id = $order['OrderID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['OrderName' => 'Updated Order']);
|
->call('patch', "{$this->endpoint}/{$id}", ['OrderName' => 'Updated Order']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Order', $showData['OrderName']);
|
$this->assertEquals('Updated Order', $showData['OrderName']);
|
||||||
$this->assertEquals($order['OrderCode'], $showData['OrderCode']);
|
$this->assertEquals($order['OrderCode'], $showData['OrderCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOrderTestNotFound()
|
public function testPartialUpdateOrderTestNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['OrderName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['OrderName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOrderTestInvalidId()
|
public function testPartialUpdateOrderTestInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['OrderName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['OrderName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOrderTestEmptyPayload()
|
public function testPartialUpdateOrderTestEmptyPayload()
|
||||||
{
|
{
|
||||||
$order = $this->createOrderTest();
|
$order = $this->createOrderTest();
|
||||||
$id = $order['OrderID'];
|
$id = $order['OrderID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateOrderTestSingleField()
|
public function testPartialUpdateOrderTestSingleField()
|
||||||
{
|
{
|
||||||
$order = $this->createOrderTest();
|
$order = $this->createOrderTest();
|
||||||
$id = $order['OrderID'];
|
$id = $order['OrderID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['OrderCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['OrderCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($order['OrderCode'], $showData['OrderCode']);
|
$this->assertNotEquals($order['OrderCode'], $showData['OrderCode']);
|
||||||
$this->assertEquals($order['OrderName'], $showData['OrderName']);
|
$this->assertEquals($order['OrderName'], $showData['OrderName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class AccountPatchTest extends CIUnitTestCase
|
class AccountPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $endpoint = 'api/organization/account';
|
protected string $endpoint = 'api/organization/account';
|
||||||
protected string $token;
|
protected string $token;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createAccount(array $data = []): int
|
private function createAccount(array $data = []): int
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'AccountName' => 'Account ' . uniqid(),
|
'AccountName' => 'Account ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetchAccount(int $id): array
|
private function fetchAccount(int $id): array
|
||||||
{
|
{
|
||||||
$response = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$response = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
|
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
return $decoded['data'] ?? [];
|
return $decoded['data'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateAccountSuccess()
|
public function testPartialUpdateAccountSuccess()
|
||||||
{
|
{
|
||||||
$id = $this->createAccount();
|
$id = $this->createAccount();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['AccountName' => 'Updated Account']);
|
->call('patch', "{$this->endpoint}/{$id}", ['AccountName' => 'Updated Account']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$this->assertSame('success', json_decode($patch->getJSON(), true)['status']);
|
$this->assertSame('success', json_decode($patch->getJSON(), true)['status']);
|
||||||
|
|
||||||
$account = $this->fetchAccount($id);
|
$account = $this->fetchAccount($id);
|
||||||
$this->assertEquals('Updated Account', $account['AccountName']);
|
$this->assertEquals('Updated Account', $account['AccountName']);
|
||||||
$this->assertEquals($id, $account['AccountID']);
|
$this->assertEquals($id, $account['AccountID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateAccountNotFound()
|
public function testPartialUpdateAccountNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['AccountName' => 'Does not matter']);
|
->call('patch', "{$this->endpoint}/999999", ['AccountName' => 'Does not matter']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateAccountInvalidId()
|
public function testPartialUpdateAccountInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['AccountName' => 'Bad']);
|
->call('patch', "{$this->endpoint}/invalid", ['AccountName' => 'Bad']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateAccountEmptyPayload()
|
public function testPartialUpdateAccountEmptyPayload()
|
||||||
{
|
{
|
||||||
$id = $this->createAccount();
|
$id = $this->createAccount();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateAccountSingleField()
|
public function testPartialUpdateAccountSingleField()
|
||||||
{
|
{
|
||||||
$id = $this->createAccount(['AccountName' => 'Original Name']);
|
$id = $this->createAccount(['AccountName' => 'Original Name']);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['AccountName' => 'New Name']);
|
->call('patch', "{$this->endpoint}/{$id}", ['AccountName' => 'New Name']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$account = $this->fetchAccount($id);
|
$account = $this->fetchAccount($id);
|
||||||
|
|
||||||
$this->assertEquals('New Name', $account['AccountName']);
|
$this->assertEquals('New Name', $account['AccountName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,31 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
|
|
||||||
class CodingSysControllerTest extends CIUnitTestCase
|
class CodingSysControllerTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected $endpoint = 'api/organization/codingsys';
|
protected $endpoint = 'api/organization/codingsys';
|
||||||
|
|
||||||
public function testIndexCodingSys()
|
public function testIndexCodingSys()
|
||||||
{
|
{
|
||||||
$result = $this->get($this->endpoint);
|
$result = $this->get($this->endpoint);
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateCodingSys()
|
public function testCreateCodingSys()
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
'CodingSysAbb' => 'ICD' . substr(time(), -3),
|
'CodingSysAbb' => 'ICD' . substr(time(), -3),
|
||||||
'FullText' => 'International Classification of Diseases 10 ' . time(),
|
'FullText' => 'International Classification of Diseases 10 ' . time(),
|
||||||
'Description' => 'Medical diagnosis coding system'
|
'Description' => 'Medical diagnosis coding system'
|
||||||
];
|
];
|
||||||
|
|
||||||
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
|
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
|
||||||
$result->assertStatus(201);
|
$result->assertStatus(201);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,123 +1,123 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class DepartmentPatchTest extends CIUnitTestCase
|
class DepartmentPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/organization/department';
|
protected string $endpoint = 'api/organization/department';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createDepartment(array $data = []): array
|
private function createDepartment(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'DepartmentCode' => 'DEPT_' . uniqid(),
|
'DepartmentCode' => 'DEPT_' . uniqid(),
|
||||||
'DepartmentName' => 'Test Department ' . uniqid(),
|
'DepartmentName' => 'Test Department ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
if ($response->getStatusCode() !== 201) {
|
if ($response->getStatusCode() !== 201) {
|
||||||
$this->markTestSkipped('Failed to create test department');
|
$this->markTestSkipped('Failed to create test department');
|
||||||
}
|
}
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'] ?? [];
|
return $decoded['data'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDepartmentSuccess()
|
public function testPartialUpdateDepartmentSuccess()
|
||||||
{
|
{
|
||||||
$dept = $this->createDepartment();
|
$dept = $this->createDepartment();
|
||||||
$id = $dept['DepartmentID'];
|
$id = $dept['DepartmentID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['DepartmentName' => 'Updated Department']);
|
->call('patch', "{$this->endpoint}/{$id}", ['DepartmentName' => 'Updated Department']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Department', $showData['DepartmentName']);
|
$this->assertEquals('Updated Department', $showData['DepartmentName']);
|
||||||
$this->assertEquals($dept['DepartmentCode'], $showData['DepartmentCode']);
|
$this->assertEquals($dept['DepartmentCode'], $showData['DepartmentCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDepartmentNotFound()
|
public function testPartialUpdateDepartmentNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['DepartmentName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['DepartmentName' => 'Updated']);
|
||||||
|
|
||||||
$this->assertTrue(in_array($patch->getStatusCode(), [404, 400, 201]));
|
$this->assertTrue(in_array($patch->getStatusCode(), [404, 400, 201]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDepartmentZeroId()
|
public function testPartialUpdateDepartmentZeroId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/0", ['DepartmentName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/0", ['DepartmentName' => 'Updated']);
|
||||||
|
|
||||||
$this->assertTrue(in_array($patch->getStatusCode(), [404, 400, 201]));
|
$this->assertTrue(in_array($patch->getStatusCode(), [404, 400, 201]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDepartmentEmptyPayload()
|
public function testPartialUpdateDepartmentEmptyPayload()
|
||||||
{
|
{
|
||||||
$dept = $this->createDepartment();
|
$dept = $this->createDepartment();
|
||||||
$id = $dept['DepartmentID'];
|
$id = $dept['DepartmentID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDepartmentSingleField()
|
public function testPartialUpdateDepartmentSingleField()
|
||||||
{
|
{
|
||||||
$dept = $this->createDepartment();
|
$dept = $this->createDepartment();
|
||||||
$id = $dept['DepartmentID'];
|
$id = $dept['DepartmentID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['DepartmentCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['DepartmentCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($dept['DepartmentCode'], $showData['DepartmentCode']);
|
$this->assertNotEquals($dept['DepartmentCode'], $showData['DepartmentCode']);
|
||||||
$this->assertEquals($dept['DepartmentName'], $showData['DepartmentName']);
|
$this->assertEquals($dept['DepartmentName'], $showData['DepartmentName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class DisciplinePatchTest extends CIUnitTestCase
|
class DisciplinePatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $endpoint = 'api/organization/discipline';
|
protected string $endpoint = 'api/organization/discipline';
|
||||||
protected string $token;
|
protected string $token;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createDiscipline(array $data = []): int
|
private function createDiscipline(array $data = []): int
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'DisciplineCode' => 'D' . strtoupper(bin2hex(random_bytes(1))),
|
'DisciplineCode' => 'D' . strtoupper(bin2hex(random_bytes(1))),
|
||||||
'DisciplineName' => 'Discipline ' . uniqid(),
|
'DisciplineName' => 'Discipline ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetchDiscipline(int $id): array
|
private function fetchDiscipline(int $id): array
|
||||||
{
|
{
|
||||||
$response = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$response = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
return $decoded['data'] ?? [];
|
return $decoded['data'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDisciplineSuccess()
|
public function testPartialUpdateDisciplineSuccess()
|
||||||
{
|
{
|
||||||
$id = $this->createDiscipline();
|
$id = $this->createDiscipline();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['DisciplineName' => 'Updated Discipline']);
|
->call('patch', "{$this->endpoint}/{$id}", ['DisciplineName' => 'Updated Discipline']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$this->assertSame('success', json_decode($patch->getJSON(), true)['status']);
|
$this->assertSame('success', json_decode($patch->getJSON(), true)['status']);
|
||||||
|
|
||||||
$discipline = $this->fetchDiscipline($id);
|
$discipline = $this->fetchDiscipline($id);
|
||||||
$this->assertEquals('Updated Discipline', $discipline['DisciplineName']);
|
$this->assertEquals('Updated Discipline', $discipline['DisciplineName']);
|
||||||
$this->assertEquals($id, $discipline['DisciplineID']);
|
$this->assertEquals($id, $discipline['DisciplineID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDisciplineNotFound()
|
public function testPartialUpdateDisciplineNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['DisciplineName' => 'Does not matter']);
|
->call('patch', "{$this->endpoint}/999999", ['DisciplineName' => 'Does not matter']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDisciplineInvalidId()
|
public function testPartialUpdateDisciplineInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['DisciplineName' => 'Bad']);
|
->call('patch', "{$this->endpoint}/invalid", ['DisciplineName' => 'Bad']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDisciplineEmptyPayload()
|
public function testPartialUpdateDisciplineEmptyPayload()
|
||||||
{
|
{
|
||||||
$id = $this->createDiscipline();
|
$id = $this->createDiscipline();
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateDisciplineSingleField()
|
public function testPartialUpdateDisciplineSingleField()
|
||||||
{
|
{
|
||||||
$id = $this->createDiscipline(['DisciplineName' => 'Original Name']);
|
$id = $this->createDiscipline(['DisciplineName' => 'Original Name']);
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['DisciplineName' => 'New Name']);
|
->call('patch', "{$this->endpoint}/{$id}", ['DisciplineName' => 'New Name']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$discipline = $this->fetchDiscipline($id);
|
$discipline = $this->fetchDiscipline($id);
|
||||||
|
|
||||||
$this->assertEquals('New Name', $discipline['DisciplineName']);
|
$this->assertEquals('New Name', $discipline['DisciplineName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,35 +1,35 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
|
|
||||||
class HostAppControllerTest extends CIUnitTestCase
|
class HostAppControllerTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected $endpoint = 'api/organization/hostapp';
|
protected $endpoint = 'api/organization/hostapp';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIndexHostApp()
|
public function testIndexHostApp()
|
||||||
{
|
{
|
||||||
$result = $this->get($this->endpoint);
|
$result = $this->get($this->endpoint);
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateHostApp()
|
public function testCreateHostApp()
|
||||||
{
|
{
|
||||||
$payload = [
|
$payload = [
|
||||||
'HostAppName' => 'Test Host Application',
|
'HostAppName' => 'Test Host Application',
|
||||||
'SiteID' => null
|
'SiteID' => null
|
||||||
];
|
];
|
||||||
|
|
||||||
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
|
$result = $this->withBodyFormat('json')->post($this->endpoint, $payload);
|
||||||
$result->assertStatus(201);
|
$result->assertStatus(201);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,122 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class HostAppPatchTest extends CIUnitTestCase
|
class HostAppPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/organization/hostapp';
|
protected string $endpoint = 'api/organization/hostapp';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createHostApp(array $data = []): array
|
private function createHostApp(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'HostAppName' => 'Test HostApp ' . uniqid(),
|
'HostAppName' => 'Test HostApp ' . uniqid(),
|
||||||
'SiteID' => null,
|
'SiteID' => null,
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
$id = $decoded['data'];
|
$id = $decoded['data'];
|
||||||
return array_merge(['HostAppID' => $id], $payload);
|
return array_merge(['HostAppID' => $id], $payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostAppSuccess()
|
public function testPartialUpdateHostAppSuccess()
|
||||||
{
|
{
|
||||||
$app = $this->createHostApp();
|
$app = $this->createHostApp();
|
||||||
$id = $app['HostAppID'];
|
$id = $app['HostAppID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['HostAppName' => 'Updated HostApp']);
|
->call('patch', "{$this->endpoint}/{$id}", ['HostAppName' => 'Updated HostApp']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated HostApp', $showData['HostAppName']);
|
$this->assertEquals('Updated HostApp', $showData['HostAppName']);
|
||||||
$this->assertEquals($app['SiteID'], $showData['SiteID']);
|
$this->assertEquals($app['SiteID'], $showData['SiteID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostAppNotFound()
|
public function testPartialUpdateHostAppNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['HostAppName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['HostAppName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostAppInvalidId()
|
public function testPartialUpdateHostAppInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['HostAppName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['HostAppName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostAppEmptyPayload()
|
public function testPartialUpdateHostAppEmptyPayload()
|
||||||
{
|
{
|
||||||
$app = $this->createHostApp();
|
$app = $this->createHostApp();
|
||||||
$id = $app['HostAppID'];
|
$id = $app['HostAppID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostAppSingleField()
|
public function testPartialUpdateHostAppSingleField()
|
||||||
{
|
{
|
||||||
$app = $this->createHostApp();
|
$app = $this->createHostApp();
|
||||||
$id = $app['HostAppID'];
|
$id = $app['HostAppID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SiteID' => 5]);
|
->call('patch', "{$this->endpoint}/{$id}", ['SiteID' => 5]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($app['SiteID'], $showData['SiteID']);
|
$this->assertNotEquals($app['SiteID'], $showData['SiteID']);
|
||||||
$this->assertEquals($app['HostAppName'], $showData['HostAppName']);
|
$this->assertEquals($app['HostAppName'], $showData['HostAppName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class HostComParaPatchTest extends CIUnitTestCase
|
class HostComParaPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/organization/hostcompara';
|
protected string $endpoint = 'api/organization/hostcompara';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createHostComPara(array $data = []): array
|
private function createHostComPara(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'HostComParaCode' => 'HCP_' . uniqid(),
|
'HostComParaCode' => 'HCP_' . uniqid(),
|
||||||
'HostComParaName' => 'Test HostComPara ' . uniqid(),
|
'HostComParaName' => 'Test HostComPara ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostComParaSuccess()
|
public function testPartialUpdateHostComParaSuccess()
|
||||||
{
|
{
|
||||||
$para = $this->createHostComPara();
|
$para = $this->createHostComPara();
|
||||||
$id = $para['HostComParaID'];
|
$id = $para['HostComParaID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['HostComParaName' => 'Updated HostComPara']);
|
->call('patch', "{$this->endpoint}/{$id}", ['HostComParaName' => 'Updated HostComPara']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated HostComPara', $showData['HostComParaName']);
|
$this->assertEquals('Updated HostComPara', $showData['HostComParaName']);
|
||||||
$this->assertEquals($para['HostComParaCode'], $showData['HostComParaCode']);
|
$this->assertEquals($para['HostComParaCode'], $showData['HostComParaCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostComParaNotFound()
|
public function testPartialUpdateHostComParaNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['HostComParaName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['HostComParaName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostComParaInvalidId()
|
public function testPartialUpdateHostComParaInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['HostComParaName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['HostComParaName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostComParaEmptyPayload()
|
public function testPartialUpdateHostComParaEmptyPayload()
|
||||||
{
|
{
|
||||||
$para = $this->createHostComPara();
|
$para = $this->createHostComPara();
|
||||||
$id = $para['HostComParaID'];
|
$id = $para['HostComParaID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateHostComParaSingleField()
|
public function testPartialUpdateHostComParaSingleField()
|
||||||
{
|
{
|
||||||
$para = $this->createHostComPara();
|
$para = $this->createHostComPara();
|
||||||
$id = $para['HostComParaID'];
|
$id = $para['HostComParaID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['HostComParaCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['HostComParaCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($para['HostComParaCode'], $showData['HostComParaCode']);
|
$this->assertNotEquals($para['HostComParaCode'], $showData['HostComParaCode']);
|
||||||
$this->assertEquals($para['HostComParaName'], $showData['HostComParaName']);
|
$this->assertEquals($para['HostComParaName'], $showData['HostComParaName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class SitePatchTest extends CIUnitTestCase
|
class SitePatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/organization/site';
|
protected string $endpoint = 'api/organization/site';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createSite(array $data = []): array
|
private function createSite(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'SiteCode' => 'SITE_' . uniqid(),
|
'SiteCode' => 'SITE_' . uniqid(),
|
||||||
'SiteName' => 'Test Site ' . uniqid(),
|
'SiteName' => 'Test Site ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSiteSuccess()
|
public function testPartialUpdateSiteSuccess()
|
||||||
{
|
{
|
||||||
$site = $this->createSite();
|
$site = $this->createSite();
|
||||||
$id = $site['SiteID'];
|
$id = $site['SiteID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SiteName' => 'Updated Site']);
|
->call('patch', "{$this->endpoint}/{$id}", ['SiteName' => 'Updated Site']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Site', $showData['SiteName']);
|
$this->assertEquals('Updated Site', $showData['SiteName']);
|
||||||
$this->assertEquals($site['SiteCode'], $showData['SiteCode']);
|
$this->assertEquals($site['SiteCode'], $showData['SiteCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSiteNotFound()
|
public function testPartialUpdateSiteNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['SiteName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['SiteName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSiteInvalidId()
|
public function testPartialUpdateSiteInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['SiteName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['SiteName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSiteEmptyPayload()
|
public function testPartialUpdateSiteEmptyPayload()
|
||||||
{
|
{
|
||||||
$site = $this->createSite();
|
$site = $this->createSite();
|
||||||
$id = $site['SiteID'];
|
$id = $site['SiteID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSiteSingleField()
|
public function testPartialUpdateSiteSingleField()
|
||||||
{
|
{
|
||||||
$site = $this->createSite();
|
$site = $this->createSite();
|
||||||
$id = $site['SiteID'];
|
$id = $site['SiteID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SiteCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['SiteCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($site['SiteCode'], $showData['SiteCode']);
|
$this->assertNotEquals($site['SiteCode'], $showData['SiteCode']);
|
||||||
$this->assertEquals($site['SiteName'], $showData['SiteName']);
|
$this->assertEquals($site['SiteName'], $showData['SiteName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,122 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Organization;
|
namespace Tests\Feature\Organization;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class WorkstationPatchTest extends CIUnitTestCase
|
class WorkstationPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/organization/workstation';
|
protected string $endpoint = 'api/organization/workstation';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createWorkstation(array $data = []): array
|
private function createWorkstation(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'WorkstationCode' => 'WS_' . uniqid(),
|
'WorkstationCode' => 'WS_' . uniqid(),
|
||||||
'WorkstationName' => 'Test Workstation ' . uniqid(),
|
'WorkstationName' => 'Test Workstation ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
$id = $decoded['data'];
|
$id = $decoded['data'];
|
||||||
return array_merge(['WorkstationID' => $id], $payload);
|
return array_merge(['WorkstationID' => $id], $payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateWorkstationSuccess()
|
public function testPartialUpdateWorkstationSuccess()
|
||||||
{
|
{
|
||||||
$ws = $this->createWorkstation();
|
$ws = $this->createWorkstation();
|
||||||
$id = $ws['WorkstationID'];
|
$id = $ws['WorkstationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['WorkstationName' => 'Updated Workstation']);
|
->call('patch', "{$this->endpoint}/{$id}", ['WorkstationName' => 'Updated Workstation']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Workstation', $showData['WorkstationName']);
|
$this->assertEquals('Updated Workstation', $showData['WorkstationName']);
|
||||||
$this->assertEquals($ws['WorkstationCode'], $showData['WorkstationCode']);
|
$this->assertEquals($ws['WorkstationCode'], $showData['WorkstationCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateWorkstationNotFound()
|
public function testPartialUpdateWorkstationNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['WorkstationName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['WorkstationName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateWorkstationInvalidId()
|
public function testPartialUpdateWorkstationInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['WorkstationName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['WorkstationName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateWorkstationEmptyPayload()
|
public function testPartialUpdateWorkstationEmptyPayload()
|
||||||
{
|
{
|
||||||
$ws = $this->createWorkstation();
|
$ws = $this->createWorkstation();
|
||||||
$id = $ws['WorkstationID'];
|
$id = $ws['WorkstationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateWorkstationSingleField()
|
public function testPartialUpdateWorkstationSingleField()
|
||||||
{
|
{
|
||||||
$ws = $this->createWorkstation();
|
$ws = $this->createWorkstation();
|
||||||
$id = $ws['WorkstationID'];
|
$id = $ws['WorkstationID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['WorkstationCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['WorkstationCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($ws['WorkstationCode'], $showData['WorkstationCode']);
|
$this->assertNotEquals($ws['WorkstationCode'], $showData['WorkstationCode']);
|
||||||
$this->assertEquals($ws['WorkstationName'], $showData['WorkstationName']);
|
$this->assertEquals($ws['WorkstationName'], $showData['WorkstationName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,97 +1,97 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\PatVisit;
|
namespace Tests\Feature\PatVisit;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Tests\Support\Traits\CreatesPatients;
|
use Tests\Support\Traits\CreatesPatients;
|
||||||
|
|
||||||
class PatVisitADTPatchTest extends CIUnitTestCase
|
class PatVisitADTPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
use CreatesPatients;
|
use CreatesPatients;
|
||||||
|
|
||||||
protected string $endpoint = 'api/patvisitadt';
|
protected string $endpoint = 'api/patvisitadt';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createPatVisitADT(array $data = []): array
|
private function createPatVisitADT(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'InternalPID' => $this->createTestPatient(),
|
'InternalPID' => $this->createTestPatient(),
|
||||||
'ADTCode' => 'A01',
|
'ADTCode' => 'A01',
|
||||||
'LocationID' => '1',
|
'LocationID' => '1',
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
$response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload);
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePatVisitADTSuccess()
|
public function testPartialUpdatePatVisitADTSuccess()
|
||||||
{
|
{
|
||||||
$adt = $this->createPatVisitADT();
|
$adt = $this->createPatVisitADT();
|
||||||
$id = $adt['ADTID'];
|
$id = $adt['ADTID'];
|
||||||
|
|
||||||
$patch = $this->withBodyFormat('json')
|
$patch = $this->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ADTCode' => 'A02']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ADTCode' => 'A02']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('A02', $showData['ADTCode']);
|
$this->assertEquals('A02', $showData['ADTCode']);
|
||||||
$this->assertEquals($adt['LocationID'], $showData['LocationID']);
|
$this->assertEquals($adt['LocationID'], $showData['LocationID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePatVisitADTNotFound()
|
public function testPartialUpdatePatVisitADTNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withBodyFormat('json')
|
$patch = $this->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['ADTCode' => 'A02']);
|
->call('patch', "{$this->endpoint}/999999", ['ADTCode' => 'A02']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePatVisitADTInvalidId()
|
public function testPartialUpdatePatVisitADTInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withBodyFormat('json')
|
$patch = $this->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['ADTCode' => 'A02']);
|
->call('patch', "{$this->endpoint}/invalid", ['ADTCode' => 'A02']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePatVisitADTEmptyPayload()
|
public function testPartialUpdatePatVisitADTEmptyPayload()
|
||||||
{
|
{
|
||||||
$adt = $this->createPatVisitADT();
|
$adt = $this->createPatVisitADT();
|
||||||
$id = $adt['ADTID'];
|
$id = $adt['ADTID'];
|
||||||
|
|
||||||
$patch = $this->withBodyFormat('json')
|
$patch = $this->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePatVisitADTSingleField()
|
public function testPartialUpdatePatVisitADTSingleField()
|
||||||
{
|
{
|
||||||
$adt = $this->createPatVisitADT();
|
$adt = $this->createPatVisitADT();
|
||||||
$id = $adt['ADTID'];
|
$id = $adt['ADTID'];
|
||||||
|
|
||||||
$patch = $this->withBodyFormat('json')
|
$patch = $this->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ADTCode' => 'A03']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ADTCode' => 'A03']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->call('get', "{$this->endpoint}/{$id}")
|
$showData = json_decode($this->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('A03', $showData['ADTCode']);
|
$this->assertEquals('A03', $showData['ADTCode']);
|
||||||
$this->assertEquals($adt['LocationID'], $showData['LocationID']);
|
$this->assertEquals($adt['LocationID'], $showData['LocationID']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,119 +1,119 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Patients;
|
namespace Tests\Feature\Patients;
|
||||||
|
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use Faker\Factory;
|
use Faker\Factory;
|
||||||
|
|
||||||
class PatientCheckTest extends CIUnitTestCase
|
class PatientCheckTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected $endpoint = 'api/patient/check';
|
protected $endpoint = 'api/patient/check';
|
||||||
|
|
||||||
public function testCheckPatientIDExists()
|
public function testCheckPatientIDExists()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'PatientID' => 'SMAJ1',
|
'PatientID' => 'SMAJ1',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $data['status']);
|
$this->assertSame('success', $data['status']);
|
||||||
$this->assertSame(false, $data['data']);
|
$this->assertSame(false, $data['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckPatientIDWithHyphenExists()
|
public function testCheckPatientIDWithHyphenExists()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'PatientID' => 'SMAJ-1',
|
'PatientID' => 'SMAJ-1',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $data['status']);
|
$this->assertSame('success', $data['status']);
|
||||||
$this->assertIsBool($data['data']);
|
$this->assertIsBool($data['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckPatientIDNotExists()
|
public function testCheckPatientIDNotExists()
|
||||||
{
|
{
|
||||||
$faker = Factory::create();
|
$faker = Factory::create();
|
||||||
|
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'PatientID' => 'NONEXISTENT-' . $faker->numberBetween(100000, 999999),
|
'PatientID' => 'NONEXISTENT-' . $faker->numberBetween(100000, 999999),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $data['status']);
|
$this->assertSame('success', $data['status']);
|
||||||
$this->assertTrue($data['data']);
|
$this->assertTrue($data['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckEmailAddressExists()
|
public function testCheckEmailAddressExists()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'EmailAddress' => 'dummy1@test.com',
|
'EmailAddress' => 'dummy1@test.com',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $data['status']);
|
$this->assertSame('success', $data['status']);
|
||||||
$this->assertIsBool($data['data']);
|
$this->assertIsBool($data['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckEmailAddressMatchesSecondaryColumn()
|
public function testCheckEmailAddressMatchesSecondaryColumn()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'EmailAddress' => 'dummy1@test.com',
|
'EmailAddress' => 'dummy1@test.com',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $data['status']);
|
$this->assertSame('success', $data['status']);
|
||||||
$this->assertIsBool($data['data']);
|
$this->assertIsBool($data['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckPhoneExists()
|
public function testCheckPhoneExists()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'Phone' => '092029',
|
'Phone' => '092029',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $data['status']);
|
$this->assertSame('success', $data['status']);
|
||||||
$this->assertIsBool($data['data']);
|
$this->assertIsBool($data['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckWithoutParams()
|
public function testCheckWithoutParams()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint);
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint);
|
||||||
|
|
||||||
$result->assertStatus(400);
|
$result->assertStatus(400);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('error', $data['status']);
|
$this->assertSame('error', $data['status']);
|
||||||
$this->assertSame('PatientID, EmailAddress, or Phone parameter is required.', $data['message']);
|
$this->assertSame('PatientID, EmailAddress, or Phone parameter is required.', $data['message']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCheckResponseStructure()
|
public function testCheckResponseStructure()
|
||||||
{
|
{
|
||||||
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
$result = $this->withHeaders(['Accept' => 'application/json'])->call('get', $this->endpoint, [
|
||||||
'PatientID' => 'TEST123',
|
'PatientID' => 'TEST123',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$result->assertStatus(200);
|
$result->assertStatus(200);
|
||||||
$data = json_decode($result->getJSON(), true);
|
$data = json_decode($result->getJSON(), true);
|
||||||
|
|
||||||
$this->assertArrayHasKey('status', $data);
|
$this->assertArrayHasKey('status', $data);
|
||||||
$this->assertArrayHasKey('message', $data);
|
$this->assertArrayHasKey('message', $data);
|
||||||
$this->assertArrayHasKey('data', $data);
|
$this->assertArrayHasKey('data', $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Result;
|
namespace Tests\Feature\Result;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class ResultPatchTest extends CIUnitTestCase
|
class ResultPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/result';
|
protected string $endpoint = 'api/result';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createResult(array $data = []): array
|
private function createResult(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'ResultCode' => 'RES_' . uniqid(),
|
'ResultCode' => 'RES_' . uniqid(),
|
||||||
'ResultValue' => 'Test Value ' . uniqid(),
|
'ResultValue' => 'Test Value ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateResultSuccess()
|
public function testPartialUpdateResultSuccess()
|
||||||
{
|
{
|
||||||
$result = $this->createResult();
|
$result = $this->createResult();
|
||||||
$id = $result['ResultID'];
|
$id = $result['ResultID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ResultValue' => 'Updated Value']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ResultValue' => 'Updated Value']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Value', $showData['ResultValue']);
|
$this->assertEquals('Updated Value', $showData['ResultValue']);
|
||||||
$this->assertEquals($result['ResultCode'], $showData['ResultCode']);
|
$this->assertEquals($result['ResultCode'], $showData['ResultCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateResultNotFound()
|
public function testPartialUpdateResultNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['ResultValue' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['ResultValue' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateResultInvalidId()
|
public function testPartialUpdateResultInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['ResultValue' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['ResultValue' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateResultEmptyPayload()
|
public function testPartialUpdateResultEmptyPayload()
|
||||||
{
|
{
|
||||||
$result = $this->createResult();
|
$result = $this->createResult();
|
||||||
$id = $result['ResultID'];
|
$id = $result['ResultID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateResultSingleField()
|
public function testPartialUpdateResultSingleField()
|
||||||
{
|
{
|
||||||
$result = $this->createResult();
|
$result = $this->createResult();
|
||||||
$id = $result['ResultID'];
|
$id = $result['ResultID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ResultCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['ResultCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($result['ResultCode'], $showData['ResultCode']);
|
$this->assertNotEquals($result['ResultCode'], $showData['ResultCode']);
|
||||||
$this->assertEquals($result['ResultValue'], $showData['ResultValue']);
|
$this->assertEquals($result['ResultValue'], $showData['ResultValue']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,122 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Rule;
|
namespace Tests\Feature\Rule;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class RulePatchTest extends CIUnitTestCase
|
class RulePatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/rule';
|
protected string $endpoint = 'api/rule';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createRule(array $data = []): array
|
private function createRule(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'RuleCode' => 'RULE_' . uniqid(),
|
'RuleCode' => 'RULE_' . uniqid(),
|
||||||
'RuleName' => 'Test Rule ' . uniqid(),
|
'RuleName' => 'Test Rule ' . uniqid(),
|
||||||
'RuleExpression' => 'test_expression',
|
'RuleExpression' => 'test_expression',
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateRuleSuccess()
|
public function testPartialUpdateRuleSuccess()
|
||||||
{
|
{
|
||||||
$rule = $this->createRule();
|
$rule = $this->createRule();
|
||||||
$id = $rule['RuleID'];
|
$id = $rule['RuleID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['RuleName' => 'Updated Rule']);
|
->call('patch', "{$this->endpoint}/{$id}", ['RuleName' => 'Updated Rule']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Rule', $showData['RuleName']);
|
$this->assertEquals('Updated Rule', $showData['RuleName']);
|
||||||
$this->assertEquals($rule['RuleCode'], $showData['RuleCode']);
|
$this->assertEquals($rule['RuleCode'], $showData['RuleCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateRuleNotFound()
|
public function testPartialUpdateRuleNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['RuleName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['RuleName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateRuleInvalidId()
|
public function testPartialUpdateRuleInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['RuleName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['RuleName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateRuleEmptyPayload()
|
public function testPartialUpdateRuleEmptyPayload()
|
||||||
{
|
{
|
||||||
$rule = $this->createRule();
|
$rule = $this->createRule();
|
||||||
$id = $rule['RuleID'];
|
$id = $rule['RuleID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateRuleSingleField()
|
public function testPartialUpdateRuleSingleField()
|
||||||
{
|
{
|
||||||
$rule = $this->createRule();
|
$rule = $this->createRule();
|
||||||
$id = $rule['RuleID'];
|
$id = $rule['RuleID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['RuleCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['RuleCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($rule['RuleCode'], $showData['RuleCode']);
|
$this->assertNotEquals($rule['RuleCode'], $showData['RuleCode']);
|
||||||
$this->assertEquals($rule['RuleName'], $showData['RuleName']);
|
$this->assertEquals($rule['RuleName'], $showData['RuleName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,118 +1,118 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Specimen;
|
namespace Tests\Feature\Specimen;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class CollectionPatchTest extends CIUnitTestCase
|
class CollectionPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/specimen/collection';
|
protected string $endpoint = 'api/specimen/collection';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createCollection(array $data = []): array
|
private function createCollection(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'BodySite' => 'BodySite_' . uniqid(),
|
'BodySite' => 'BodySite_' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCollectionSuccess()
|
public function testPartialUpdateCollectionSuccess()
|
||||||
{
|
{
|
||||||
$collection = $this->createCollection();
|
$collection = $this->createCollection();
|
||||||
$id = $collection['SpcColID'];
|
$id = $collection['SpcColID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['BodySite' => 'UpdatedBodySite']);
|
->call('patch', "{$this->endpoint}/{$id}", ['BodySite' => 'UpdatedBodySite']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('UpdatedBodySite', $showData['BodySite']);
|
$this->assertEquals('UpdatedBodySite', $showData['BodySite']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCollectionNotFound()
|
public function testPartialUpdateCollectionNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['BodySite' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['BodySite' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCollectionInvalidId()
|
public function testPartialUpdateCollectionInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['BodySite' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['BodySite' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCollectionEmptyPayload()
|
public function testPartialUpdateCollectionEmptyPayload()
|
||||||
{
|
{
|
||||||
$collection = $this->createCollection();
|
$collection = $this->createCollection();
|
||||||
$id = $collection['SpcColID'];
|
$id = $collection['SpcColID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateCollectionSingleField()
|
public function testPartialUpdateCollectionSingleField()
|
||||||
{
|
{
|
||||||
$collection = $this->createCollection();
|
$collection = $this->createCollection();
|
||||||
$id = $collection['SpcColID'];
|
$id = $collection['SpcColID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['BodySite' => 'NewBodySite']);
|
->call('patch', "{$this->endpoint}/{$id}", ['BodySite' => 'NewBodySite']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('NewBodySite', $showData['BodySite']);
|
$this->assertEquals('NewBodySite', $showData['BodySite']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,122 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Specimen;
|
namespace Tests\Feature\Specimen;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class ContainerPatchTest extends CIUnitTestCase
|
class ContainerPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/specimen/container';
|
protected string $endpoint = 'api/specimen/container';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createContainer(array $data = []): array
|
private function createContainer(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'ConCode' => 'CON_' . uniqid(),
|
'ConCode' => 'CON_' . uniqid(),
|
||||||
'ConName' => 'Test Container ' . uniqid(),
|
'ConName' => 'Test Container ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
$id = $decoded['data'];
|
$id = $decoded['data'];
|
||||||
return array_merge(['ConDefID' => $id], $payload);
|
return array_merge(['ConDefID' => $id], $payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateContainerSuccess()
|
public function testPartialUpdateContainerSuccess()
|
||||||
{
|
{
|
||||||
$container = $this->createContainer();
|
$container = $this->createContainer();
|
||||||
$id = $container['ConDefID'];
|
$id = $container['ConDefID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ConName' => 'Updated Container']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ConName' => 'Updated Container']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Container', $showData['ConName']);
|
$this->assertEquals('Updated Container', $showData['ConName']);
|
||||||
$this->assertEquals($container['ConCode'], $showData['ConCode']);
|
$this->assertEquals($container['ConCode'], $showData['ConCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateContainerNotFound()
|
public function testPartialUpdateContainerNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['ConName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['ConName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateContainerInvalidId()
|
public function testPartialUpdateContainerInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['ConName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['ConName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateContainerEmptyPayload()
|
public function testPartialUpdateContainerEmptyPayload()
|
||||||
{
|
{
|
||||||
$container = $this->createContainer();
|
$container = $this->createContainer();
|
||||||
$id = $container['ConDefID'];
|
$id = $container['ConDefID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateContainerSingleField()
|
public function testPartialUpdateContainerSingleField()
|
||||||
{
|
{
|
||||||
$container = $this->createContainer();
|
$container = $this->createContainer();
|
||||||
$id = $container['ConDefID'];
|
$id = $container['ConDefID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ConCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['ConCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($container['ConCode'], $showData['ConCode']);
|
$this->assertNotEquals($container['ConCode'], $showData['ConCode']);
|
||||||
$this->assertEquals($container['ConName'], $showData['ConName']);
|
$this->assertEquals($container['ConName'], $showData['ConName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Specimen;
|
namespace Tests\Feature\Specimen;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class PrepPatchTest extends CIUnitTestCase
|
class PrepPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/specimen/prep';
|
protected string $endpoint = 'api/specimen/prep';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createPrep(array $data = []): array
|
private function createPrep(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'SpcPrpCode' => 'PREP_' . uniqid(),
|
'SpcPrpCode' => 'PREP_' . uniqid(),
|
||||||
'Description' => 'Test Prep ' . uniqid(),
|
'Description' => 'Test Prep ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePrepSuccess()
|
public function testPartialUpdatePrepSuccess()
|
||||||
{
|
{
|
||||||
$prep = $this->createPrep();
|
$prep = $this->createPrep();
|
||||||
$id = $prep['SpcPrpID'];
|
$id = $prep['SpcPrpID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['Description' => 'Updated Prep']);
|
->call('patch', "{$this->endpoint}/{$id}", ['Description' => 'Updated Prep']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Prep', $showData['Description']);
|
$this->assertEquals('Updated Prep', $showData['Description']);
|
||||||
$this->assertEquals($prep['SpcPrpCode'], $showData['SpcPrpCode']);
|
$this->assertEquals($prep['SpcPrpCode'], $showData['SpcPrpCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePrepNotFound()
|
public function testPartialUpdatePrepNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['Description' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['Description' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePrepInvalidId()
|
public function testPartialUpdatePrepInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['Description' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['Description' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePrepEmptyPayload()
|
public function testPartialUpdatePrepEmptyPayload()
|
||||||
{
|
{
|
||||||
$prep = $this->createPrep();
|
$prep = $this->createPrep();
|
||||||
$id = $prep['SpcPrpID'];
|
$id = $prep['SpcPrpID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdatePrepSingleField()
|
public function testPartialUpdatePrepSingleField()
|
||||||
{
|
{
|
||||||
$prep = $this->createPrep();
|
$prep = $this->createPrep();
|
||||||
$id = $prep['SpcPrpID'];
|
$id = $prep['SpcPrpID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SpcPrpCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['SpcPrpCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($prep['SpcPrpCode'], $showData['SpcPrpCode']);
|
$this->assertNotEquals($prep['SpcPrpCode'], $showData['SpcPrpCode']);
|
||||||
$this->assertEquals($prep['Description'], $showData['Description']);
|
$this->assertEquals($prep['Description'], $showData['Description']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Specimen;
|
namespace Tests\Feature\Specimen;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class SpecimenPatchTest extends CIUnitTestCase
|
class SpecimenPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/specimen';
|
protected string $endpoint = 'api/specimen';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createSpecimen(array $data = []): array
|
private function createSpecimen(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'SpecimenCode' => 'SPEC_' . uniqid(),
|
'SpecimenCode' => 'SPEC_' . uniqid(),
|
||||||
'SpecimenName' => 'Test Specimen ' . uniqid(),
|
'SpecimenName' => 'Test Specimen ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenSuccess()
|
public function testPartialUpdateSpecimenSuccess()
|
||||||
{
|
{
|
||||||
$specimen = $this->createSpecimen();
|
$specimen = $this->createSpecimen();
|
||||||
$id = $specimen['SpecimenID'];
|
$id = $specimen['SpecimenID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SpecimenName' => 'Updated Specimen']);
|
->call('patch', "{$this->endpoint}/{$id}", ['SpecimenName' => 'Updated Specimen']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Specimen', $showData['SpecimenName']);
|
$this->assertEquals('Updated Specimen', $showData['SpecimenName']);
|
||||||
$this->assertEquals($specimen['SpecimenCode'], $showData['SpecimenCode']);
|
$this->assertEquals($specimen['SpecimenCode'], $showData['SpecimenCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenNotFound()
|
public function testPartialUpdateSpecimenNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['SpecimenName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['SpecimenName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenInvalidId()
|
public function testPartialUpdateSpecimenInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['SpecimenName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['SpecimenName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenEmptyPayload()
|
public function testPartialUpdateSpecimenEmptyPayload()
|
||||||
{
|
{
|
||||||
$specimen = $this->createSpecimen();
|
$specimen = $this->createSpecimen();
|
||||||
$id = $specimen['SpecimenID'];
|
$id = $specimen['SpecimenID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateSpecimenSingleField()
|
public function testPartialUpdateSpecimenSingleField()
|
||||||
{
|
{
|
||||||
$specimen = $this->createSpecimen();
|
$specimen = $this->createSpecimen();
|
||||||
$id = $specimen['SpecimenID'];
|
$id = $specimen['SpecimenID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SpecimenCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['SpecimenCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($specimen['SpecimenCode'], $showData['SpecimenCode']);
|
$this->assertNotEquals($specimen['SpecimenCode'], $showData['SpecimenCode']);
|
||||||
$this->assertEquals($specimen['SpecimenName'], $showData['SpecimenName']);
|
$this->assertEquals($specimen['SpecimenName'], $showData['SpecimenName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,118 +1,118 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Specimen;
|
namespace Tests\Feature\Specimen;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class StatusPatchTest extends CIUnitTestCase
|
class StatusPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/specimen/status';
|
protected string $endpoint = 'api/specimen/status';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createStatus(array $data = []): array
|
private function createStatus(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'SpcStatus' => 'Status_' . uniqid(),
|
'SpcStatus' => 'Status_' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateStatusSuccess()
|
public function testPartialUpdateStatusSuccess()
|
||||||
{
|
{
|
||||||
$status = $this->createStatus();
|
$status = $this->createStatus();
|
||||||
$id = $status['SpcStaID'];
|
$id = $status['SpcStaID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SpcStatus' => 'UpdatedStatus']);
|
->call('patch', "{$this->endpoint}/{$id}", ['SpcStatus' => 'UpdatedStatus']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('UpdatedStatus', $showData['SpcStatus']);
|
$this->assertEquals('UpdatedStatus', $showData['SpcStatus']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateStatusNotFound()
|
public function testPartialUpdateStatusNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['SpcStatus' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['SpcStatus' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateStatusInvalidId()
|
public function testPartialUpdateStatusInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['SpcStatus' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['SpcStatus' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateStatusEmptyPayload()
|
public function testPartialUpdateStatusEmptyPayload()
|
||||||
{
|
{
|
||||||
$status = $this->createStatus();
|
$status = $this->createStatus();
|
||||||
$id = $status['SpcStaID'];
|
$id = $status['SpcStaID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateStatusSingleField()
|
public function testPartialUpdateStatusSingleField()
|
||||||
{
|
{
|
||||||
$status = $this->createStatus();
|
$status = $this->createStatus();
|
||||||
$id = $status['SpcStaID'];
|
$id = $status['SpcStaID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['SpcStatus' => 'NewStatus']);
|
->call('patch', "{$this->endpoint}/{$id}", ['SpcStatus' => 'NewStatus']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('NewStatus', $showData['SpcStatus']);
|
$this->assertEquals('NewStatus', $showData['SpcStatus']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,140 +1,140 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Test;
|
namespace Tests\Feature\Test;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class TestMapDetailPatchTest extends CIUnitTestCase
|
class TestMapDetailPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/test/testmap/detail';
|
protected string $endpoint = 'api/test/testmap/detail';
|
||||||
protected string $mapEndpoint = 'api/test/testmap';
|
protected string $mapEndpoint = 'api/test/testmap';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createTestMapDetail(array $data = []): array
|
private function createTestMapDetail(array $data = []): array
|
||||||
{
|
{
|
||||||
$mapResponse = $this->withHeaders($this->authHeaders())
|
$mapResponse = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->mapEndpoint, [
|
->call('post', $this->mapEndpoint, [
|
||||||
'HostType' => 'SITE',
|
'HostType' => 'SITE',
|
||||||
'HostID' => 1,
|
'HostID' => 1,
|
||||||
'ClientType' => 'SITE',
|
'ClientType' => 'SITE',
|
||||||
'ClientID' => 1,
|
'ClientID' => 1,
|
||||||
]);
|
]);
|
||||||
$mapResponse->assertStatus(201);
|
$mapResponse->assertStatus(201);
|
||||||
$mapID = json_decode($mapResponse->getJSON(), true)['data'];
|
$mapID = json_decode($mapResponse->getJSON(), true)['data'];
|
||||||
|
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'TestMapID' => $mapID,
|
'TestMapID' => $mapID,
|
||||||
'HostTestCode' => 'HB',
|
'HostTestCode' => 'HB',
|
||||||
'HostTestName' => 'Hemoglobin',
|
'HostTestName' => 'Hemoglobin',
|
||||||
'ClientTestCode' => '2',
|
'ClientTestCode' => '2',
|
||||||
'ClientTestName' => 'Hemoglobin',
|
'ClientTestName' => 'Hemoglobin',
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
$detailID = $decoded['data'];
|
$detailID = $decoded['data'];
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$detailID}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$detailID}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
return json_decode($show->getJSON(), true)['data'];
|
return json_decode($show->getJSON(), true)['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailSuccess()
|
public function testPartialUpdateTestMapDetailSuccess()
|
||||||
{
|
{
|
||||||
$detail = $this->createTestMapDetail();
|
$detail = $this->createTestMapDetail();
|
||||||
$id = $detail['TestMapDetailID'];
|
$id = $detail['TestMapDetailID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['ClientTestName' => 'Updated Detail']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ClientTestName' => 'Updated Detail']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Detail', $showData['ClientTestName']);
|
$this->assertEquals('Updated Detail', $showData['ClientTestName']);
|
||||||
$this->assertEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
$this->assertEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailNotFound()
|
public function testPartialUpdateTestMapDetailNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['ClientTestName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['ClientTestName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailInvalidId()
|
public function testPartialUpdateTestMapDetailInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['ClientTestName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['ClientTestName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailEmptyPayload()
|
public function testPartialUpdateTestMapDetailEmptyPayload()
|
||||||
{
|
{
|
||||||
$detail = $this->createTestMapDetail();
|
$detail = $this->createTestMapDetail();
|
||||||
$id = $detail['TestMapDetailID'];
|
$id = $detail['TestMapDetailID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailSingleField()
|
public function testPartialUpdateTestMapDetailSingleField()
|
||||||
{
|
{
|
||||||
$detail = $this->createTestMapDetail();
|
$detail = $this->createTestMapDetail();
|
||||||
$id = $detail['TestMapDetailID'];
|
$id = $detail['TestMapDetailID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['HostTestCode' => 'HBA1C']);
|
->call('patch', "{$this->endpoint}/{$id}", ['HostTestCode' => 'HBA1C']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
$this->assertNotEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
||||||
$this->assertEquals($detail['ClientTestName'], $showData['ClientTestName']);
|
$this->assertEquals($detail['ClientTestName'], $showData['ClientTestName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,38 +1,38 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tests\Feature\Test;
|
namespace Tests\Feature\Test;
|
||||||
|
|
||||||
use App\Models\Test\TestDefSiteModel;
|
use App\Models\Test\TestDefSiteModel;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
|
|
||||||
class TestShowResponseTest extends CIUnitTestCase
|
class TestShowResponseTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
public function testShowTechnicalDoesNotReturnNestedTestDefTech(): void
|
public function testShowTechnicalDoesNotReturnNestedTestDefTech(): void
|
||||||
{
|
{
|
||||||
$model = new TestDefSiteModel();
|
$model = new TestDefSiteModel();
|
||||||
|
|
||||||
$test = $model->where('TestSiteCode', 'GLU')->where('EndDate IS NULL')->first();
|
$test = $model->where('TestSiteCode', 'GLU')->where('EndDate IS NULL')->first();
|
||||||
if (!$test) {
|
if (!$test) {
|
||||||
$test = $model->where('TestType', 'TEST')->where('EndDate IS NULL')->first();
|
$test = $model->where('TestType', 'TEST')->where('EndDate IS NULL')->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertNotEmpty($test, 'No active technical test record found for show endpoint test.');
|
$this->assertNotEmpty($test, 'No active technical test record found for show endpoint test.');
|
||||||
|
|
||||||
$response = $this->call('get', 'api/test/' . $test['TestSiteID']);
|
$response = $this->call('get', 'api/test/' . $test['TestSiteID']);
|
||||||
|
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
|
|
||||||
$json = json_decode($response->getJSON(), true);
|
$json = json_decode($response->getJSON(), true);
|
||||||
|
|
||||||
$this->assertSame('success', $json['status'] ?? null);
|
$this->assertSame('success', $json['status'] ?? null);
|
||||||
$this->assertArrayHasKey('data', $json);
|
$this->assertArrayHasKey('data', $json);
|
||||||
$this->assertArrayNotHasKey('testdeftech', $json['data']);
|
$this->assertArrayNotHasKey('testdeftech', $json['data']);
|
||||||
$this->assertArrayHasKey('TestSiteID', $json['data']);
|
$this->assertArrayHasKey('TestSiteID', $json['data']);
|
||||||
$this->assertArrayHasKey('ResultType', $json['data']);
|
$this->assertArrayHasKey('ResultType', $json['data']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,121 +1,121 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\Test;
|
namespace Tests\Feature\Test;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class TestsPatchTest extends CIUnitTestCase
|
class TestsPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/test';
|
protected string $endpoint = 'api/test';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createTest(array $data = []): array
|
private function createTest(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'TestCode' => 'TEST_' . uniqid(),
|
'TestCode' => 'TEST_' . uniqid(),
|
||||||
'TestName' => 'Test Name ' . uniqid(),
|
'TestName' => 'Test Name ' . uniqid(),
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestSuccess()
|
public function testPartialUpdateTestSuccess()
|
||||||
{
|
{
|
||||||
$test = $this->createTest();
|
$test = $this->createTest();
|
||||||
$id = $test['TestID'];
|
$id = $test['TestID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['TestName' => 'Updated Test']);
|
->call('patch', "{$this->endpoint}/{$id}", ['TestName' => 'Updated Test']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Test', $showData['TestName']);
|
$this->assertEquals('Updated Test', $showData['TestName']);
|
||||||
$this->assertEquals($test['TestCode'], $showData['TestCode']);
|
$this->assertEquals($test['TestCode'], $showData['TestCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestNotFound()
|
public function testPartialUpdateTestNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['TestName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['TestName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestInvalidId()
|
public function testPartialUpdateTestInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['TestName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['TestName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestEmptyPayload()
|
public function testPartialUpdateTestEmptyPayload()
|
||||||
{
|
{
|
||||||
$test = $this->createTest();
|
$test = $this->createTest();
|
||||||
$id = $test['TestID'];
|
$id = $test['TestID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestSingleField()
|
public function testPartialUpdateTestSingleField()
|
||||||
{
|
{
|
||||||
$test = $this->createTest();
|
$test = $this->createTest();
|
||||||
$id = $test['TestID'];
|
$id = $test['TestID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['TestCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['TestCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($test['TestCode'], $showData['TestCode']);
|
$this->assertNotEquals($test['TestCode'], $showData['TestCode']);
|
||||||
$this->assertEquals($test['TestName'], $showData['TestName']);
|
$this->assertEquals($test['TestName'], $showData['TestName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,122 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Feature\User;
|
namespace Tests\Feature\User;
|
||||||
|
|
||||||
use CodeIgniter\Test\FeatureTestTrait;
|
use CodeIgniter\Test\FeatureTestTrait;
|
||||||
use CodeIgniter\Test\CIUnitTestCase;
|
use CodeIgniter\Test\CIUnitTestCase;
|
||||||
use Firebase\JWT\JWT;
|
use Firebase\JWT\JWT;
|
||||||
|
|
||||||
class UserPatchTest extends CIUnitTestCase
|
class UserPatchTest extends CIUnitTestCase
|
||||||
{
|
{
|
||||||
use FeatureTestTrait;
|
use FeatureTestTrait;
|
||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/user';
|
protected string $endpoint = 'api/user';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
$key = getenv('JWT_SECRET') ?: 'my-secret-key';
|
||||||
$payload = [
|
$payload = [
|
||||||
'iss' => 'localhost',
|
'iss' => 'localhost',
|
||||||
'aud' => 'localhost',
|
'aud' => 'localhost',
|
||||||
'iat' => time(),
|
'iat' => time(),
|
||||||
'nbf' => time(),
|
'nbf' => time(),
|
||||||
'exp' => time() + 3600,
|
'exp' => time() + 3600,
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'email' => 'admin@admin.com',
|
'email' => 'admin@admin.com',
|
||||||
];
|
];
|
||||||
$this->token = JWT::encode($payload, $key, 'HS256');
|
$this->token = JWT::encode($payload, $key, 'HS256');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function authHeaders(): array
|
private function authHeaders(): array
|
||||||
{
|
{
|
||||||
return ['Cookie' => 'token=' . $this->token];
|
return ['Cookie' => 'token=' . $this->token];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createUser(array $data = []): array
|
private function createUser(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'UserCode' => 'USR_' . uniqid(),
|
'UserCode' => 'USR_' . uniqid(),
|
||||||
'UserName' => 'Test User ' . uniqid(),
|
'UserName' => 'Test User ' . uniqid(),
|
||||||
'Email' => 'user_' . uniqid() . '@test.com',
|
'Email' => 'user_' . uniqid() . '@test.com',
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
return $decoded['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateUserSuccess()
|
public function testPartialUpdateUserSuccess()
|
||||||
{
|
{
|
||||||
$user = $this->createUser();
|
$user = $this->createUser();
|
||||||
$id = $user['UserID'];
|
$id = $user['UserID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['UserName' => 'Updated User']);
|
->call('patch', "{$this->endpoint}/{$id}", ['UserName' => 'Updated User']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
$this->assertEquals('success', $patchData['status']);
|
$this->assertEquals('success', $patchData['status']);
|
||||||
|
|
||||||
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$id}");
|
||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated User', $showData['UserName']);
|
$this->assertEquals('Updated User', $showData['UserName']);
|
||||||
$this->assertEquals($user['UserCode'], $showData['UserCode']);
|
$this->assertEquals($user['UserCode'], $showData['UserCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateUserNotFound()
|
public function testPartialUpdateUserNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['UserName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['UserName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateUserInvalidId()
|
public function testPartialUpdateUserInvalidId()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['UserName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['UserName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateUserEmptyPayload()
|
public function testPartialUpdateUserEmptyPayload()
|
||||||
{
|
{
|
||||||
$user = $this->createUser();
|
$user = $this->createUser();
|
||||||
$id = $user['UserID'];
|
$id = $user['UserID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", []);
|
->call('patch', "{$this->endpoint}/{$id}", []);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateUserSingleField()
|
public function testPartialUpdateUserSingleField()
|
||||||
{
|
{
|
||||||
$user = $this->createUser();
|
$user = $this->createUser();
|
||||||
$id = $user['UserID'];
|
$id = $user['UserID'];
|
||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['UserCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['UserCode' => 'NEW_' . uniqid()]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($user['UserCode'], $showData['UserCode']);
|
$this->assertNotEquals($user['UserCode'], $showData['UserCode']);
|
||||||
$this->assertEquals($user['UserName'], $showData['UserName']);
|
$this->assertEquals($user['UserName'], $showData['UserName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,50 +1,50 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/codeigniter4/framework/system/Test/bootstrap.php';
|
require_once __DIR__ . '/../vendor/codeigniter4/framework/system/Test/bootstrap.php';
|
||||||
|
|
||||||
use CodeIgniter\Config\DotEnv;
|
use CodeIgniter\Config\DotEnv;
|
||||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||||
use CodeIgniter\Database\MigrationRunner;
|
use CodeIgniter\Database\MigrationRunner;
|
||||||
use Config\Database;
|
use Config\Database;
|
||||||
use Config\Migrations as MigrationsConfig;
|
use Config\Migrations as MigrationsConfig;
|
||||||
|
|
||||||
if (defined('CLQMS_PHPUNIT_BOOTSTRAPPED') || ENVIRONMENT !== 'testing') {
|
if (defined('CLQMS_PHPUNIT_BOOTSTRAPPED') || ENVIRONMENT !== 'testing') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
define('CLQMS_PHPUNIT_BOOTSTRAPPED', true);
|
define('CLQMS_PHPUNIT_BOOTSTRAPPED', true);
|
||||||
|
|
||||||
(new DotEnv(ROOTPATH))->load();
|
(new DotEnv(ROOTPATH))->load();
|
||||||
|
|
||||||
$db = Database::connect('tests');
|
$db = Database::connect('tests');
|
||||||
$forge = Database::forge('tests');
|
$forge = Database::forge('tests');
|
||||||
|
|
||||||
$db->query('SET FOREIGN_KEY_CHECKS=0');
|
$db->query('SET FOREIGN_KEY_CHECKS=0');
|
||||||
foreach ($db->listTables() as $table) {
|
foreach ($db->listTables() as $table) {
|
||||||
$forge->dropTable($table, true);
|
$forge->dropTable($table, true);
|
||||||
}
|
}
|
||||||
$db->query('SET FOREIGN_KEY_CHECKS=1');
|
$db->query('SET FOREIGN_KEY_CHECKS=1');
|
||||||
|
|
||||||
$migrationsConfig = config(MigrationsConfig::class);
|
$migrationsConfig = config(MigrationsConfig::class);
|
||||||
$migrationRunner = new MigrationRunner($migrationsConfig, 'tests');
|
$migrationRunner = new MigrationRunner($migrationsConfig, 'tests');
|
||||||
try {
|
try {
|
||||||
$migrationRunner->latest();
|
$migrationRunner->latest();
|
||||||
} catch (DatabaseException $e) {
|
} catch (DatabaseException $e) {
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
if (strpos($message, 'already exists') === false) {
|
if (strpos($message, 'already exists') === false) {
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$initialBufferLevel = ob_get_level();
|
$initialBufferLevel = ob_get_level();
|
||||||
ob_start();
|
ob_start();
|
||||||
try {
|
try {
|
||||||
$seeder = Database::seeder('tests');
|
$seeder = Database::seeder('tests');
|
||||||
$seeder->setSilent(true)->call('DBSeeder');
|
$seeder->setSilent(true)->call('DBSeeder');
|
||||||
} finally {
|
} finally {
|
||||||
while (ob_get_level() > $initialBufferLevel) {
|
while (ob_get_level() > $initialBufferLevel) {
|
||||||
ob_end_clean();
|
ob_end_clean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user