docs: extract ERD documentation and add database schema files
- Remove deprecated valueset migration docs and old project planning files - Add ERD_EXTRACT.md with complete database table definitions - Add clqms_database.dbml for database modeling - Add clqms_database.dbdiagram for visual database design - Add updated prj_3c.md project documentation
This commit is contained in:
parent
42a5260f9a
commit
351d3b6279
1129
docs/ERD_EXTRACT.md
Normal file
1129
docs/ERD_EXTRACT.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,645 +0,0 @@
|
|||||||
# Migration Plan: Valueset VID → VValue
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Transition from using database `valueset` table (VID as primary key) to the new `App\Libraries\ValueSet` library (VValue as key). This eliminates database joins for lookup values and uses JSON-based static lookup files.
|
|
||||||
|
|
||||||
## Current State
|
|
||||||
|
|
||||||
- Database `valueset` table with columns: `VID` (PK, INT), `VValue` (VARCHAR), `VDesc` (VARCHAR)
|
|
||||||
- 30+ places using `->join('valueset', 'valueset.VID = ...')`
|
|
||||||
- Selects use `valueset.VValue` and `valueset.VDesc` for display text
|
|
||||||
|
|
||||||
## Target State
|
|
||||||
|
|
||||||
- Use `App\Libraries\ValueSet` library with `getLabel(lookupName, key)` method
|
|
||||||
- Lookup names use table-prefixed PascalCase (e.g., `patient_Sex`, `test_TestType`, `container_ContainerCapColor`)
|
|
||||||
- All fields store `VValue` codes directly (e.g., '1', '2', 'M', 'F', 'TEST')
|
|
||||||
- Remove all `valueset` table joins from queries
|
|
||||||
- Keep raw field values for codes; use `ValueSet::getLabel()` for display text
|
|
||||||
- JSON files in `app/Libraries/Data/valuesets/` are already populated
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 1: JSON Files Rename
|
|
||||||
|
|
||||||
Rename all JSON files in `app/Libraries/Data/valuesets/` to use table-prefixed PascalCase format:
|
|
||||||
|
|
||||||
| Old Name | New Name | Source Table | Field |
|
|
||||||
|----------|----------|--------------|-------|
|
|
||||||
| `gender.json` | `patient_Sex.json` | patient | Gender |
|
|
||||||
| `country.json` | `patient_Country.json` | patient | Country |
|
|
||||||
| `race.json` | `patient_Race.json` | patient | Race |
|
|
||||||
| `religion.json` | `patient_Religion.json` | patient | Religion |
|
|
||||||
| `ethnic.json` | `patient_Ethnic.json` | patient | Ethnic |
|
|
||||||
| `marital_status.json` | `patient_MaritalStatus.json` | patient | MaritalStatus |
|
|
||||||
| `death_indicator.json` | `patient_DeathIndicator.json` | patient | DeathIndicator |
|
|
||||||
| `test_type.json` | `test_TestType.json` | testdefsite | TestType |
|
|
||||||
| `container_cap_color.json` | `container_ContainerCapColor.json` | containerdef | Color |
|
|
||||||
| `container_class.json` | `container_ContainerClass.json` | containerdef | ConClass |
|
|
||||||
| `additive.json` | `container_Additive.json` | containerdef | Additive |
|
|
||||||
| `location_type.json` | `location_LocationType.json` | location | LocType |
|
|
||||||
| `ws_type.json` | `organization_WorkstationType.json` | workstation | Type |
|
|
||||||
| `enable_disable.json` | `organization_EnableDisable.json` | workstation | Enable |
|
|
||||||
| `site_type.json` | `organization_SiteType.json` | site | SiteTypeID |
|
|
||||||
| `site_class.json` | `organization_SiteClass.json` | site | SiteClassID |
|
|
||||||
| `numeric_ref_type.json` | `ref_NumericRefType.json` | refnum | NumRefType |
|
|
||||||
| `range_type.json` | `ref_RangeType.json` | refnum | RangeType |
|
|
||||||
| `text_ref_type.json` | `ref_TextRefType.json` | reftxt | TxtRefType |
|
|
||||||
| `reference_type.json` | `test_ReferenceType.json` | testdeftech | RefType |
|
|
||||||
| `math_sign.json` | `ref_MathSign.json` | refnum | LowSign, HighSign |
|
|
||||||
| `country.json` | `account_Country.json` | account | Country |
|
|
||||||
| ... | ... | ... | ... |
|
|
||||||
|
|
||||||
All lookup names use `{table}_{Field}` format for clarity and namespace isolation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 2: Database Schema Migration
|
|
||||||
|
|
||||||
### Files to DELETE
|
|
||||||
|
|
||||||
| File | Action |
|
|
||||||
|------|--------|
|
|
||||||
| `app\Database\Seeds\ValueSetSeeder.php` | DELETE |
|
|
||||||
| `app\Database\Seeds\ValueSetCountrySeeder.php` | DELETE |
|
|
||||||
| `app\Database\Seeds\MinimalMasterDataSeeder.php` | DELETE |
|
|
||||||
| `app\Database\Seeds\PatientSeeder.php` | DELETE |
|
|
||||||
| `app\Database\Migrations\2025-09-15-130122_ValueSet.php` | DELETE |
|
|
||||||
|
|
||||||
### Migration: Modify Columns INT → VARCHAR(10)
|
|
||||||
|
|
||||||
**File:** `app\Database\Migrations\2026-01-12-000001_ValuesetVidToVvalue.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Database\Migrations;
|
|
||||||
|
|
||||||
use CodeIgniter\Database\Migration;
|
|
||||||
|
|
||||||
class ValuesetVidToVvalue extends Migration
|
|
||||||
{
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
// patient table
|
|
||||||
$this->forge->modifyColumn('patient', [
|
|
||||||
'Gender' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'Country' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'Race' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'Religion' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'Ethnic' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'MaritalStatus' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'DeathIndicator' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// testdefsite table
|
|
||||||
$this->forge->modifyColumn('testdefsite', [
|
|
||||||
'TestType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => false],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// containerdef table
|
|
||||||
$this->forge->modifyColumn('containerdef', [
|
|
||||||
'Additive' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'ConClass' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'Color' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// location table
|
|
||||||
$this->forge->modifyColumn('location', [
|
|
||||||
'LocType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// workstation table
|
|
||||||
$this->forge->modifyColumn('workstation', [
|
|
||||||
'Type' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'Enable' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// site table
|
|
||||||
$this->forge->modifyColumn('site', [
|
|
||||||
'SiteTypeID' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'SiteClassID' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// account table
|
|
||||||
$this->forge->modifyColumn('account', [
|
|
||||||
'Country' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// refnum table
|
|
||||||
$this->forge->modifyColumn('refnum', [
|
|
||||||
'Sex' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'NumRefType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'RangeType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'LowSign' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'HighSign' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// reftxt table
|
|
||||||
$this->forge->modifyColumn('reftxt', [
|
|
||||||
'Sex' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
'TxtRefType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// orderstatus table
|
|
||||||
$this->forge->modifyColumn('orderstatus', [
|
|
||||||
'OrderStatus' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => false],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
// Revert to INT
|
|
||||||
$this->forge->modifyColumn('patient', [
|
|
||||||
'Gender' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'Country' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'Race' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'Religion' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'Ethnic' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'MaritalStatus' => ['type' => 'TINYINT', 'null' => true],
|
|
||||||
'DeathIndicator' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('testdefsite', [
|
|
||||||
'TestType' => ['type' => 'INT', 'null' => false],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('containerdef', [
|
|
||||||
'Additive' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'ConClass' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'Color' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('location', [
|
|
||||||
'LocType' => ['type' => 'INT', 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('workstation', [
|
|
||||||
'Type' => ['type' => 'TINYINT', 'null' => true],
|
|
||||||
'Enable' => ['type' => 'INT', 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('site', [
|
|
||||||
'SiteTypeID' => ['type' => 'INT', 'null' => true],
|
|
||||||
'SiteClassID' => ['type' => 'INT', 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('account', [
|
|
||||||
'Country' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('refnum', [
|
|
||||||
'Sex' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'NumRefType' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'RangeType' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'LowSign' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'HighSign' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('reftxt', [
|
|
||||||
'Sex' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
'TxtRefType' => ['type' => 'INT', 'constraint' => 11, 'null' => true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->forge->modifyColumn('orderstatus', [
|
|
||||||
'OrderStatus' => ['type' => 'INT', 'null' => false],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** No data migration needed - dummy data will be lost. This is acceptable for development/testing environments.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 3: Library & Model Updates
|
|
||||||
|
|
||||||
### ValueSet Library - Update to read from JSON files
|
|
||||||
|
|
||||||
**File:** `app/Libraries/ValueSet.php`
|
|
||||||
|
|
||||||
Ensure the library reads from JSON files in `app/Libraries/Data/valuesets/`:
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Libraries;
|
|
||||||
|
|
||||||
class ValueSet
|
|
||||||
{
|
|
||||||
private static $cache = [];
|
|
||||||
|
|
||||||
private static function loadFile(string $name): array
|
|
||||||
{
|
|
||||||
if (!isset(self::$cache[$name])) {
|
|
||||||
$path = APPPATH . 'Libraries/Data/valuesets/' . $name . '.json';
|
|
||||||
if (file_exists($path)) {
|
|
||||||
$content = file_get_contents($path);
|
|
||||||
self::$cache[$name] = json_decode($content, true)['values'] ?? [];
|
|
||||||
} else {
|
|
||||||
self::$cache[$name] = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return self::$cache[$name];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getLabel(string $lookupName, string $key): ?string
|
|
||||||
{
|
|
||||||
$values = self::loadFile($lookupName);
|
|
||||||
foreach ($values as $item) {
|
|
||||||
if (($item['key'] ?? $item['value'] ?? null) === $key) {
|
|
||||||
return $item['value'] ?? $item['label'] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getOptions(string $lookupName): array
|
|
||||||
{
|
|
||||||
$values = self::loadFile($lookupName);
|
|
||||||
return array_map(function ($item) {
|
|
||||||
return [
|
|
||||||
'key' => $item['key'] ?? '',
|
|
||||||
'value' => $item['value'] ?? $item['label'] ?? '',
|
|
||||||
];
|
|
||||||
}, $values);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function transformLabels(array $data, array $fieldMappings): array
|
|
||||||
{
|
|
||||||
foreach ($data as &$row) {
|
|
||||||
foreach ($fieldMappings as $field => $lookupName) {
|
|
||||||
if (isset($row[$field]) && $row[$field] !== null) {
|
|
||||||
$row[$field . 'Text'] = self::getLabel($lookupName, $row[$field]) ?? '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### ValueSetModel - Deprecate or Repurpose
|
|
||||||
|
|
||||||
**File:** `app/Models/ValueSet/ValueSetModel.php`
|
|
||||||
|
|
||||||
Options:
|
|
||||||
1. **Deprecate entirely** - No longer needed after migration
|
|
||||||
2. **Repurpose for JSON file management** - Read/write to JSON files
|
|
||||||
3. **Keep as-is for backward compatibility** - If database valuesets are still needed
|
|
||||||
|
|
||||||
Recommended: Deprecate and remove references after migration.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 4: Model Changes
|
|
||||||
|
|
||||||
### Pattern for Model Updates
|
|
||||||
|
|
||||||
**Before:**
|
|
||||||
```php
|
|
||||||
$this->select("..., gender.VValue as Gender, gender.VDesc as GenderText")
|
|
||||||
->join('valueset gender', 'gender.VID = patient.Gender', 'left')
|
|
||||||
```
|
|
||||||
|
|
||||||
**After:**
|
|
||||||
```php
|
|
||||||
use App\Libraries\ValueSet;
|
|
||||||
|
|
||||||
$this->select("..., patient.Gender");
|
|
||||||
// After fetching:
|
|
||||||
$rows = ValueSet::transformLabels($rows, [
|
|
||||||
'Gender' => 'patient_Sex',
|
|
||||||
'Country' => 'patient_Country',
|
|
||||||
'Race' => 'patient_Race',
|
|
||||||
'Religion' => 'patient_Religion',
|
|
||||||
'Ethnic' => 'patient_Ethnic',
|
|
||||||
'DeathIndicator' => 'patient_DeathIndicator',
|
|
||||||
'MaritalStatus' => 'patient_MaritalStatus',
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Models to Modify (8 files)
|
|
||||||
|
|
||||||
#### 1. `app/Models/Patient/PatientModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Line 27: `$this->join('valueset vs', 'vs.vid = Gender', 'left');`
|
|
||||||
- Lines 52-64: All `*.VID as *VID` aliases
|
|
||||||
- Lines 75-81: All `valueset.*` joins
|
|
||||||
|
|
||||||
**Add transformation in `getPatient()`:**
|
|
||||||
```php
|
|
||||||
$patient = ValueSet::transformLabels([$patient], [
|
|
||||||
'Gender' => 'patient_gender',
|
|
||||||
'Country' => 'patient_country',
|
|
||||||
'Race' => 'patient_race',
|
|
||||||
'Religion' => 'patient_religion',
|
|
||||||
'Ethnic' => 'patient_ethnic',
|
|
||||||
'DeathIndicator' => 'patient_death_indicator',
|
|
||||||
'MaritalStatus' => 'patient_marital_status',
|
|
||||||
])[0];
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. `app/Models/Location/LocationModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Lines 18, 30: `->join("valueset v", "v.VID=location.loctype", ...)`
|
|
||||||
|
|
||||||
**Add transformation:**
|
|
||||||
```php
|
|
||||||
$rows = ValueSet::transformLabels($rows, [
|
|
||||||
'LocType' => 'location_LocationType',
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. `app/Models/Test/TestDefSiteModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Lines 42, 75, 103: `->join("valueset", "valueset.VID=...")`
|
|
||||||
|
|
||||||
**Add transformation:**
|
|
||||||
```php
|
|
||||||
$rows = ValueSet::transformLabels($rows, [
|
|
||||||
'TestType' => 'test_TestType',
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. `app/Models/Test/TestDefGrpModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Line 32: `->join('valueset vs', 'vs.VID=t.TestType', 'left')`
|
|
||||||
|
|
||||||
#### 5. `app/Models/Specimen/ContainerDefModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Lines 20-22, 37-39: All 6 `valueset.*` joins
|
|
||||||
|
|
||||||
**Add transformation:**
|
|
||||||
```php
|
|
||||||
$rows = ValueSet::transformLabels($rows, [
|
|
||||||
'Color' => 'container_ContainerCapColor',
|
|
||||||
'ConClass' => 'container_ContainerClass',
|
|
||||||
'Additive' => 'container_Additive',
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 6. `app/Models/Organization/SiteModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Lines 38-39: `->join('valueset sitetype'...)` and `->join('valueset siteclass'...)`
|
|
||||||
|
|
||||||
**Add transformation:**
|
|
||||||
```php
|
|
||||||
$row = ValueSet::transformLabels([$row], [
|
|
||||||
'SiteTypeID' => 'organization_SiteType',
|
|
||||||
'SiteClassID' => 'organization_SiteClass',
|
|
||||||
])[0];
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 7. `app/Models/Organization/AccountModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Line 41: `->join('valueset country'...)`
|
|
||||||
|
|
||||||
**Remove from select:**
|
|
||||||
- Line 36: `country.VID as country`
|
|
||||||
|
|
||||||
**Add transformation in controller if needed:**
|
|
||||||
```php
|
|
||||||
$rows = ValueSet::transformLabels($rows, [
|
|
||||||
'Country' => 'account_Country',
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 8. `app/Models/Organization/WorkstationModel.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Lines 36-37: `->join('valueset wstype'...)` and `->join('valueset enable'...)`
|
|
||||||
|
|
||||||
**Add transformation:**
|
|
||||||
```php
|
|
||||||
$row = ValueSet::transformLabels([$row], [
|
|
||||||
'Type' => 'organization_WorkstationType',
|
|
||||||
'Enable' => 'organization_EnableDisable',
|
|
||||||
])[0];
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 5: Controller Changes
|
|
||||||
|
|
||||||
### `app/Controllers/TestsController.php`
|
|
||||||
|
|
||||||
**Remove:**
|
|
||||||
- Line 69: `->join("valueset", "valueset.VID=testdefsite.TestType", "left")`
|
|
||||||
- Line 111: `->join("valueset", "valueset.VID=testdefsite.TestType", "left")`
|
|
||||||
- Line 140: `->join('valueset vs', 'vs.VID=t.TestType', 'left')`
|
|
||||||
|
|
||||||
**Replace `getVValue()` method:**
|
|
||||||
```php
|
|
||||||
private function getVValue($vsetID, $vid) {
|
|
||||||
// DEPRECATED - Use ValueSet::getLabel() instead
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Update references from `getVValue()` to `ValueSet::getLabel()`:**
|
|
||||||
```php
|
|
||||||
// Before:
|
|
||||||
'NumRefTypeVValue' => $this->getVValue(46, $r['NumRefType']),
|
|
||||||
|
|
||||||
// After:
|
|
||||||
'NumRefTypeVValue' => \App\Libraries\ValueSet::getLabel('ref_NumericRefType', $r['NumRefType']),
|
|
||||||
```
|
|
||||||
|
|
||||||
**VSetID to Lookup Name Mapping:**
|
|
||||||
| VSetID | Constant | Lookup Name |
|
|
||||||
|--------|----------|-------------|
|
|
||||||
| 44 | `VALUESET_REF_TYPE` | `test_ReferenceType` |
|
|
||||||
| 45 | `VALUESET_RANGE_TYPE` | `ref_RangeType` |
|
|
||||||
| 46 | `VALUESET_NUM_REF_TYPE` | `ref_NumericRefType` |
|
|
||||||
| 47 | `VALUESET_TXT_REF_TYPE` | `ref_TextRefType` |
|
|
||||||
| 3 | `VALUESET_SEX` | `patient_Sex` |
|
|
||||||
| 41 | `VALUESET_MATH_SIGN` | `ref_MathSign` |
|
|
||||||
|
|
||||||
**Update `getValuesetOptions()` to use JSON:**
|
|
||||||
```php
|
|
||||||
private function getValuesetOptions($lookupName)
|
|
||||||
{
|
|
||||||
return \App\Libraries\ValueSet::getOptions($lookupName);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 6: API Endpoints - Replace with JSON-based endpoints
|
|
||||||
|
|
||||||
### New API Controller: `app/Controllers/ValueSetApiController.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Controllers;
|
|
||||||
|
|
||||||
use App\Libraries\ValueSet;
|
|
||||||
|
|
||||||
class ValueSetApiController extends \CodeIgniter\Controller
|
|
||||||
{
|
|
||||||
use \CodeIgniter\API\ResponseTrait;
|
|
||||||
|
|
||||||
public function index(string $lookupName)
|
|
||||||
{
|
|
||||||
$data = ValueSet::getOptions($lookupName);
|
|
||||||
return $this->respond([
|
|
||||||
'status' => 'success',
|
|
||||||
'data' => $data
|
|
||||||
], 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function all()
|
|
||||||
{
|
|
||||||
$dir = APPPATH . 'Libraries/Data/valuesets/';
|
|
||||||
$files = glob($dir . '*.json');
|
|
||||||
$result = [];
|
|
||||||
foreach ($files as $file) {
|
|
||||||
$name = basename($file, '.json');
|
|
||||||
$result[] = [
|
|
||||||
'name' => $name,
|
|
||||||
'options' => ValueSet::getOptions($name)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return $this->respond([
|
|
||||||
'status' => 'success',
|
|
||||||
'data' => $result
|
|
||||||
], 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Update Routes: `app/Config/Routes.php`
|
|
||||||
|
|
||||||
```php
|
|
||||||
$routes->group('api', function ($routes) {
|
|
||||||
$routes->get('valueset/(:segment)', 'ValueSetApiController::index/$1');
|
|
||||||
$routes->get('valueset', 'ValueSetApiController::all');
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 7: View Updates
|
|
||||||
|
|
||||||
### 1. `app/Views/v2/master/valuesets/valuesets_index.php`
|
|
||||||
|
|
||||||
Repurpose to manage JSON-based valuesets instead of database table.
|
|
||||||
|
|
||||||
| Before | After |
|
|
||||||
|--------|-------|
|
|
||||||
| `fetch(...api/valueset...)` | `fetch(...api/valueset/lookupName...)` |
|
|
||||||
| Database CRUD operations | File-based CRUD operations |
|
|
||||||
|
|
||||||
### 2. `app/Views/v2/master/valuesets/valueset_nested_crud.php`
|
|
||||||
|
|
||||||
Repurpose for JSON file management.
|
|
||||||
|
|
||||||
### 3. `app/Views/v2/master/valuesets/valueset_dialog.php`
|
|
||||||
|
|
||||||
Update for JSON file format.
|
|
||||||
|
|
||||||
### 4. `app/Views/v2/master/tests/tests_index.php`
|
|
||||||
|
|
||||||
| Before | After |
|
|
||||||
|--------|-------|
|
|
||||||
| `type?.VID` | `type?.key` |
|
|
||||||
| `type?.VValue` | `type?.value` |
|
|
||||||
| `type?.VDesc` | `type?.label` |
|
|
||||||
| `{ VID: 1, VValue: 'TEST', ... }` | `{ key: 'TEST', value: 'Test', ... }` |
|
|
||||||
| `getTypeName(vid)` | `getTypeName(value)` |
|
|
||||||
| `api/valuesetdef/27` | `api/valueset/test_TestType` |
|
|
||||||
| Hardcoded fallback: `{ VID: 1, VValue: 'TEST', VDesc: 'Test' }` | `{ key: 'TEST', value: 'Test' }` |
|
|
||||||
|
|
||||||
### 5. Additional Views to Update
|
|
||||||
|
|
||||||
| View File | Fields to Update | Lookup Name |
|
|
||||||
|-----------|------------------|-------------|
|
|
||||||
| `app/Views/v2/patients/patients_index.php` | Gender, Country, Race, Religion, Ethnic, MaritalStatus, DeathIndicator | `patient_*` |
|
|
||||||
| `app/Views/v2/master/specimen/containers_index.php` | Color, ConClass, Additive | `container_*` |
|
|
||||||
| `app/Views/v2/master/organization/sites_index.php` | SiteTypeID, SiteClassID | `organization_*` |
|
|
||||||
| `app/Views/v2/master/organization/workstations_index.php` | Type, Enable | `organization_*` |
|
|
||||||
| `app/Views/v2/master/organization/accounts_index.php` | Country | `account_Country` |
|
|
||||||
| `app/Views/v2/master/organization/locations_index.php` | LocType | `location_LocationType` |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 8: Test Files Update
|
|
||||||
|
|
||||||
### `tests/feature/ValueSet/ValueSetApiControllerTest.php`
|
|
||||||
|
|
||||||
Update tests to use new JSON-based API endpoints.
|
|
||||||
|
|
||||||
### `tests/_support/v2/MasterTestCase.php`
|
|
||||||
|
|
||||||
Update any valueset-related test data setup.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
1. **Unit Tests**
|
|
||||||
- Test `ValueSet::getLabel('patient_Sex', '1')` returns 'Female'
|
|
||||||
- Test `ValueSet::getLabel('test_TestType', 'TEST')` returns 'Test'
|
|
||||||
- Test `ValueSet::getOptions('container_ContainerCapColor')` returns correct format
|
|
||||||
- Test `ValueSet::transformLabels()` with table-prefixed field mappings
|
|
||||||
|
|
||||||
2. **Integration Tests**
|
|
||||||
- Patient CRUD (create, read, update, delete)
|
|
||||||
- Test definition CRUD
|
|
||||||
- Location CRUD
|
|
||||||
- Container definition CRUD
|
|
||||||
- Organization (site, account, workstation) CRUD
|
|
||||||
|
|
||||||
3. **Manual Testing**
|
|
||||||
- Verify all dropdowns display correct labels
|
|
||||||
- Verify filtering by valueset fields works
|
|
||||||
- Verify form submissions save correct VValue codes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Rollback Plan
|
|
||||||
|
|
||||||
1. Run migration `down()` to revert column types
|
|
||||||
2. Restore deleted seeders from git if needed
|
|
||||||
3. Restore deleted migration file from git
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Files Summary
|
|
||||||
|
|
||||||
| Phase | Action | Files |
|
|
||||||
|-------|--------|-------|
|
|
||||||
| 1 | RENAME | ~50 JSON files in `app/Libraries/Data/valuesets/` |
|
|
||||||
| 2 | DELETE | 5 seeders, 1 migration |
|
|
||||||
| 2 | CREATE | 1 migration (column changes) |
|
|
||||||
| 3 | UPDATE | 1 library (ValueSet.php), ValueSetModel.php deprecation |
|
|
||||||
| 4 | UPDATE | 8 Model files |
|
|
||||||
| 5 | UPDATE | 1 Controller, Routes |
|
|
||||||
| 6 | CREATE | 1 Controller (ValueSetApiController.php) |
|
|
||||||
| 6 | UPDATE | ~6+ View files |
|
|
||||||
| 8 | UPDATE | 2+ Test files |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Estimated Effort
|
|
||||||
|
|
||||||
- Phase 1 (JSON Rename): 15 minutes
|
|
||||||
- Phase 2 (Migration): 30 minutes
|
|
||||||
- Phase 3 (Library + Model): 30 minutes
|
|
||||||
- Phase 4 (Models): 1.5 hours
|
|
||||||
- Phase 5 (Controller): 30 minutes
|
|
||||||
- Phase 6 (API + Views): 2 hours
|
|
||||||
- Phase 8 (Tests): 30 minutes
|
|
||||||
- Testing: 1 hour
|
|
||||||
|
|
||||||
**Total Estimated Time: ~7 hours**
|
|
||||||
1914
docs/clqms_database.dbdiagram
Normal file
1914
docs/clqms_database.dbdiagram
Normal file
File diff suppressed because it is too large
Load Diff
854
docs/clqms_database.dbml
Normal file
854
docs/clqms_database.dbml
Normal file
@ -0,0 +1,854 @@
|
|||||||
|
// CLQMS Database Schema
|
||||||
|
// Generated from ERD_EXTRACT.md
|
||||||
|
// Database Markup Language (DBML) for dbdiagram.io and other tools
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// TABLE 1: Organization Structure
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
Table account {
|
||||||
|
AccountID int [pk]
|
||||||
|
AccountName varchar(255)
|
||||||
|
ParentAccountID int
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table site {
|
||||||
|
SiteID int [pk]
|
||||||
|
AccountID int
|
||||||
|
SiteName varchar(255)
|
||||||
|
Location varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table discipline {
|
||||||
|
DisciplineID int [pk]
|
||||||
|
DisciplineName varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table department {
|
||||||
|
DepartmentID int [pk]
|
||||||
|
DepartmentName varchar(255)
|
||||||
|
DisciplineID int
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table workstation {
|
||||||
|
WorkstationID int [pk]
|
||||||
|
SiteID int
|
||||||
|
DepartmentID int
|
||||||
|
WorkstationName varchar(255)
|
||||||
|
LocalDB boolean
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table instrument {
|
||||||
|
InstrumentID int [pk]
|
||||||
|
SiteID int
|
||||||
|
WorkstationID int
|
||||||
|
InstrumentAlias varchar(255)
|
||||||
|
InstrumentName varchar(255)
|
||||||
|
InstrumentType varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table personnel {
|
||||||
|
PersonnelID int [pk]
|
||||||
|
SiteID int
|
||||||
|
PersonnelName varchar(255)
|
||||||
|
Position varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table personneldocument {
|
||||||
|
DocID int [pk]
|
||||||
|
PersonnelID int
|
||||||
|
DocType varchar(255)
|
||||||
|
DocFile blob
|
||||||
|
ExpiryDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table personnelaccess {
|
||||||
|
AccessID int [pk]
|
||||||
|
PersonnelID int
|
||||||
|
Role varchar(255)
|
||||||
|
Permissions text
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table location {
|
||||||
|
LocationID int [pk]
|
||||||
|
SiteID int
|
||||||
|
ParentLocationID int
|
||||||
|
LocationTypeID int
|
||||||
|
LocationName varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table locationaddress {
|
||||||
|
AddressID int [pk]
|
||||||
|
LocationID int
|
||||||
|
AddressLine1 varchar(255)
|
||||||
|
AddressLine2 varchar(255)
|
||||||
|
City varchar(100)
|
||||||
|
PostalCode varchar(20)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patient {
|
||||||
|
PatientID int [pk]
|
||||||
|
SiteID int
|
||||||
|
InternalPID int
|
||||||
|
FirstName varchar(255)
|
||||||
|
LastName varchar(255)
|
||||||
|
DateOfBirth datetime
|
||||||
|
Sex varchar(10)
|
||||||
|
Race varchar(50)
|
||||||
|
Ethnicity varchar(50)
|
||||||
|
Religion varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
DelDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patientcontact {
|
||||||
|
ContactID int [pk]
|
||||||
|
InternalPID int
|
||||||
|
ContactType varchar(50)
|
||||||
|
ContactValue varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patientinsurance {
|
||||||
|
InsuranceID int [pk]
|
||||||
|
InternalPID int
|
||||||
|
InsuranceProvider varchar(255)
|
||||||
|
PolicyNumber varchar(100)
|
||||||
|
GroupNumber varchar(100)
|
||||||
|
EffectiveDate datetime
|
||||||
|
ExpiryDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patientvisit {
|
||||||
|
VisitID int [pk]
|
||||||
|
InternalPID int
|
||||||
|
SiteID int
|
||||||
|
VisitClass varchar(50)
|
||||||
|
VisitType varchar(50)
|
||||||
|
VisitDate datetime
|
||||||
|
DischargeDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table admission {
|
||||||
|
AdmissionID int [pk]
|
||||||
|
VisitID int
|
||||||
|
PatientID int
|
||||||
|
SiteID int
|
||||||
|
AdmissionDate datetime
|
||||||
|
DischargeDate datetime
|
||||||
|
ADTCode varchar(50)
|
||||||
|
ReferringParty varchar(255)
|
||||||
|
BillingAccount varchar(255)
|
||||||
|
AttendingDoctor varchar(255)
|
||||||
|
ReferringDoctor varchar(255)
|
||||||
|
VitalSigns text
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table admissionlocation {
|
||||||
|
ID int [pk]
|
||||||
|
AdmissionID int
|
||||||
|
LocationID int
|
||||||
|
TransferDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table testorder {
|
||||||
|
OrderID varchar(13) [pk]
|
||||||
|
SiteID int
|
||||||
|
PatientID int
|
||||||
|
VisitID int
|
||||||
|
OrderDate datetime
|
||||||
|
Urgency varchar(50)
|
||||||
|
Status varchar(50)
|
||||||
|
OrderingProvider varchar(255)
|
||||||
|
ProductionSiteID int
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table testorderdetail {
|
||||||
|
OrderDetailID int [pk]
|
||||||
|
OrderID varchar(13)
|
||||||
|
TestID int
|
||||||
|
Priority int
|
||||||
|
Status varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table specimen {
|
||||||
|
SID varchar(17) [pk]
|
||||||
|
OrderID varchar(13)
|
||||||
|
SpecimenDefID int
|
||||||
|
ParentSID varchar(17)
|
||||||
|
SpecimenType varchar(50)
|
||||||
|
SpecimenRole varchar(50)
|
||||||
|
CollectionDate datetime
|
||||||
|
CollectionSite int
|
||||||
|
CollectedBy int
|
||||||
|
ContainerType varchar(50)
|
||||||
|
Additive varchar(50)
|
||||||
|
CollectionMethod varchar(50)
|
||||||
|
BodySite varchar(50)
|
||||||
|
SpecimenCondition varchar(50)
|
||||||
|
Status varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table specimencollection {
|
||||||
|
ID int [pk]
|
||||||
|
SID varchar(17)
|
||||||
|
Activity varchar(50)
|
||||||
|
ActivityName varchar(100)
|
||||||
|
ActRes varchar(50)
|
||||||
|
LocationID int
|
||||||
|
EquipmentID int
|
||||||
|
PersonnelID int
|
||||||
|
ActivityDate datetime
|
||||||
|
Notes text
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table specimentransport {
|
||||||
|
TransportID int [pk]
|
||||||
|
SID varchar(17)
|
||||||
|
SenderID int
|
||||||
|
ReceiverID int
|
||||||
|
TransportDate datetime
|
||||||
|
Condition text
|
||||||
|
PackagingID varchar(50)
|
||||||
|
FromLocation int
|
||||||
|
ToLocation int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table specimenstorage {
|
||||||
|
StorageID int [pk]
|
||||||
|
SID varchar(17)
|
||||||
|
LocationID int
|
||||||
|
StorageTemperature decimal(10,2)
|
||||||
|
StorageDate datetime
|
||||||
|
ThawCount int
|
||||||
|
ExpiryDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table testdef {
|
||||||
|
TestID int [pk]
|
||||||
|
TestName varchar(255)
|
||||||
|
TestCode varchar(50)
|
||||||
|
LOINCCode varchar(50)
|
||||||
|
TestType varchar(50)
|
||||||
|
DisciplineID int
|
||||||
|
SpecimenTypeID int
|
||||||
|
ContainerTypeID int
|
||||||
|
ResultType varchar(50)
|
||||||
|
ResultUnit varchar(50)
|
||||||
|
Methodology varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table testdefsite {
|
||||||
|
ID int [pk]
|
||||||
|
TestID int
|
||||||
|
SiteID int
|
||||||
|
TestNameLocal varchar(255)
|
||||||
|
TestCodeLocal varchar(50)
|
||||||
|
WorkstationID int
|
||||||
|
InstrumentID int
|
||||||
|
Active boolean
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table testdeftech {
|
||||||
|
ID int [pk]
|
||||||
|
TestID int
|
||||||
|
InstrumentID int
|
||||||
|
InstrumentTestCode varchar(50)
|
||||||
|
TestMapping varchar(255)
|
||||||
|
Active boolean
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table calculatedtest {
|
||||||
|
CalculatedTestID int [pk]
|
||||||
|
TestID int
|
||||||
|
Formula text
|
||||||
|
ParamTestID1 int
|
||||||
|
ParamTestID2 int
|
||||||
|
ParamTestID3 int
|
||||||
|
ParamTestID4 int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table grouptest {
|
||||||
|
GroupTestID int [pk]
|
||||||
|
GroupTestName varchar(255)
|
||||||
|
GroupTestType varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table grouptestmember {
|
||||||
|
ID int [pk]
|
||||||
|
GroupTestID int
|
||||||
|
TestID int
|
||||||
|
Sequence int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table panel {
|
||||||
|
PanelID int [pk]
|
||||||
|
PanelName varchar(255)
|
||||||
|
PanelType varchar(50)
|
||||||
|
ParentPanelID int
|
||||||
|
DisciplineID int
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table panelmember {
|
||||||
|
ID int [pk]
|
||||||
|
PanelID int
|
||||||
|
TestID int
|
||||||
|
Sequence int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table referencerangenumeric {
|
||||||
|
RefRangeID int [pk]
|
||||||
|
TestID int
|
||||||
|
AgeFrom int
|
||||||
|
AgeTo int
|
||||||
|
Sex varchar(10)
|
||||||
|
LowValue decimal(10,2)
|
||||||
|
HighValue decimal(10,2)
|
||||||
|
Unit varchar(20)
|
||||||
|
SpecimenTypeID int
|
||||||
|
SiteID int
|
||||||
|
EffectiveDate datetime
|
||||||
|
ExpiryDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table referencerangethreshold {
|
||||||
|
RefRangeID int [pk]
|
||||||
|
TestID int
|
||||||
|
AgeFrom int
|
||||||
|
AgeTo int
|
||||||
|
Sex varchar(10)
|
||||||
|
CutOffLow decimal(10,2)
|
||||||
|
CutOffHigh decimal(10,2)
|
||||||
|
GrayZoneLow decimal(10,2)
|
||||||
|
GrayZoneHigh decimal(10,2)
|
||||||
|
SpecimenTypeID int
|
||||||
|
SiteID int
|
||||||
|
EffectiveDate datetime
|
||||||
|
ExpiryDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table referencerangetext {
|
||||||
|
RefRangeID int [pk]
|
||||||
|
TestID int
|
||||||
|
AgeFrom int
|
||||||
|
AgeTo int
|
||||||
|
Sex varchar(10)
|
||||||
|
TextValue text
|
||||||
|
SpecimenTypeID int
|
||||||
|
SiteID int
|
||||||
|
EffectiveDate datetime
|
||||||
|
ExpiryDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table calibrator {
|
||||||
|
CalibratorID int [pk]
|
||||||
|
CalibratorName varchar(255)
|
||||||
|
Manufacturer varchar(255)
|
||||||
|
LotNumber varchar(50)
|
||||||
|
ExpiryDate datetime
|
||||||
|
TestID int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table calibration {
|
||||||
|
CalibrationID int [pk]
|
||||||
|
InstrumentID int
|
||||||
|
TestID int
|
||||||
|
CalibratorID int
|
||||||
|
Level int
|
||||||
|
CalibrationDate datetime
|
||||||
|
Factor decimal(10,4)
|
||||||
|
Absorbance decimal(10,4)
|
||||||
|
TargetValue decimal(10,4)
|
||||||
|
TargetUnit varchar(20)
|
||||||
|
PersonnelID int
|
||||||
|
Status varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table calparinst {
|
||||||
|
CalParInstID int [pk]
|
||||||
|
EquipmentID int
|
||||||
|
Calibrator varchar(255)
|
||||||
|
LotNo varchar(50)
|
||||||
|
ExpiryDate datetime
|
||||||
|
TestInstID1 int
|
||||||
|
SampleType varchar(50)
|
||||||
|
Level int
|
||||||
|
Concentration decimal(10,4)
|
||||||
|
CalUnit varchar(20)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table qcmaterial {
|
||||||
|
QCMaterialID int [pk]
|
||||||
|
MaterialName varchar(255)
|
||||||
|
Manufacturer varchar(255)
|
||||||
|
LotNumber varchar(50)
|
||||||
|
ExpiryDate datetime
|
||||||
|
Level int
|
||||||
|
TestID int
|
||||||
|
TargetMean decimal(10,4)
|
||||||
|
TargetSD decimal(10,4)
|
||||||
|
TargetCV decimal(10,4)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table qcresult {
|
||||||
|
QCResultID int [pk]
|
||||||
|
InstrumentID int
|
||||||
|
TestID int
|
||||||
|
QCMaterialID int
|
||||||
|
Level int
|
||||||
|
QCDate datetime
|
||||||
|
ResultValue decimal(10,4)
|
||||||
|
Mean decimal(10,4)
|
||||||
|
SD decimal(10,4)
|
||||||
|
CV decimal(10,4)
|
||||||
|
Sigma decimal(10,4)
|
||||||
|
ZScore decimal(10,4)
|
||||||
|
Flag varchar(10)
|
||||||
|
PersonnelID int
|
||||||
|
Status varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table qcstatistic {
|
||||||
|
StatisticID int [pk]
|
||||||
|
InstrumentID int
|
||||||
|
TestID int
|
||||||
|
QCMaterialID int
|
||||||
|
Level int
|
||||||
|
StatisticDate datetime
|
||||||
|
Mean decimal(10,4)
|
||||||
|
SD decimal(10,4)
|
||||||
|
CV decimal(10,4)
|
||||||
|
SampleSize int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patres {
|
||||||
|
ResultID int [pk]
|
||||||
|
SID varchar(17)
|
||||||
|
TestID int
|
||||||
|
OrderID varchar(13)
|
||||||
|
ResultValue varchar(100)
|
||||||
|
ResultNumeric decimal(15,5)
|
||||||
|
ResultText text
|
||||||
|
ResultUnit varchar(20)
|
||||||
|
ResultStatus varchar(50)
|
||||||
|
PersonnelID int
|
||||||
|
VerificationDate datetime
|
||||||
|
VerificationPersonnel int
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patrestech {
|
||||||
|
TechResultID int [pk]
|
||||||
|
ResultID int
|
||||||
|
InstrumentID int
|
||||||
|
RawResult text
|
||||||
|
ResultDate datetime
|
||||||
|
RerunCount int
|
||||||
|
Dilution decimal(10,4)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table patresflag {
|
||||||
|
FlagID int [pk]
|
||||||
|
ResultID int
|
||||||
|
FlagType varchar(10)
|
||||||
|
FlagDescription varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table resultdistribution {
|
||||||
|
DistributionID int [pk]
|
||||||
|
ResultID int
|
||||||
|
RecipientType varchar(50)
|
||||||
|
RecipientID int
|
||||||
|
DistributionDate datetime
|
||||||
|
DistributionMethod varchar(50)
|
||||||
|
Status varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table valuesetmember {
|
||||||
|
MemberID int [pk]
|
||||||
|
ValueSetID int
|
||||||
|
MemberCode varchar(50)
|
||||||
|
MemberValue varchar(255)
|
||||||
|
DisplayOrder int
|
||||||
|
Active boolean
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table reagent {
|
||||||
|
ReagentID int [pk]
|
||||||
|
ReagentName varchar(255)
|
||||||
|
Manufacturer varchar(255)
|
||||||
|
CatalogNumber varchar(100)
|
||||||
|
LotNumber varchar(50)
|
||||||
|
ExpiryDate datetime
|
||||||
|
TestID int
|
||||||
|
InstrumentID int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table reagentusage {
|
||||||
|
UsageID int [pk]
|
||||||
|
ReagentID int
|
||||||
|
TestID int
|
||||||
|
UsageDate datetime
|
||||||
|
QuantityUsed decimal(10,2)
|
||||||
|
PersonnelID int
|
||||||
|
OrderID varchar(13)
|
||||||
|
SID varchar(17)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table product {
|
||||||
|
ProductID int [pk]
|
||||||
|
CatalogID int
|
||||||
|
SiteID int
|
||||||
|
LotNumber varchar(50)
|
||||||
|
ExpiryDate datetime
|
||||||
|
Quantity int
|
||||||
|
ReorderLevel int
|
||||||
|
LocationID int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table inventorytransaction {
|
||||||
|
TransactionID int [pk]
|
||||||
|
ProductID int
|
||||||
|
TransactionType varchar(50)
|
||||||
|
Quantity int
|
||||||
|
TransactionDate datetime
|
||||||
|
PersonnelID int
|
||||||
|
ReferenceID varchar(100)
|
||||||
|
Notes text
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table equipment {
|
||||||
|
EquipmentID int [pk]
|
||||||
|
EquipmentName varchar(255)
|
||||||
|
EquipmentType varchar(50)
|
||||||
|
Manufacturer varchar(255)
|
||||||
|
Model varchar(100)
|
||||||
|
SerialNumber varchar(100)
|
||||||
|
SiteID int
|
||||||
|
LocationID int
|
||||||
|
Status varchar(50)
|
||||||
|
InstallDate datetime
|
||||||
|
DecommissionDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table equipmentmaintenance {
|
||||||
|
MaintenanceID int [pk]
|
||||||
|
EquipmentID int
|
||||||
|
MaintenanceType varchar(100)
|
||||||
|
MaintenanceDate datetime
|
||||||
|
Description text
|
||||||
|
PerformedBy varchar(255)
|
||||||
|
NextMaintenanceDate datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table equipmentactivity {
|
||||||
|
ActivityID int [pk]
|
||||||
|
EquipmentID int
|
||||||
|
ActivityType varchar(100)
|
||||||
|
ActivityDate datetime
|
||||||
|
ActivityResult varchar(50)
|
||||||
|
PersonnelID int
|
||||||
|
Notes text
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table equipmenttestcount {
|
||||||
|
ID int [pk]
|
||||||
|
EquipmentID int
|
||||||
|
TestDate datetime
|
||||||
|
TestType varchar(50)
|
||||||
|
TestCount int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table doctor {
|
||||||
|
DoctorID int [pk]
|
||||||
|
DoctorName varchar(255)
|
||||||
|
DoctorCode varchar(50)
|
||||||
|
Specialty varchar(100)
|
||||||
|
SIP varchar(50)
|
||||||
|
PracticeLocation varchar(255)
|
||||||
|
ContactID int
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table contactdetail {
|
||||||
|
DetailID int [pk]
|
||||||
|
ContactID int
|
||||||
|
DetailType varchar(50)
|
||||||
|
DetailValue varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table auditarchive {
|
||||||
|
ArchiveID int [pk]
|
||||||
|
AuditID int
|
||||||
|
ArchiveDate datetime
|
||||||
|
ArchiveLocation varchar(255)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table user {
|
||||||
|
UserID int [pk]
|
||||||
|
Username varchar(100)
|
||||||
|
PasswordHash varchar(255)
|
||||||
|
PersonnelID int
|
||||||
|
Role varchar(50)
|
||||||
|
Status varchar(20)
|
||||||
|
LastLogin datetime
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table usersession {
|
||||||
|
SessionID int [pk]
|
||||||
|
UserID int
|
||||||
|
SessionToken varchar(255)
|
||||||
|
ExpiryDate datetime
|
||||||
|
IPAddress varchar(50)
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table reporttemplate {
|
||||||
|
TemplateID int [pk]
|
||||||
|
TemplateName varchar(255)
|
||||||
|
TemplateType varchar(50)
|
||||||
|
DisciplineID int
|
||||||
|
TemplateConfig text
|
||||||
|
CreateDate datetime
|
||||||
|
EndDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table reportoutput {
|
||||||
|
OutputID int [pk]
|
||||||
|
TemplateID int
|
||||||
|
OrderID varchar(13)
|
||||||
|
OutputFormat varchar(50)
|
||||||
|
OutputData blob
|
||||||
|
GeneratedDate datetime
|
||||||
|
PersonnelID int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table hosttestmapping {
|
||||||
|
MappingID int [pk]
|
||||||
|
HostID int
|
||||||
|
HostTestCode varchar(50)
|
||||||
|
LocalTestID int
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
Table hostsynclog {
|
||||||
|
LogID int [pk]
|
||||||
|
HostID int
|
||||||
|
SyncDate datetime
|
||||||
|
RecordsProcessed int
|
||||||
|
Errors int
|
||||||
|
Status varchar(20)
|
||||||
|
Details text
|
||||||
|
CreateDate datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// RELATIONSHIPS
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// Organization Structure
|
||||||
|
Ref: account.ParentAccountID > account.AccountID [delete: cascade]
|
||||||
|
Ref: site.AccountID > account.AccountID
|
||||||
|
Ref: department.DisciplineID > discipline.DisciplineID
|
||||||
|
Ref: workstation.SiteID > site.SiteID
|
||||||
|
Ref: workstation.DepartmentID > department.DepartmentID
|
||||||
|
Ref: instrument.SiteID > site.SiteID
|
||||||
|
Ref: instrument.WorkstationID > workstation.WorkstationID
|
||||||
|
|
||||||
|
// Personnel
|
||||||
|
Ref: personnel.SiteID > site.SiteID
|
||||||
|
Ref: personneldocument.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: personnelaccess.PersonnelID > personnel.PersonnelID
|
||||||
|
|
||||||
|
// Location Management
|
||||||
|
Ref: location.SiteID > site.SiteID
|
||||||
|
Ref: location.ParentLocationID > location.LocationID
|
||||||
|
Ref: locationaddress.LocationID > location.LocationID
|
||||||
|
|
||||||
|
// Patient Registration
|
||||||
|
Ref: patient.SiteID > site.SiteID
|
||||||
|
Ref: patientcontact.InternalPID > patient.InternalPID
|
||||||
|
Ref: patientinsurance.InternalPID > patient.InternalPID
|
||||||
|
Ref: patientvisit.InternalPID > patient.InternalPID
|
||||||
|
Ref: patientvisit.SiteID > site.SiteID
|
||||||
|
|
||||||
|
// Patient Admission
|
||||||
|
Ref: admission.VisitID > patientvisit.VisitID
|
||||||
|
Ref: admission.PatientID > patient.PatientID
|
||||||
|
Ref: admission.SiteID > site.SiteID
|
||||||
|
Ref: admissionlocation.AdmissionID > admission.AdmissionID
|
||||||
|
Ref: admissionlocation.LocationID > location.LocationID
|
||||||
|
|
||||||
|
// Test Ordering
|
||||||
|
Ref: testorder.SiteID > site.SiteID
|
||||||
|
Ref: testorder.PatientID > patient.PatientID
|
||||||
|
Ref: testorder.VisitID > patientvisit.VisitID
|
||||||
|
Ref: testorder.ProductionSiteID > site.SiteID
|
||||||
|
Ref: testorderdetail.OrderID > testorder.OrderID
|
||||||
|
|
||||||
|
// Specimen Management
|
||||||
|
Ref: specimen.OrderID > testorder.OrderID
|
||||||
|
Ref: specimencollection.SID > specimen.SID
|
||||||
|
Ref: specimencollection.LocationID > location.LocationID
|
||||||
|
Ref: specimencollection.EquipmentID > instrument.InstrumentID
|
||||||
|
Ref: specimencollection.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: specimentransport.SID > specimen.SID
|
||||||
|
Ref: specimentransport.SenderID > personnel.PersonnelID
|
||||||
|
Ref: specimentransport.ReceiverID > personnel.PersonnelID
|
||||||
|
Ref: specimenstorage.SID > specimen.SID
|
||||||
|
Ref: specimenstorage.LocationID > location.LocationID
|
||||||
|
|
||||||
|
// Test Management
|
||||||
|
Ref: testdef.DisciplineID > discipline.DisciplineID
|
||||||
|
Ref: testdefsite.TestID > testdef.TestID
|
||||||
|
Ref: testdefsite.SiteID > site.SiteID
|
||||||
|
Ref: testdefsite.WorkstationID > workstation.WorkstationID
|
||||||
|
Ref: testdefsite.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: testdeftech.TestID > testdef.TestID
|
||||||
|
Ref: testdeftech.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: calculatedtest.TestID > testdef.TestID
|
||||||
|
Ref: grouptestmember.GroupTestID > grouptest.GroupTestID
|
||||||
|
Ref: grouptestmember.TestID > testdef.TestID
|
||||||
|
Ref: panel.ParentPanelID > panel.PanelID
|
||||||
|
Ref: panel.DisciplineID > discipline.DisciplineID
|
||||||
|
Ref: panelmember.PanelID > panel.PanelID
|
||||||
|
Ref: panelmember.TestID > testdef.TestID
|
||||||
|
|
||||||
|
// Reference Range
|
||||||
|
Ref: referencerangenumeric.TestID > testdef.TestID
|
||||||
|
Ref: referencerangenumeric.SiteID > site.SiteID
|
||||||
|
Ref: referencerangethreshold.TestID > testdef.TestID
|
||||||
|
Ref: referencerangethreshold.SiteID > site.SiteID
|
||||||
|
Ref: referencerangetext.TestID > testdef.TestID
|
||||||
|
Ref: referencerangetext.SiteID > site.SiteID
|
||||||
|
|
||||||
|
// Calibration
|
||||||
|
Ref: calibrator.TestID > testdef.TestID
|
||||||
|
Ref: calibration.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: calibration.TestID > testdef.TestID
|
||||||
|
Ref: calibration.CalibratorID > calibrator.CalibratorID
|
||||||
|
Ref: calibration.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: calparinst.EquipmentID > instrument.InstrumentID
|
||||||
|
|
||||||
|
// Quality Control
|
||||||
|
Ref: qcmaterial.TestID > testdef.TestID
|
||||||
|
Ref: qcresult.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: qcresult.TestID > testdef.TestID
|
||||||
|
Ref: qcresult.QCMaterialID > qcmaterial.QCMaterialID
|
||||||
|
Ref: qcresult.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: qcstatistic.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: qcstatistic.TestID > testdef.TestID
|
||||||
|
Ref: qcstatistic.QCMaterialID > qcmaterial.QCMaterialID
|
||||||
|
|
||||||
|
// Test Results
|
||||||
|
Ref: patres.SID > specimen.SID
|
||||||
|
Ref: patres.TestID > testdef.TestID
|
||||||
|
Ref: patres.OrderID > testorder.OrderID
|
||||||
|
Ref: patres.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: patrestech.ResultID > patres.ResultID
|
||||||
|
Ref: patrestech.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: patresflag.ResultID > patres.ResultID
|
||||||
|
Ref: resultdistribution.ResultID > patres.ResultID
|
||||||
|
|
||||||
|
// Reagent & Inventory
|
||||||
|
Ref: reagent.TestID > testdef.TestID
|
||||||
|
Ref: reagent.InstrumentID > instrument.InstrumentID
|
||||||
|
Ref: reagentusage.ReagentID > reagent.ReagentID
|
||||||
|
Ref: reagentusage.TestID > testdef.TestID
|
||||||
|
Ref: reagentusage.PersonnelID > personnel.PersonnelID
|
||||||
|
|
||||||
|
Ref: product.SiteID > site.SiteID
|
||||||
|
Ref: product.LocationID > location.LocationID
|
||||||
|
Ref: inventorytransaction.ProductID > product.ProductID
|
||||||
|
Ref: inventorytransaction.PersonnelID > personnel.PersonnelID
|
||||||
|
|
||||||
|
// Equipment Management
|
||||||
|
Ref: equipment.SiteID > site.SiteID
|
||||||
|
Ref: equipment.LocationID > location.LocationID
|
||||||
|
Ref: equipmentmaintenance.EquipmentID > equipment.EquipmentID
|
||||||
|
Ref: equipmentactivity.EquipmentID > equipment.EquipmentID
|
||||||
|
Ref: equipmentactivity.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: equipmenttestcount.EquipmentID > equipment.EquipmentID
|
||||||
|
|
||||||
|
|
||||||
|
// User & Authentication
|
||||||
|
Ref: user.PersonnelID > personnel.PersonnelID
|
||||||
|
Ref: usersession.UserID > user.UserID
|
||||||
|
|
||||||
|
// Visualization & Reporting
|
||||||
|
Ref: reporttemplate.DisciplineID > discipline.DisciplineID
|
||||||
|
Ref: reportoutput.TemplateID > reporttemplate.TemplateID
|
||||||
|
Ref: reportoutput.OrderID > testorder.OrderID
|
||||||
|
Ref: reportoutput.PersonnelID > personnel.PersonnelID
|
||||||
|
|
||||||
|
// Host System Integration
|
||||||
|
Ref: hosttestmapping.LocalTestID > testdef.TestID
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user