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.
This commit is contained in:
parent
e99a60fe93
commit
c5c958b58e
@ -6,18 +6,20 @@ use App\Controllers\BaseController;
|
|||||||
use App\Libraries\ValueSet;
|
use App\Libraries\ValueSet;
|
||||||
use App\Models\Contact\ContactModel;
|
use App\Models\Contact\ContactModel;
|
||||||
|
|
||||||
class ContactController extends BaseController {
|
class ContactController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $model;
|
protected $model;
|
||||||
protected $rules;
|
protected $rules;
|
||||||
|
protected $patchRules;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new ContactModel();
|
$this->model = new ContactModel();
|
||||||
$this->rules = [ 'NameFirst' => 'required' ];
|
$this->rules = [ 'NameFirst' => 'required' ];
|
||||||
}
|
$this->patchRules = [ 'NameFirst' => 'permit_empty' ];
|
||||||
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$ContactName = $this->request->getVar('ContactName');
|
$ContactName = $this->request->getVar('ContactName');
|
||||||
@ -84,8 +86,16 @@ class ContactController extends BaseController {
|
|||||||
'data' => []
|
'data' => []
|
||||||
], 400);
|
], 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;
|
$input['ContactID'] = (int) $ContactID;
|
||||||
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
|
|
||||||
try {
|
try {
|
||||||
$this->model->saveContact($input);
|
$this->model->saveContact($input);
|
||||||
$id = $input['ContactID'];
|
$id = $input['ContactID'];
|
||||||
|
|||||||
@ -5,19 +5,24 @@ use App\Traits\ResponseTrait;
|
|||||||
use App\Controllers\BaseController;
|
use App\Controllers\BaseController;
|
||||||
use App\Models\Location\LocationModel;
|
use App\Models\Location\LocationModel;
|
||||||
|
|
||||||
class LocationController extends BaseController {
|
class LocationController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
|
protected $model;
|
||||||
|
protected $rules;
|
||||||
|
protected $patchRules;
|
||||||
|
|
||||||
protected $model;
|
public function __construct() {
|
||||||
protected $rules;
|
$this->model = new LocationModel();
|
||||||
|
$this->rules = [
|
||||||
public function __construct() {
|
'LocCode' => 'required|max_length[6]',
|
||||||
$this->model = new LocationModel();
|
'LocFull' => 'required',
|
||||||
$this->rules = [
|
];
|
||||||
'LocCode' => 'required|max_length[6]',
|
$this->patchRules = [
|
||||||
'LocFull' => 'required',
|
'LocCode' => 'permit_empty|max_length[6]',
|
||||||
];
|
'LocFull' => 'permit_empty',
|
||||||
}
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$LocName = $this->request->getVar('LocName');
|
$LocName = $this->request->getVar('LocName');
|
||||||
@ -59,12 +64,20 @@ class LocationController extends BaseController {
|
|||||||
'data' => []
|
'data' => []
|
||||||
], 400);
|
], 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;
|
$input['LocationID'] = (int) $LocationID;
|
||||||
try {
|
try {
|
||||||
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors( $this->validator->getErrors()); }
|
|
||||||
$result = $this->model->saveLocation($input, true);
|
$result = $this->model->saveLocation($input, true);
|
||||||
return $this->respondCreated([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $result ], 201);
|
return $this->respondCreated([ 'status' => 'success', 'message' => 'data updated successfully', 'data' => $result ], 201);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,21 +7,26 @@ use App\Controllers\BaseController;
|
|||||||
use App\Libraries\ValueSet;
|
use App\Libraries\ValueSet;
|
||||||
use App\Models\Specimen\ContainerDefModel;
|
use App\Models\Specimen\ContainerDefModel;
|
||||||
|
|
||||||
class ContainerDefController extends BaseController {
|
class ContainerDefController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $model;
|
protected $model;
|
||||||
protected $rules;
|
protected $rules;
|
||||||
|
protected $patchRules;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new ContainerDefModel();
|
$this->model = new ContainerDefModel();
|
||||||
$this->rules = [
|
$this->rules = [
|
||||||
'ConCode' => 'required|max_length[50]',
|
'ConCode' => 'required|max_length[50]',
|
||||||
'ConName' => '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() {
|
public function index() {
|
||||||
try {
|
try {
|
||||||
@ -78,11 +83,20 @@ class ContainerDefController extends BaseController {
|
|||||||
if (!$ConDefID || !ctype_digit((string) $ConDefID)) {
|
if (!$ConDefID || !ctype_digit((string) $ConDefID)) {
|
||||||
return $this->failValidationErrors('ConDefID is required.');
|
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;
|
$input['ConDefID'] = (int) $ConDefID;
|
||||||
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors($this->validator->getErrors()); }
|
|
||||||
try {
|
try {
|
||||||
$ConDefID = $this->model->update($input['ConDefID'], $input);
|
$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) {
|
} catch (\Exception $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,10 +10,11 @@ use App\Models\Test\TestMapDetailModel;
|
|||||||
class TestMapController extends BaseController {
|
class TestMapController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $rules;
|
protected $rules;
|
||||||
protected $model;
|
protected $patchRules;
|
||||||
protected $modelDetail;
|
protected $model;
|
||||||
|
protected $modelDetail;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
@ -23,7 +24,11 @@ class TestMapController extends BaseController {
|
|||||||
'HostID' => 'required|integer',
|
'HostID' => 'required|integer',
|
||||||
'ClientID' => 'required|integer',
|
'ClientID' => 'required|integer',
|
||||||
];
|
];
|
||||||
}
|
$this->patchRules = [
|
||||||
|
'HostID' => 'permit_empty|integer',
|
||||||
|
'ClientID' => 'permit_empty|integer',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
$rows = $this->model->getUniqueGroupings();
|
$rows = $this->model->getUniqueGroupings();
|
||||||
@ -70,15 +75,23 @@ class TestMapController extends BaseController {
|
|||||||
public function update($TestMapID = null) {
|
public function update($TestMapID = null) {
|
||||||
$input = $this->request->getJSON(true);
|
$input = $this->request->getJSON(true);
|
||||||
if (!$TestMapID || !ctype_digit((string) $TestMapID)) { return $this->failValidationErrors('TestMapID is required.'); }
|
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;
|
$id = (int) $TestMapID;
|
||||||
if (isset($input['TestMapID']) && (string) $input['TestMapID'] !== (string) $id) {
|
if (isset($input['TestMapID']) && (string) $input['TestMapID'] !== (string) $id) {
|
||||||
return $this->failValidationErrors('TestMapID in URL does not match body.');
|
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;
|
$input['TestMapID'] = $id;
|
||||||
if (!$this->validateData($input, $this->rules)) { return $this->failValidationErrors( $this->validator->getErrors() ); }
|
|
||||||
try {
|
try {
|
||||||
$this->model->update($id,$input);
|
$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) {
|
} catch (\Exception $e) {
|
||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,22 +9,31 @@ use App\Models\Test\TestMapDetailModel;
|
|||||||
class TestMapDetailController extends BaseController {
|
class TestMapDetailController extends BaseController {
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
protected $db;
|
protected $db;
|
||||||
protected $rules;
|
protected $rules;
|
||||||
protected $model;
|
protected $patchRules;
|
||||||
|
protected $model;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->db = \Config\Database::connect();
|
$this->db = \Config\Database::connect();
|
||||||
$this->model = new TestMapDetailModel;
|
$this->model = new TestMapDetailModel;
|
||||||
$this->rules = [
|
$this->rules = [
|
||||||
'TestMapID' => 'required|integer',
|
'TestMapID' => 'required|integer',
|
||||||
'HostTestCode' => 'permit_empty|max_length[10]',
|
'HostTestCode' => 'permit_empty|max_length[10]',
|
||||||
'HostTestName' => 'permit_empty|max_length[100]',
|
'HostTestName' => 'permit_empty|max_length[100]',
|
||||||
'ConDefID' => 'permit_empty|integer',
|
'ConDefID' => 'permit_empty|integer',
|
||||||
'ClientTestCode' => 'permit_empty|max_length[10]',
|
'ClientTestCode' => 'permit_empty|max_length[10]',
|
||||||
'ClientTestName' => 'permit_empty|max_length[100]',
|
'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() {
|
public function index() {
|
||||||
$testMapID = $this->request->getGet('TestMapID');
|
$testMapID = $this->request->getGet('TestMapID');
|
||||||
@ -94,15 +103,19 @@ class TestMapDetailController extends BaseController {
|
|||||||
if (!$TestMapDetailID || !ctype_digit((string) $TestMapDetailID)) {
|
if (!$TestMapDetailID || !ctype_digit((string) $TestMapDetailID)) {
|
||||||
return $this->failValidationErrors('TestMapDetailID is required.');
|
return $this->failValidationErrors('TestMapDetailID is required.');
|
||||||
}
|
}
|
||||||
|
if (empty($input) || !is_array($input)) {
|
||||||
|
return $this->failValidationErrors('No data provided for update.');
|
||||||
|
}
|
||||||
$id = (int) $TestMapDetailID;
|
$id = (int) $TestMapDetailID;
|
||||||
if (isset($input['TestMapDetailID']) && (string) $input['TestMapDetailID'] !== (string) $id) {
|
if (isset($input['TestMapDetailID']) && (string) $input['TestMapDetailID'] !== (string) $id) {
|
||||||
return $this->failValidationErrors('TestMapDetailID in URL does not match body.');
|
return $this->failValidationErrors('TestMapDetailID in URL does not match body.');
|
||||||
}
|
}
|
||||||
$input['TestMapDetailID'] = $id;
|
$input['TestMapDetailID'] = $id;
|
||||||
|
|
||||||
if (!$this->validateData($input, $this->rules)) {
|
$validationInput = array_intersect_key($input, $this->patchRules);
|
||||||
return $this->failValidationErrors($this->validator->getErrors());
|
if (!empty($validationInput) && !$this->validateData($validationInput, $this->patchRules)) {
|
||||||
}
|
return $this->failValidationErrors($this->validator->getErrors());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->model->update($id, $input);
|
$this->model->update($id, $input);
|
||||||
@ -179,7 +192,7 @@ class TestMapDetailController extends BaseController {
|
|||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function batchUpdate() {
|
public function batchUpdate() {
|
||||||
$items = $this->request->getJSON(true);
|
$items = $this->request->getJSON(true);
|
||||||
|
|
||||||
if (!is_array($items)) {
|
if (!is_array($items)) {
|
||||||
@ -189,24 +202,32 @@ class TestMapDetailController extends BaseController {
|
|||||||
$results = ['success' => [], 'failed' => []];
|
$results = ['success' => [], 'failed' => []];
|
||||||
$this->db->transStart();
|
$this->db->transStart();
|
||||||
|
|
||||||
foreach ($items as $index => $item) {
|
foreach ($items as $index => $item) {
|
||||||
$id = $item['TestMapDetailID'] ?? null;
|
$id = $item['TestMapDetailID'] ?? null;
|
||||||
|
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
$results['failed'][] = ['index' => $index, 'error' => 'TestMapDetailID required'];
|
$results['failed'][] = ['index' => $index, 'error' => 'TestMapDetailID required'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->validateData($item, $this->rules)) {
|
$updateData = $item;
|
||||||
$results['failed'][] = ['index' => $index, 'errors' => $this->validator->getErrors()];
|
unset($updateData['TestMapDetailID']);
|
||||||
continue;
|
|
||||||
}
|
if ($updateData === []) {
|
||||||
|
$results['failed'][] = ['index' => $index, 'error' => 'No fields to update'];
|
||||||
try {
|
continue;
|
||||||
$this->model->update($id, $item);
|
}
|
||||||
$results['success'][] = ['index' => $index, 'TestMapDetailID' => $id];
|
|
||||||
} catch (\Exception $e) {
|
if (!$this->validateData($updateData, $this->patchRules)) {
|
||||||
$results['failed'][] = ['index' => $index, 'error' => $e->getMessage()];
|
$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()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -262,11 +262,11 @@ class TestsController extends BaseController
|
|||||||
'StartDate',
|
'StartDate',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($allowedUpdateFields as $field) {
|
foreach ($allowedUpdateFields as $field) {
|
||||||
if (isset($input[$field])) {
|
if (array_key_exists($field, $input)) {
|
||||||
$testSiteData[$field] = $input[$field];
|
$testSiteData[$field] = $input[$field];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($testSiteData)) {
|
if (!empty($testSiteData)) {
|
||||||
$this->model->update($id, $testSiteData);
|
$this->model->update($id, $testSiteData);
|
||||||
@ -421,24 +421,33 @@ class TestsController extends BaseController
|
|||||||
|
|
||||||
private function saveTechDetails($testSiteID, $data, $action, $typeCode)
|
private function saveTechDetails($testSiteID, $data, $action, $typeCode)
|
||||||
{
|
{
|
||||||
$techData = [
|
$allowedFields = [
|
||||||
'DisciplineID' => $data['DisciplineID'] ?? null,
|
'DisciplineID',
|
||||||
'DepartmentID' => $data['DepartmentID'] ?? null,
|
'DepartmentID',
|
||||||
'ResultType' => $data['ResultType'] ?? null,
|
'ResultType',
|
||||||
'RefType' => $data['RefType'] ?? null,
|
'RefType',
|
||||||
'VSet' => $data['VSet'] ?? null,
|
'VSet',
|
||||||
'ReqQty' => $data['ReqQty'] ?? null,
|
'ReqQty',
|
||||||
'ReqQtyUnit' => $data['ReqQtyUnit'] ?? null,
|
'ReqQtyUnit',
|
||||||
'Unit1' => $data['Unit1'] ?? null,
|
'Unit1',
|
||||||
'Factor' => $data['Factor'] ?? null,
|
'Factor',
|
||||||
'Unit2' => $data['Unit2'] ?? null,
|
'Unit2',
|
||||||
'Decimal' => array_key_exists('Decimal', $data) ? $data['Decimal'] : null,
|
'Decimal',
|
||||||
'CollReq' => $data['CollReq'] ?? null,
|
'CollReq',
|
||||||
'Method' => $data['Method'] ?? null,
|
'Method',
|
||||||
'ExpectedTAT' => $data['ExpectedTAT'] ?? null,
|
'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)
|
private function saveRefNumRanges($testSiteID, $ranges, $action, $siteID)
|
||||||
@ -461,50 +470,89 @@ class TestsController extends BaseController
|
|||||||
|
|
||||||
private function saveCalcDetails($testSiteID, $data, $input, $action)
|
private function saveCalcDetails($testSiteID, $data, $input, $action)
|
||||||
{
|
{
|
||||||
$calcData = [
|
$calcData = [];
|
||||||
'TestSiteID' => $testSiteID,
|
$fieldMap = [
|
||||||
'DisciplineID' => $data['DisciplineID'] ?? null,
|
'DisciplineID' => 'DisciplineID',
|
||||||
'DepartmentID' => $data['DepartmentID'] ?? null,
|
'DepartmentID' => 'DepartmentID',
|
||||||
'FormulaCode' => $data['FormulaCode'] ?? $data['Formula'] ?? null,
|
'Factor' => 'Factor',
|
||||||
'ResultType' => 'NMRIC',
|
'Unit2' => 'Unit2',
|
||||||
'RefType' => $data['RefType'] ?? 'RANGE',
|
'Decimal' => 'Decimal',
|
||||||
'Unit1' => $data['Unit1'] ?? $data['ResultUnit'] ?? null,
|
'Method' => 'Method',
|
||||||
'Factor' => $data['Factor'] ?? null,
|
|
||||||
'Unit2' => $data['Unit2'] ?? null,
|
|
||||||
'Decimal' => array_key_exists('Decimal', $data) ? $data['Decimal'] : null,
|
|
||||||
'Method' => $data['Method'] ?? null,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($action === 'update') {
|
foreach ($fieldMap as $source => $target) {
|
||||||
$exists = $this->modelCal->existsByTestSiteID($testSiteID);
|
if (array_key_exists($source, $data)) {
|
||||||
|
$calcData[$target] = $data[$source];
|
||||||
if ($exists) {
|
}
|
||||||
$this->modelCal->update($exists['TestCalID'], $calcData);
|
}
|
||||||
} else {
|
|
||||||
$this->modelCal->insert($calcData);
|
if (array_key_exists('FormulaCode', $data) || array_key_exists('Formula', $data)) {
|
||||||
}
|
$calcData['FormulaCode'] = $data['FormulaCode'] ?? $data['Formula'] ?? null;
|
||||||
} else {
|
}
|
||||||
$this->modelCal->insert($calcData);
|
|
||||||
}
|
if (array_key_exists('RefType', $data)) {
|
||||||
|
$calcData['RefType'] = $data['RefType'];
|
||||||
if ($action === 'update') {
|
}
|
||||||
$this->modelGrp->disableByTestSiteID($testSiteID);
|
|
||||||
}
|
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);
|
$memberIDs = $this->resolveMemberIDs($input);
|
||||||
|
|
||||||
// Validate member IDs before insertion
|
$validation = $this->validateMemberIDs($memberIDs);
|
||||||
$validation = $this->validateMemberIDs($memberIDs);
|
if (!$validation['valid']) {
|
||||||
if (!$validation['valid']) {
|
throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.');
|
||||||
throw new \Exception('Invalid member TestSiteID(s): ' . implode(', ', $validation['invalid']) . '. Make sure to use TestSiteID, not SeqScr or other values.');
|
}
|
||||||
}
|
|
||||||
|
foreach ($memberIDs as $memberID) {
|
||||||
foreach ($memberIDs as $memberID) {
|
$this->modelGrp->insert([
|
||||||
$this->modelGrp->insert([
|
'TestSiteID' => $testSiteID,
|
||||||
'TestSiteID' => $testSiteID,
|
'Member' => $memberID,
|
||||||
'Member' => $memberID,
|
]);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveMemberIDs(array $input): array
|
private function resolveMemberIDs(array $input): array
|
||||||
@ -558,6 +606,14 @@ class TestsController extends BaseController
|
|||||||
|
|
||||||
private function saveGroupDetails($testSiteID, $data, $input, $action)
|
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') {
|
if ($action === 'update') {
|
||||||
$this->modelGrp->disableByTestSiteID($testSiteID);
|
$this->modelGrp->disableByTestSiteID($testSiteID);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,20 +107,27 @@ class PatVisitModel extends BaseModel {
|
|||||||
throw new \Exception("Visit not found or has been deleted.");
|
throw new \Exception("Visit not found or has been deleted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->where('InternalPVID',$InternalPVID)->set($input)->update();
|
$visitData = array_intersect_key($input, array_flip($this->allowedFields));
|
||||||
|
if (!empty($visitData)) {
|
||||||
// patdiag
|
$this->where('InternalPVID', $InternalPVID)->set($visitData)->update();
|
||||||
$exist = $modelPD->where('InternalPVID',$InternalPVID)->find();
|
}
|
||||||
if($exist) {
|
|
||||||
if( !empty($input['PatDiag']) && ( !empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']) ) ) {
|
// patdiag
|
||||||
$tmp = $modelPD->where('InternalPVID',$InternalPVID)->set($input['PatDiag'])->update();
|
if (array_key_exists('PatDiag', $input)) {
|
||||||
} else { $tmp = $modelPD->delete($InternalPVID); }
|
$exist = $modelPD->where('InternalPVID', $InternalPVID)->find();
|
||||||
} else {
|
if ($exist) {
|
||||||
if( !empty($input['PatDiag']) && ( !empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']) ) ) {
|
if (!empty($input['PatDiag']) && (!empty($input['PatDiag']['DiagCode']) || !empty($input['PatDiag']['Diagnosis']))) {
|
||||||
$input['PatDiag']['InternalPVID'] = $InternalPVID;
|
$tmp = $modelPD->where('InternalPVID', $InternalPVID)->set($input['PatDiag'])->update();
|
||||||
$tmp = $modelPD->insert($input['PatDiag']);
|
} 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) {
|
if (isset($tmp) && $tmp === false) {
|
||||||
$error = $db->error();
|
$error = $db->error();
|
||||||
throw new \Exception("Failed to update PatDiag record. ". $error['message']);
|
throw new \Exception("Failed to update PatDiag record. ". $error['message']);
|
||||||
@ -141,9 +148,9 @@ class PatVisitModel extends BaseModel {
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
$db->transCommit();
|
$db->transCommit();
|
||||||
$data = [ "PVID" => $input['PVID'], "InternalPVID" => $InternalPVID ];
|
$data = [ "PVID" => $input['PVID'] ?? $visit['PVID'], "InternalPVID" => $InternalPVID ];
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->db->transRollback();
|
$this->db->transRollback();
|
||||||
|
|||||||
@ -152,5 +152,39 @@ class PatVisitUpdateTest extends CIUnitTestCase
|
|||||||
'message' => 'Invalid or missing ID'
|
'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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user