From c5c958b58ec255c9b7fe6fab681ed8ae38e089f6 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Mon, 6 Apr 2026 15:38:30 +0700 Subject: [PATCH] fix: support partial PATCH updates across controllers and PatVisit Allow update endpoints to validate only provided fields, avoid overwriting unchanged data, and preserve existing PatDiag when omitted from PatVisit PATCH payloads. --- app/Controllers/Contact/ContactController.php | 30 ++- app/Controllers/LocationController.php | 43 +++-- .../Specimen/ContainerDefController.php | 38 ++-- app/Controllers/Test/TestMapController.php | 27 ++- .../Test/TestMapDetailController.php | 89 +++++---- app/Controllers/Test/TestsController.php | 182 ++++++++++++------ app/Models/PatVisit/PatVisitModel.php | 41 ++-- tests/feature/PatVisit/PatVisitUpdateTest.php | 38 +++- 8 files changed, 328 insertions(+), 160 deletions(-) diff --git a/app/Controllers/Contact/ContactController.php b/app/Controllers/Contact/ContactController.php index 9236fc8..090f2fe 100644 --- a/app/Controllers/Contact/ContactController.php +++ b/app/Controllers/Contact/ContactController.php @@ -6,18 +6,20 @@ use App\Controllers\BaseController; use App\Libraries\ValueSet; use App\Models\Contact\ContactModel; -class ContactController extends BaseController { +class ContactController extends BaseController { use ResponseTrait; - protected $db; - protected $model; - protected $rules; + protected $db; + protected $model; + protected $rules; + protected $patchRules; - public function __construct() { - $this->db = \Config\Database::connect(); - $this->model = new ContactModel(); - $this->rules = [ 'NameFirst' => 'required' ]; - } + public function __construct() { + $this->db = \Config\Database::connect(); + $this->model = new ContactModel(); + $this->rules = [ 'NameFirst' => 'required' ]; + $this->patchRules = [ 'NameFirst' => 'permit_empty' ]; + } public function index() { $ContactName = $this->request->getVar('ContactName'); @@ -84,8 +86,16 @@ class ContactController extends BaseController { 'data' => [] ], 400); } + if (empty($input) || !is_array($input)) { + return $this->failValidationErrors('No data provided for update.'); + } + + $validationInput = array_intersect_key($input, $this->patchRules); + if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) { + return $this->failValidationErrors($this->validator->getErrors()); + } + $input['ContactID'] = (int) $ContactID; - if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); } try { $this->model->saveContact($input); $id = $input['ContactID']; diff --git a/app/Controllers/LocationController.php b/app/Controllers/LocationController.php index c26af65..c43f753 100644 --- a/app/Controllers/LocationController.php +++ b/app/Controllers/LocationController.php @@ -5,19 +5,24 @@ use App\Traits\ResponseTrait; use App\Controllers\BaseController; use App\Models\Location\LocationModel; -class LocationController extends BaseController { - use ResponseTrait; +class LocationController extends BaseController { + use ResponseTrait; + + protected $model; + protected $rules; + protected $patchRules; - protected $model; - protected $rules; - - public function __construct() { - $this->model = new LocationModel(); - $this->rules = [ - 'LocCode' => 'required|max_length[6]', - 'LocFull' => 'required', - ]; - } + public function __construct() { + $this->model = new LocationModel(); + $this->rules = [ + 'LocCode' => 'required|max_length[6]', + 'LocFull' => 'required', + ]; + $this->patchRules = [ + 'LocCode' => 'permit_empty|max_length[6]', + 'LocFull' => 'permit_empty', + ]; + } public function index() { $LocName = $this->request->getVar('LocName'); @@ -59,12 +64,20 @@ class LocationController extends BaseController { 'data' => [] ], 400); } + if (empty($input) || !is_array($input)) { + return $this->failValidationErrors('No data provided for update.'); + } + + $validationInput = array_intersect_key($input, $this->patchRules); + if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) { + return $this->failValidationErrors($this->validator->getErrors()); + } + $input['LocationID'] = (int) $LocationID; try { - if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors( $this->validator->getErrors()); } $result = $this->model->saveLocation($input, true); - return $this->respondCreated([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $result ], 201); - } catch (\Throwable $e) { + return $this->respondCreated([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $result ], 201); + } catch (\Throwable $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } } diff --git a/app/Controllers/Specimen/ContainerDefController.php b/app/Controllers/Specimen/ContainerDefController.php index 5d081a6..5531dd4 100644 --- a/app/Controllers/Specimen/ContainerDefController.php +++ b/app/Controllers/Specimen/ContainerDefController.php @@ -7,21 +7,26 @@ use App\Controllers\BaseController; use App\Libraries\ValueSet; use App\Models\Specimen\ContainerDefModel; -class ContainerDefController extends BaseController { +class ContainerDefController extends BaseController { use ResponseTrait; - protected $db; - protected $model; - protected $rules; + protected $db; + protected $model; + protected $rules; + protected $patchRules; public function __construct() { $this->db = \Config\Database::connect(); - $this->model = new ContainerDefModel(); - $this->rules = [ - 'ConCode' => 'required|max_length[50]', - 'ConName' => 'required|max_length[50]' - ]; - } + $this->model = new ContainerDefModel(); + $this->rules = [ + 'ConCode' => 'required|max_length[50]', + 'ConName' => 'required|max_length[50]' + ]; + $this->patchRules = [ + 'ConCode' => 'permit_empty|max_length[50]', + 'ConName' => 'permit_empty|max_length[50]' + ]; + } public function index() { try { @@ -78,11 +83,20 @@ class ContainerDefController extends BaseController { if (!$ConDefID || !ctype_digit((string) $ConDefID)) { return $this->failValidationErrors('ConDefID is required.'); } + + if (empty($input) || !is_array($input)) { + return $this->failValidationErrors('No data provided for update.'); + } + + $validationInput = array_intersect_key($input, $this->patchRules); + if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) { + return $this->failValidationErrors($this->validator->getErrors()); + } + $input['ConDefID'] = (int) $ConDefID; - if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); } try { $ConDefID = $this->model->update($input['ConDefID'], $input); - return $this->respondCreated([ 'status' => 'success', 'message' => "data $ConDefID updated successfully" ]); + return $this->respondCreated([ 'status' => 'success', 'message' => "data $ConDefID updated successfully" ]); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } diff --git a/app/Controllers/Test/TestMapController.php b/app/Controllers/Test/TestMapController.php index a7fc61b..68081fb 100644 --- a/app/Controllers/Test/TestMapController.php +++ b/app/Controllers/Test/TestMapController.php @@ -10,10 +10,11 @@ use App\Models\Test\TestMapDetailModel; class TestMapController extends BaseController { use ResponseTrait; - protected $db; - protected $rules; - protected $model; - protected $modelDetail; + protected $db; + protected $rules; + protected $patchRules; + protected $model; + protected $modelDetail; public function __construct() { $this->db = \Config\Database::connect(); @@ -23,7 +24,11 @@ class TestMapController extends BaseController { 'HostID' => 'required|integer', 'ClientID' => 'required|integer', ]; - } + $this->patchRules = [ + 'HostID' => 'permit_empty|integer', + 'ClientID' => 'permit_empty|integer', + ]; + } public function index() { $rows = $this->model->getUniqueGroupings(); @@ -70,15 +75,23 @@ class TestMapController extends BaseController { public function update($TestMapID = null) { $input = $this->request->getJSON(true); if (!$TestMapID || !ctype_digit((string) $TestMapID)) { return $this->failValidationErrors('TestMapID is required.'); } + if (empty($input) || !is_array($input)) { + return $this->failValidationErrors('No data provided for update.'); + } $id = (int) $TestMapID; if (isset($input['TestMapID']) && (string) $input['TestMapID'] !== (string) $id) { return $this->failValidationErrors('TestMapID in URL does not match body.'); } + + $validationInput = array_intersect_key($input, $this->patchRules); + if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) { + return $this->failValidationErrors($this->validator->getErrors()); + } + $input['TestMapID'] = $id; - if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors( $this->validator->getErrors() ); } try { $this->model->update($id,$input); - return $this->respondCreated([ 'status' => 'success', 'message' => "data updated successfully", 'data' => $id ]); + return $this->respondCreated([ 'status' => 'success', 'message' => "data updated successfully", 'data' => $id ]); } catch (\Exception $e) { return $this->failServerError('Something went wrong: ' . $e->getMessage()); } diff --git a/app/Controllers/Test/TestMapDetailController.php b/app/Controllers/Test/TestMapDetailController.php index 8a100a3..f698e76 100644 --- a/app/Controllers/Test/TestMapDetailController.php +++ b/app/Controllers/Test/TestMapDetailController.php @@ -9,22 +9,31 @@ use App\Models\Test\TestMapDetailModel; class TestMapDetailController extends BaseController { use ResponseTrait; - protected $db; - protected $rules; - protected $model; + protected $db; + protected $rules; + protected $patchRules; + protected $model; public function __construct() { $this->db = \Config\Database::connect(); $this->model = new TestMapDetailModel; - $this->rules = [ - 'TestMapID' => 'required|integer', - 'HostTestCode' => 'permit_empty|max_length[10]', - 'HostTestName' => 'permit_empty|max_length[100]', - 'ConDefID' => 'permit_empty|integer', - 'ClientTestCode' => 'permit_empty|max_length[10]', - 'ClientTestName' => 'permit_empty|max_length[100]', - ]; - } + $this->rules = [ + 'TestMapID' => 'required|integer', + 'HostTestCode' => 'permit_empty|max_length[10]', + 'HostTestName' => 'permit_empty|max_length[100]', + 'ConDefID' => 'permit_empty|integer', + 'ClientTestCode' => 'permit_empty|max_length[10]', + 'ClientTestName' => 'permit_empty|max_length[100]', + ]; + $this->patchRules = [ + 'TestMapID' => 'permit_empty|integer', + 'HostTestCode' => 'permit_empty|max_length[10]', + 'HostTestName' => 'permit_empty|max_length[100]', + 'ConDefID' => 'permit_empty|integer', + 'ClientTestCode' => 'permit_empty|max_length[10]', + 'ClientTestName' => 'permit_empty|max_length[100]', + ]; + } public function index() { $testMapID = $this->request->getGet('TestMapID'); @@ -94,15 +103,19 @@ class TestMapDetailController extends BaseController { if (!$TestMapDetailID || !ctype_digit((string) $TestMapDetailID)) { return $this->failValidationErrors('TestMapDetailID is required.'); } + if (empty($input) || !is_array($input)) { + return $this->failValidationErrors('No data provided for update.'); + } $id = (int) $TestMapDetailID; if (isset($input['TestMapDetailID']) && (string) $input['TestMapDetailID'] !== (string) $id) { return $this->failValidationErrors('TestMapDetailID in URL does not match body.'); } $input['TestMapDetailID'] = $id; - - if (!$this->validateData($input, $this->rules)) { - return $this->failValidationErrors($this->validator->getErrors()); - } + + $validationInput = array_intersect_key($input, $this->patchRules); + if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) { + return $this->failValidationErrors($this->validator->getErrors()); + } try { $this->model->update($id, $input); @@ -179,7 +192,7 @@ class TestMapDetailController extends BaseController { ], 200); } - public function batchUpdate() { + public function batchUpdate() { $items = $this->request->getJSON(true); if (!is_array($items)) { @@ -189,24 +202,32 @@ class TestMapDetailController extends BaseController { $results = ['success' => [], 'failed' => []]; $this->db->transStart(); - foreach ($items as $index => $item) { - $id = $item['TestMapDetailID'] ?? null; + foreach ($items as $index => $item) { + $id = $item['TestMapDetailID'] ?? null; - if (!$id) { - $results['failed'][] = ['index' => $index, 'error' => 'TestMapDetailID required']; - continue; - } - - if (!$this->validateData($item, $this->rules)) { - $results['failed'][] = ['index' => $index, 'errors' => $this->validator->getErrors()]; - continue; - } - - try { - $this->model->update($id, $item); - $results['success'][] = ['index' => $index, 'TestMapDetailID' => $id]; - } catch (\Exception $e) { - $results['failed'][] = ['index' => $index, 'error' => $e->getMessage()]; + if (!$id) { + $results['failed'][] = ['index' => $index, 'error' => 'TestMapDetailID required']; + continue; + } + + $updateData = $item; + unset($updateData['TestMapDetailID']); + + if ($updateData === []) { + $results['failed'][] = ['index' => $index, 'error' => 'No fields to update']; + continue; + } + + if (!$this->validateData($updateData, $this->patchRules)) { + $results['failed'][] = ['index' => $index, 'errors' => $this->validator->getErrors()]; + continue; + } + + try { + $this->model->update($id, $updateData); + $results['success'][] = ['index' => $index, 'TestMapDetailID' => $id]; + } catch (\Exception $e) { + $results['failed'][] = ['index' => $index, 'error' => $e->getMessage()]; } } diff --git a/app/Controllers/Test/TestsController.php b/app/Controllers/Test/TestsController.php index c2a84d5..05a9704 100644 --- a/app/Controllers/Test/TestsController.php +++ b/app/Controllers/Test/TestsController.php @@ -262,11 +262,11 @@ class TestsController extends BaseController 'StartDate', ]; - foreach ($allowedUpdateFields as $field) { - if (isset($input[$field])) { - $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); @@ -421,24 +421,33 @@ 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' => array_key_exists('Decimal', $data) ? $data['Decimal'] : null, - 'CollReq' => $data['CollReq'] ?? null, - 'Method' => $data['Method'] ?? null, - 'ExpectedTAT' => $data['ExpectedTAT'] ?? null, + $allowedFields = [ + 'DisciplineID', + 'DepartmentID', + 'ResultType', + 'RefType', + 'VSet', + 'ReqQty', + 'ReqQtyUnit', + 'Unit1', + 'Factor', + 'Unit2', + 'Decimal', + 'CollReq', + 'Method', + 'ExpectedTAT', ]; - $this->model->update($testSiteID, $techData); + $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) @@ -461,50 +470,89 @@ class TestsController extends BaseController 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, + $calcData = []; + $fieldMap = [ + 'DisciplineID' => 'DisciplineID', + 'DepartmentID' => 'DepartmentID', + 'Factor' => 'Factor', + 'Unit2' => 'Unit2', + 'Decimal' => 'Decimal', + 'Method' => 'Method', ]; - - if ($action === 'update') { - $exists = $this->modelCal->existsByTestSiteID($testSiteID); - - if ($exists) { - $this->modelCal->update($exists['TestCalID'], $calcData); - } else { - $this->modelCal->insert($calcData); - } - } else { - $this->modelCal->insert($calcData); - } - - if ($action === 'update') { - $this->modelGrp->disableByTestSiteID($testSiteID); - } - + + 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); - - // Validate member IDs before insertion - $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, - ]); - } + + $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 @@ -558,6 +606,14 @@ 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); } diff --git a/app/Models/PatVisit/PatVisitModel.php b/app/Models/PatVisit/PatVisitModel.php index 8ff9231..5740c24 100644 --- a/app/Models/PatVisit/PatVisitModel.php +++ b/app/Models/PatVisit/PatVisitModel.php @@ -107,20 +107,27 @@ class PatVisitModel extends BaseModel { throw new \Exception("Visit not found or has been deleted."); } - $this->where('InternalPVID',$InternalPVID)->set($input)->update(); - - // patdiag - $exist = $modelPD->where('InternalPVID',$InternalPVID)->find(); - if($exist) { - if( !empty($input['PatDiag']) && ( !empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']) ) ) { - $tmp = $modelPD->where('InternalPVID',$InternalPVID)->set($input['PatDiag'])->update(); - } else { $tmp = $modelPD->delete($InternalPVID); } - } else { - if( !empty($input['PatDiag']) && ( !empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']) ) ) { - $input['PatDiag']['InternalPVID'] = $InternalPVID; - $tmp = $modelPD->insert($input['PatDiag']); - } - } + $visitData = array_intersect_key($input, array_flip($this->allowedFields)); + if (!empty($visitData)) { + $this->where('InternalPVID', $InternalPVID)->set($visitData)->update(); + } + + // patdiag + if (array_key_exists('PatDiag', $input)) { + $exist = $modelPD->where('InternalPVID', $InternalPVID)->find(); + if ($exist) { + if (!empty($input['PatDiag']) && (!empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']))) { + $tmp = $modelPD->where('InternalPVID', $InternalPVID)->set($input['PatDiag'])->update(); + } else { + $tmp = $modelPD->delete($InternalPVID); + } + } else { + if (!empty($input['PatDiag']) && (!empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']))) { + $input['PatDiag']['InternalPVID'] = $InternalPVID; + $tmp = $modelPD->insert($input['PatDiag']); + } + } + } if (isset($tmp) && $tmp === false) { $error = $db->error(); throw new \Exception("Failed to update PatDiag record. ". $error['message']); @@ -141,9 +148,9 @@ class PatVisitModel extends BaseModel { return false; } else { $db->transCommit(); - $data = [ "PVID" => $input['PVID'], "InternalPVID" => $InternalPVID ]; - return $data; - } + $data = [ "PVID" => $input['PVID'] ?? $visit['PVID'], "InternalPVID" => $InternalPVID ]; + return $data; + } } catch (\Exception $e) { $this->db->transRollback(); diff --git a/tests/feature/PatVisit/PatVisitUpdateTest.php b/tests/feature/PatVisit/PatVisitUpdateTest.php index ae01b98..54219ab 100644 --- a/tests/feature/PatVisit/PatVisitUpdateTest.php +++ b/tests/feature/PatVisit/PatVisitUpdateTest.php @@ -152,5 +152,39 @@ class PatVisitUpdateTest extends CIUnitTestCase 'message' => 'Invalid or missing ID' ]); } - -} + + public function testPatchWithoutPatDiagKeepsExistingPatDiag(): void + { + $createPayload = [ + 'InternalPID' => $this->createTestPatient(), + 'EpisodeID' => 'KEEP-DIAG', + 'PatDiag' => [ + 'DiagCode' => 'A02', + 'DiagName' => 'Original Diagnosis', + ], + 'PatVisitADT' => [ + 'ADTCode' => 'A01', + 'LocationID' => '1', + ], + ]; + + $createResponse = $this->withBodyFormat('json')->call('post', 'api/patvisit', $createPayload); + $createResponse->assertStatus(201); + + $createJson = json_decode($createResponse->getJSON(), true); + $internalPVID = $createJson['data']['InternalPVID']; + $pvid = $createJson['data']['PVID']; + + $patchResponse = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/' . $internalPVID, [ + 'EpisodeID' => 'KEEP-DIAG-UPDATED', + ]); + $patchResponse->assertStatus(200); + + $showResponse = $this->call('get', $this->endpoint . '/' . $pvid); + $showResponse->assertStatus(200); + + $showJson = json_decode($showResponse->getJSON(), true); + $this->assertEquals('A02', $showJson['data']['DiagCode'] ?? null); + } + +}