Update site controller, organization & test models, migrations, and API docs
This commit is contained in:
parent
011a2456c2
commit
ad8e1cc977
97
.serena/memories/code_conventions.md
Normal file
97
.serena/memories/code_conventions.md
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# CLQMS Code Conventions
|
||||||
|
|
||||||
|
## PHP Standards
|
||||||
|
- **Version**: PHP 8.1+
|
||||||
|
- **Autoloading**: PSR-4
|
||||||
|
- **Coding Style**: PSR-12 (where applicable)
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
|
||||||
|
| Element | Convention | Example |
|
||||||
|
|---------|-----------|---------|
|
||||||
|
| Classes | PascalCase | `PatientController` |
|
||||||
|
| Methods | camelCase | `createPatient()` |
|
||||||
|
| Properties | snake_case (legacy) / camelCase (new) | `$patient_id` / `$patientId` |
|
||||||
|
| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
|
||||||
|
| Database Tables | snake_case | `patient_visits` |
|
||||||
|
| Database Columns | PascalCase (legacy) | `PatientID`, `NameFirst` |
|
||||||
|
| JSON Fields | PascalCase | `"PatientID": "123"` |
|
||||||
|
|
||||||
|
## Imports & Namespaces
|
||||||
|
- Fully qualified namespaces at top of file
|
||||||
|
- Group imports: Framework first, then App, then external
|
||||||
|
- Alphabetical order within groups
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
namespace App\Controllers;
|
||||||
|
|
||||||
|
use CodeIgniter\Controller;
|
||||||
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
|
use App\Traits\ResponseTrait;
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Controller Pattern
|
||||||
|
Controllers handle HTTP requests, delegate business logic to Models (no DB queries in controllers).
|
||||||
|
|
||||||
|
```php
|
||||||
|
class ExampleController extends Controller
|
||||||
|
{
|
||||||
|
use ResponseTrait;
|
||||||
|
protected $model;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->model = new \App\Models\ExampleModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response Format
|
||||||
|
All API responses use standardized format:
|
||||||
|
```php
|
||||||
|
// Success
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Operation completed',
|
||||||
|
'data' => $data
|
||||||
|
], 200);
|
||||||
|
|
||||||
|
// Error
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'message' => 'Error description',
|
||||||
|
'data' => []
|
||||||
|
], 400);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Operations
|
||||||
|
- Use CodeIgniter Query Builder or Model methods
|
||||||
|
- Use `helper('utc')` for UTC date conversion
|
||||||
|
- Wrap multi-table operations in transactions
|
||||||
|
|
||||||
|
```php
|
||||||
|
$this->db->transStart();
|
||||||
|
// ... operations
|
||||||
|
$this->db->transComplete();
|
||||||
|
|
||||||
|
if ($this->db->transStatus() === false) {
|
||||||
|
return $this->respond(['status' => 'error', ...], 500);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Naming Convention
|
||||||
|
Format: `test<Action><Scenario><ExpectedResult>`
|
||||||
|
Examples: `testCreatePatientValidationFail`, `testUpdatePatientSuccess`
|
||||||
|
|
||||||
|
## HTTP Status Codes
|
||||||
|
- 200: GET/PATCH success
|
||||||
|
- 201: POST success
|
||||||
|
- 400: Validation error
|
||||||
|
- 401: Unauthorized
|
||||||
|
- 404: Not found
|
||||||
|
- 500: Server error
|
||||||
|
|
||||||
|
## Legacy Field Naming
|
||||||
|
Database uses PascalCase: `PatientID`, `NameFirst`, `Birthdate`, `CreatedAt`
|
||||||
@ -1,55 +1,54 @@
|
|||||||
# CLQMS Project Overview
|
# CLQMS Project Overview
|
||||||
|
|
||||||
## Project Purpose
|
## Project Purpose
|
||||||
|
CLQMS (Clinical Laboratory Quality Management System) is a headless REST API backend for clinical laboratory workflows. It provides comprehensive JSON endpoints for:
|
||||||
|
- Patient management
|
||||||
|
- Order/test management
|
||||||
|
- Specimen tracking
|
||||||
|
- Result management and verification
|
||||||
|
- Reference ranges
|
||||||
|
- Laboratory instrument integration (Edge API)
|
||||||
|
|
||||||
CLQMS (Clinical Laboratory Quality Management System) is a **headless REST API backend** designed for modern clinical laboratory workflows. This API-only system provides comprehensive JSON endpoints for laboratory operations without any view layer. Frontend applications (web, mobile, desktop) consume these REST endpoints to build laboratory information systems.
|
## Tech Stack
|
||||||
|
- **Language**: PHP 8.1+
|
||||||
|
- **Framework**: CodeIgniter 4 (API-only mode)
|
||||||
|
- **Database**: MySQL with MySQLi driver
|
||||||
|
- **Authentication**: JWT (JSON Web Tokens)
|
||||||
|
- **Testing**: PHPUnit 10.5+
|
||||||
|
- **Documentation**: OpenAPI/Swagger YAML
|
||||||
|
|
||||||
### Core Features
|
## Architecture
|
||||||
- Patient registration and management
|
- **API-First**: No view layer, headless REST API only
|
||||||
- Laboratory test ordering and tracking
|
- **Stateless**: JWT-based authentication per request
|
||||||
- Specimen lifecycle management (collection → transport → reception → prep → analysis)
|
- **UTC Dates**: All dates stored in UTC, converted for display
|
||||||
- Result entry with reference range validation
|
- **PSR-4 Autoloading**: `App\` → `app/`, `Config\` → `app/Config/`
|
||||||
- Multi-level result verification (Technical → Clinical → Reporting)
|
|
||||||
- Instrument integration via Edge API (tiny-edge middleware)
|
|
||||||
- Master data management (value sets, test definitions, reference ranges)
|
|
||||||
- Quality control and calibration tracking
|
|
||||||
|
|
||||||
### Product Vision
|
## Key Directories
|
||||||
To provide a headless, API-first laboratory information system serving as the backend for any frontend client while streamlining laboratory operations, ensuring regulatory compliance, and integrating seamlessly with laboratory instruments.
|
```
|
||||||
|
app/
|
||||||
|
Controllers/ # API endpoint handlers
|
||||||
|
Models/ # Database models
|
||||||
|
Libraries/ # Helper classes (Lookups, ValueSet)
|
||||||
|
Database/
|
||||||
|
Migrations/ # Schema migrations
|
||||||
|
Seeds/ # Test data seeders
|
||||||
|
Helpers/ # json_helper.php, utc_helper.php
|
||||||
|
Traits/ # ResponseTrait
|
||||||
|
Config/ # Configuration files
|
||||||
|
Filters/ # AuthFilter, CORS
|
||||||
|
|
||||||
## Technology Stack
|
public/ # Web root
|
||||||
|
paths/ # OpenAPI path definitions
|
||||||
|
components/schemas/ # OpenAPI schemas
|
||||||
|
|
||||||
| Component | Specification |
|
tests/
|
||||||
|-----------|---------------|
|
feature/ # Feature/integration tests
|
||||||
| **Language** | PHP 8.1+ (PSR-compliant) |
|
unit/ # Unit tests
|
||||||
| **Framework** | CodeIgniter 4 (API-only mode) |
|
_support/ # Test support files
|
||||||
| **Database** | MySQL 8.0+ |
|
```
|
||||||
| **Security** | JWT (JSON Web Tokens) via firebase/php-jwt |
|
|
||||||
| **Testing** | PHPUnit 10.5+ |
|
|
||||||
| **API Format** | RESTful JSON |
|
|
||||||
| **Architecture** | Clean architecture, API-first design |
|
|
||||||
|
|
||||||
### Key Dependencies
|
## Key Dependencies
|
||||||
- `codeigniter4/framework` - Main framework
|
- `codeigniter4/framework` - Core framework
|
||||||
- `firebase/php-jwt` - JWT authentication
|
- `firebase/php-jwt` - JWT authentication
|
||||||
- `fakerphp/faker` - Test data generation
|
- `fakerphp/faker` - Test data generation (dev)
|
||||||
- `phpunit/phpunit` - Unit/feature testing
|
- `phpunit/phpunit` - Testing (dev)
|
||||||
|
|
||||||
## Strategic Pillars
|
|
||||||
- **Precision & Accuracy**: Strict validation for all laboratory parameters and reference ranges
|
|
||||||
- **Scalability**: Optimized for high-volume diagnostic environments
|
|
||||||
- **Compliance**: Built-in audit trails and status history for full traceability
|
|
||||||
- **Interoperability**: Modular architecture designed for LIS, HIS, and analyzer integrations
|
|
||||||
|
|
||||||
## Key Characteristics
|
|
||||||
- **API-Only**: No view layer, no server-side rendering
|
|
||||||
- **Frontend Agnostic**: Any client can consume these APIs
|
|
||||||
- **JSON-First**: All requests/responses use JSON format
|
|
||||||
- **Stateless**: Each API request is independent with JWT authentication
|
|
||||||
- **UTC Normalization**: Automatic UTC timestamp handling via BaseModel
|
|
||||||
|
|
||||||
## Current Architecture Status
|
|
||||||
The system is undergoing an **Architectural Redesign** to consolidate legacy structures into a high-performance, maintainable schema focusing on:
|
|
||||||
- Unified Test Definitions (consolidating technical, calculated, and site-specific test data)
|
|
||||||
- Reference Range Centralization (unified engine for numeric, threshold, text, and coded results)
|
|
||||||
- Ordered Workflow Management (precise tracking of orders from collection to verification)
|
|
||||||
|
|||||||
@ -1,393 +1,100 @@
|
|||||||
# CLQMS Suggested Commands
|
# CLQMS Suggested Commands
|
||||||
|
|
||||||
## Database Commands
|
## Testing
|
||||||
|
|
||||||
### Migrations
|
|
||||||
```bash
|
|
||||||
# Run all pending migrations
|
|
||||||
php spark migrate
|
|
||||||
|
|
||||||
# Run specific migration
|
|
||||||
php spark migrate [migration_file]
|
|
||||||
|
|
||||||
# Rollback last batch of migrations
|
|
||||||
php spark migrate:rollback
|
|
||||||
|
|
||||||
# Rollback and re-run migrations
|
|
||||||
php spark migrate:refresh
|
|
||||||
|
|
||||||
# Refresh and seed database
|
|
||||||
php spark migrate:refresh --seed
|
|
||||||
|
|
||||||
# Check migration status
|
|
||||||
php spark migrate:status
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Seeding
|
|
||||||
```bash
|
|
||||||
# Run all seeders
|
|
||||||
php spark db:seed
|
|
||||||
|
|
||||||
# Run specific seeder
|
|
||||||
php spark db:seed DBSeeder
|
|
||||||
|
|
||||||
# Create new database
|
|
||||||
php spark db:create
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Query
|
|
||||||
```bash
|
|
||||||
# Get table information
|
|
||||||
php spark db:table [table_name]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing Commands
|
|
||||||
|
|
||||||
### PHPUnit Tests
|
|
||||||
```bash
|
```bash
|
||||||
# Run all tests
|
# Run all tests
|
||||||
vendor/bin/phpunit
|
./vendor/bin/phpunit
|
||||||
|
|
||||||
# Run specific test file (IMPORTANT for debugging)
|
# Run specific test file
|
||||||
vendor/bin/phpunit tests/feature/UniformShowTest.php
|
./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php
|
||||||
vendor/bin/phpunit tests/feature/Patient/PatientCreateTest.php
|
|
||||||
|
|
||||||
# Run tests in specific directory
|
|
||||||
vendor/bin/phpunit tests/feature/Patient/
|
|
||||||
|
|
||||||
# Run tests with coverage (text output)
|
|
||||||
vendor/bin/phpunit --coverage-text=tests/coverage.txt -d memory_limit=1024m
|
|
||||||
|
|
||||||
# Run tests with coverage (HTML report)
|
|
||||||
vendor/bin/phpunit --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m
|
|
||||||
|
|
||||||
# Run with verbose output
|
|
||||||
vendor/bin/phpunit --verbose
|
|
||||||
|
|
||||||
# Run specific test method
|
# Run specific test method
|
||||||
vendor/bin/phpunit --filter testCanCreatePatient
|
./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php
|
||||||
```
|
|
||||||
|
|
||||||
## Code Generation Commands
|
# Run tests with coverage
|
||||||
|
./vendor/bin/phpunit --coverage-html build/logs/html
|
||||||
|
|
||||||
### Generate Code Files
|
# Run tests by suite
|
||||||
```bash
|
./vendor/bin/phpunit --testsuite App
|
||||||
# Generate new model
|
|
||||||
php spark make:model ModelName
|
|
||||||
|
|
||||||
# Generate new controller
|
# Run via composer
|
||||||
php spark make:controller ControllerName
|
composer test
|
||||||
|
|
||||||
# Generate new migration
|
|
||||||
php spark make:migration MigrationName
|
|
||||||
|
|
||||||
# Generate new seeder
|
|
||||||
php spark make:seeder SeederName
|
|
||||||
|
|
||||||
# Generate new test
|
|
||||||
php spark make:test TestName
|
|
||||||
|
|
||||||
# Generate scaffold (complete set)
|
|
||||||
php spark make:scaffold ModelName
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development Server
|
## Development Server
|
||||||
|
|
||||||
### Start Development Server
|
|
||||||
```bash
|
```bash
|
||||||
# Start CodeIgniter dev server (default port 8080)
|
# Start PHP development server
|
||||||
php spark serve
|
php spark serve
|
||||||
|
|
||||||
# Start on specific port
|
# Or specify port
|
||||||
php spark serve --port=8080
|
php spark serve --port 8080
|
||||||
|
|
||||||
# Start with specific host
|
|
||||||
php spark serve --host=0.0.0.0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cache Management
|
## Database
|
||||||
|
|
||||||
### Clear Caches
|
|
||||||
```bash
|
```bash
|
||||||
# Clear application cache
|
# Run migrations
|
||||||
php spark cache:clear
|
php spark migrate
|
||||||
|
|
||||||
# Show cache information
|
# Rollback migrations
|
||||||
php spark cache:info
|
php spark migrate:rollback
|
||||||
|
|
||||||
# Clear debug bar JSON files
|
# Create new migration
|
||||||
php spark debugbar:clear
|
php spark make:migration CreateUsersTable
|
||||||
|
|
||||||
# Clear log files
|
# Run database seeds
|
||||||
php spark logs:clear
|
php spark db:seed DBSeeder
|
||||||
|
php spark db:seed PatientSeeder
|
||||||
```
|
```
|
||||||
|
|
||||||
## System Utilities
|
## Code Generation (Scaffolding)
|
||||||
|
|
||||||
### Configuration & Environment
|
|
||||||
```bash
|
```bash
|
||||||
# Get current environment
|
# Create controller
|
||||||
php spark env
|
php spark make:controller Users
|
||||||
|
|
||||||
# Set environment
|
# Create model
|
||||||
php spark env development
|
php spark make:model UserModel
|
||||||
|
|
||||||
# Check configuration values
|
# Create migration
|
||||||
php spark config:check
|
php spark make:migration CreateUsersTable
|
||||||
|
|
||||||
# Check php.ini values (for production)
|
# Create seeder
|
||||||
php spark phpini:check
|
php spark make:seeder UserSeeder
|
||||||
|
|
||||||
# Verify namespaces
|
|
||||||
php spark namespaces
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Routes
|
## API Documentation
|
||||||
```bash
|
```bash
|
||||||
# Display all routes
|
# After updating YAML files, regenerate bundled docs
|
||||||
php spark routes
|
node public/bundle-api-docs.js
|
||||||
|
|
||||||
# Check filters for a route
|
# Produces: public/api-docs.bundled.yaml
|
||||||
php spark filter:check
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Optimization
|
## Utilities (Windows)
|
||||||
```bash
|
```bash
|
||||||
# Optimize for production
|
# List files
|
||||||
php spark optimize
|
|
||||||
```
|
|
||||||
|
|
||||||
## Utility Commands
|
|
||||||
|
|
||||||
### Encryption
|
|
||||||
```bash
|
|
||||||
# Generate new encryption key (writes to .env)
|
|
||||||
php spark key:generate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Publish
|
|
||||||
```bash
|
|
||||||
# Publish predefined resources
|
|
||||||
php spark publish
|
|
||||||
```
|
|
||||||
|
|
||||||
## General Utility Commands (Windows)
|
|
||||||
|
|
||||||
### File & Directory Operations
|
|
||||||
```bash
|
|
||||||
# List files in current directory
|
|
||||||
dir
|
dir
|
||||||
|
|
||||||
# List files with details
|
# Search in files (PowerShell)
|
||||||
dir /a
|
Select-String -Path "app\*.php" -Pattern "PatientModel"
|
||||||
|
|
||||||
# Change directory
|
# Or using git bash (if available)
|
||||||
cd path\to\directory
|
grep -r "PatientModel" app/
|
||||||
|
|
||||||
# Go to parent directory
|
# Clear writable cache
|
||||||
cd ..
|
del /q writable\cache\*
|
||||||
|
|
||||||
# Create directory
|
|
||||||
mkdir directory_name
|
|
||||||
|
|
||||||
# Remove directory (empty)
|
|
||||||
rmdir directory_name
|
|
||||||
|
|
||||||
# Remove directory with contents
|
|
||||||
rmdir /s /q directory_name
|
|
||||||
|
|
||||||
# Copy file
|
|
||||||
copy source_file destination
|
|
||||||
|
|
||||||
# Move/Rename file
|
|
||||||
move source destination
|
|
||||||
|
|
||||||
# Delete file
|
|
||||||
del filename
|
|
||||||
|
|
||||||
# Search for file
|
|
||||||
dir /s filename
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### File Content Operations
|
## Git Commands
|
||||||
```bash
|
```bash
|
||||||
# Display file content
|
# Check status
|
||||||
type filename
|
|
||||||
|
|
||||||
# Display file content page by page
|
|
||||||
more filename
|
|
||||||
|
|
||||||
# Search for text in file
|
|
||||||
findstr "pattern" filename
|
|
||||||
|
|
||||||
# Search recursively
|
|
||||||
findstr /s /i "pattern" *.php
|
|
||||||
```
|
|
||||||
|
|
||||||
### Git Commands
|
|
||||||
```bash
|
|
||||||
# Check git status
|
|
||||||
git status
|
git status
|
||||||
|
|
||||||
# View changes
|
# Add files
|
||||||
git diff
|
|
||||||
|
|
||||||
# View staged changes
|
|
||||||
git diff --staged
|
|
||||||
|
|
||||||
# Add files to staging
|
|
||||||
git add .
|
git add .
|
||||||
|
|
||||||
# Add specific file
|
# Commit (only when explicitly asked)
|
||||||
git add path/to/file
|
git commit -m "message"
|
||||||
|
|
||||||
# Commit changes
|
# View recent commits
|
||||||
git commit -m "commit message"
|
git log --oneline -10
|
||||||
|
|
||||||
# Push to remote
|
|
||||||
git push
|
|
||||||
|
|
||||||
# Pull from remote
|
|
||||||
git pull
|
|
||||||
|
|
||||||
# View commit history
|
|
||||||
git log
|
|
||||||
|
|
||||||
# View commit history with graph
|
|
||||||
git log --graph --oneline
|
|
||||||
|
|
||||||
# Create new branch
|
|
||||||
git checkout -b branch_name
|
|
||||||
|
|
||||||
# Switch branch
|
|
||||||
git checkout branch_name
|
|
||||||
|
|
||||||
# Merge branch
|
|
||||||
git merge branch_name
|
|
||||||
|
|
||||||
# View branches
|
|
||||||
git branch
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Process Management
|
|
||||||
```bash
|
|
||||||
# List running processes
|
|
||||||
tasklist
|
|
||||||
|
|
||||||
# Kill process by PID
|
|
||||||
taskkill /PID pid_number
|
|
||||||
|
|
||||||
# Kill process by name
|
|
||||||
taskkill /IM process_name.exe
|
|
||||||
|
|
||||||
# Kill process forcefully
|
|
||||||
taskkill /F /PID pid_number
|
|
||||||
```
|
|
||||||
|
|
||||||
### Network Operations
|
|
||||||
```bash
|
|
||||||
# Check port usage
|
|
||||||
netstat -an | findstr :port
|
|
||||||
|
|
||||||
# Test network connectivity
|
|
||||||
ping hostname
|
|
||||||
|
|
||||||
# View active connections
|
|
||||||
netstat -an
|
|
||||||
```
|
|
||||||
|
|
||||||
## After Task Completion Checklist
|
|
||||||
|
|
||||||
When completing a task, run the following commands to ensure code quality:
|
|
||||||
|
|
||||||
### 1. Run Tests
|
|
||||||
```bash
|
|
||||||
# Run all tests
|
|
||||||
vendor/bin/phpunit
|
|
||||||
|
|
||||||
# If tests fail, run specific test file for debugging
|
|
||||||
vendor/bin/phpunit tests/feature/[SpecificTestFile].php
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Check for Linting Issues (if configured)
|
|
||||||
```bash
|
|
||||||
# Check for PHP syntax errors
|
|
||||||
php -l app/Controllers/YourController.php
|
|
||||||
php -l app/Models/YourModel.php
|
|
||||||
|
|
||||||
# Run any custom linting tools if configured in composer.json
|
|
||||||
composer test # if 'test' script includes linting
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Type Checking (if configured)
|
|
||||||
```bash
|
|
||||||
# Run static analysis tools if configured
|
|
||||||
vendor/bin/phpstan analyse # if phpstan is installed
|
|
||||||
vendor/bin/psalm # if psalm is installed
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Database Verification
|
|
||||||
```bash
|
|
||||||
# Check migration status
|
|
||||||
php spark migrate:status
|
|
||||||
|
|
||||||
# If you created a migration, run it
|
|
||||||
php spark migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. API Documentation Update (CRITICAL)
|
|
||||||
```bash
|
|
||||||
# After modifying ANY controller, MUST update api-docs.yaml
|
|
||||||
# This is a manual process - edit public/api-docs.yaml
|
|
||||||
|
|
||||||
# Verify YAML syntax (optional, if yamllint is available)
|
|
||||||
yamllint public/api-docs.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Code Review Checklist
|
|
||||||
- [ ] All tests passing
|
|
||||||
- [ ] No PHP syntax errors
|
|
||||||
- [ ] Database migrations applied (if any)
|
|
||||||
- [ ] API documentation updated (`public/api-docs.yaml`)
|
|
||||||
- [ ] Code follows style conventions (see `code_style_conventions.md`)
|
|
||||||
- [ ] Proper error handling in place
|
|
||||||
- [ ] Input validation implemented
|
|
||||||
- [ ] JWT authentication required where needed
|
|
||||||
- [ ] UTC date handling via BaseModel
|
|
||||||
- [ ] Soft delete using `DelDate` where applicable
|
|
||||||
- [ ] ValueSet lookups properly used and cached cleared if modified
|
|
||||||
|
|
||||||
### 7. Verify API Endpoints (if applicable)
|
|
||||||
```bash
|
|
||||||
# If you have curl or a REST client, test the endpoints
|
|
||||||
# Example using curl:
|
|
||||||
curl -X GET http://localhost:8080/api/patient -H "Cookie: token=your_jwt_token"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Workflows
|
|
||||||
|
|
||||||
### Creating a New API Endpoint
|
|
||||||
1. Create controller: `php spark make:controller ControllerName`
|
|
||||||
2. Create model: `php spark make:model ModelName`
|
|
||||||
3. Create migration (if new table): `php spark make:migration MigrationName`
|
|
||||||
4. Run migration: `php spark migrate`
|
|
||||||
5. Add routes in `app/Config/Routes.php`
|
|
||||||
6. Implement controller methods following pattern
|
|
||||||
7. Create tests: `php spark make:test Feature/EndpointNameTest`
|
|
||||||
8. Run tests: `vendor/bin/phpunit tests/feature/EndpointNameTest.php`
|
|
||||||
9. Update `public/api-docs.yaml`
|
|
||||||
10. Verify with test client
|
|
||||||
|
|
||||||
### Debugging a Failing Test
|
|
||||||
1. Run specific test file: `vendor/bin/phpunit tests/feature/SpecificTest.php`
|
|
||||||
2. Add debug output: `var_dump($result); die();` temporarily
|
|
||||||
3. Check database state: View with database client
|
|
||||||
4. Check logs: `writable/logs/` directory
|
|
||||||
5. Run with verbose: `vendor/bin/phpunit --verbose`
|
|
||||||
6. Isolate specific test: `vendor/bin/phpunit --filter testMethodName`
|
|
||||||
|
|
||||||
### Working with ValueSets
|
|
||||||
1. Create/edit JSON file: `app/Libraries/Data/valuesets/{name}.json`
|
|
||||||
2. Clear cache: `ValueSet::clearCache();` (in code) or via code
|
|
||||||
3. Verify via API: GET `/api/valueset/{name}`
|
|
||||||
4. Test lookup: `ValueSet::get('name')` in controller/model
|
|
||||||
|
|||||||
@ -1,129 +1,67 @@
|
|||||||
# CLQMS Task Completion Guidelines
|
# CLQMS Task Completion Checklist
|
||||||
|
|
||||||
## When a Task is Completed
|
When completing a task, ensure:
|
||||||
|
|
||||||
### 1. Run Tests
|
|
||||||
Always run relevant tests after making changes:
|
|
||||||
|
|
||||||
|
## 1. Tests Pass
|
||||||
```bash
|
```bash
|
||||||
# Run all tests
|
|
||||||
./vendor/bin/phpunit
|
./vendor/bin/phpunit
|
||||||
|
|
||||||
# Run specific test file
|
|
||||||
./vendor/bin/phpunit tests/feature/Patients/PatientCreateTest.php
|
|
||||||
|
|
||||||
# Run specific test method
|
|
||||||
./vendor/bin/phpunit --filter testCreatePatientSuccess tests/feature/Patients/PatientCreateTest.php
|
|
||||||
```
|
```
|
||||||
|
- All existing tests must pass
|
||||||
|
- Add new tests for new features
|
||||||
|
- Test naming: `test<Action><Scenario><Result>`
|
||||||
|
|
||||||
### 2. Verify Code Quality
|
## 2. API Documentation Updated (CRITICAL)
|
||||||
|
When updating ANY controller, update corresponding OpenAPI YAML:
|
||||||
|
|
||||||
#### Check for Syntax Errors
|
| Controller | YAML Path File | YAML Schema File |
|
||||||
|
|-----------|----------------|------------------|
|
||||||
|
| `PatientController` | `paths/patients.yaml` | `components/schemas/patient.yaml` |
|
||||||
|
| `PatVisitController` | `paths/patient-visits.yaml` | `components/schemas/patient-visit.yaml` |
|
||||||
|
| `OrderTestController` | `paths/orders.yaml` | `components/schemas/orders.yaml` |
|
||||||
|
| `SpecimenController` | `paths/specimen.yaml` | `components/schemas/specimen.yaml` |
|
||||||
|
| `TestsController` | `paths/tests.yaml` | `components/schemas/tests.yaml` |
|
||||||
|
| `AuthController` | `paths/authentication.yaml` | `components/schemas/authentication.yaml` |
|
||||||
|
| `ResultController` | `paths/results.yaml` | `components/schemas/*.yaml` |
|
||||||
|
| `EdgeController` | `paths/edge-api.yaml` | `components/schemas/edge-api.yaml` |
|
||||||
|
| `LocationController` | `paths/locations.yaml` | `components/schemas/master-data.yaml` |
|
||||||
|
| `ValueSetController` | `paths/valuesets.yaml` | `components/schemas/valuesets.yaml` |
|
||||||
|
| `ContactController` | `paths/contact.yaml` | (inline schemas) |
|
||||||
|
|
||||||
|
After updating YAML files:
|
||||||
```bash
|
```bash
|
||||||
php -l app/Controllers/Patient/PatientController.php
|
node public/bundle-api-docs.js
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Check Test Results
|
## 3. Code Quality Checks
|
||||||
Ensure:
|
- PSR-12 compliance where applicable
|
||||||
- All existing tests still pass
|
- No database queries in controllers
|
||||||
- New tests (if any) pass
|
|
||||||
- No unexpected warnings or errors
|
|
||||||
|
|
||||||
### 3. Code Review Checklist
|
|
||||||
|
|
||||||
#### Controller Changes
|
|
||||||
- [ ] Validation rules are properly defined
|
|
||||||
- [ ] Error handling uses try-catch blocks
|
|
||||||
- [ ] Responses use standardized format with `ResponseTrait`
|
|
||||||
- [ ] Authentication filter applied where needed
|
|
||||||
- [ ] Input sanitization via validation rules
|
|
||||||
- [ ] Database operations wrapped in transactions (if multi-table)
|
|
||||||
|
|
||||||
#### Model Changes
|
|
||||||
- [ ] Extends `BaseModel` for UTC handling
|
|
||||||
- [ ] Table name, primary key, allowed fields defined
|
|
||||||
- [ ] Uses `checkDbError()` for error detection
|
|
||||||
- [ ] Audit logging via `AuditService::logData()` for data changes
|
|
||||||
- [ ] Soft delete fields configured if using soft deletes
|
|
||||||
- [ ] Nested data properly handled (extracted before filtering)
|
|
||||||
|
|
||||||
#### New Routes
|
|
||||||
- [ ] Added to `app/Config/Routes.php`
|
|
||||||
- [ ] Follows REST conventions (GET, POST, PATCH, DELETE)
|
|
||||||
- [ ] Grouped appropriately under `/api/`
|
|
||||||
- [ ] Auth filter applied if needed
|
|
||||||
|
|
||||||
#### New Tests
|
|
||||||
- [ ] Test name follows `test<Action><Scenario><ExpectedResult>` pattern
|
|
||||||
- [ ] Uses `FeatureTestTrait`
|
|
||||||
- [ ] Uses `Factory::create('id_ID')` for Indonesian test data
|
|
||||||
- [ ] Asserts correct status codes (200, 201, 400, 401, 404, 500)
|
|
||||||
- [ ] Tests both success and failure scenarios
|
|
||||||
|
|
||||||
### 4. Common Issues to Check
|
|
||||||
|
|
||||||
#### Database Operations
|
|
||||||
- Multi-table operations should use transactions
|
|
||||||
- Use parameterized queries (Query Builder handles this)
|
|
||||||
- Check for empty/null arrays before processing
|
|
||||||
|
|
||||||
#### Nested Data
|
|
||||||
- Extract nested arrays before filtering/processing
|
|
||||||
- Handle empty/null nested data appropriately
|
|
||||||
- Use transactions for multi-table operations
|
- Use transactions for multi-table operations
|
||||||
|
- Proper error handling with try-catch for JWT/external calls
|
||||||
|
- Log errors: `log_message('error', $message)`
|
||||||
|
|
||||||
#### Date Handling
|
## 4. Response Format Verification
|
||||||
- All dates stored in UTC
|
Ensure all responses follow the standard format:
|
||||||
- Use `helper('utc')` for conversions
|
```php
|
||||||
- BaseModel extends with automatic UTC conversion
|
return $this->respond([
|
||||||
|
'status' => 'success|failed',
|
||||||
#### Security
|
'message' => 'Description',
|
||||||
- Input validation rules defined
|
'data' => $data
|
||||||
- SQL injection prevention via parameterized queries
|
], $httpStatus);
|
||||||
- JWT validation on protected endpoints
|
|
||||||
- No sensitive data logged or exposed
|
|
||||||
|
|
||||||
### 5. What NOT to Do
|
|
||||||
|
|
||||||
- **Do NOT commit** unless explicitly asked by the user
|
|
||||||
- **Do NOT push** to remote repository unless asked
|
|
||||||
- **Do NOT** skip running tests
|
|
||||||
- **Do NOT** add comments unless specifically requested
|
|
||||||
- **Do NOT** modify `.env` (database credentials, secrets)
|
|
||||||
- **Do NOT** include hardcoded secrets in code
|
|
||||||
|
|
||||||
### 6. Common Test Status Codes Reference
|
|
||||||
|
|
||||||
| Code | Usage | Example |
|
|
||||||
|------|-------|---------|
|
|
||||||
| 200 | GET/PATCH success | `->assertStatus(200)` |
|
|
||||||
| 201 | POST success (created) | `->assertStatus(201)` |
|
|
||||||
| 400 | Validation error | `->assertStatus(400)` |
|
|
||||||
| 401 | Unauthorized | `->assertStatus(401)` |
|
|
||||||
| 404 | Not found | `->assertStatus(404)` |
|
|
||||||
| 500 | Server error | `->assertStatus(500)` |
|
|
||||||
|
|
||||||
### 7. After Completing Tasks
|
|
||||||
|
|
||||||
Simply inform the user the task is complete. For example:
|
|
||||||
```
|
|
||||||
Task completed. The patient create endpoint now validates the identifier type dynamically.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Or if tests were run:
|
## 5. Security Checklist
|
||||||
```
|
- Use `auth` filter for protected routes
|
||||||
Task completed. All tests passing:
|
- Sanitize user inputs
|
||||||
- testCreatePatientSuccess ✓
|
- Use parameterized queries
|
||||||
- testCreatePatientValidationFail ✓
|
- No secrets committed to repo (use .env)
|
||||||
```
|
|
||||||
|
|
||||||
### 8. When Something Goes Wrong
|
## 6. Naming Conventions
|
||||||
|
- Classes: PascalCase
|
||||||
|
- Methods: camelCase
|
||||||
|
- Properties: snake_case (legacy) / camelCase (new)
|
||||||
|
- Database columns: PascalCase (legacy convention)
|
||||||
|
|
||||||
If tests fail or errors occur:
|
## 7. Do NOT Commit Unless Explicitly Asked
|
||||||
1. Check the error message carefully
|
- Check status: `git status`
|
||||||
2. Review the code against the patterns in this guide
|
- Never commit .env files
|
||||||
3. Check database connection and configuration
|
- Never commit secrets
|
||||||
4. Verify all required dependencies are installed
|
|
||||||
5. Review log files in `writable/logs/`
|
|
||||||
|
|
||||||
If unable to resolve, inform the user with details of the issue.
|
|
||||||
|
|||||||
@ -125,3 +125,8 @@ language_backend:
|
|||||||
# 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: []
|
||||||
|
|
||||||
|
# line ending convention to use when writing source files.
|
||||||
|
# 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.
|
||||||
|
line_ending:
|
||||||
|
|||||||
@ -56,6 +56,17 @@ class SiteController extends BaseController {
|
|||||||
|
|
||||||
public function create() {
|
public function create() {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
|
|
||||||
|
$validation = service('validation');
|
||||||
|
$validation->setRules([
|
||||||
|
'SiteCode' => 'required|regex_match[/^[A-Z0-9]{2}$/]',
|
||||||
|
'SiteName' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$validation->run($input)) {
|
||||||
|
return $this->failValidationErrors($validation->getErrors());
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -66,9 +77,22 @@ class SiteController extends BaseController {
|
|||||||
|
|
||||||
public function update() {
|
public function update() {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
|
|
||||||
|
$id = $input['SiteID'];
|
||||||
|
if (!$id) { return $this->failValidationErrors('ID is required.'); }
|
||||||
|
|
||||||
|
if (!empty($input['SiteCode'])) {
|
||||||
|
$validation = service('validation');
|
||||||
|
$validation->setRules([
|
||||||
|
'SiteCode' => 'regex_match[/^[A-Z0-9]{2}$/]',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!$validation->run($input)) {
|
||||||
|
return $this->failValidationErrors($validation->getErrors());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$id = $input['SiteID'];
|
|
||||||
if (!$id) { return $this->failValidationErrors('ID is required.'); }
|
|
||||||
$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) {
|
||||||
|
|||||||
@ -11,7 +11,6 @@ class TestsController extends BaseController
|
|||||||
{
|
{
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
protected $db;
|
|
||||||
protected $model;
|
protected $model;
|
||||||
protected $modelCal;
|
protected $modelCal;
|
||||||
protected $modelGrp;
|
protected $modelGrp;
|
||||||
@ -23,7 +22,6 @@ class TestsController extends BaseController
|
|||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->db = \Config\Database::connect();
|
|
||||||
$this->model = new \App\Models\Test\TestDefSiteModel;
|
$this->model = new \App\Models\Test\TestDefSiteModel;
|
||||||
$this->modelCal = new \App\Models\Test\TestDefCalModel;
|
$this->modelCal = new \App\Models\Test\TestDefCalModel;
|
||||||
$this->modelGrp = new \App\Models\Test\TestDefGrpModel;
|
$this->modelGrp = new \App\Models\Test\TestDefGrpModel;
|
||||||
@ -81,9 +79,7 @@ class TestsController extends BaseController
|
|||||||
return $this->failValidationErrors('TestSiteID is required');
|
return $this->failValidationErrors('TestSiteID is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = $this->model->select('testdefsite.*')
|
$row = $this->model->getTestById($id);
|
||||||
->where('testdefsite.TestSiteID', $id)
|
|
||||||
->find($id);
|
|
||||||
|
|
||||||
if (!$row) {
|
if (!$row) {
|
||||||
return $this->respond([
|
return $this->respond([
|
||||||
@ -93,25 +89,14 @@ class TestsController extends BaseController
|
|||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = ValueSet::transformLabels([$row], [
|
|
||||||
'TestType' => 'test_type',
|
|
||||||
])[0];
|
|
||||||
|
|
||||||
$typeCode = $row['TestType'] ?? '';
|
$typeCode = $row['TestType'] ?? '';
|
||||||
|
|
||||||
if ($typeCode === 'CALC') {
|
if ($typeCode === 'CALC') {
|
||||||
$row['testdefcal'] = $this->modelCal->getByTestSiteID($id);
|
$row['testdefcal'] = $this->modelCal->getByTestSiteID($id);
|
||||||
} elseif ($typeCode === 'GROUP') {
|
} elseif ($typeCode === 'GROUP') {
|
||||||
$row['testdefgrp'] = $this->modelGrp->getGroupMembers($id);
|
$row['testdefgrp'] = $this->modelGrp->getGroupMembers($id);
|
||||||
} elseif ($typeCode === 'TITLE') {
|
} elseif ($typeCode !== 'TITLE') {
|
||||||
} else {
|
$row['testdeftech'] = $this->model->getTestTechWithRelations($id);
|
||||||
$row['testdeftech'] = $this->db->table('testdefsite')
|
|
||||||
->select('testdefsite.*, d.DisciplineName, dept.DepartmentName')
|
|
||||||
->join('discipline d', 'd.DisciplineID=testdefsite.DisciplineID', 'left')
|
|
||||||
->join('department dept', 'dept.DepartmentID=testdefsite.DepartmentID', 'left')
|
|
||||||
->where('testdefsite.TestSiteID', $id)
|
|
||||||
->where('testdefsite.EndDate IS NULL')
|
|
||||||
->get()->getResultArray();
|
|
||||||
|
|
||||||
if (!empty($row['testdeftech'])) {
|
if (!empty($row['testdeftech'])) {
|
||||||
$techData = $row['testdeftech'][0];
|
$techData = $row['testdeftech'][0];
|
||||||
@ -119,47 +104,11 @@ class TestsController extends BaseController
|
|||||||
$resultType = $techData['ResultType'] ?? '';
|
$resultType = $techData['ResultType'] ?? '';
|
||||||
|
|
||||||
if (TestValidationService::usesRefNum($resultType, $refType)) {
|
if (TestValidationService::usesRefNum($resultType, $refType)) {
|
||||||
$refnumData = $this->modelRefNum->getActiveByTestSiteID($id);
|
$row['refnum'] = $this->modelRefNum->getFormattedByTestSiteID($id);
|
||||||
|
|
||||||
$row['refnum'] = array_map(function ($r) {
|
|
||||||
return [
|
|
||||||
'RefNumID' => $r['RefNumID'],
|
|
||||||
'NumRefType' => $r['NumRefType'],
|
|
||||||
'NumRefTypeLabel' => $r['NumRefType'] ? ValueSet::getLabel('numeric_ref_type', $r['NumRefType']) : '',
|
|
||||||
'RangeType' => $r['RangeType'],
|
|
||||||
'RangeTypeLabel' => $r['RangeType'] ? ValueSet::getLabel('range_type', $r['RangeType']) : '',
|
|
||||||
'Sex' => $r['Sex'],
|
|
||||||
'SexLabel' => $r['Sex'] ? ValueSet::getLabel('gender', $r['Sex']) : '',
|
|
||||||
'LowSign' => $r['LowSign'],
|
|
||||||
'LowSignLabel' => $r['LowSign'] ? ValueSet::getLabel('math_sign', $r['LowSign']) : '',
|
|
||||||
'HighSign' => $r['HighSign'],
|
|
||||||
'HighSignLabel' => $r['HighSign'] ? ValueSet::getLabel('math_sign', $r['HighSign']) : '',
|
|
||||||
'High' => $r['High'] !== null ? (float) $r['High'] : null,
|
|
||||||
'Low' => $r['Low'] !== null ? (float) $r['Low'] : null,
|
|
||||||
'AgeStart' => (int) $r['AgeStart'],
|
|
||||||
'AgeEnd' => (int) $r['AgeEnd'],
|
|
||||||
'Flag' => $r['Flag'],
|
|
||||||
'Interpretation' => $r['Interpretation'],
|
|
||||||
];
|
|
||||||
}, $refnumData ?? []);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TestValidationService::usesRefTxt($resultType, $refType)) {
|
if (TestValidationService::usesRefTxt($resultType, $refType)) {
|
||||||
$reftxtData = $this->modelRefTxt->getActiveByTestSiteID($id);
|
$row['reftxt'] = $this->modelRefTxt->getFormattedByTestSiteID($id);
|
||||||
|
|
||||||
$row['reftxt'] = array_map(function ($r) {
|
|
||||||
return [
|
|
||||||
'RefTxtID' => $r['RefTxtID'],
|
|
||||||
'TxtRefType' => $r['TxtRefType'],
|
|
||||||
'TxtRefTypeLabel'=> $r['TxtRefType'] ? ValueSet::getLabel('text_ref_type', $r['TxtRefType']) : '',
|
|
||||||
'Sex' => $r['Sex'],
|
|
||||||
'SexLabel' => $r['Sex'] ? ValueSet::getLabel('gender', $r['Sex']) : '',
|
|
||||||
'AgeStart' => (int) $r['AgeStart'],
|
|
||||||
'AgeEnd' => (int) $r['AgeEnd'],
|
|
||||||
'RefTxt' => $r['RefTxt'],
|
|
||||||
'Flag' => $r['Flag'],
|
|
||||||
];
|
|
||||||
}, $reftxtData ?? []);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +148,8 @@ class TestsController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->db->transStart();
|
$db = \Config\Database::connect();
|
||||||
|
$db->transStart();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$testSiteData = [
|
$testSiteData = [
|
||||||
@ -225,9 +175,9 @@ class TestsController extends BaseController
|
|||||||
|
|
||||||
$this->handleDetails($id, $input, 'insert');
|
$this->handleDetails($id, $input, 'insert');
|
||||||
|
|
||||||
$this->db->transComplete();
|
$db->transComplete();
|
||||||
|
|
||||||
if ($this->db->transStatus() === false) {
|
if ($db->transStatus() === false) {
|
||||||
return $this->failServerError('Transaction failed');
|
return $this->failServerError('Transaction failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +187,7 @@ class TestsController extends BaseController
|
|||||||
'data' => ['TestSiteId' => $id],
|
'data' => ['TestSiteId' => $id],
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->db->transRollback();
|
$db->transRollback();
|
||||||
|
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
@ -279,7 +229,8 @@ class TestsController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->db->transStart();
|
$db = \Config\Database::connect();
|
||||||
|
$db->transStart();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$testSiteData = [];
|
$testSiteData = [];
|
||||||
@ -310,9 +261,9 @@ class TestsController extends BaseController
|
|||||||
|
|
||||||
$this->handleDetails($id, $input, 'update');
|
$this->handleDetails($id, $input, 'update');
|
||||||
|
|
||||||
$this->db->transComplete();
|
$db->transComplete();
|
||||||
|
|
||||||
if ($this->db->transStatus() === false) {
|
if ($db->transStatus() === false) {
|
||||||
return $this->failServerError('Transaction failed');
|
return $this->failServerError('Transaction failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,7 +273,7 @@ class TestsController extends BaseController
|
|||||||
'data' => ['TestSiteId' => $id],
|
'data' => ['TestSiteId' => $id],
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->db->transRollback();
|
$db->transRollback();
|
||||||
|
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
@ -348,7 +299,8 @@ class TestsController extends BaseController
|
|||||||
return $this->failValidationErrors('Test is already disabled');
|
return $this->failValidationErrors('Test is already disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->db->transStart();
|
$db = \Config\Database::connect();
|
||||||
|
$db->transStart();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$now = date('Y-m-d H:i:s');
|
$now = date('Y-m-d H:i:s');
|
||||||
@ -363,8 +315,8 @@ class TestsController extends BaseController
|
|||||||
} elseif (TestValidationService::isGroup($typeCode)) {
|
} elseif (TestValidationService::isGroup($typeCode)) {
|
||||||
$this->modelGrp->disableByTestSiteID($id);
|
$this->modelGrp->disableByTestSiteID($id);
|
||||||
} elseif (TestValidationService::isTechnicalTest($typeCode)) {
|
} elseif (TestValidationService::isTechnicalTest($typeCode)) {
|
||||||
$this->modelRefNum->where('TestSiteID', $id)->set('EndDate', $now)->update();
|
$this->modelRefNum->disableByTestSiteID($id);
|
||||||
$this->modelRefTxt->where('TestSiteID', $id)->set('EndDate', $now)->update();
|
$this->modelRefTxt->disableByTestSiteID($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable testmap by test code
|
// Disable testmap by test code
|
||||||
@ -372,17 +324,14 @@ class TestsController extends BaseController
|
|||||||
if ($testSiteCode) {
|
if ($testSiteCode) {
|
||||||
$existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode);
|
$existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode);
|
||||||
foreach ($existingMaps as $existingMap) {
|
foreach ($existingMaps as $existingMap) {
|
||||||
$this->modelMapDetail->where('TestMapID', $existingMap['TestMapID'])
|
$this->modelMapDetail->disableByTestMapID($existingMap['TestMapID']);
|
||||||
->where('EndDate', null)
|
|
||||||
->set('EndDate', $now)
|
|
||||||
->update();
|
|
||||||
$this->modelMap->update($existingMap['TestMapID'], ['EndDate' => $now]);
|
$this->modelMap->update($existingMap['TestMapID'], ['EndDate' => $now]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->db->transComplete();
|
$db->transComplete();
|
||||||
|
|
||||||
if ($this->db->transStatus() === false) {
|
if ($db->transStatus() === false) {
|
||||||
return $this->failServerError('Transaction failed');
|
return $this->failServerError('Transaction failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +341,7 @@ class TestsController extends BaseController
|
|||||||
'data' => ['TestSiteId' => $id, 'EndDate' => $now],
|
'data' => ['TestSiteId' => $id, 'EndDate' => $now],
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->db->transRollback();
|
$db->transRollback();
|
||||||
|
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
@ -488,53 +437,19 @@ class TestsController extends BaseController
|
|||||||
private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID)
|
private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID)
|
||||||
{
|
{
|
||||||
if ($action === 'update') {
|
if ($action === 'update') {
|
||||||
$this->modelRefNum->where('TestSiteID', $testSiteID)
|
$this->modelRefNum->disableByTestSiteID($testSiteID);
|
||||||
->set('EndDate', date('Y-m-d H:i:s'))
|
|
||||||
->update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($ranges as $index => $range) {
|
$this->modelRefNum->batchInsert($testSiteID, $siteID, $ranges);
|
||||||
$this->modelRefNum->insert([
|
|
||||||
'TestSiteID' => $testSiteID,
|
|
||||||
'SiteID' => $siteID,
|
|
||||||
'NumRefType' => $range['NumRefType'],
|
|
||||||
'RangeType' => $range['RangeType'],
|
|
||||||
'Sex' => $range['Sex'],
|
|
||||||
'AgeStart' => (int) ($range['AgeStart'] ?? 0),
|
|
||||||
'AgeEnd' => (int) ($range['AgeEnd'] ?? 150),
|
|
||||||
'LowSign' => !empty($range['LowSign']) ? $range['LowSign'] : null,
|
|
||||||
'Low' => !empty($range['Low']) ? (float) $range['Low'] : null,
|
|
||||||
'HighSign' => !empty($range['HighSign']) ? $range['HighSign'] : null,
|
|
||||||
'High' => !empty($range['High']) ? (float) $range['High'] : null,
|
|
||||||
'Flag' => $range['Flag'] ?? null,
|
|
||||||
'Interpretation'=> $range['Interpretation'] ?? null,
|
|
||||||
'Display' => $index,
|
|
||||||
'CreateDate' => date('Y-m-d H:i:s'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function saveRefTxtRanges($testSiteID, $ranges, $action, $siteID)
|
private function saveRefTxtRanges($testSiteID, $ranges, $action, $siteID)
|
||||||
{
|
{
|
||||||
if ($action === 'update') {
|
if ($action === 'update') {
|
||||||
$this->modelRefTxt->where('TestSiteID', $testSiteID)
|
$this->modelRefTxt->disableByTestSiteID($testSiteID);
|
||||||
->set('EndDate', date('Y-m-d H:i:s'))
|
|
||||||
->update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($ranges as $range) {
|
$this->modelRefTxt->batchInsert($testSiteID, $siteID, $ranges);
|
||||||
$this->modelRefTxt->insert([
|
|
||||||
'TestSiteID' => $testSiteID,
|
|
||||||
'SiteID' => $siteID,
|
|
||||||
'TxtRefType' => $range['TxtRefType'],
|
|
||||||
'Sex' => $range['Sex'],
|
|
||||||
'AgeStart' => (int) ($range['AgeStart'] ?? 0),
|
|
||||||
'AgeEnd' => (int) ($range['AgeEnd'] ?? 150),
|
|
||||||
'RefTxt' => $range['RefTxt'] ?? '',
|
|
||||||
'Flag' => $range['Flag'] ?? null,
|
|
||||||
'CreateDate' => date('Y-m-d H:i:s'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function saveCalcDetails($testSiteID, $data, $action)
|
private function saveCalcDetails($testSiteID, $data, $action)
|
||||||
@ -595,10 +510,7 @@ class TestsController extends BaseController
|
|||||||
$existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode);
|
$existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode);
|
||||||
|
|
||||||
foreach ($existingMaps as $existingMap) {
|
foreach ($existingMaps as $existingMap) {
|
||||||
$this->modelMapDetail->where('TestMapID', $existingMap['TestMapID'])
|
$this->modelMapDetail->disableByTestMapID($existingMap['TestMapID']);
|
||||||
->where('EndDate', null)
|
|
||||||
->set('EndDate', date('Y-m-d H:i:s'))
|
|
||||||
->update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Soft delete the testmap headers
|
// Soft delete the testmap headers
|
||||||
|
|||||||
@ -36,6 +36,7 @@ class CreateLookups extends Migration {
|
|||||||
'CounterValue' => ['type' => 'INT', 'null' => false],
|
'CounterValue' => ['type' => 'INT', 'null' => false],
|
||||||
'CounterStart' => ['type' => 'INT', 'null' => false],
|
'CounterStart' => ['type' => 'INT', 'null' => false],
|
||||||
'CounterEnd' => ['type' => 'INT', 'null' => false],
|
'CounterEnd' => ['type' => 'INT', 'null' => false],
|
||||||
|
'CounterName' => [ 'type' => 'VARCHAR', 'constraint' => 50, 'null' => true, 'after' => 'CounterID' ],
|
||||||
'CounterDesc' => ['type' => 'varchar', 'constraint' => 255, 'null' => true],
|
'CounterDesc' => ['type' => 'varchar', 'constraint' => 255, 'null' => true],
|
||||||
'CounterReset' => ['type' => 'varchar', 'constraint' => 1, 'null' => true],
|
'CounterReset' => ['type' => 'varchar', 'constraint' => 1, 'null' => true],
|
||||||
'CreateDate' => ['type' => 'Datetime', 'null' => true],
|
'CreateDate' => ['type' => 'Datetime', 'null' => true],
|
||||||
|
|||||||
@ -31,12 +31,13 @@ class CreateOrganization extends Migration {
|
|||||||
|
|
||||||
$this->forge->addField([
|
$this->forge->addField([
|
||||||
'SiteID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
'SiteID' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
||||||
'SiteCode' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => false],
|
'ExtSiteID' => ['type' => 'int', 'null' => true],
|
||||||
|
'SiteCode' => ['type' => 'VARCHAR', 'constraint' => 2, 'null' => false],
|
||||||
'SiteName' => ['type' => 'VARCHAR', 'constraint' => 100, 'null' => false],
|
'SiteName' => ['type' => 'VARCHAR', 'constraint' => 100, 'null' => false],
|
||||||
'AccountID' => ['type' => 'int', 'null' => true],
|
'AccountID' => ['type' => 'int', 'null' => true],
|
||||||
'SiteTypeID' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
'SiteType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
||||||
'Parent' => ['type' => 'int', 'null' => true],
|
'Parent' => ['type' => 'int', 'null' => true],
|
||||||
'SiteClassID' => ['type' => 'VARCHAR', 'constraint' => 50, 'null' => true],
|
'SiteClass' => ['type' => 'VARCHAR', 'constraint' => 50, 'null' => true],
|
||||||
'ME' => ['type' => 'VARCHAR', 'constraint' => 50, 'null' => true],
|
'ME' => ['type' => 'VARCHAR', 'constraint' => 50, 'null' => true],
|
||||||
'CreateDate' => ['type' => 'datetime', 'null'=> true],
|
'CreateDate' => ['type' => 'datetime', 'null'=> true],
|
||||||
'EndDate' => ['type' => 'datetime', 'null'=> true]
|
'EndDate' => ['type' => 'datetime', 'null'=> true]
|
||||||
@ -81,6 +82,8 @@ class CreateOrganization extends Migration {
|
|||||||
'DisciplineCode' => ['type' => 'varchar', 'constraint'=> 10, 'null'=> false],
|
'DisciplineCode' => ['type' => 'varchar', 'constraint'=> 10, 'null'=> false],
|
||||||
'DisciplineName' => ['type' => 'varchar', 'constraint'=> 150, 'null'=> true],
|
'DisciplineName' => ['type' => 'varchar', 'constraint'=> 150, 'null'=> true],
|
||||||
'Parent' => ['type' => 'int', 'null'=> true],
|
'Parent' => ['type' => 'int', 'null'=> true],
|
||||||
|
'SeqScr' => ['type' => 'int', 'null' => true],
|
||||||
|
'SeqRpt' => ['type' => 'int', 'null' => true],
|
||||||
'CreateDate' => ['type'=>'DATETIME', 'null' => true],
|
'CreateDate' => ['type'=>'DATETIME', 'null' => true],
|
||||||
'EndDate' => ['type'=>'DATETIME', 'null' => true]
|
'EndDate' => ['type'=>'DATETIME', 'null' => true]
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -20,25 +20,25 @@ class OrganizationSeeder extends Seeder
|
|||||||
$this->db->table('account')->insertBatch($data);
|
$this->db->table('account')->insertBatch($data);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
[ 'SiteID' => 1, 'SiteCode' => 'QSIT', 'SiteName' => 'Dummy Site', 'AccountID' => 1, 'Parent' => null, 'CreateDate' => "$now" ],
|
[ 'SiteID' => 1, 'SiteCode' => 'Q1', 'SiteName' => 'Dummy Site', 'AccountID' => 1, 'Parent' => null, 'CreateDate' => "$now" ],
|
||||||
[ 'SiteID' => 2, 'SiteCode' => 'XSIT', 'SiteName' => 'Dummy Child Site', 'AccountID' => 1, 'Parent' => 1, 'CreateDate' => "$now" ],
|
[ 'SiteID' => 2, 'SiteCode' => 'X1', 'SiteName' => 'Dummy Child Site', 'AccountID' => 1, 'Parent' => 1, 'CreateDate' => "$now" ],
|
||||||
];
|
];
|
||||||
$this->db->table('site')->insertBatch($data);
|
$this->db->table('site')->insertBatch($data);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
['DisciplineID' => '1', 'DisciplineCode' => 'HEMA', 'DisciplineName' => 'Hematology', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '1', 'DisciplineCode' => 'HEMA', 'DisciplineName' => 'Hematology', 'Parent' => null, 'SeqScr' => 10, 'SeqRpt' => 10, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '2', 'DisciplineCode' => 'CHEM', 'DisciplineName' => 'Clinical Chemistry', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '2', 'DisciplineCode' => 'CHEM', 'DisciplineName' => 'Clinical Chemistry', 'Parent' => null, 'SeqScr' => 20, 'SeqRpt' => 20, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '3', 'DisciplineCode' => 'IMSR', 'DisciplineName' => 'Immunology/Serology', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '3', 'DisciplineCode' => 'IMSR', 'DisciplineName' => 'Immunology/Serology', 'Parent' => null, 'SeqScr' => 30, 'SeqRpt' => 30, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '4', 'DisciplineCode' => 'URIN', 'DisciplineName' => 'Urinalysis', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '4', 'DisciplineCode' => 'URIN', 'DisciplineName' => 'Urinalysis', 'Parent' => null, 'SeqScr' => 40, 'SeqRpt' => 40, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '5', 'DisciplineCode' => 'FECAL', 'DisciplineName' => 'Fecal Analysis', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '5', 'DisciplineCode' => 'FECAL', 'DisciplineName' => 'Fecal Analysis', 'Parent' => null, 'SeqScr' => 50, 'SeqRpt' => 50, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '6', 'DisciplineCode' => 'HC', 'DisciplineName' => 'Pathology/Cytology', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '6', 'DisciplineCode' => 'HC', 'DisciplineName' => 'Pathology/Cytology', 'Parent' => null, 'SeqScr' => 60, 'SeqRpt' => 60, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '7', 'DisciplineCode' => 'MICRO', 'DisciplineName' => 'Microbiology', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '7', 'DisciplineCode' => 'MICRO', 'DisciplineName' => 'Microbiology', 'Parent' => null, 'SeqScr' => 70, 'SeqRpt' => 70, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '8', 'DisciplineCode' => 'TXC', 'DisciplineName' => 'Toxicology', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '8', 'DisciplineCode' => 'TXC', 'DisciplineName' => 'Toxicology', 'Parent' => null, 'SeqScr' => 80, 'SeqRpt' => 80, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '9', 'DisciplineCode' => 'LF', 'DisciplineName' => 'Life Sciences', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '9', 'DisciplineCode' => 'LF', 'DisciplineName' => 'Life Sciences', 'Parent' => null, 'SeqScr' => 90, 'SeqRpt' => 90, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '10', 'DisciplineCode' => 'ND', 'DisciplineName' => 'Non-discipline', 'Parent' => null, 'CreateDate' => "$now"],
|
['DisciplineID' => '10', 'DisciplineCode' => 'ND', 'DisciplineName' => 'Non-discipline', 'Parent' => null, 'SeqScr' => 100, 'SeqRpt' => 100, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '11', 'DisciplineCode' => 'HEMO', 'DisciplineName' => 'Hemostasis', 'Parent' => '1', 'CreateDate' => "$now"],
|
['DisciplineID' => '11', 'DisciplineCode' => 'HEMO', 'DisciplineName' => 'Hemostasis', 'Parent' => '1', 'SeqScr' => 15, 'SeqRpt' => 15, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '12', 'DisciplineCode' => 'BLGLU', 'DisciplineName' => 'Blood Glucose', 'Parent' => '2', 'CreateDate' => "$now"],
|
['DisciplineID' => '12', 'DisciplineCode' => 'BLGLU', 'DisciplineName' => 'Blood Glucose', 'Parent' => '2', 'SeqScr' => 25, 'SeqRpt' => 25, 'CreateDate' => "$now"],
|
||||||
['DisciplineID' => '13', 'DisciplineCode' => 'KIDF', 'DisciplineName' => 'Kidney Function', 'Parent' => '2', 'CreateDate' => "$now"],
|
['DisciplineID' => '13', 'DisciplineCode' => 'KIDF', 'DisciplineName' => 'Kidney Function', 'Parent' => '2', 'SeqScr' => 26, 'SeqRpt' => 26, 'CreateDate' => "$now"],
|
||||||
];
|
];
|
||||||
$this->db->table('discipline')->insertBatch($data);
|
$this->db->table('discipline')->insertBatch($data);
|
||||||
|
|
||||||
|
|||||||
@ -65,128 +65,51 @@ class TestSeeder extends Seeder
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
// TEST TYPE - Actual Laboratory Tests
|
// DEPARTMENT 1 - HEMATOLOGY (Discipline 1)
|
||||||
|
// Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
|
||||||
// ========================================
|
// ========================================
|
||||||
// Hematology Tests - Technical details merged into testdefsite
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'HB', 'TestSiteName' => 'Hemoglobin', 'TestType' => 'TEST', 'Description' => '', 'SeqScr' => '2', 'SeqRpt' => '2', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'g/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
// GROUP: CBC (Complete Blood Count)
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'CBC', 'TestSiteName' => 'Complete Blood Count', 'TestType' => 'GROUP', 'Description' => 'Darah Lengkap', 'SeqScr' => '10', 'SeqRpt' => '10', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['CBC'] = $this->db->insertID();
|
||||||
|
|
||||||
|
// PARAM: (none for Hematology)
|
||||||
|
|
||||||
|
// TEST: Hematology Tests
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'HB', 'TestSiteName' => 'Hemoglobin', 'TestType' => 'TEST', 'Description' => '', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'g/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['HB'] = $this->db->insertID();
|
$tIDs['HB'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'HCT', 'TestSiteName' => 'Hematocrit', 'TestType' => 'TEST', 'Description' => '', 'SeqScr' => '3', 'SeqRpt' => '3', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => '%', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'HCT', 'TestSiteName' => 'Hematocrit', 'TestType' => 'TEST', 'Description' => '', 'SeqScr' => '110', 'SeqRpt' => '110', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => '%', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['HCT'] = $this->db->insertID();
|
$tIDs['HCT'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'RBC', 'TestSiteName' => 'Red Blood Cell', 'TestType' => 'TEST', 'Description' => 'Eritrosit', 'SeqScr' => '4', 'SeqRpt' => '4', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^6/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'RBC', 'TestSiteName' => 'Red Blood Cell', 'TestType' => 'TEST', 'Description' => 'Eritrosit', 'SeqScr' => '120', 'SeqRpt' => '120', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^6/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['RBC'] = $this->db->insertID();
|
$tIDs['RBC'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'WBC', 'TestSiteName' => 'White Blood Cell', 'TestType' => 'TEST', 'Description' => 'Leukosit', 'SeqScr' => '5', 'SeqRpt' => '5', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^3/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'WBC', 'TestSiteName' => 'White Blood Cell', 'TestType' => 'TEST', 'Description' => 'Leukosit', 'SeqScr' => '130', 'SeqRpt' => '130', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^3/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '2', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['WBC'] = $this->db->insertID();
|
$tIDs['WBC'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'PLT', 'TestSiteName' => 'Platelet', 'TestType' => 'TEST', 'Description' => 'Trombosit', 'SeqScr' => '6', 'SeqRpt' => '6', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^3/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'PLT', 'TestSiteName' => 'Platelet', 'TestType' => 'TEST', 'Description' => 'Trombosit', 'SeqScr' => '140', 'SeqRpt' => '140', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'x10^3/uL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['PLT'] = $this->db->insertID();
|
$tIDs['PLT'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'MCV', 'TestSiteName' => 'MCV', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Volume', 'SeqScr' => '7', 'SeqRpt' => '7', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'fL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'MCV', 'TestSiteName' => 'MCV', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Volume', 'SeqScr' => '150', 'SeqRpt' => '150', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'fL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['MCV'] = $this->db->insertID();
|
$tIDs['MCV'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'MCH', 'TestSiteName' => 'MCH', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Hemoglobin', 'SeqScr' => '8', 'SeqRpt' => '8', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'pg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'MCH', 'TestSiteName' => 'MCH', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Hemoglobin', 'SeqScr' => '160', 'SeqRpt' => '160', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'pg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['MCH'] = $this->db->insertID();
|
$tIDs['MCH'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'MCHC', 'TestSiteName' => 'MCHC', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Hemoglobin Concentration', 'SeqScr' => '9', 'SeqRpt' => '9', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'g/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'MCHC', 'TestSiteName' => 'MCHC', 'TestType' => 'TEST', 'Description' => 'Mean Corpuscular Hemoglobin Concentration', 'SeqScr' => '170', 'SeqRpt' => '170', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '1', 'DepartmentID' => '1', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '500', 'ReqQtyUnit' => 'uL', 'Unit1' => 'g/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'CBC Analyzer', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['MCHC'] = $this->db->insertID();
|
$tIDs['MCHC'] = $this->db->insertID();
|
||||||
|
|
||||||
// Chemistry Tests
|
// Add CBC members now that tests are defined
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'GLU', 'TestSiteName' => 'Glucose', 'TestType' => 'TEST', 'Description' => 'Glukosa Sewaktu', 'SeqScr' => '11', 'SeqRpt' => '11', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '0.0555', 'Unit2' => 'mmol/L', 'Decimal' => '0', 'Method' => 'Hexokinase', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['GLU'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'CREA', 'TestSiteName' => 'Creatinine', 'TestType' => 'TEST', 'Description' => 'Kreatinin', 'SeqScr' => '12', 'SeqRpt' => '12', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '88.4', 'Unit2' => 'umol/L', 'Decimal' => '2', 'Method' => 'Enzymatic', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['CREA'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'UREA', 'TestSiteName' => 'Blood Urea Nitrogen', 'TestType' => 'TEST', 'Description' => 'BUN', 'SeqScr' => '13', 'SeqRpt' => '13', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'Urease-GLDH', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['UREA'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'SGOT', 'TestSiteName' => 'AST (SGOT)', 'TestType' => 'TEST', 'Description' => 'Aspartate Aminotransferase', 'SeqScr' => '14', 'SeqRpt' => '14', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'U/L', 'Factor' => '0.017', 'Unit2' => 'ukat/L', 'Decimal' => '0', 'Method' => 'IFCC', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['SGOT'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'SGPT', 'TestSiteName' => 'ALT (SGPT)', 'TestType' => 'TEST', 'Description' => 'Alanine Aminotransferase', 'SeqScr' => '15', 'SeqRpt' => '15', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'U/L', 'Factor' => '0.017', 'Unit2' => 'ukat/L', 'Decimal' => '0', 'Method' => 'IFCC', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['SGPT'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'CHOL', 'TestSiteName' => 'Total Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol Total', 'SeqScr' => '16', 'SeqRpt' => '16', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Enzymatic', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['CHOL'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'TG', 'TestSiteName' => 'Triglycerides', 'TestType' => 'TEST', 'Description' => 'Trigliserida', 'SeqScr' => '17', 'SeqRpt' => '17', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'GPO-PAP', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['TG'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'HDL', 'TestSiteName' => 'HDL Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol HDL', 'SeqScr' => '18', 'SeqRpt' => '18', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Direct', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['HDL'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'LDL', 'TestSiteName' => 'LDL Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol LDL', 'SeqScr' => '19', 'SeqRpt' => '19', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Direct', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['LDL'] = $this->db->insertID();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// PARAM TYPE - Parameters (non-lab values)
|
|
||||||
// ========================================
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'HEIGHT', 'TestSiteName' => 'Height', 'TestType' => 'PARAM', 'Description' => 'Tinggi Badan', 'SeqScr' => '40', 'SeqRpt' => '40', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'cm', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['HEIGHT'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'WEIGHT', 'TestSiteName' => 'Weight', 'TestType' => 'PARAM', 'Description' => 'Berat Badan', 'SeqScr' => '41', 'SeqRpt' => '41', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'kg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => '', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['WEIGHT'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'AGE', 'TestSiteName' => 'Age', 'TestType' => 'PARAM', 'Description' => 'Usia', 'SeqScr' => '42', 'SeqRpt' => '42', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'years', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['AGE'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'SYSTL', 'TestSiteName' => 'Systolic BP', 'TestType' => 'PARAM', 'Description' => 'Tekanan Darah Sistolik', 'SeqScr' => '43', 'SeqRpt' => '43', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'mmHg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['SYSTL'] = $this->db->insertID();
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'DIASTL', 'TestSiteName' => 'Diastolic BP', 'TestType' => 'PARAM', 'Description' => 'Tekanan Darah Diastolik', 'SeqScr' => '44', 'SeqRpt' => '44', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'mmHg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['DIASTL'] = $this->db->insertID();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CALC TYPE - Calculated Tests
|
|
||||||
// ========================================
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'BMI', 'TestSiteName' => 'Body Mass Index', 'TestType' => 'CALC', 'Description' => 'Indeks Massa Tubuh - weight/(height^2)', 'SeqScr' => '45', 'SeqRpt' => '45', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '0', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['BMI'] = $this->db->insertID();
|
|
||||||
$data = ['TestSiteID' => $tIDs['BMI'], 'DisciplineID' => '10', 'DepartmentID' => '', 'FormulaInput' => 'WEIGHT,HEIGHT', 'FormulaCode' => 'WEIGHT / ((HEIGHT/100) * (HEIGHT/100))', 'RefType' => 'RANGE', 'Unit1' => 'kg/m2', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefcal')->insert($data);
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'EGFR', 'TestSiteName' => 'eGFR (CKD-EPI)', 'TestType' => 'CALC', 'Description' => 'Estimated Glomerular Filtration Rate', 'SeqScr' => '20', 'SeqRpt' => '20', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '0', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['EGFR'] = $this->db->insertID();
|
|
||||||
$data = ['TestSiteID' => $tIDs['EGFR'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaInput' => 'CREA,AGE,GENDER', 'FormulaCode' => 'CKD_EPI(CREA,AGE,GENDER)', 'RefType' => 'RANGE', 'Unit1' => 'mL/min/1.73m2', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefcal')->insert($data);
|
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'LDLCALC', 'TestSiteName' => 'LDL Cholesterol (Calculated)', 'TestType' => 'CALC', 'Description' => 'Friedewald formula: TC - HDL - (TG/5)', 'SeqScr' => '21', 'SeqRpt' => '21', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '0', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['LDLCALC'] = $this->db->insertID();
|
|
||||||
$data = ['TestSiteID' => $tIDs['LDLCALC'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaInput' => 'CHOL,HDL,TG', 'FormulaCode' => 'CHOL - HDL - (TG/5)', 'RefType' => 'RANGE', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefcal')->insert($data);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// GROUP TYPE - Panel/Profile Tests
|
|
||||||
// ========================================
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'CBC', 'TestSiteName' => 'Complete Blood Count', 'TestType' => 'GROUP', 'Description' => 'Darah Lengkap', 'SeqScr' => '50', 'SeqRpt' => '50', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['CBC'] = $this->db->insertID();
|
|
||||||
$this->db->table('testdefgrp')->insertBatch([
|
$this->db->table('testdefgrp')->insertBatch([
|
||||||
['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['HB'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['HB'], 'CreateDate' => "$now"],
|
||||||
['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['HCT'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['HCT'], 'CreateDate' => "$now"],
|
||||||
@ -198,9 +121,79 @@ class TestSeeder extends Seeder
|
|||||||
['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['MCHC'], 'CreateDate' => "$now"]
|
['TestSiteID' => $tIDs['CBC'], 'Member' => $tIDs['MCHC'], 'CreateDate' => "$now"]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'LIPID', 'TestSiteName' => 'Lipid Profile', 'TestType' => 'GROUP', 'Description' => 'Profil Lipid', 'SeqScr' => '51', 'SeqRpt' => '51', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
// CALC: (none for Hematology)
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// DEPARTMENT 2 - CHEMISTRY (Discipline 2)
|
||||||
|
// Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// GROUP: LIPID, LFT, RFT
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'LIPID', 'TestSiteName' => 'Lipid Profile', 'TestType' => 'GROUP', 'Description' => 'Profil Lipid', 'SeqScr' => '10', 'SeqRpt' => '10', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['LIPID'] = $this->db->insertID();
|
$tIDs['LIPID'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'LFT', 'TestSiteName' => 'Liver Function Test', 'TestType' => 'GROUP', 'Description' => 'Fungsi Hati', 'SeqScr' => '20', 'SeqRpt' => '20', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['LFT'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'RFT', 'TestSiteName' => 'Renal Function Test', 'TestType' => 'GROUP', 'Description' => 'Fungsi Ginjal', 'SeqScr' => '30', 'SeqRpt' => '30', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['RFT'] = $this->db->insertID();
|
||||||
|
|
||||||
|
// PARAM: (none for Chemistry)
|
||||||
|
|
||||||
|
// TEST: Chemistry Tests
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'GLU', 'TestSiteName' => 'Glucose', 'TestType' => 'TEST', 'Description' => 'Glukosa Sewaktu', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '0.0555', 'Unit2' => 'mmol/L', 'Decimal' => '0', 'Method' => 'Hexokinase', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['GLU'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'CREA', 'TestSiteName' => 'Creatinine', 'TestType' => 'TEST', 'Description' => 'Kreatinin', 'SeqScr' => '110', 'SeqRpt' => '110', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '88.4', 'Unit2' => 'umol/L', 'Decimal' => '2', 'Method' => 'Enzymatic', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['CREA'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'UREA', 'TestSiteName' => 'Blood Urea Nitrogen', 'TestType' => 'TEST', 'Description' => 'BUN', 'SeqScr' => '120', 'SeqRpt' => '120', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'Urease-GLDH', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['UREA'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'SGOT', 'TestSiteName' => 'AST (SGOT)', 'TestType' => 'TEST', 'Description' => 'Aspartate Aminotransferase', 'SeqScr' => '130', 'SeqRpt' => '130', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'U/L', 'Factor' => '0.017', 'Unit2' => 'ukat/L', 'Decimal' => '0', 'Method' => 'IFCC', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['SGOT'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'SGPT', 'TestSiteName' => 'ALT (SGPT)', 'TestType' => 'TEST', 'Description' => 'Alanine Aminotransferase', 'SeqScr' => '140', 'SeqRpt' => '140', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'U/L', 'Factor' => '0.017', 'Unit2' => 'ukat/L', 'Decimal' => '0', 'Method' => 'IFCC', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['SGPT'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'CHOL', 'TestSiteName' => 'Total Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol Total', 'SeqScr' => '150', 'SeqRpt' => '150', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Enzymatic', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['CHOL'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'TG', 'TestSiteName' => 'Triglycerides', 'TestType' => 'TEST', 'Description' => 'Trigliserida', 'SeqScr' => '160', 'SeqRpt' => '160', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'GPO-PAP', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['TG'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'HDL', 'TestSiteName' => 'HDL Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol HDL', 'SeqScr' => '170', 'SeqRpt' => '170', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Direct', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['HDL'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'LDL', 'TestSiteName' => 'LDL Cholesterol', 'TestType' => 'TEST', 'Description' => 'Kolesterol LDL', 'SeqScr' => '180', 'SeqRpt' => '180', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '2', 'DepartmentID' => '2', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '300', 'ReqQtyUnit' => 'uL', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => 'Direct', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['LDL'] = $this->db->insertID();
|
||||||
|
|
||||||
|
// CALC: Chemistry Calculated Tests
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'EGFR', 'TestSiteName' => 'eGFR (CKD-EPI)', 'TestType' => 'CALC', 'Description' => 'Estimated Glomerular Filtration Rate', 'SeqScr' => '190', 'SeqRpt' => '190', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '0', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['EGFR'] = $this->db->insertID();
|
||||||
|
$data = ['TestSiteID' => $tIDs['EGFR'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaInput' => 'CREA,AGE,GENDER', 'FormulaCode' => 'CKD_EPI(CREA,AGE,GENDER)', 'RefType' => 'RANGE', 'Unit1' => 'mL/min/1.73m2', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefcal')->insert($data);
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'LDLCALC', 'TestSiteName' => 'LDL Cholesterol (Calculated)', 'TestType' => 'CALC', 'Description' => 'Friedewald formula: TC - HDL - (TG/5)', 'SeqScr' => '200', 'SeqRpt' => '200', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '0', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['LDLCALC'] = $this->db->insertID();
|
||||||
|
$data = ['TestSiteID' => $tIDs['LDLCALC'], 'DisciplineID' => '2', 'DepartmentID' => '2', 'FormulaInput' => 'CHOL,HDL,TG', 'FormulaCode' => 'CHOL - HDL - (TG/5)', 'RefType' => 'RANGE', 'Unit1' => 'mg/dL', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefcal')->insert($data);
|
||||||
|
|
||||||
|
// Add Chemistry Group members now that tests are defined
|
||||||
$this->db->table('testdefgrp')->insertBatch([
|
$this->db->table('testdefgrp')->insertBatch([
|
||||||
['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['CHOL'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['CHOL'], 'CreateDate' => "$now"],
|
||||||
['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['TG'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['TG'], 'CreateDate' => "$now"],
|
||||||
@ -209,48 +202,87 @@ class TestSeeder extends Seeder
|
|||||||
['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['LDLCALC'], 'CreateDate' => "$now"]
|
['TestSiteID' => $tIDs['LIPID'], 'Member' => $tIDs['LDLCALC'], 'CreateDate' => "$now"]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'LFT', 'TestSiteName' => 'Liver Function Test', 'TestType' => 'GROUP', 'Description' => 'Fungsi Hati', 'SeqScr' => '52', 'SeqRpt' => '52', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['LFT'] = $this->db->insertID();
|
|
||||||
$this->db->table('testdefgrp')->insertBatch([
|
$this->db->table('testdefgrp')->insertBatch([
|
||||||
['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['SGOT'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['SGOT'], 'CreateDate' => "$now"],
|
||||||
['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['SGPT'], 'CreateDate' => "$now"]
|
['TestSiteID' => $tIDs['LFT'], 'Member' => $tIDs['SGPT'], 'CreateDate' => "$now"]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'RFT', 'TestSiteName' => 'Renal Function Test', 'TestType' => 'GROUP', 'Description' => 'Fungsi Ginjal', 'SeqScr' => '53', 'SeqRpt' => '53', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'ResultType' => 'NORES', 'RefType' => 'NOREF', 'CreateDate' => "$now"];
|
|
||||||
$this->db->table('testdefsite')->insert($data);
|
|
||||||
$tIDs['RFT'] = $this->db->insertID();
|
|
||||||
$this->db->table('testdefgrp')->insertBatch([
|
$this->db->table('testdefgrp')->insertBatch([
|
||||||
['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['UREA'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['UREA'], 'CreateDate' => "$now"],
|
||||||
['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['CREA'], 'CreateDate' => "$now"],
|
['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['CREA'], 'CreateDate' => "$now"],
|
||||||
['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['EGFR'], 'CreateDate' => "$now"]
|
['TestSiteID' => $tIDs['RFT'], 'Member' => $tIDs['EGFR'], 'CreateDate' => "$now"]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Urinalysis Tests (with valueset result type)
|
// ========================================
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'UCOLOR', 'TestSiteName' => 'Urine Color', 'TestType' => 'TEST', 'Description' => 'Warna Urine', 'SeqScr' => '31', 'SeqRpt' => '31', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1001', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Visual', 'CreateDate' => "$now"];
|
// DEPARTMENT 4 - URINALYSIS (Discipline 4)
|
||||||
|
// Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// GROUP: (none for Urinalysis in current setup)
|
||||||
|
|
||||||
|
// PARAM: (none for Urinalysis)
|
||||||
|
|
||||||
|
// TEST: Urinalysis Tests
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'UCOLOR', 'TestSiteName' => 'Urine Color', 'TestType' => 'TEST', 'Description' => 'Warna Urine', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1001', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Visual', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['UCOLOR'] = $this->db->insertID();
|
$tIDs['UCOLOR'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'UGLUC', 'TestSiteName' => 'Urine Glucose', 'TestType' => 'TEST', 'Description' => 'Glukosa Urine', 'SeqScr' => '32', 'SeqRpt' => '32', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1002', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'UGLUC', 'TestSiteName' => 'Urine Glucose', 'TestType' => 'TEST', 'Description' => 'Glukosa Urine', 'SeqScr' => '110', 'SeqRpt' => '110', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1002', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['UGLUC'] = $this->db->insertID();
|
$tIDs['UGLUC'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'UPROT', 'TestSiteName' => 'Urine Protein', 'TestType' => 'TEST', 'Description' => 'Protein Urine', 'SeqScr' => '33', 'SeqRpt' => '33', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1003', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'UPROT', 'TestSiteName' => 'Urine Protein', 'TestType' => 'TEST', 'Description' => 'Protein Urine', 'SeqScr' => '120', 'SeqRpt' => '120', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'VSET', 'RefType' => 'VSET', 'VSet' => '1003', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['UPROT'] = $this->db->insertID();
|
$tIDs['UPROT'] = $this->db->insertID();
|
||||||
|
|
||||||
$data = ['SiteID' => '1', 'TestSiteCode' => 'PH', 'TestSiteName' => 'Urine pH', 'TestType' => 'TEST', 'Description' => 'pH Urine', 'SeqScr' => '34', 'SeqRpt' => '34', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'PH', 'TestSiteName' => 'Urine pH', 'TestType' => 'TEST', 'Description' => 'pH Urine', 'SeqScr' => '130', 'SeqRpt' => '130', 'IndentLeft' => '1', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '1', 'DisciplineID' => '4', 'DepartmentID' => '4', 'ResultType' => 'NMRIC', 'RefType' => 'RANGE', 'VSet' => '', 'ReqQty' => '10', 'ReqQtyUnit' => 'mL', 'Unit1' => '', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => 'Dipstick', 'CreateDate' => "$now"];
|
||||||
$this->db->table('testdefsite')->insert($data);
|
$this->db->table('testdefsite')->insert($data);
|
||||||
$tIDs['PH'] = $this->db->insertID();
|
$tIDs['PH'] = $this->db->insertID();
|
||||||
|
|
||||||
|
// CALC: (none for Urinalysis)
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// DEPARTMENT 10 - GENERAL (Discipline 10)
|
||||||
|
// Order: GROUP (<100) → PARAM (<100) → TEST (100+) → CALC (100+)
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// GROUP: (none for General)
|
||||||
|
|
||||||
|
// PARAM: General Parameters (< 100)
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'HEIGHT', 'TestSiteName' => 'Height', 'TestType' => 'PARAM', 'Description' => 'Tinggi Badan', 'SeqScr' => '10', 'SeqRpt' => '10', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'cm', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['HEIGHT'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'WEIGHT', 'TestSiteName' => 'Weight', 'TestType' => 'PARAM', 'Description' => 'Berat Badan', 'SeqScr' => '20', 'SeqRpt' => '20', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'kg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'Method' => '', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['WEIGHT'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'AGE', 'TestSiteName' => 'Age', 'TestType' => 'PARAM', 'Description' => 'Usia', 'SeqScr' => '30', 'SeqRpt' => '30', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'years', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['AGE'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'SYSTL', 'TestSiteName' => 'Systolic BP', 'TestType' => 'PARAM', 'Description' => 'Tekanan Darah Sistolik', 'SeqScr' => '40', 'SeqRpt' => '40', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'mmHg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['SYSTL'] = $this->db->insertID();
|
||||||
|
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'DIASTL', 'TestSiteName' => 'Diastolic BP', 'TestType' => 'PARAM', 'Description' => 'Tekanan Darah Diastolik', 'SeqScr' => '50', 'SeqRpt' => '50', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '0', 'CountStat' => '0', 'DisciplineID' => '10', 'DepartmentID' => '', 'ResultType' => 'NMRIC', 'RefType' => '', 'VSet' => '', 'ReqQty' => '', 'ReqQtyUnit' => '', 'Unit1' => 'mmHg', 'Factor' => '', 'Unit2' => '', 'Decimal' => '0', 'Method' => '', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['DIASTL'] = $this->db->insertID();
|
||||||
|
|
||||||
|
// TEST: (none for General)
|
||||||
|
|
||||||
|
// CALC: BMI (>= 100)
|
||||||
|
$data = ['SiteID' => '1', 'TestSiteCode' => 'BMI', 'TestSiteName' => 'Body Mass Index', 'TestType' => 'CALC', 'Description' => 'Indeks Massa Tubuh - weight/(height^2)', 'SeqScr' => '100', 'SeqRpt' => '100', 'IndentLeft' => '0', 'VisibleScr' => '1', 'VisibleRpt' => '1', 'CountStat' => '0', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefsite')->insert($data);
|
||||||
|
$tIDs['BMI'] = $this->db->insertID();
|
||||||
|
$data = ['TestSiteID' => $tIDs['BMI'], 'DisciplineID' => '10', 'DepartmentID' => '', 'FormulaInput' => 'WEIGHT,HEIGHT', 'FormulaCode' => 'WEIGHT / ((HEIGHT/100) * (HEIGHT/100))', 'RefType' => 'RANGE', 'Unit1' => 'kg/m2', 'Factor' => '', 'Unit2' => '', 'Decimal' => '1', 'CreateDate' => "$now"];
|
||||||
|
$this->db->table('testdefcal')->insert($data);
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
// TEST MAP - Specimen Mapping
|
// TEST MAP - Specimen Mapping
|
||||||
// Maps tests to workstations and containers
|
|
||||||
// New structure: testmap (header) + testmapdetail (details)
|
|
||||||
// ========================================
|
// ========================================
|
||||||
|
|
||||||
// Get container IDs (inserted by SpecimenSeeder in order)
|
// Get container IDs (inserted by SpecimenSeeder in order)
|
||||||
// ConCode order: 1, 11, 12, 13, 14, 15, 16, 20, 101, 150, 200, 290, 295, 900
|
|
||||||
$conSST = 1; // SST (Serum Separator Tube)
|
$conSST = 1; // SST (Serum Separator Tube)
|
||||||
$conEDTA = 9; // EDTA - Hematology
|
$conEDTA = 9; // EDTA - Hematology
|
||||||
$conCitrate = 10; // Citrate - Koagulasi
|
$conCitrate = 10; // Citrate - Koagulasi
|
||||||
@ -299,10 +331,7 @@ class TestSeeder extends Seeder
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================
|
// Test mappings configuration
|
||||||
// TEST MAP CONFIGURATION
|
|
||||||
// Grouped by discipline for maintainability
|
|
||||||
// ============================================
|
|
||||||
$testMappings = [
|
$testMappings = [
|
||||||
// Hematology: Site → HAUTO → Sysmex (EDTA)
|
// Hematology: Site → HAUTO → Sysmex (EDTA)
|
||||||
[
|
[
|
||||||
@ -347,7 +376,7 @@ class TestSeeder extends Seeder
|
|||||||
$entityInst = $this->getEntityType('INST') ?? 'INST';
|
$entityInst = $this->getEntityType('INST') ?? 'INST';
|
||||||
|
|
||||||
foreach ($testMappings as $mapping) {
|
foreach ($testMappings as $mapping) {
|
||||||
// Site → Workstation mapping (one header per workstation)
|
// Site → Workstation mapping
|
||||||
$testMapSiteWsID = $getTestMapID($entitySite, '1', $entityWst, (string)$mapping['siteToWs']['ws']);
|
$testMapSiteWsID = $getTestMapID($entitySite, '1', $entityWst, (string)$mapping['siteToWs']['ws']);
|
||||||
foreach ($mapping['tests'] as $testCode) {
|
foreach ($mapping['tests'] as $testCode) {
|
||||||
$addDetail($testMapSiteWsID, $testCode, $testCode, $mapping['siteToWs']['con'], $testCode, $testCode);
|
$addDetail($testMapSiteWsID, $testCode, $testCode, $mapping['siteToWs']['con'], $testCode, $testCode);
|
||||||
@ -356,7 +385,7 @@ class TestSeeder extends Seeder
|
|||||||
$addDetail($testMapSiteWsID, $panelCode, $panelCode, $mapping['siteToWs']['con'], $panelCode, $panelCode);
|
$addDetail($testMapSiteWsID, $panelCode, $panelCode, $mapping['siteToWs']['con'], $panelCode, $panelCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workstation → Instrument mapping (one header per instrument)
|
// Workstation → Instrument mapping
|
||||||
if ($mapping['wsToInst'] !== null) {
|
if ($mapping['wsToInst'] !== null) {
|
||||||
$testMapWsInstID = $getTestMapID($entityWst, (string)$mapping['wsToInst']['ws'], $entityInst, (string)$mapping['wsToInst']['inst']);
|
$testMapWsInstID = $getTestMapID($entityWst, (string)$mapping['wsToInst']['ws'], $entityInst, (string)$mapping['wsToInst']['inst']);
|
||||||
foreach ($mapping['tests'] as $testCode) {
|
foreach ($mapping['tests'] as $testCode) {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use App\Models\BaseModel;
|
|||||||
class CounterModel extends BaseModel {
|
class CounterModel extends BaseModel {
|
||||||
protected $table = 'counter';
|
protected $table = 'counter';
|
||||||
protected $primaryKey = 'CounterID';
|
protected $primaryKey = 'CounterID';
|
||||||
protected $allowedFields = ['CounterValue', 'CounterStart', 'CounterEnd', 'CounterReset', 'CreateDate', 'EndDate'];
|
protected $allowedFields = ['CounterValue', 'CounterStart', 'CounterEnd', 'CounterReset', 'CounterName', 'CreateDate', 'EndDate'];
|
||||||
|
|
||||||
protected $useTimestamps = true;
|
protected $useTimestamps = true;
|
||||||
protected $createdField = "CreateDate";
|
protected $createdField = "CreateDate";
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class OrderTestModel extends BaseModel {
|
|||||||
$this->db->transStart();
|
$this->db->transStart();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$orderID = $data['OrderID'] ?? $this->generateOrderID($data['SiteCode'] ?? '00');
|
$orderID = !empty($data['OrderID']) ? $data['OrderID'] : $this->generateOrderID($data['SiteCode'] ?? '00');
|
||||||
|
|
||||||
$orderData = [
|
$orderData = [
|
||||||
'OrderID' => $orderID,
|
'OrderID' => $orderID,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use App\Models\BaseModel;
|
|||||||
class DisciplineModel extends BaseModel {
|
class DisciplineModel extends BaseModel {
|
||||||
protected $table = 'discipline';
|
protected $table = 'discipline';
|
||||||
protected $primaryKey = 'DisciplineID';
|
protected $primaryKey = 'DisciplineID';
|
||||||
protected $allowedFields = ['DisciplineCode', 'DisciplineName', 'SiteID', 'Parent', 'CreateDate', 'EndDate'];
|
protected $allowedFields = ['DisciplineCode', 'DisciplineName', 'SiteID', 'Parent', 'SeqScr', 'SeqRpt', 'CreateDate', 'EndDate'];
|
||||||
|
|
||||||
protected $useTimestamps = true;
|
protected $useTimestamps = true;
|
||||||
protected $createdField = 'CreateDate';
|
protected $createdField = 'CreateDate';
|
||||||
@ -15,7 +15,7 @@ class DisciplineModel extends BaseModel {
|
|||||||
|
|
||||||
public function getDisciplines($filter) {
|
public function getDisciplines($filter) {
|
||||||
$builder = $this->select('discipline.DisciplineID, discipline.DisciplineCode, discipline.DisciplineName, discipline.SiteID,
|
$builder = $this->select('discipline.DisciplineID, discipline.DisciplineCode, discipline.DisciplineName, discipline.SiteID,
|
||||||
discipline.Parent, d.DisciplineCode as ParentCode,d.DisciplineName as ParentName')
|
discipline.Parent, discipline.SeqScr, discipline.SeqRpt, d.DisciplineCode as ParentCode,d.DisciplineName as ParentName')
|
||||||
->join('discipline as d', 'd.DisciplineID = discipline.Parent', 'left');
|
->join('discipline as d', 'd.DisciplineID = discipline.Parent', 'left');
|
||||||
|
|
||||||
if (!empty($filter['DisciplineCode'])) {
|
if (!empty($filter['DisciplineCode'])) {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use App\Libraries\ValueSet;
|
|||||||
class SiteModel extends BaseModel {
|
class SiteModel extends BaseModel {
|
||||||
protected $table = 'site';
|
protected $table = 'site';
|
||||||
protected $primaryKey = 'SiteID';
|
protected $primaryKey = 'SiteID';
|
||||||
protected $allowedFields = ['SiteCode', 'SiteName', 'AccountID', 'SiteTypeID', 'Parent', 'SiteClassID', 'ME',
|
protected $allowedFields = ['SiteCode', 'ExtSiteID', 'SiteName', 'AccountID', 'SiteType', 'Parent', 'SiteClass', 'ME',
|
||||||
'CreateDate', 'EndDate'];
|
'CreateDate', 'EndDate'];
|
||||||
|
|
||||||
protected $useTimestamps = true;
|
protected $useTimestamps = true;
|
||||||
|
|||||||
@ -46,4 +46,82 @@ class RefNumModel extends BaseModel
|
|||||||
->orderBy('Display', 'ASC')
|
->orderBy('Display', 'ASC')
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted numeric reference ranges with labels
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFormattedByTestSiteID($testSiteID)
|
||||||
|
{
|
||||||
|
$rows = $this->getActiveByTestSiteID($testSiteID);
|
||||||
|
|
||||||
|
return array_map(function ($r) {
|
||||||
|
return [
|
||||||
|
'RefNumID' => $r['RefNumID'],
|
||||||
|
'NumRefType' => $r['NumRefType'],
|
||||||
|
'NumRefTypeLabel' => $r['NumRefType'] ? \App\Libraries\ValueSet::getLabel('numeric_ref_type', $r['NumRefType']) : '',
|
||||||
|
'RangeType' => $r['RangeType'],
|
||||||
|
'RangeTypeLabel' => $r['RangeType'] ? \App\Libraries\ValueSet::getLabel('range_type', $r['RangeType']) : '',
|
||||||
|
'Sex' => $r['Sex'],
|
||||||
|
'SexLabel' => $r['Sex'] ? \App\Libraries\ValueSet::getLabel('gender', $r['Sex']) : '',
|
||||||
|
'LowSign' => $r['LowSign'],
|
||||||
|
'LowSignLabel' => $r['LowSign'] ? \App\Libraries\ValueSet::getLabel('math_sign', $r['LowSign']) : '',
|
||||||
|
'HighSign' => $r['HighSign'],
|
||||||
|
'HighSignLabel' => $r['HighSign'] ? \App\Libraries\ValueSet::getLabel('math_sign', $r['HighSign']) : '',
|
||||||
|
'High' => $r['High'] !== null ? (float) $r['High'] : null,
|
||||||
|
'Low' => $r['Low'] !== null ? (float) $r['Low'] : null,
|
||||||
|
'AgeStart' => (int) $r['AgeStart'],
|
||||||
|
'AgeEnd' => (int) $r['AgeEnd'],
|
||||||
|
'Flag' => $r['Flag'],
|
||||||
|
'Interpretation' => $r['Interpretation'],
|
||||||
|
];
|
||||||
|
}, $rows ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable all numeric reference ranges for a test
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function disableByTestSiteID($testSiteID)
|
||||||
|
{
|
||||||
|
$this->where('TestSiteID', $testSiteID)
|
||||||
|
->set('EndDate', date('Y-m-d H:i:s'))
|
||||||
|
->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch insert numeric reference ranges
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @param int $siteID
|
||||||
|
* @param array $ranges
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function batchInsert($testSiteID, $siteID, $ranges)
|
||||||
|
{
|
||||||
|
foreach ($ranges as $index => $range) {
|
||||||
|
$this->insert([
|
||||||
|
'TestSiteID' => $testSiteID,
|
||||||
|
'SiteID' => $siteID,
|
||||||
|
'NumRefType' => $range['NumRefType'],
|
||||||
|
'RangeType' => $range['RangeType'],
|
||||||
|
'Sex' => $range['Sex'],
|
||||||
|
'AgeStart' => (int) ($range['AgeStart'] ?? 0),
|
||||||
|
'AgeEnd' => (int) ($range['AgeEnd'] ?? 150),
|
||||||
|
'LowSign' => !empty($range['LowSign']) ? $range['LowSign'] : null,
|
||||||
|
'Low' => !empty($range['Low']) ? (float) $range['Low'] : null,
|
||||||
|
'HighSign' => !empty($range['HighSign']) ? $range['HighSign'] : null,
|
||||||
|
'High' => !empty($range['High']) ? (float) $range['High'] : null,
|
||||||
|
'Flag' => $range['Flag'] ?? null,
|
||||||
|
'Interpretation'=> $range['Interpretation'] ?? null,
|
||||||
|
'Display' => $index,
|
||||||
|
'CreateDate' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,4 +40,68 @@ class RefTxtModel extends BaseModel
|
|||||||
->orderBy('RefTxtID', 'ASC')
|
->orderBy('RefTxtID', 'ASC')
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted text reference ranges with labels
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFormattedByTestSiteID($testSiteID)
|
||||||
|
{
|
||||||
|
$rows = $this->getActiveByTestSiteID($testSiteID);
|
||||||
|
|
||||||
|
return array_map(function ($r) {
|
||||||
|
return [
|
||||||
|
'RefTxtID' => $r['RefTxtID'],
|
||||||
|
'TxtRefType' => $r['TxtRefType'],
|
||||||
|
'TxtRefTypeLabel'=> $r['TxtRefType'] ? \App\Libraries\ValueSet::getLabel('text_ref_type', $r['TxtRefType']) : '',
|
||||||
|
'Sex' => $r['Sex'],
|
||||||
|
'SexLabel' => $r['Sex'] ? \App\Libraries\ValueSet::getLabel('gender', $r['Sex']) : '',
|
||||||
|
'AgeStart' => (int) $r['AgeStart'],
|
||||||
|
'AgeEnd' => (int) $r['AgeEnd'],
|
||||||
|
'RefTxt' => $r['RefTxt'],
|
||||||
|
'Flag' => $r['Flag'],
|
||||||
|
];
|
||||||
|
}, $rows ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable all text reference ranges for a test
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function disableByTestSiteID($testSiteID)
|
||||||
|
{
|
||||||
|
$this->where('TestSiteID', $testSiteID)
|
||||||
|
->set('EndDate', date('Y-m-d H:i:s'))
|
||||||
|
->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch insert text reference ranges
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @param int $siteID
|
||||||
|
* @param array $ranges
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function batchInsert($testSiteID, $siteID, $ranges)
|
||||||
|
{
|
||||||
|
foreach ($ranges as $range) {
|
||||||
|
$this->insert([
|
||||||
|
'TestSiteID' => $testSiteID,
|
||||||
|
'SiteID' => $siteID,
|
||||||
|
'TxtRefType' => $range['TxtRefType'],
|
||||||
|
'Sex' => $range['Sex'],
|
||||||
|
'AgeStart' => (int) ($range['AgeStart'] ?? 0),
|
||||||
|
'AgeEnd' => (int) ($range['AgeEnd'] ?? 150),
|
||||||
|
'RefTxt' => $range['RefTxt'] ?? '',
|
||||||
|
'Flag' => $range['Flag'] ?? null,
|
||||||
|
'CreateDate' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,8 @@ class TestDefGrpModel extends BaseModel {
|
|||||||
protected $allowedFields = [
|
protected $allowedFields = [
|
||||||
'TestSiteID',
|
'TestSiteID',
|
||||||
'Member',
|
'Member',
|
||||||
|
'SeqScr',
|
||||||
|
'SeqRpt',
|
||||||
'CreateDate',
|
'CreateDate',
|
||||||
'EndDate'
|
'EndDate'
|
||||||
];
|
];
|
||||||
@ -25,10 +27,12 @@ class TestDefGrpModel extends BaseModel {
|
|||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
$rows = $db->table('testdefgrp')
|
$rows = $db->table('testdefgrp')
|
||||||
->select('testdefgrp.*, t.TestSiteID as MemberTestSiteID, t.TestSiteCode, t.TestSiteName, t.TestType')
|
->select('t.TestSiteID as TestSiteID, t.TestSiteCode, t.TestSiteName, t.TestType, t.SeqScr, t. SeqRpt')
|
||||||
->join('testdefsite t', 't.TestSiteID=testdefgrp.Member', 'left')
|
->join('testdefsite t', 't.TestSiteID=testdefgrp.Member', 'left')
|
||||||
->where('testdefgrp.TestSiteID', $testSiteID)
|
->where('testdefgrp.TestSiteID', $testSiteID)
|
||||||
->where('testdefgrp.EndDate IS NULL')
|
->where('testdefgrp.EndDate IS NULL')
|
||||||
|
->orderBy('t.SeqScr', 'ASC')
|
||||||
|
->orderBy('t.SeqRpt', 'ASC')
|
||||||
->orderBy('testdefgrp.TestGrpID', 'ASC')
|
->orderBy('testdefgrp.TestGrpID', 'ASC')
|
||||||
->get()->getResultArray();
|
->get()->getResultArray();
|
||||||
|
|
||||||
|
|||||||
@ -158,17 +158,8 @@ class TestDefSiteModel extends BaseModel {
|
|||||||
$row['testmap'] = $testMapModel->getMappingsByTestCode($row['TestSiteCode']);
|
$row['testmap'] = $testMapModel->getMappingsByTestCode($row['TestSiteCode']);
|
||||||
|
|
||||||
} elseif (TestValidationService::isGroup($typeCode)) {
|
} elseif (TestValidationService::isGroup($typeCode)) {
|
||||||
$row['testdefgrp'] = $db->table('testdefgrp')
|
$testDefGrpModel = new \App\Models\Test\TestDefGrpModel();
|
||||||
->select('testdefgrp.*, t.TestSiteID as MemberTestSiteID, t.TestSiteCode, t.TestSiteName, t.TestType')
|
$row['testdefgrp'] = $testDefGrpModel->getGroupMembers($TestSiteID);
|
||||||
->join('testdefsite t', 't.TestSiteID=testdefgrp.Member', 'left')
|
|
||||||
->where('testdefgrp.TestSiteID', $TestSiteID)
|
|
||||||
->where('testdefgrp.EndDate IS NULL')
|
|
||||||
->orderBy('testdefgrp.TestGrpID', 'ASC')
|
|
||||||
->get()->getResultArray();
|
|
||||||
|
|
||||||
$row['testdefgrp'] = ValueSet::transformLabels($row['testdefgrp'], [
|
|
||||||
'TestType' => 'test_type',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$testMapModel = new \App\Models\Test\TestMapModel();
|
$testMapModel = new \App\Models\Test\TestMapModel();
|
||||||
$row['testmap'] = $testMapModel->getMappingsByTestCode($row['TestSiteCode']);
|
$row['testmap'] = $testMapModel->getMappingsByTestCode($row['TestSiteCode']);
|
||||||
@ -230,4 +221,45 @@ class TestDefSiteModel extends BaseModel {
|
|||||||
{
|
{
|
||||||
return TestValidationService::getReferenceTable($resultType, $refType);
|
return TestValidationService::getReferenceTable($resultType, $refType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get test by ID with ValueSet transformation
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function getTestById($id)
|
||||||
|
{
|
||||||
|
$row = $this->select('testdefsite.*')
|
||||||
|
->where('testdefsite.TestSiteID', $id)
|
||||||
|
->find($id);
|
||||||
|
|
||||||
|
if (!$row) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = ValueSet::transformLabels([$row], [
|
||||||
|
'TestType' => 'test_type',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get technical test with discipline and department relations
|
||||||
|
*
|
||||||
|
* @param int $testSiteID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTestTechWithRelations($testSiteID)
|
||||||
|
{
|
||||||
|
return $this->db->table('testdefsite')
|
||||||
|
->select('testdefsite.*, d.DisciplineName, dept.DepartmentName')
|
||||||
|
->join('discipline d', 'd.DisciplineID=testdefsite.DisciplineID', 'left')
|
||||||
|
->join('department dept', 'dept.DepartmentID=testdefsite.DepartmentID', 'left')
|
||||||
|
->where('testdefsite.TestSiteID', $testSiteID)
|
||||||
|
->where('testdefsite.EndDate IS NULL')
|
||||||
|
->get()
|
||||||
|
->getResultArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,4 +50,19 @@ class TestMapDetailModel extends BaseModel {
|
|||||||
->where('EndDate IS NULL')
|
->where('EndDate IS NULL')
|
||||||
->findAll();
|
->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable all details for a test map
|
||||||
|
*
|
||||||
|
* @param int $testMapID
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function disableByTestMapID($testMapID)
|
||||||
|
{
|
||||||
|
$this->where('TestMapID', $testMapID)
|
||||||
|
->where('EndDate', null)
|
||||||
|
->set('EndDate', date('Y-m-d H:i:s'))
|
||||||
|
->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5519,6 +5519,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
SiteCode:
|
SiteCode:
|
||||||
type: string
|
type: string
|
||||||
|
maxLength: 2
|
||||||
|
pattern: ^[A-Z0-9]{2}$
|
||||||
AccountID:
|
AccountID:
|
||||||
type: integer
|
type: integer
|
||||||
Discipline:
|
Discipline:
|
||||||
|
|||||||
@ -19,6 +19,8 @@ Site:
|
|||||||
type: string
|
type: string
|
||||||
SiteCode:
|
SiteCode:
|
||||||
type: string
|
type: string
|
||||||
|
maxLength: 2
|
||||||
|
pattern: '^[A-Z0-9]{2}$'
|
||||||
AccountID:
|
AccountID:
|
||||||
type: integer
|
type: integer
|
||||||
|
|
||||||
@ -31,6 +33,12 @@ Discipline:
|
|||||||
type: string
|
type: string
|
||||||
DisciplineCode:
|
DisciplineCode:
|
||||||
type: string
|
type: string
|
||||||
|
SeqScr:
|
||||||
|
type: integer
|
||||||
|
description: Display order on screen
|
||||||
|
SeqRpt:
|
||||||
|
type: integer
|
||||||
|
description: Display order in reports
|
||||||
|
|
||||||
Department:
|
Department:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@ -150,6 +150,12 @@
|
|||||||
type: string
|
type: string
|
||||||
DisciplineCode:
|
DisciplineCode:
|
||||||
type: string
|
type: string
|
||||||
|
SeqScr:
|
||||||
|
type: integer
|
||||||
|
description: Display order on screen
|
||||||
|
SeqRpt:
|
||||||
|
type: integer
|
||||||
|
description: Display order in reports
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Discipline updated
|
description: Discipline updated
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user