diff --git a/app/Controllers/Test/TestsController.php b/app/Controllers/Test/TestsController.php index 8da3acb..da9e70c 100644 --- a/app/Controllers/Test/TestsController.php +++ b/app/Controllers/Test/TestsController.php @@ -30,12 +30,11 @@ class TestsController extends BaseController $this->modelRefNum = new \App\Models\RefRange\RefNumModel; $this->modelRefTxt = new \App\Models\RefRange\RefTxtModel; - $this->rules = [ - 'TestSiteCode' => 'required', - 'TestSiteName' => 'required', - 'TestType' => 'required', - 'SiteID' => 'required', - ]; + $this->rules = [ + 'TestSiteCode' => 'required', + 'TestSiteName' => 'required', + 'TestType' => 'required', + ]; } public function index() @@ -148,15 +147,15 @@ class TestsController extends BaseController $db->transStart(); try { - $testSiteData = [ - 'SiteID' => $input['SiteID'], - 'TestSiteCode'=> $input['TestSiteCode'], - 'TestSiteName'=> $input['TestSiteName'], - 'TestType' => $input['TestType'], - 'Description' => $input['Description'] ?? null, - 'SeqScr' => $input['SeqScr'] ?? 0, - 'SeqRpt' => $input['SeqRpt'] ?? 0, - 'IndentLeft' => $input['IndentLeft'] ?? 0, + $testSiteData = [ + 'SiteID' => array_key_exists('SiteID', $input) ? $input['SiteID'] : null, + 'TestSiteCode'=> $input['TestSiteCode'], + 'TestSiteName'=> $input['TestSiteName'], + 'TestType' => $input['TestType'], + 'Description' => $input['Description'] ?? null, + 'SeqScr' => array_key_exists('SeqScr', $input) ? $input['SeqScr'] : null, + 'SeqRpt' => array_key_exists('SeqRpt', $input) ? $input['SeqRpt'] : null, + 'IndentLeft' => $input['IndentLeft'] ?? 0, 'FontStyle' => $input['FontStyle'] ?? null, 'isVisibleScr' => $input['isVisibleScr'] ?? 1, 'isVisibleRpt' => $input['isVisibleRpt'] ?? 1, @@ -372,9 +371,9 @@ class TestsController extends BaseController $typeCode = $testTypeID; - $details = $input['details'] ?? $input; - $details['TestSiteID'] = $testSiteID; - $details['SiteID'] = $input['SiteID'] ?? 1; + $details = $input['details'] ?? $input; + $details['TestSiteID'] = $testSiteID; + $details['SiteID'] = array_key_exists('SiteID', $input) ? $input['SiteID'] : null; switch ($typeCode) { case 'CALC': @@ -403,14 +402,14 @@ class TestsController extends BaseController $refType = (string) $details['RefType']; $resultType = $details['ResultType'] ?? ''; - if (TestValidationService::usesRefNum($resultType, $refType) && isset($input['refnum']) && is_array($input['refnum'])) { - $this->saveRefNumRanges($testSiteID, $input['refnum'], $action, $input['SiteID'] ?? 1); - } - - if (TestValidationService::usesRefTxt($resultType, $refType) && isset($input['reftxt']) && is_array($input['reftxt'])) { - $this->saveRefTxtRanges($testSiteID, $input['reftxt'], $action, $input['SiteID'] ?? 1); - } - } + if (TestValidationService::usesRefNum($resultType, $refType) && isset($input['refnum']) && is_array($input['refnum'])) { + $this->saveRefNumRanges($testSiteID, $input['refnum'], $action, array_key_exists('SiteID', $input) ? $input['SiteID'] : null); + } + + if (TestValidationService::usesRefTxt($resultType, $refType) && isset($input['reftxt']) && is_array($input['reftxt'])) { + $this->saveRefTxtRanges($testSiteID, $input['reftxt'], $action, array_key_exists('SiteID', $input) ? $input['SiteID'] : null); + } + } break; } @@ -420,30 +419,30 @@ class TestsController extends BaseController } } - private function saveTechDetails($testSiteID, $data, $action, $typeCode) - { - $techData = [ - 'DisciplineID' => $data['DisciplineID'] ?? null, - 'DepartmentID' => $data['DepartmentID'] ?? null, - 'ResultType' => $data['ResultType'] ?? null, - 'RefType' => $data['RefType'] ?? null, - 'VSet' => $data['VSet'] ?? null, - 'ReqQty' => $data['ReqQty'] ?? null, - 'ReqQtyUnit' => $data['ReqQtyUnit'] ?? null, - 'Unit1' => $data['Unit1'] ?? null, - 'Factor' => $data['Factor'] ?? null, - 'Unit2' => $data['Unit2'] ?? null, - 'Decimal' => $data['Decimal'] ?? 2, - 'CollReq' => $data['CollReq'] ?? null, - 'Method' => $data['Method'] ?? null, - 'ExpectedTAT' => $data['ExpectedTAT'] ?? null, - ]; - - $this->model->update($testSiteID, $techData); - } - - private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID) - { + private function saveTechDetails($testSiteID, $data, $action, $typeCode) + { + $techData = [ + 'DisciplineID' => $data['DisciplineID'] ?? null, + 'DepartmentID' => $data['DepartmentID'] ?? null, + 'ResultType' => $data['ResultType'] ?? null, + 'RefType' => $data['RefType'] ?? null, + 'VSet' => $data['VSet'] ?? null, + 'ReqQty' => $data['ReqQty'] ?? null, + 'ReqQtyUnit' => $data['ReqQtyUnit'] ?? null, + 'Unit1' => $data['Unit1'] ?? null, + 'Factor' => $data['Factor'] ?? null, + 'Unit2' => $data['Unit2'] ?? null, + 'Decimal' => array_key_exists('Decimal', $data) ? $data['Decimal'] : null, + 'CollReq' => $data['CollReq'] ?? null, + 'Method' => $data['Method'] ?? null, + 'ExpectedTAT' => $data['ExpectedTAT'] ?? null, + ]; + + $this->model->update($testSiteID, $techData); + } + + private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID) + { if ($action === 'update') { $this->modelRefNum->disableByTestSiteID($testSiteID); } @@ -460,21 +459,21 @@ class TestsController extends BaseController $this->modelRefTxt->batchInsert($testSiteID, $siteID, $ranges); } - private function saveCalcDetails($testSiteID, $data, $input, $action) - { - $calcData = [ - 'TestSiteID' => $testSiteID, - 'DisciplineID' => $data['DisciplineID'] ?? null, - 'DepartmentID' => $data['DepartmentID'] ?? null, - 'FormulaCode' => $data['FormulaCode'] ?? $data['Formula'] ?? null, - 'ResultType' => 'NMRIC', - 'RefType' => $data['RefType'] ?? 'RANGE', - 'Unit1' => $data['Unit1'] ?? $data['ResultUnit'] ?? null, - 'Factor' => $data['Factor'] ?? null, - 'Unit2' => $data['Unit2'] ?? null, - 'Decimal' => $data['Decimal'] ?? 2, - 'Method' => $data['Method'] ?? null, - ]; + private function saveCalcDetails($testSiteID, $data, $input, $action) + { + $calcData = [ + 'TestSiteID' => $testSiteID, + 'DisciplineID' => $data['DisciplineID'] ?? null, + 'DepartmentID' => $data['DepartmentID'] ?? null, + 'FormulaCode' => $data['FormulaCode'] ?? $data['Formula'] ?? null, + 'ResultType' => 'NMRIC', + 'RefType' => $data['RefType'] ?? 'RANGE', + 'Unit1' => $data['Unit1'] ?? $data['ResultUnit'] ?? null, + 'Factor' => $data['Factor'] ?? null, + 'Unit2' => $data['Unit2'] ?? null, + 'Decimal' => array_key_exists('Decimal', $data) ? $data['Decimal'] : null, + 'Method' => $data['Method'] ?? null, + ]; if ($action === 'update') { $exists = $this->modelCal->existsByTestSiteID($testSiteID); diff --git a/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php b/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php index 0174ee1..064028f 100644 --- a/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php +++ b/app/Database/Migrations/2026-01-01-000004_CreateTestDefinitions.php @@ -8,7 +8,7 @@ class CreateTestDefinitions extends Migration { public function up() { $this->forge->addField([ 'TestSiteID' => ['type' => 'INT', 'auto_increment' => true, 'unsigned' => true], - 'SiteID' => ['type' => 'INT', 'null' => false], + 'SiteID' => ['type' => 'INT', 'null' => true], 'TestSiteCode' => ['type' => 'varchar', 'constraint'=> 10, 'null' => false], 'TestSiteName' => ['type' => 'varchar', 'constraint'=> 100, 'null' => false], 'TestType' => ['type' => 'VARCHAR', 'constraint' => 10, 'null' => false], @@ -23,7 +23,7 @@ class CreateTestDefinitions extends Migration { 'Unit1' => ['type' => 'varchar', 'constraint'=> 20, 'null' => true], 'Factor' => ['type' => 'DECIMAL', 'constraint'=> '10,4', 'null' => true], 'Unit2' => ['type' => 'varchar', 'constraint'=> 20, 'null' => true], - 'Decimal' => ['type' => 'int', 'null' => true, 'default' => 2], + 'Decimal' => ['type' => 'int', 'null' => true ], 'CollReq' => ['type' => 'varchar', 'constraint'=> 255, 'null' => true], 'Method' => ['type' => 'varchar', 'constraint'=> 50, 'null' => true], 'ExpectedTAT' => ['type' => 'INT', 'null' => true], @@ -31,11 +31,11 @@ class CreateTestDefinitions extends Migration { 'SeqRpt' => ['type' => 'int', 'null' => true], 'IndentLeft' => ['type' => 'int', 'null' => true, 'default' => 0], 'FontStyle' => ['type' => 'varchar', 'constraint'=> 50, 'null' => true], - 'isVisibleScr' => ['type' => 'int', 'null' => true, 'default' => 1], - 'isVisibleRpt' => ['type' => 'int', 'null' => true, 'default' => 1], - 'isCountStat' => ['type' => 'int', 'null' => true, 'default' => 1], - 'Level' => ['type' => 'int', 'null' => true], - 'isRequestable' => [ 'type' => 'TINYINT', 'constraint' => 1, 'null' => true, 'default' => 1, 'comment' => 'Flag indicating if test can be requested (1=yes, 0=no)' ], + 'isVisibleScr' => ['type' => 'int', 'null' => true, 'default' => 1], + 'isVisibleRpt' => ['type' => 'int', 'null' => true, 'default' => 1], + 'isCountStat' => ['type' => 'int', 'null' => true, 'default' => 1], + 'Level' => ['type' => 'int', 'null' => true], + 'isRequestable' => [ 'type' => 'TINYINT', 'constraint' => 1, 'null' => true, 'default' => 1, 'comment' => 'Flag indicating if test can be requested (1=yes, 0=no)' ], 'CreateDate' => ['type' => 'Datetime', 'null' => true], 'StartDate' => ['type' => 'Datetime', 'null' => true], 'EndDate' => ['type' => 'Datetime', 'null' => true], diff --git a/app/Models/PatResultModel.php b/app/Models/PatResultModel.php index 2a979c4..b95b71c 100644 --- a/app/Models/PatResultModel.php +++ b/app/Models/PatResultModel.php @@ -72,19 +72,19 @@ class PatResultModel extends BaseModel { } } - // Check age criteria - if ($ref['AgeStart'] !== null || $ref['AgeEnd'] !== null) { - $birthdate = new \DateTime($patient['Birthdate']); - $today = new \DateTime(); - $age = $birthdate->diff($today)->y; - - if ($ref['AgeStart'] !== null && $age < $ref['AgeStart']) { - return null; - } - if ($ref['AgeEnd'] !== null && $age > $ref['AgeEnd']) { - return null; - } - } + // Check age criteria (AgeStart/AgeEnd stored in days) + if ($ref['AgeStart'] !== null || $ref['AgeEnd'] !== null) { + $birthdate = new \DateTime($patient['Birthdate']); + $today = new \DateTime(); + $ageInDays = $birthdate->diff($today, true)->days; + + if ($ref['AgeStart'] !== null && $ageInDays < (int) $ref['AgeStart']) { + return null; + } + if ($ref['AgeEnd'] !== null && $ageInDays > (int) $ref['AgeEnd']) { + return null; + } + } $value = floatval($resultValue); $low = floatval($ref['Low']); diff --git a/app/Models/RefRange/RefNumModel.php b/app/Models/RefRange/RefNumModel.php index 48230c8..b1fdae2 100644 --- a/app/Models/RefRange/RefNumModel.php +++ b/app/Models/RefRange/RefNumModel.php @@ -74,8 +74,8 @@ class RefNumModel extends BaseModel 'HighSignLabel' => $r['HighSign'] ? \App\Libraries\ValueSet::getLabel('math_sign', $r['HighSign']) : '', 'High' => $r['High'] !== null ? (float) $r['High'] : null, 'Low' => $r['Low'] !== null ? (float) $r['Low'] : null, - 'AgeStart' => (int) $r['AgeStart'], - 'AgeEnd' => (int) $r['AgeEnd'], + 'AgeStart' => $r['AgeStart'] !== null ? (int) $r['AgeStart'] : null, + 'AgeEnd' => $r['AgeEnd'] !== null ? (int) $r['AgeEnd'] : null, 'Flag' => $r['Flag'], 'Interpretation' => $r['Interpretation'], 'Notes' => $r['Notes'], @@ -104,9 +104,16 @@ class RefNumModel extends BaseModel * @param array $ranges * @return void */ - public function batchInsert($testSiteID, $siteID, $ranges) - { - foreach ($ranges as $index => $range) { + public function batchInsert($testSiteID, $siteID, $ranges) + { + foreach ($ranges as $index => $range) { + $ageStart = array_key_exists('AgeStart', $range) && $range['AgeStart'] !== '' && $range['AgeStart'] !== null + ? (int) $range['AgeStart'] + : null; + $ageEnd = array_key_exists('AgeEnd', $range) && $range['AgeEnd'] !== '' && $range['AgeEnd'] !== null + ? (int) $range['AgeEnd'] + : null; + $this->insert([ 'TestSiteID' => $testSiteID, 'SiteID' => $siteID, @@ -114,8 +121,8 @@ class RefNumModel extends BaseModel 'NumRefType' => $range['NumRefType'], 'RangeType' => $range['RangeType'], 'Sex' => $range['Sex'], - 'AgeStart' => (int) ($range['AgeStart'] ?? 0), - 'AgeEnd' => (int) ($range['AgeEnd'] ?? 150), + 'AgeStart' => $ageStart, + 'AgeEnd' => $ageEnd, 'LowSign' => !empty($range['LowSign']) ? $range['LowSign'] : null, 'Low' => !empty($range['Low']) ? (float) $range['Low'] : null, 'HighSign' => !empty($range['HighSign']) ? $range['HighSign'] : null, diff --git a/app/Models/RefRange/RefTxtModel.php b/app/Models/RefRange/RefTxtModel.php index f3d0b42..7d3a9a5 100644 --- a/app/Models/RefRange/RefTxtModel.php +++ b/app/Models/RefRange/RefTxtModel.php @@ -59,8 +59,8 @@ class RefTxtModel extends BaseModel 'TxtRefTypeLabel'=> $r['TxtRefType'] ? \App\Libraries\ValueSet::getLabel('text_ref_type', $r['TxtRefType']) : '', 'Sex' => $r['Sex'], 'SexLabel' => $r['Sex'] ? \App\Libraries\ValueSet::getLabel('gender', $r['Sex']) : '', - 'AgeStart' => (int) $r['AgeStart'], - 'AgeEnd' => (int) $r['AgeEnd'], + 'AgeStart' => $r['AgeStart'] !== null ? (int) $r['AgeStart'] : null, + 'AgeEnd' => $r['AgeEnd'] !== null ? (int) $r['AgeEnd'] : null, 'RefTxt' => $r['RefTxt'], 'Flag' => $r['Flag'], ]; @@ -88,17 +88,24 @@ class RefTxtModel extends BaseModel * @param array $ranges * @return void */ - public function batchInsert($testSiteID, $siteID, $ranges) - { + public function batchInsert($testSiteID, $siteID, $ranges) + { foreach ($ranges as $range) { + $ageStart = array_key_exists('AgeStart', $range) && $range['AgeStart'] !== '' && $range['AgeStart'] !== null + ? (int) $range['AgeStart'] + : null; + $ageEnd = array_key_exists('AgeEnd', $range) && $range['AgeEnd'] !== '' && $range['AgeEnd'] !== null + ? (int) $range['AgeEnd'] + : null; + $this->insert([ 'TestSiteID' => $testSiteID, 'SiteID' => $siteID, 'SpcType' => $range['SpcType'] ?? 'GEN', 'TxtRefType' => $range['TxtRefType'], 'Sex' => $range['Sex'], - 'AgeStart' => (int) ($range['AgeStart'] ?? 0), - 'AgeEnd' => (int) ($range['AgeEnd'] ?? 150), + 'AgeStart' => $ageStart, + 'AgeEnd' => $ageEnd, 'RefTxt' => $range['RefTxt'] ?? '', 'Flag' => $range['Flag'] ?? null, 'CreateDate' => date('Y-m-d H:i:s'), diff --git a/public/api-docs.bundled.yaml b/public/api-docs.bundled.yaml index 7975d54..c41effa 100644 --- a/public/api-docs.bundled.yaml +++ b/public/api-docs.bundled.yaml @@ -4756,8 +4756,8 @@ paths: Low: 70 HighSign: LE High: 100 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: 'N' DisciplineID: 2 DepartmentID: 2 @@ -4785,8 +4785,8 @@ paths: Low: 70 HighSign: LE High: 100 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: 'N' - NumRefType: NMRC RangeType: REF @@ -4795,8 +4795,8 @@ paths: Low: 75 HighSign: < High: 105 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: 'N' testmap: - HostType: SITE @@ -4849,7 +4849,7 @@ paths: LowSign: LT Low: 120 AgeStart: 0 - AgeEnd: 125 + AgeEnd: 45625 Flag: H DisciplineID: 2 DepartmentID: 2 @@ -4876,7 +4876,7 @@ paths: LowSign: LT Low: 120 AgeStart: 0 - AgeEnd: 125 + AgeEnd: 45625 Flag: H - NumRefType: THOLD RangeType: PANIC @@ -4884,7 +4884,7 @@ paths: LowSign: < Low: 121 AgeStart: 0 - AgeEnd: 125 + AgeEnd: 45625 Flag: H testmap: - HostType: SITE @@ -4924,8 +4924,8 @@ paths: - SpcType: GEN TxtRefType: TEXT Sex: '2' - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: NORM=Normal;HIGH=High Flag: 'N' DisciplineID: 1 @@ -4949,15 +4949,15 @@ paths: - SpcType: GEN TxtRefType: TEXT Sex: '2' - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: NORM=Normal Flag: 'N' - SpcType: GEN TxtRefType: TEXT Sex: '1' - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: ABN=Abnormal Flag: 'N' testmap: @@ -4992,7 +4992,7 @@ paths: TxtRefType: VSET Sex: '2' AgeStart: 0 - AgeEnd: 120 + AgeEnd: 43800 RefTxt: NORM=Normal;MACRO=Macro Flag: 'N' DisciplineID: 4 @@ -5017,7 +5017,7 @@ paths: TxtRefType: VSET Sex: '2' AgeStart: 0 - AgeEnd: 120 + AgeEnd: 43800 RefTxt: NORM=Normal;ABN=Abnormal Flag: 'N' testmap: @@ -5102,8 +5102,8 @@ paths: Low: 10 HighSign: LE High: 20 - AgeStart: 18 - AgeEnd: 120 + AgeStart: 6570 + AgeEnd: 43800 Flag: 'N' testmap: - HostType: SITE @@ -7102,8 +7102,10 @@ components: format: float AgeStart: type: integer + description: Minimum patient age in days AgeEnd: type: integer + description: Maximum patient age in days Flag: type: string Interpretation: @@ -7133,8 +7135,10 @@ components: type: string AgeStart: type: integer + description: Minimum patient age in days AgeEnd: type: integer + description: Maximum patient age in days RefTxt: type: string Flag: @@ -7176,8 +7180,8 @@ components: HighSignLabel: <= Low: 70 High: 100 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: 'N' Interpretation: Normal TEST_threshold: @@ -7212,7 +7216,7 @@ components: LowSignLabel: < High: 40 AgeStart: 0 - AgeEnd: 120 + AgeEnd: 43800 Flag: L Interpretation: Critical Low TEST_text: @@ -7238,8 +7242,8 @@ components: TxtRefTypeLabel: Text Sex: '2' SexLabel: Male - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: NORM=Normal;HYPO=Hypochromic;MACRO=Macrocytic Flag: 'N' PARAM: @@ -7306,8 +7310,8 @@ components: HighSignLabel: <= Low: 10 High: 20 - AgeStart: 18 - AgeEnd: 120 + AgeStart: 6570 + AgeEnd: 43800 Flag: 'N' Interpretation: Normal GROUP: diff --git a/public/components/schemas/tests.yaml b/public/components/schemas/tests.yaml index 7890d6c..32aef2a 100644 --- a/public/components/schemas/tests.yaml +++ b/public/components/schemas/tests.yaml @@ -264,8 +264,10 @@ TestDefinition: format: float AgeStart: type: integer + description: Minimum patient age in days AgeEnd: type: integer + description: Maximum patient age in days Flag: type: string Interpretation: @@ -291,10 +293,12 @@ TestDefinition: type: string SexLabel: type: string - AgeStart: - type: integer - AgeEnd: - type: integer + AgeStart: + type: integer + description: Minimum patient age in days + AgeEnd: + type: integer + description: Maximum patient age in days RefTxt: type: string Flag: @@ -336,8 +340,8 @@ TestDefinition: HighSignLabel: "<=" Low: 70 High: 100 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: N Interpretation: Normal TEST_threshold: @@ -372,7 +376,7 @@ TestDefinition: LowSignLabel: "<" High: 40 AgeStart: 0 - AgeEnd: 120 + AgeEnd: 43800 Flag: L Interpretation: Critical Low TEST_text: @@ -398,8 +402,8 @@ TestDefinition: TxtRefTypeLabel: Text Sex: '2' SexLabel: Male - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: 'NORM=Normal;HYPO=Hypochromic;MACRO=Macrocytic' Flag: N PARAM: @@ -466,8 +470,8 @@ TestDefinition: HighSignLabel: "<=" Low: 10 High: 20 - AgeStart: 18 - AgeEnd: 120 + AgeStart: 6570 + AgeEnd: 43800 Flag: N Interpretation: Normal GROUP: diff --git a/public/paths/tests.yaml b/public/paths/tests.yaml index 2378522..4eb18a4 100644 --- a/public/paths/tests.yaml +++ b/public/paths/tests.yaml @@ -270,8 +270,8 @@ Low: 70 HighSign: LE High: 100 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: N DisciplineID: 2 DepartmentID: 2 @@ -299,8 +299,8 @@ Low: 70 HighSign: LE High: 100 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: N - NumRefType: NMRC RangeType: REF @@ -309,8 +309,8 @@ Low: 75 HighSign: < High: 105 - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 Flag: N testmap: - HostType: SITE @@ -363,7 +363,7 @@ LowSign: LT Low: 120 AgeStart: 0 - AgeEnd: 125 + AgeEnd: 45625 Flag: H DisciplineID: 2 DepartmentID: 2 @@ -390,7 +390,7 @@ LowSign: LT Low: 120 AgeStart: 0 - AgeEnd: 125 + AgeEnd: 45625 Flag: H - NumRefType: THOLD RangeType: PANIC @@ -398,7 +398,7 @@ LowSign: < Low: 121 AgeStart: 0 - AgeEnd: 125 + AgeEnd: 45625 Flag: H testmap: - HostType: SITE @@ -438,8 +438,8 @@ - SpcType: GEN TxtRefType: TEXT Sex: '2' - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: NORM=Normal;HIGH=High Flag: N DisciplineID: 1 @@ -463,15 +463,15 @@ - SpcType: GEN TxtRefType: TEXT Sex: '2' - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: NORM=Normal Flag: N - SpcType: GEN TxtRefType: TEXT Sex: '1' - AgeStart: 18 - AgeEnd: 99 + AgeStart: 6570 + AgeEnd: 36135 RefTxt: ABN=Abnormal Flag: N testmap: @@ -506,7 +506,7 @@ TxtRefType: VSET Sex: '2' AgeStart: 0 - AgeEnd: 120 + AgeEnd: 43800 RefTxt: NORM=Normal;MACRO=Macro Flag: N DisciplineID: 4 @@ -531,7 +531,7 @@ TxtRefType: VSET Sex: '2' AgeStart: 0 - AgeEnd: 120 + AgeEnd: 43800 RefTxt: NORM=Normal;ABN=Abnormal Flag: N testmap: @@ -616,8 +616,8 @@ Low: 10 HighSign: LE High: 20 - AgeStart: 18 - AgeEnd: 120 + AgeStart: 6570 + AgeEnd: 43800 Flag: N testmap: - HostType: SITE diff --git a/tests/feature/Test/TestCreateVariantsTest.php b/tests/feature/Test/TestCreateVariantsTest.php index aaa2c32..a7fee03 100644 --- a/tests/feature/Test/TestCreateVariantsTest.php +++ b/tests/feature/Test/TestCreateVariantsTest.php @@ -31,6 +31,54 @@ class TestCreateVariantsTest extends CIUnitTestCase } } + public function testCreateTechnicalCanAcceptNullSiteAndNumericFields(): void + { + $payload = $this->buildTechnicalPayload('TEST', [ + 'ResultType' => 'NMRIC', + 'RefType' => 'RANGE', + 'Decimal' => null, + 'Factor' => 2.5, + 'ReqQty' => 1.75, + 'ReqQtyUnit' => 'uL', + ]); + $payload['SiteID'] = null; + $payload['SeqScr'] = null; + $payload['SeqRpt'] = null; + $payload['refnum'] = [ + [ + 'NumRefType' => 'NMRC', + 'RangeType' => 'REF', + 'Sex' => '2', + 'LowSign' => 'GE', + 'Low' => 10, + 'HighSign' => 'LE', + 'High' => 20, + 'AgeStart' => null, + 'AgeEnd' => null, + 'Flag' => 'N', + 'Interpretation' => 'Nullable range', + 'SpcType' => 'GEN', + ], + ]; + + $response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload); + $response->assertStatus(201); + + $testSiteId = json_decode($response->getJSON(), true)['data']['TestSiteId']; + $show = $this->call('get', $this->endpoint . '/' . $testSiteId); + $show->assertStatus(200); + + $data = json_decode($show->getJSON(), true)['data']; + $this->assertNull($data['SiteID']); + $this->assertNull($data['SeqScr']); + $this->assertNull($data['SeqRpt']); + $this->assertNull($data['Decimal']); + $this->assertSame(2.5, (float) $data['Factor']); + $this->assertSame(1.75, (float) $data['ReqQty']); + $this->assertNull($data['refnum'][0]['AgeStart']); + $this->assertNull($data['refnum'][0]['AgeEnd']); + } + public function testCreateTechnicalWithNumericReference(): void { $refnum = $this->buildRefNumEntries('NMRC', true); @@ -42,6 +90,42 @@ class TestCreateVariantsTest extends CIUnitTestCase } } + public function testCreateTechnicalNumericReferenceReturnsAgeInDays(): void + { + $payload = $this->buildTechnicalPayload('TEST', [ + 'ResultType' => 'NMRIC', + 'RefType' => 'RANGE', + ]); + + $payload['refnum'] = [ + [ + 'NumRefType' => 'NMRC', + 'RangeType' => 'REF', + 'Sex' => '2', + 'LowSign' => 'GE', + 'Low' => 10, + 'HighSign' => 'LE', + 'High' => 20, + 'AgeStart' => 6570, + 'AgeEnd' => 36135, + 'Flag' => 'N', + 'Interpretation' => 'Adult range in days', + 'SpcType' => 'GEN', + ], + ]; + + $response = $this->withBodyFormat('json')->call('post', $this->endpoint, $payload); + $response->assertStatus(201); + + $testSiteId = json_decode($response->getJSON(), true)['data']['TestSiteId']; + $show = $this->call('get', $this->endpoint . '/' . $testSiteId); + $show->assertStatus(200); + + $data = json_decode($show->getJSON(), true)['data']; + $this->assertSame(6570, (int) $data['refnum'][0]['AgeStart']); + $this->assertSame(36135, (int) $data['refnum'][0]['AgeEnd']); + } + public function testNumericRefRangeNotesPersistAfterCreate(): void { $notes = 'Auto note ' . uniqid(); @@ -339,10 +423,10 @@ class TestCreateVariantsTest extends CIUnitTestCase 'DepartmentID' => $details['DepartmentID'] ?? 2, 'Method' => $details['Method'] ?? 'Automated test', 'Unit1' => $details['Unit1'] ?? 'mg/dL', - 'Decimal' => $details['Decimal'] ?? 0, + 'Decimal' => array_key_exists('Decimal', $details) ? $details['Decimal'] : 0, ]; - foreach (['ResultType', 'RefType', 'FormulaCode', 'members', 'ExpectedTAT'] as $key) { + foreach (['ResultType', 'RefType', 'FormulaCode', 'members', 'ExpectedTAT', 'Factor', 'ReqQty', 'ReqQtyUnit', 'Unit2', 'VSet', 'CollReq'] as $key) { if (array_key_exists($key, $details)) { $normalized[$key] = $details[$key]; } @@ -364,7 +448,7 @@ class TestCreateVariantsTest extends CIUnitTestCase 'HighSign' => 'LE', 'High' => $numRefType === 'THOLD' ? 40 : 20, 'AgeStart' => 0, - 'AgeEnd' => 120, + 'AgeEnd' => 43800, 'Flag' => 'N', 'Interpretation' => 'Normal range', 'SpcType' => 'GEN', @@ -382,7 +466,7 @@ class TestCreateVariantsTest extends CIUnitTestCase 'HighSign' => '<', 'High' => $numRefType === 'THOLD' ? 50 : 15, 'AgeStart' => 0, - 'AgeEnd' => 99, + 'AgeEnd' => 36135, 'Flag' => 'N', 'Interpretation' => 'Alternate range', 'SpcType' => 'GEN', @@ -401,7 +485,7 @@ class TestCreateVariantsTest extends CIUnitTestCase 'TxtRefType' => $txtRefType, 'Sex' => '2', 'AgeStart' => 0, - 'AgeEnd' => 120, + 'AgeEnd' => 43800, 'RefTxt' => $txtRefType === 'VSET' ? 'NORM=Normal;ABN=Abnormal' : 'NORM=Normal', 'Flag' => 'N', ], @@ -413,7 +497,7 @@ class TestCreateVariantsTest extends CIUnitTestCase 'TxtRefType' => $txtRefType, 'Sex' => '1', 'AgeStart' => 0, - 'AgeEnd' => 120, + 'AgeEnd' => 43800, 'RefTxt' => $txtRefType === 'VSET' ? 'HIGH=High;LOW=Low' : 'ABN=Abnormal', 'Flag' => 'N', ];