From 83278d332a9b4cc628dc661763b9d6c3cd3af5e7 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Thu, 23 Apr 2026 16:24:49 +0700 Subject: [PATCH] Add DepartmentID filter to tests index endpoint - Adds DepartmentID query parameter filter to /api/tests - Filters by COALESCE(testdefsite.DepartmentID, cal.DepartmentID) for calculated tests - Updates TestDefSiteModel::getTestsWithRelations() for backend filtering --- app/Controllers/Test/TestsController.php | 715 ++++++++++++----------- app/Models/Test/TestDefSiteModel.php | 122 ++-- 2 files changed, 421 insertions(+), 416 deletions(-) diff --git a/app/Controllers/Test/TestsController.php b/app/Controllers/Test/TestsController.php index f9ab280..4b9e5a0 100755 --- a/app/Controllers/Test/TestsController.php +++ b/app/Controllers/Test/TestsController.php @@ -2,16 +2,16 @@ namespace App\Controllers\Test; -use App\Controllers\BaseController; -use App\Libraries\TestValidationService; -use App\Libraries\ValueSet; -use App\Traits\PatchValidationTrait; -use App\Traits\ResponseTrait; +use App\Controllers\BaseController; +use App\Libraries\TestValidationService; +use App\Libraries\ValueSet; +use App\Traits\PatchValidationTrait; +use App\Traits\ResponseTrait; -class TestsController extends BaseController -{ - use ResponseTrait; - use PatchValidationTrait; +class TestsController extends BaseController +{ + use ResponseTrait; + use PatchValidationTrait; protected $model; protected $modelCal; @@ -32,24 +32,25 @@ 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', - ]; + $this->rules = [ + 'TestSiteCode' => 'required', + 'TestSiteName' => 'required', + 'TestType' => 'required', + ]; } public function index() { $search = $this->request->getGet('search'); - $filters = [ - 'SiteID' => $this->request->getGet('SiteID'), - 'TestType' => $this->request->getGet('TestType'), - 'isVisibleScr' => $this->request->getGet('isVisibleScr'), - 'isVisibleRpt' => $this->request->getGet('isVisibleRpt'), + $filters = [ + 'SiteID' => $this->request->getGet('SiteID'), + 'TestType' => $this->request->getGet('TestType'), + 'isVisibleScr' => $this->request->getGet('isVisibleScr'), + 'isVisibleRpt' => $this->request->getGet('isVisibleRpt'), 'TestSiteName' => $this->request->getGet('TestSiteName'), 'TestSiteCode' => $this->request->getGet('TestSiteCode'), + 'DepartmentID' => $this->request->getGet('DepartmentID'), 'search' => $search, ]; @@ -92,36 +93,36 @@ class TestsController extends BaseController $typeCode = $row['TestType'] ?? ''; - if ($typeCode === 'CALC') { - $row['testdefcal'] = $this->modelCal->getByTestSiteID($id); - $row['testdefgrp'] = [ - 'members' => $this->modelGrp->getGroupMembers($id), - ]; - } elseif ($typeCode === 'GROUP') { - $row['testdefgrp'] = [ - 'members' => $this->modelGrp->getGroupMembers($id), - ]; - } elseif ($typeCode !== 'TITLE') { - $refType = $row['RefType'] ?? ''; - $resultType = $row['ResultType'] ?? ''; - - if (TestValidationService::usesRefNum($resultType, $refType)) { - $row['refnum'] = $this->modelRefNum->getFormattedByTestSiteID($id); - } - - if (TestValidationService::usesRefTxt($resultType, $refType)) { - $row['reftxt'] = $this->modelRefTxt->getFormattedByTestSiteID($id); - } - } - - // Keep /api/test payload focused on test definition fields. - unset($row['testmap']); - - return $this->respond([ - 'status' => 'success', - 'message' => 'Data fetched successfully', - 'data' => $row, - ], 200); + if ($typeCode === 'CALC') { + $row['testdefcal'] = $this->modelCal->getByTestSiteID($id); + $row['testdefgrp'] = [ + 'members' => $this->modelGrp->getGroupMembers($id), + ]; + } elseif ($typeCode === 'GROUP') { + $row['testdefgrp'] = [ + 'members' => $this->modelGrp->getGroupMembers($id), + ]; + } elseif ($typeCode !== 'TITLE') { + $refType = $row['RefType'] ?? ''; + $resultType = $row['ResultType'] ?? ''; + + if (TestValidationService::usesRefNum($resultType, $refType)) { + $row['refnum'] = $this->modelRefNum->getFormattedByTestSiteID($id); + } + + if (TestValidationService::usesRefTxt($resultType, $refType)) { + $row['reftxt'] = $this->modelRefTxt->getFormattedByTestSiteID($id); + } + } + + // Keep /api/test payload focused on test definition fields. + unset($row['testmap']); + + return $this->respond([ + 'status' => 'success', + 'message' => 'Data fetched successfully', + 'data' => $row, + ], 200); } public function create() @@ -156,50 +157,50 @@ class TestsController extends BaseController $db->transStart(); try { - $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, - 'isCountStat' => $input['isCountStat'] ?? 1, - 'isRequestable' => $input['isRequestable'] ?? 1, + $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, + 'isCountStat' => $input['isCountStat'] ?? 1, + 'isRequestable' => $input['isRequestable'] ?? 1, 'StartDate' => $input['StartDate'] ?? date('Y-m-d H:i:s'), ]; - $id = $this->model->insert($testSiteData); - if (!$id) { - $dbError = $db->error(); - log_message('error', 'Test insert failed: ' . json_encode($dbError, JSON_UNESCAPED_SLASHES)); - $message = $dbError['message'] ?? 'Failed to insert main test definition'; - throw new \Exception('Failed to insert main test definition: ' . $message); - } - - $this->handleDetails($id, $input, 'insert'); + $id = $this->model->insert($testSiteData); + if (!$id) { + $dbError = $db->error(); + log_message('error', 'Test insert failed: ' . json_encode($dbError, JSON_UNESCAPED_SLASHES)); + $message = $dbError['message'] ?? 'Failed to insert main test definition'; + throw new \Exception('Failed to insert main test definition: ' . $message); + } + + $this->handleDetails($id, $input, 'insert'); $db->transComplete(); - if ($db->transStatus() === false) { - $dbError = $db->error(); - $lastQuery = $db->showLastQuery(); - log_message('error', 'TestController transaction failed: ' . json_encode([ - 'error' => $dbError, - 'last_query' => $lastQuery, - ], JSON_UNESCAPED_SLASHES)); - return $this->failServerError('Transaction failed'); - } + if ($db->transStatus() === false) { + $dbError = $db->error(); + $lastQuery = $db->showLastQuery(); + log_message('error', 'TestController transaction failed: ' . json_encode([ + 'error' => $dbError, + 'last_query' => $lastQuery, + ], JSON_UNESCAPED_SLASHES)); + return $this->failServerError('Transaction failed'); + } - return $this->respondCreated([ - 'status' => 'success', - 'message' => 'Test created successfully', - 'data' => ['TestSiteId' => $id], - ]); + return $this->respondCreated([ + 'status' => 'success', + 'message' => 'Test created successfully', + 'data' => ['TestSiteId' => $id], + ]); } catch (\Exception $e) { $db->transRollback(); @@ -207,30 +208,30 @@ class TestsController extends BaseController } } - public function update($id = null) - { - $input = $this->requirePatchPayload($this->request->getJSON(true)); - if ($input === null) { - return; - } - - if (!$id && isset($input['TestSiteID'])) { - $id = $input['TestSiteID']; - } - - $id = $this->requirePatchId($id, 'TestSiteID'); - if ($id === null) { - return; - } - - $existing = $this->model->find($id); - if (!$existing) { - return $this->respond([ - 'status' => 'failed', - 'message' => 'Test not found', - 'data' => [] - ], 404); - } + public function update($id = null) + { + $input = $this->requirePatchPayload($this->request->getJSON(true)); + if ($input === null) { + return; + } + + if (!$id && isset($input['TestSiteID'])) { + $id = $input['TestSiteID']; + } + + $id = $this->requirePatchId($id, 'TestSiteID'); + if ($id === null) { + return; + } + + $existing = $this->model->find($id); + if (!$existing) { + return $this->respond([ + 'status' => 'failed', + 'message' => 'Test not found', + 'data' => [] + ], 404); + } $testType = $input['TestType'] ?? $existing['TestType'] ?? ''; $details = $input['details'] ?? $input; @@ -266,18 +267,18 @@ class TestsController extends BaseController 'SeqRpt', 'IndentLeft', 'FontStyle', - 'isVisibleScr', - 'isVisibleRpt', - 'isCountStat', - 'isRequestable', - 'StartDate', - ]; + 'isVisibleScr', + 'isVisibleRpt', + 'isCountStat', + 'isRequestable', + 'StartDate', + ]; - foreach ($allowedUpdateFields as $field) { - if (array_key_exists($field, $input)) { - $testSiteData[$field] = $input[$field]; - } - } + foreach ($allowedUpdateFields as $field) { + if (array_key_exists($field, $input)) { + $testSiteData[$field] = $input[$field]; + } + } if (!empty($testSiteData)) { $this->model->update($id, $testSiteData); @@ -389,9 +390,9 @@ class TestsController extends BaseController $typeCode = $testTypeID; - $details = $input['details'] ?? $input; - $details['TestSiteID'] = $testSiteID; - $details['SiteID'] = array_key_exists('SiteID', $input) ? $input['SiteID'] : null; + $details = $input['details'] ?? $input; + $details['TestSiteID'] = $testSiteID; + $details['SiteID'] = array_key_exists('SiteID', $input) ? $input['SiteID'] : null; switch ($typeCode) { case 'CALC': @@ -404,8 +405,8 @@ class TestsController extends BaseController break; - case 'TITLE': - break; + case 'TITLE': + break; case 'TEST': case 'PARAM': @@ -416,53 +417,53 @@ 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, 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); - } - } + 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; } - } + } - private function saveTechDetails($testSiteID, $data, $action, $typeCode) - { - $allowedFields = [ - 'DisciplineID', - 'DepartmentID', - 'ResultType', - 'RefType', - 'VSet', - 'ReqQty', - 'ReqQtyUnit', - 'Unit1', - 'Factor', - 'Unit2', - 'Decimal', - 'CollReq', - 'Method', - 'ExpectedTAT', - ]; - - $techData = []; - foreach ($allowedFields as $field) { - if (array_key_exists($field, $data)) { - $techData[$field] = $data[$field]; - } - } - - if ($techData !== []) { - $this->model->update($testSiteID, $techData); - } - } - - private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID) - { + private function saveTechDetails($testSiteID, $data, $action, $typeCode) + { + $allowedFields = [ + 'DisciplineID', + 'DepartmentID', + 'ResultType', + 'RefType', + 'VSet', + 'ReqQty', + 'ReqQtyUnit', + 'Unit1', + 'Factor', + 'Unit2', + 'Decimal', + 'CollReq', + 'Method', + 'ExpectedTAT', + ]; + + $techData = []; + foreach ($allowedFields as $field) { + if (array_key_exists($field, $data)) { + $techData[$field] = $data[$field]; + } + } + + if ($techData !== []) { + $this->model->update($testSiteID, $techData); + } + } + + private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID) + { if ($action === 'update') { $this->modelRefNum->disableByTestSiteID($testSiteID); } @@ -479,104 +480,104 @@ class TestsController extends BaseController $this->modelRefTxt->batchInsert($testSiteID, $siteID, $ranges); } - private function saveCalcDetails($testSiteID, $data, $input, $action) - { - $calcData = []; - $fieldMap = [ - 'DisciplineID' => 'DisciplineID', - 'DepartmentID' => 'DepartmentID', - 'Factor' => 'Factor', - 'Unit2' => 'Unit2', - 'Decimal' => 'Decimal', - 'Method' => 'Method', - ]; - - foreach ($fieldMap as $source => $target) { - if (array_key_exists($source, $data)) { - $calcData[$target] = $data[$source]; - } - } - - if (array_key_exists('FormulaCode', $data) || array_key_exists('Formula', $data)) { - $calcData['FormulaCode'] = $data['FormulaCode'] ?? $data['Formula'] ?? null; - } - - if (array_key_exists('RefType', $data)) { - $calcData['RefType'] = $data['RefType']; - } - - if (array_key_exists('Unit1', $data) || array_key_exists('ResultUnit', $data)) { - $calcData['Unit1'] = $data['Unit1'] ?? $data['ResultUnit'] ?? null; - } - - $hasMemberPayload = isset($input['testdefgrp']) - && is_array($input['testdefgrp']) - && array_key_exists('members', $input['testdefgrp']); - - if ($action === 'insert' && !array_key_exists('ResultType', $calcData)) { - $calcData['ResultType'] = 'NMRIC'; - } - - if ($action === 'insert' && !array_key_exists('RefType', $calcData)) { - $calcData['RefType'] = 'RANGE'; - } - - if ($calcData !== []) { - $calcData['TestSiteID'] = $testSiteID; - if ($action === 'update') { - $exists = $this->modelCal->existsByTestSiteID($testSiteID); - - if ($exists) { - unset($calcData['TestSiteID']); - $this->modelCal->update($exists['TestCalID'], $calcData); - } else { - if (!array_key_exists('ResultType', $calcData)) { - $calcData['ResultType'] = 'NMRIC'; - } - if (!array_key_exists('RefType', $calcData)) { - $calcData['RefType'] = 'RANGE'; - } - $this->modelCal->insert($calcData); - } - } else { - $this->modelCal->insert($calcData); - } - } - - if ($action === 'update' && !$hasMemberPayload) { - return; - } - - if ($action === 'update') { - $this->modelGrp->disableByTestSiteID($testSiteID); - } - - $memberIDs = $this->resolveMemberIDs($input); - - $validation = $this->validateMemberIDs($memberIDs); - if (!$validation['valid']) { - throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.'); - } - - foreach ($memberIDs as $memberID) { - $this->modelGrp->insert([ - 'TestSiteID' => $testSiteID, - 'Member' => $memberID, - ]); - } + private function saveCalcDetails($testSiteID, $data, $input, $action) + { + $calcData = []; + $fieldMap = [ + 'DisciplineID' => 'DisciplineID', + 'DepartmentID' => 'DepartmentID', + 'Factor' => 'Factor', + 'Unit2' => 'Unit2', + 'Decimal' => 'Decimal', + 'Method' => 'Method', + ]; + + foreach ($fieldMap as $source => $target) { + if (array_key_exists($source, $data)) { + $calcData[$target] = $data[$source]; + } + } + + if (array_key_exists('FormulaCode', $data) || array_key_exists('Formula', $data)) { + $calcData['FormulaCode'] = $data['FormulaCode'] ?? $data['Formula'] ?? null; + } + + if (array_key_exists('RefType', $data)) { + $calcData['RefType'] = $data['RefType']; + } + + if (array_key_exists('Unit1', $data) || array_key_exists('ResultUnit', $data)) { + $calcData['Unit1'] = $data['Unit1'] ?? $data['ResultUnit'] ?? null; + } + + $hasMemberPayload = isset($input['testdefgrp']) + && is_array($input['testdefgrp']) + && array_key_exists('members', $input['testdefgrp']); + + if ($action === 'insert' && !array_key_exists('ResultType', $calcData)) { + $calcData['ResultType'] = 'NMRIC'; + } + + if ($action === 'insert' && !array_key_exists('RefType', $calcData)) { + $calcData['RefType'] = 'RANGE'; + } + + if ($calcData !== []) { + $calcData['TestSiteID'] = $testSiteID; + if ($action === 'update') { + $exists = $this->modelCal->existsByTestSiteID($testSiteID); + + if ($exists) { + unset($calcData['TestSiteID']); + $this->modelCal->update($exists['TestCalID'], $calcData); + } else { + if (!array_key_exists('ResultType', $calcData)) { + $calcData['ResultType'] = 'NMRIC'; + } + if (!array_key_exists('RefType', $calcData)) { + $calcData['RefType'] = 'RANGE'; + } + $this->modelCal->insert($calcData); + } + } else { + $this->modelCal->insert($calcData); + } + } + + if ($action === 'update' && !$hasMemberPayload) { + return; + } + + if ($action === 'update') { + $this->modelGrp->disableByTestSiteID($testSiteID); + } + + $memberIDs = $this->resolveMemberIDs($input); + + $validation = $this->validateMemberIDs($memberIDs); + if (!$validation['valid']) { + throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.'); + } + + foreach ($memberIDs as $memberID) { + $this->modelGrp->insert([ + 'TestSiteID' => $testSiteID, + 'Member' => $memberID, + ]); + } } - private function resolveMemberIDs(array $input): array - { - $memberIDs = []; - - $rawMembers = $input['testdefgrp']['members'] ?? []; - if (is_array($rawMembers)) { - foreach ($rawMembers as $member) { - if (is_array($member)) { - $rawID = $member['TestSiteID'] ?? null; - } else { - $rawID = is_numeric($member) ? $member : null; + private function resolveMemberIDs(array $input): array + { + $memberIDs = []; + + $rawMembers = $input['testdefgrp']['members'] ?? []; + if (is_array($rawMembers)) { + foreach ($rawMembers as $member) { + if (is_array($member)) { + $rawID = $member['TestSiteID'] ?? null; + } else { + $rawID = is_numeric($member) ? $member : null; } if ($rawID !== null && is_numeric($rawID)) { @@ -615,21 +616,21 @@ class TestsController extends BaseController ]; } - private function saveGroupDetails($testSiteID, $data, $input, $action) - { - $hasMemberPayload = isset($input['testdefgrp']) - && is_array($input['testdefgrp']) - && array_key_exists('members', $input['testdefgrp']); - - if ($action === 'update' && !$hasMemberPayload) { - return; - } - - if ($action === 'update') { - $this->modelGrp->disableByTestSiteID($testSiteID); - } - - $memberIDs = $this->resolveMemberIDs($input); + private function saveGroupDetails($testSiteID, $data, $input, $action) + { + $hasMemberPayload = isset($input['testdefgrp']) + && is_array($input['testdefgrp']) + && array_key_exists('members', $input['testdefgrp']); + + if ($action === 'update' && !$hasMemberPayload) { + return; + } + + if ($action === 'update') { + $this->modelGrp->disableByTestSiteID($testSiteID); + } + + $memberIDs = $this->resolveMemberIDs($input); // Validate member IDs before insertion $validation = $this->validateMemberIDs($memberIDs); @@ -645,9 +646,9 @@ class TestsController extends BaseController } } - private function saveTestMap($testSiteID, $testSiteCode, $mappings, $action) - { - if ($action === 'update' && $testSiteCode) { + private function saveTestMap($testSiteID, $testSiteCode, $mappings, $action) + { + if ($action === 'update' && $testSiteCode) { // Find existing mappings by test code through testmapdetail $existingMaps = $this->modelMap->getMappingsByTestCode($testSiteCode); @@ -658,78 +659,78 @@ class TestsController extends BaseController // Soft delete the testmap headers foreach ($existingMaps as $existingMap) { $this->modelMap->update($existingMap['TestMapID'], ['EndDate' => date('Y-m-d H:i:s')]); - } - } - - foreach ($this->normalizeTestMapPayload($mappings) as $map) { - $mapData = [ - 'HostType' => $map['HostType'] ?? null, - 'HostID' => $map['HostID'] ?? null, - 'ClientType' => $map['ClientType'] ?? null, - 'ClientID' => $map['ClientID'] ?? null, - ]; - - $testMapID = $this->modelMap->insert($mapData); - if (!$testMapID) { - continue; - } - - foreach ($this->extractTestMapDetails($map) as $detail) { - $detailData = [ - 'TestMapID' => $testMapID, - 'HostTestCode' => $detail['HostTestCode'] ?? null, - 'HostTestName' => $detail['HostTestName'] ?? null, - 'ConDefID' => $detail['ConDefID'] ?? null, - 'ClientTestCode' => $detail['ClientTestCode'] ?? null, - 'ClientTestName' => $detail['ClientTestName'] ?? null, - ]; - $this->modelMapDetail->insert($detailData); - } - } - } - - private function normalizeTestMapPayload($mappings): array - { - if (!is_array($mappings)) { - return []; - } - - if ($this->isAssoc($mappings)) { - return [$mappings]; - } - - return array_values(array_filter($mappings, static fn ($map) => is_array($map))); - } - - private function extractTestMapDetails(array $map): array - { - if (isset($map['details']) && is_array($map['details'])) { - return array_values(array_filter($map['details'], static fn ($detail) => is_array($detail))); - } - - $flatDetail = [ - 'HostTestCode' => $map['HostTestCode'] ?? null, - 'HostTestName' => $map['HostTestName'] ?? null, - 'ConDefID' => $map['ConDefID'] ?? null, - 'ClientTestCode' => $map['ClientTestCode'] ?? null, - 'ClientTestName' => $map['ClientTestName'] ?? null, - ]; - - foreach ($flatDetail as $value) { - if ($value !== null && $value !== '') { - return [$flatDetail]; - } - } - - return []; - } - - private function isAssoc(array $array): bool - { - if ($array === []) { - return false; - } - - return array_keys($array) !== range(0, count($array) - 1); - } -} + } + } + + foreach ($this->normalizeTestMapPayload($mappings) as $map) { + $mapData = [ + 'HostType' => $map['HostType'] ?? null, + 'HostID' => $map['HostID'] ?? null, + 'ClientType' => $map['ClientType'] ?? null, + 'ClientID' => $map['ClientID'] ?? null, + ]; + + $testMapID = $this->modelMap->insert($mapData); + if (!$testMapID) { + continue; + } + + foreach ($this->extractTestMapDetails($map) as $detail) { + $detailData = [ + 'TestMapID' => $testMapID, + 'HostTestCode' => $detail['HostTestCode'] ?? null, + 'HostTestName' => $detail['HostTestName'] ?? null, + 'ConDefID' => $detail['ConDefID'] ?? null, + 'ClientTestCode' => $detail['ClientTestCode'] ?? null, + 'ClientTestName' => $detail['ClientTestName'] ?? null, + ]; + $this->modelMapDetail->insert($detailData); + } + } + } + + private function normalizeTestMapPayload($mappings): array + { + if (!is_array($mappings)) { + return []; + } + + if ($this->isAssoc($mappings)) { + return [$mappings]; + } + + return array_values(array_filter($mappings, static fn ($map) => is_array($map))); + } + + private function extractTestMapDetails(array $map): array + { + if (isset($map['details']) && is_array($map['details'])) { + return array_values(array_filter($map['details'], static fn ($detail) => is_array($detail))); + } + + $flatDetail = [ + 'HostTestCode' => $map['HostTestCode'] ?? null, + 'HostTestName' => $map['HostTestName'] ?? null, + 'ConDefID' => $map['ConDefID'] ?? null, + 'ClientTestCode' => $map['ClientTestCode'] ?? null, + 'ClientTestName' => $map['ClientTestName'] ?? null, + ]; + + foreach ($flatDetail as $value) { + if ($value !== null && $value !== '') { + return [$flatDetail]; + } + } + + return []; + } + + private function isAssoc(array $array): bool + { + if ($array === []) { + return false; + } + + return array_keys($array) !== range(0, count($array) - 1); + } +} diff --git a/app/Models/Test/TestDefSiteModel.php b/app/Models/Test/TestDefSiteModel.php index 532fc26..69f8407 100755 --- a/app/Models/Test/TestDefSiteModel.php +++ b/app/Models/Test/TestDefSiteModel.php @@ -16,8 +16,8 @@ class TestDefSiteModel extends BaseModel { 'ResultType', 'RefType', 'Vset', 'Unit1', 'Factor', 'Unit2', 'Decimal', 'ReqQty', 'ReqQtyUnit', 'CollReq', 'Method', 'ExpectedTAT', - 'SeqScr', 'SeqRpt', 'IndentLeft', 'FontStyle', 'isVisibleScr', 'isVisibleRpt', - 'isCountStat', 'Level', 'isRequestable', + 'SeqScr', 'SeqRpt', 'IndentLeft', 'FontStyle', 'isVisibleScr', 'isVisibleRpt', + 'isCountStat', 'Level', 'isRequestable', 'CreateDate', 'StartDate','EndDate' ]; @@ -28,9 +28,9 @@ class TestDefSiteModel extends BaseModel { protected $deletedField = "EndDate"; public function getTests($siteId = null, $testType = null, $visibleScr = null, $visibleRpt = null, $search = null, $page = 1, $perPage = 20) { - $builder = $this->select("testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, - testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.isVisibleScr, testdefsite.isVisibleRpt, - testdefsite.isCountStat, testdefsite.StartDate, testdefsite.EndDate") + $builder = $this->select("testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, + testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.isVisibleScr, testdefsite.isVisibleRpt, + testdefsite.isCountStat, testdefsite.StartDate, testdefsite.EndDate") ->where('testdefsite.EndDate IS NULL'); if ($siteId) { @@ -41,13 +41,13 @@ class TestDefSiteModel extends BaseModel { $builder->where('testdefsite.TestType', $testType); } - if ($visibleScr !== null) { - $builder->where('testdefsite.isVisibleScr', $visibleScr); - } - - if ($visibleRpt !== null) { - $builder->where('testdefsite.isVisibleRpt', $visibleRpt); - } + if ($visibleScr !== null) { + $builder->where('testdefsite.isVisibleScr', $visibleScr); + } + + if ($visibleRpt !== null) { + $builder->where('testdefsite.isVisibleRpt', $visibleRpt); + } if ($search) { $builder->groupStart() @@ -83,10 +83,10 @@ class TestDefSiteModel extends BaseModel { */ public function getTestsWithRelations($filters = []) { $builder = $this->db->table('testdefsite') - ->select( - "testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, - testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.isVisibleScr, testdefsite.isVisibleRpt, - testdefsite.isCountStat, testdefsite.StartDate, testdefsite.EndDate, + ->select( + "testdefsite.TestSiteID, testdefsite.TestSiteCode, testdefsite.TestSiteName, testdefsite.TestType, + testdefsite.SeqScr, testdefsite.SeqRpt, testdefsite.isVisibleScr, testdefsite.isVisibleRpt, + testdefsite.isCountStat, testdefsite.StartDate, testdefsite.EndDate, COALESCE(testdefsite.DisciplineID, cal.DisciplineID) as DisciplineID, COALESCE(testdefsite.DepartmentID, cal.DepartmentID) as DepartmentID, d.DisciplineName, dept.DepartmentName" @@ -104,13 +104,13 @@ class TestDefSiteModel extends BaseModel { $builder->where('testdefsite.TestType', $filters['TestType']); } - if (isset($filters['isVisibleScr'])) { - $builder->where('testdefsite.isVisibleScr', $filters['isVisibleScr']); - } - - if (isset($filters['isVisibleRpt'])) { - $builder->where('testdefsite.isVisibleRpt', $filters['isVisibleRpt']); - } + if (isset($filters['isVisibleScr'])) { + $builder->where('testdefsite.isVisibleScr', $filters['isVisibleScr']); + } + + if (isset($filters['isVisibleRpt'])) { + $builder->where('testdefsite.isVisibleRpt', $filters['isVisibleRpt']); + } if (!empty($filters['TestSiteName'])) { $builder->like('testdefsite.TestSiteName', $filters['TestSiteName']); @@ -120,6 +120,10 @@ class TestDefSiteModel extends BaseModel { $builder->like('testdefsite.TestSiteCode', $filters['TestSiteCode']); } + if (!empty($filters['DepartmentID'])) { + $builder->where('COALESCE(testdefsite.DepartmentID, cal.DepartmentID)', $filters['DepartmentID']); + } + if (!empty($filters['search'])) { $builder->groupStart() ->like('testdefsite.TestSiteCode', $filters['search']) @@ -145,32 +149,32 @@ class TestDefSiteModel extends BaseModel { $typeCode = $row['TestType'] ?? ''; - if (TestValidationService::isCalc($typeCode)) { - $row['testdefcal'] = $db->table('testdefcal') - ->select('testdefcal.*, d.DisciplineName, dept.DepartmentName') - ->join('discipline d', 'd.DisciplineID=testdefcal.DisciplineID', 'left') - ->join('department dept', 'dept.DepartmentID=testdefcal.DepartmentID', 'left') - ->where('testdefcal.TestSiteID', $TestSiteID) - ->where('testdefcal.EndDate IS NULL') - ->get()->getResultArray(); - - } elseif (TestValidationService::isGroup($typeCode)) { - $testDefGrpModel = new \App\Models\Test\TestDefGrpModel(); - $row['testdefgrp'] = $testDefGrpModel->getGroupMembers($TestSiteID); - - } elseif (TestValidationService::isTitle($typeCode)) { - - } elseif (TestValidationService::isTechnicalTest($typeCode)) { - // Technical details are now flattened into the main row - if ($row['DisciplineID']) { - $discipline = $db->table('discipline')->where('DisciplineID', $row['DisciplineID'])->get()->getRowArray(); - $row['DisciplineName'] = $discipline['DisciplineName'] ?? null; + if (TestValidationService::isCalc($typeCode)) { + $row['testdefcal'] = $db->table('testdefcal') + ->select('testdefcal.*, d.DisciplineName, dept.DepartmentName') + ->join('discipline d', 'd.DisciplineID=testdefcal.DisciplineID', 'left') + ->join('department dept', 'dept.DepartmentID=testdefcal.DepartmentID', 'left') + ->where('testdefcal.TestSiteID', $TestSiteID) + ->where('testdefcal.EndDate IS NULL') + ->get()->getResultArray(); + + } elseif (TestValidationService::isGroup($typeCode)) { + $testDefGrpModel = new \App\Models\Test\TestDefGrpModel(); + $row['testdefgrp'] = $testDefGrpModel->getGroupMembers($TestSiteID); + + } elseif (TestValidationService::isTitle($typeCode)) { + + } elseif (TestValidationService::isTechnicalTest($typeCode)) { + // Technical details are now flattened into the main row + if ($row['DisciplineID']) { + $discipline = $db->table('discipline')->where('DisciplineID', $row['DisciplineID'])->get()->getRowArray(); + $row['DisciplineName'] = $discipline['DisciplineName'] ?? null; } - if ($row['DepartmentID']) { - $department = $db->table('department')->where('DepartmentID', $row['DepartmentID'])->get()->getRowArray(); - $row['DepartmentName'] = $department['DepartmentName'] ?? null; - } - } + if ($row['DepartmentID']) { + $department = $db->table('department')->where('DepartmentID', $row['DepartmentID'])->get()->getRowArray(); + $row['DepartmentName'] = $department['DepartmentName'] ?? null; + } + } return $row; } @@ -217,16 +221,16 @@ class TestDefSiteModel extends BaseModel { * @param int $id * @return array|null */ - public function getTestById($id) - { - $row = $this->db->table('testdefsite') - ->select('testdefsite.*, d.DisciplineName, dept.DepartmentName') - ->join('discipline d', 'd.DisciplineID = testdefsite.DisciplineID', 'left') - ->join('department dept', 'dept.DepartmentID = testdefsite.DepartmentID', 'left') - ->where('testdefsite.TestSiteID', $id) - ->where('testdefsite.EndDate IS NULL') - ->get() - ->getRowArray(); + public function getTestById($id) + { + $row = $this->db->table('testdefsite') + ->select('testdefsite.*, d.DisciplineName, dept.DepartmentName') + ->join('discipline d', 'd.DisciplineID = testdefsite.DisciplineID', 'left') + ->join('department dept', 'dept.DepartmentID = testdefsite.DepartmentID', 'left') + ->where('testdefsite.TestSiteID', $id) + ->where('testdefsite.EndDate IS NULL') + ->get() + ->getRowArray(); if (!$row) { return null; @@ -239,4 +243,4 @@ class TestDefSiteModel extends BaseModel { return $rows[0]; } -} +}