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