clqms-be/app/Controllers/Patient.php

307 lines
13 KiB
PHP

<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;
use App\Models\PatientModel;
class Patient extends Controller {
use ResponseTrait;
protected $db;
protected $modelPatient;
protected $rulesPatient;
protected $rulesPatIdt;
public function __construct() {
$this->db = \Config\Database::connect();
$this->modelPatient = new PatientModel();
$this->rulesPatient = [
'PatientID' => 'required|is_unique[patient.PatientID]|max_length[50]',
'AlternatePID' => 'permit_empty|max_length[50]',
'NameFirst' => 'required|min_length[1]|max_length[255]',
'EmailAddress1' => 'required|is_unique[patient.EmailAddress1]',
'Gender' => 'required'
];
$this->rulesPatIdt = ['Identifier' => 'required|is_unique[patidt.Identifier]'];
}
public function index() {
$filters = [
'InternalPID' => $this->request->getVar('InternalPID'),
'PatientID' => $this->request->getVar('PatientID'),
'Name' => $this->request->getVar('Name'),
'Birthdate' => $this->request->getVar('Birthdate'),
];
try {
$rows = $this->modelPatient->getPatients($filters);
return $this->respond([ 'status' => 'success', 'message'=> "data fetched successfully", 'data' => $rows ], 200);
} catch (\Exception $e) {
return $this->failServerError('Exception : '.$e->getMessage());
}
}
public function show($InternalPID = null) {
try {
$rows = $this->modelPatient->getPatient($InternalPID);
if (empty($rows)) { return $this->respond([ 'status' => 'success', 'message' => "data not found." ], 200); }
return $this->respond([ 'status' => 'success', 'message' => "data fetched successfully", 'data' => $rows ], 200);
} catch (\Exception $e) {
return $this->failServerError('Something went wrong: ' . $e->getMessage());
}
}
public function create() {
$input = $this->request->getJSON(true);
if (!$this->validateData($input, $this->rulesPatient)) { return $this->validationError('patient', $this->validator->getErrors()); }
if (!$this->validateData($input, $this->rulesPatIdt)) { return $this->validationError('patidt', $this->validator->getErrors()); }
try {
$newInternalPID = $this->modelPatient->createPatient($input);
return $this->respondCreated([ 'status' => 'success', 'message' => 'data created successfully', 'data' => $newInternalPID]);
} catch (\Exception $e) {
return $this->failServerError('Something went wrong: ' . $e->getMessage());
}
}
// Setting up data
private function preparePatientData(array $input, string $mode = 'create'): array {
$LinkTo = null;
if (!empty($input['LinkTo'])) {
$ids = array_column($input['LinkTo'], 'InternalPID');
$LinkTo = implode(',', $ids);
}
$data = [
"PatientID" => $input['PatientID'] ?? null,
"AlternatePID" => $input['AlternatePID'] ?? null,
"Prefix" => $input['Prefix'] ?? null,
"NameFirst" => $input['NameFirst'] ?? null,
"NameMiddle" => $input['NameMiddle'] ?? null,
"NameMaiden" => $input['NameMaiden'] ?? null,
"NameLast" => $input['NameLast'] ?? null,
"Suffix" => $input['Suffix'] ?? null,
"NameAlias" => $input['NameAlias'] ?? null,
"Gender" => !empty($input['Gender']) ? (int)$input['Gender'] : null,
"PlaceOfBirth" => $input['PlaceOfBirth'] ?? null,
"Birthdate" => $input['Birthdate'] ?? null,
"Street_1" => $input['Street_1'] ?? null,
"Street_2" => $input['Street_2'] ?? null,
"Street_3" => $input['Street_3'] ?? null,
"City" => $input['City'] ?? null,
"Province" => $input['Province'] ?? null,
"ZIP" => $input['ZIP'] ?? null,
"EmailAddress1" => $input['EmailAddress1'] ?? null,
"EmailAddress2" => $input['EmailAddress2'] ?? null,
"Phone" => $input['Phone'] ?? null,
"MobilePhone" => $input['MobilePhone'] ?? null,
"RaceID" => isset($input['RaceID']) ? (int)$input['RaceID'] : null,
"IntCountryID" => isset($input['IntCountryID']) ? (int)$input['IntCountryID'] : null,
"MaritalStatus" => $input['MaritalStatus'] ?? null,
"ReligionID" => isset($input['ReligionID']) ? (int)$input['ReligionID'] : null,
"EthnicID" => isset($input['EthnicID']) ? (int)$input['EthnicID'] : null,
"Citizenship" => $input['Citizenship'] ?? null,
"DeathIndicator" => isset($input['DeathIndicator']) ? (int)$input['DeathIndicator'] : null,
"DeathDateTime" => $input['DeathDateTime'] ?? null,
"Custodian" => isset($input['Custodian']) ? (int)$input['Custodian'] : null,
"DelDate" => null,
"LinkTo" => $LinkTo
];
if(!empty($input['InternalPID'])) { $data["InternalPID"] = $input["InternalPID"]; }
return $data;
}
private function preparePatidtData(array $input ): array {
$data = [
"IdentifierType" => $input['Identity']['IdentifierType'] ?? null,
"Identifier" => $input['Identity']['Identifier'] ?? null,
];
return $data;
}
private function preparePatattData(array $input): array {
if (empty($input['Attachments'])) {
return [];
}
return array_map(function ($attachment) {
$row = [
"Address" => $attachment['Address'] ?? null,
];
return $row;
}, $input['Attachments']);
}
private function preparePatcomData(array $input): array {
$data = [
"Comment" => $input['Comment'] ?? null,
];
return $data;
}
private function validationError(string $context, array $errors) {
return $this->respond([
'status' => 'error',
'message' => "Validation failed ({$context})",
'errors' => $errors
], 400);
}
// Unit Testing Pass : On Progress
public function update() {
try {
$input = $this->request->getJSON(true);
if (!$input) { return $this->respond(['status' => 'error', 'message' => 'Invalid JSON input'], 400); }
if (!$input["InternalPID"] || !is_numeric($input["InternalPID"])) { return $this->respond(['status' => 'error', 'message' => 'Invalid or missing InternalPID'], 400); }
$InternalPID = $input["InternalPID"];
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRowArray();
if (!$patient) { return $this->respond(['status' => 'error', 'message' => 'Patient not found'], 404); }
$dataPatient = $this->preparePatientData($input);
$dataPatIdt = $this->preparePatidtData($input);
$dataPatCom = $this->preparePatcomData($input);
$dataPatAtt = $this->preparePatattData($input);
// Validasi
if (!$this->validateData($dataPatient, $this->rulesPatient)) {
return $this->respond([
'status' => 'error',
'message' => 'Validation failed (patient)',
'errors' => $this->validator->getErrors()
], 400);
}
if (!$this->validateData($dataPatIdt, $this->rulesPatIdt)) {
return $this->respond([
'status' => 'error',
'message' => 'Validation failed (patidt)',
'errors' => $this->validator->getErrors()
], 400);
}
$this->db->transStart();
$this->db->table('patient')->where('InternalPID', $InternalPID)->update($dataPatient);
$dbError = $this->db->error();
if (!empty($dbError['message'])) {
$this->db->transRollback();
return $this->failServerError('Update patient failed: ' . $dbError['message']);
}
$this->db->table('patidt')->where('InternalPID', $InternalPID)->update($dataPatIdt);
$dbError = $this->db->error();
if (!empty($dbError['message'])) {
$this->db->transRollback();
return $this->failServerError('Update patidt failed: ' . $dbError['message']);
}
if (!empty($dataPatAtt)) {
foreach ($dataPatAtt as &$row) {
$row['InternalPID'] = $InternalPID;
}
$this->db->table('patatt')->upsertBatch($dataPatAtt);
$addresses = array_column($dataPatAtt, 'Address');
$this->db->table('patatt')->where('InternalPID', $InternalPID)->WhereNotIn('Address', $addresses)->update(['DelDate' => date('Y-m-d H:i:s')]);
} else {
$this->db->table('patatt')->where('InternalPID', $InternalPID)->update(['DelDate' => date('Y-m-d H:i:s')]);
}
if(!empty($dataPatcom['Comment'])) {
$dataPatcom['InternalPID'] = $InternalPID;
$this->db->table('patcom')->upsert($dataPatCom);
}
$this->db->transComplete();
if ($this->db->transStatus() === false) {
$dbError = $this->db->error();
return $this->failServerError('Failed to update patient data (transaction rolled back): ' . ($dbError['message'] ?? 'Unknown error'));
}
return $this->respond([
'status' => 'success',
'message' => 'Patient updated successfully',
'data' => $dataPatient
], 200);
} catch (\Exception $e) {
$this->db->transRollback();
return $this->failServerError('Something went wrong: ' . $e->getMessage());
}
}
// Unit Testing Pass : \clqms-be\tests\feature\Patients\PatientDeleteTest.php
public function delete() {
try {
$input = $this->request->getJSON(true);
$InternalPID = $input["InternalPID"];
// Mencegah Inputan 0, [], null, sql injection
if (empty($InternalPID) || !ctype_digit((string) $InternalPID)) {
return $this->respond([
'status' => 'error',
'message' => "Patient ID must be a valid integer."
], 400);
}
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRow();
if (!$patient) {
return $this->failNotFound("Patient ID with {$InternalPID} not found.");
}
$this->db->table('patient')->where('InternalPID', $InternalPID)->update(['DelDate' => date('Y-m-d H:i:s')]);
return $this->respondDeleted([
'status' => 'success',
'message' => "Patient ID with {$InternalPID} deleted successfully."
]);
} catch (\Exception $e) {
return $this->failServerError("Internal server error: " . $e->getMessage());
}
}
public function patientCheck() {
try {
$PatientID = $this->request->getVar('PatientID');
$EmailAddress1 = $this->request->getVar('EmailAddress1');
if ($PatientID!=null){
$tableName = 'PatientID';
$searchName = $PatientID;
}
if ($EmailAddress1!=null){
$tableName = 'EmailAddress1';
$searchName = $EmailAddress1;
}
$patient = $this->db->table('patient')
->where($tableName, $searchName)
->get()
->getRowArray();
if (!$patient) {
return $this->respond([
'status' => 'success',
'message' => "$tableName not found.",
'data' => true,
], 200);
}
return $this->respond([
'status' => 'success',
'message' => "$tableName already exists.",
'data' => false,
], 200);
} catch (\Exception $e) {
// Error Server Mengembalikan 500
return $this->failServerError('Something went wrong.'.$e->getMessage());
}
}
}