2025-07-02 16:10:37 +07:00
|
|
|
<?php
|
|
|
|
|
namespace App\Controllers;
|
|
|
|
|
|
|
|
|
|
use CodeIgniter\API\ResponseTrait;
|
|
|
|
|
use CodeIgniter\Controller;
|
|
|
|
|
use CodeIgniter\Database\RawSql;
|
|
|
|
|
|
|
|
|
|
class Patient extends Controller {
|
|
|
|
|
use ResponseTrait;
|
|
|
|
|
|
|
|
|
|
public function __construct() {
|
|
|
|
|
$this->db = \Config\Database::connect();
|
2025-09-04 11:05:13 +07:00
|
|
|
$this->now = date('Y-m-d H:i:s');
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-01 22:18:45 +07:00
|
|
|
// OK - Done
|
2025-07-02 16:10:37 +07:00
|
|
|
public function index() {
|
2025-07-23 11:03:46 +07:00
|
|
|
try {
|
2025-08-04 13:21:13 +07:00
|
|
|
$InternalPID = $this->request->getVar('InternalPID');
|
2025-08-01 13:37:13 +07:00
|
|
|
$PatientID = $this->request->getVar('PatientID');
|
2025-08-04 13:21:13 +07:00
|
|
|
$Name = $this->request->getVar('Name');
|
2025-08-07 09:47:59 +07:00
|
|
|
$Birthdate = $this->request->getVar('Birthdate');
|
2025-08-05 10:34:58 +07:00
|
|
|
$qname = "LOWER(CONCAT_WS(' ', IFNULL(Prefix,''), IFNULL(NameFirst,''), IFNULL(NameMiddle,''), IFNULL(NameLast,''), IFNULL(NameMaiden,''), IFNULL(Suffix,'')))";
|
2025-08-01 22:26:27 +07:00
|
|
|
$builder = $this->db->table('patient');
|
2025-08-07 09:47:59 +07:00
|
|
|
$builder->select("InternalPID, PatientID, $qname as FullName, Gender, Birthdate, EmailAddress1 as Email, MobilePhone");
|
2025-08-04 13:21:13 +07:00
|
|
|
if ($Name !== null) {
|
2025-08-05 10:34:58 +07:00
|
|
|
$sql = $qname;
|
2025-07-23 11:03:46 +07:00
|
|
|
$rawSql = new RawSql($sql);
|
2025-08-04 13:21:13 +07:00
|
|
|
$builder->like($rawSql, $Name, 'both');
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
2025-08-04 13:21:13 +07:00
|
|
|
if ($InternalPID !== null) { $builder->where('InternalPID', $InternalPID); }
|
2025-08-05 11:38:11 +07:00
|
|
|
if ($PatientID !== null) { $builder->like('PatientID', $PatientID, 'both'); }
|
2025-08-07 09:47:59 +07:00
|
|
|
if ($Birthdate !== null) { $builder->where('Birthdate', $Birthdate); }
|
2025-07-23 11:03:46 +07:00
|
|
|
|
|
|
|
|
$filteredPatients = $builder->get()->getResultArray();
|
2025-07-02 16:10:37 +07:00
|
|
|
|
2025-07-23 11:03:46 +07:00
|
|
|
// Data pasien tidak ada mengembalikan - success 200
|
|
|
|
|
if (empty($filteredPatients)) {
|
|
|
|
|
return $this->respond([
|
2025-07-16 09:19:47 +07:00
|
|
|
'status' => 'success',
|
2025-07-23 11:03:46 +07:00
|
|
|
'message' => 'No patient records found matching the criteria.',
|
|
|
|
|
'data' => []
|
|
|
|
|
], 200);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Data pasien ditemukan dan mengembalikan - success 200
|
|
|
|
|
return $this->respond([
|
|
|
|
|
'status' => 'success',
|
|
|
|
|
'message'=> "Patients fetched successfully",
|
|
|
|
|
'data' => $filteredPatients,
|
|
|
|
|
], 200);
|
|
|
|
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
|
|
|
|
// Error Server Mengembalikan 500
|
2025-08-01 22:33:41 +07:00
|
|
|
return $this->failServerError('Something went wrong.'.$e->getMessage());
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-01 22:18:45 +07:00
|
|
|
public function show($InternalPID = null) {
|
2025-07-23 11:03:46 +07:00
|
|
|
try {
|
2025-09-08 15:56:38 +07:00
|
|
|
$rows = $this->db->table('patient')
|
|
|
|
|
->select("
|
|
|
|
|
patient.*,
|
|
|
|
|
country.Country as CountryName,
|
|
|
|
|
race.Race as RaceName,
|
|
|
|
|
religion.Religion as ReligionName,
|
|
|
|
|
ethnic.Ethnic as EthnicName,
|
|
|
|
|
patcom.Comment as Comment,
|
|
|
|
|
patidt.IdentifierType,
|
|
|
|
|
patidt.Identifier,
|
|
|
|
|
patatt.Address
|
|
|
|
|
")
|
|
|
|
|
->join('country', 'country.IntCountryID = patient.IntCountryID', 'left')
|
|
|
|
|
->join('race', 'race.RaceID = patient.RaceID', 'left')
|
|
|
|
|
->join('religion', 'religion.ReligionID = patient.ReligionID', 'left')
|
|
|
|
|
->join('ethnic', 'ethnic.EthnicID = patient.EthnicID', 'left')
|
|
|
|
|
->join('patcom', 'patcom.InternalPID = patient.InternalPID', 'left')
|
|
|
|
|
->join('patidt', 'patidt.InternalPID = patient.InternalPID', 'left')
|
|
|
|
|
->join('patatt', 'patatt.InternalPID = patient.InternalPID', 'left')
|
|
|
|
|
->where('patient.InternalPID', (int) $InternalPID)
|
|
|
|
|
->get()
|
|
|
|
|
->getResultArray();
|
|
|
|
|
|
|
|
|
|
if (empty($rows)) {
|
2025-07-23 11:03:46 +07:00
|
|
|
return $this->respond([
|
2025-09-08 15:56:38 +07:00
|
|
|
'status' => 'success',
|
|
|
|
|
'message' => "Patient with ID {$InternalPID} not found.",
|
|
|
|
|
'data' => [],
|
2025-07-23 11:03:46 +07:00
|
|
|
], 200);
|
2025-09-08 15:56:38 +07:00
|
|
|
}
|
2025-08-11 14:37:47 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
// Use first row as base patient data
|
|
|
|
|
$patient = $rows[0];
|
2025-08-25 10:35:05 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
$patient = $this->transformPatientData($patient);
|
2025-08-25 09:02:10 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
$patient['Identity'] = null;
|
|
|
|
|
$patient['Attachments'] = [];
|
|
|
|
|
|
|
|
|
|
foreach ($rows as $row) {
|
|
|
|
|
if ($row['IdentifierType'] && $row['Identifier'] && !$patient['Identity']) {
|
|
|
|
|
$patient['Identity'] = [
|
|
|
|
|
'IdentifierType' => $row['IdentifierType'],
|
|
|
|
|
'Identifier' => $row['Identifier'],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
if ($row['Address']) {
|
|
|
|
|
$patient['Attachments'][] = ['Address' => $row['Address']];
|
|
|
|
|
}
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
if (empty($patient['Identity'])) { $patient['Identity'] = null; }
|
|
|
|
|
if (empty($patient['Attachments'])) { $patient['Attachments'] = null; }
|
|
|
|
|
|
2025-07-23 11:03:46 +07:00
|
|
|
return $this->respond([
|
2025-09-08 15:56:38 +07:00
|
|
|
'status' => 'success',
|
|
|
|
|
'message' => "Patient Show Successfully",
|
|
|
|
|
'data' => $patient,
|
|
|
|
|
], 200);
|
2025-07-23 11:03:46 +07:00
|
|
|
|
|
|
|
|
} catch (\Exception $e) {
|
2025-09-08 15:56:38 +07:00
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-23 11:03:46 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
|
|
|
|
|
private function transformPatientData(array $patient): array {
|
|
|
|
|
$patient["Age"] = $this->calculateAgeFromBirthdate($patient["Birthdate"]);
|
|
|
|
|
$patient["Birthdate"] = $this->formatedDate($patient["Birthdate"]);
|
|
|
|
|
$patient["CreateDate"] = $this->formatedDate($patient["CreateDate"]);
|
|
|
|
|
$patient["DelDate"] = $this->formatedDate($patient["DelDate"]);
|
|
|
|
|
$patient["DeathDateTime"] = $this->formatedDate($patient["DeathDateTime"]);
|
|
|
|
|
$patient["BirthdateConversion"] = $this->formatedDateForDisplay($patient["Birthdate"]);
|
|
|
|
|
|
|
|
|
|
$patient["LinkTo"] = $this->getLinkedPatients($patient['LinkTo']);
|
|
|
|
|
$patient["Custodian"] = $this->getCustodian($patient['Custodian']);
|
|
|
|
|
|
|
|
|
|
return $patient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function getLinkedPatients(?string $linkTo): ?array {
|
|
|
|
|
if (empty($linkTo)) {
|
|
|
|
|
return null;
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
2025-07-16 09:19:47 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
$ids = array_filter(explode(',', $linkTo));
|
|
|
|
|
|
|
|
|
|
return $this->db->table('patient')
|
|
|
|
|
->select('InternalPID, PatientID')
|
|
|
|
|
->whereIn('InternalPID', $ids)
|
|
|
|
|
->get()
|
|
|
|
|
->getResultArray() ?: null;
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
private function getCustodian($custodianId): ?array {
|
|
|
|
|
if (empty($custodianId)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->db->table('patient')
|
|
|
|
|
->select('InternalPID, PatientID')
|
|
|
|
|
->where('InternalPID', (int) $custodianId)
|
|
|
|
|
->get()
|
|
|
|
|
->getRowArray() ?: null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-07-02 16:10:37 +07:00
|
|
|
public function create() {
|
2025-07-23 11:03:46 +07:00
|
|
|
try {
|
|
|
|
|
$input = $this->request->getJSON(true);
|
2025-09-08 15:56:38 +07:00
|
|
|
$now = date('Y-m-d H:i:s');
|
2025-08-11 14:12:07 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
// Prepare data
|
|
|
|
|
$dataPatient = $this->preparePatientData($input, $now, 'create');
|
|
|
|
|
$dataPatidt = $this->preparePatidtData($input, $now, 'create');
|
|
|
|
|
$dataPatatt = $this->preparePatattData($input, $now, 'create');
|
|
|
|
|
$dataPatcom = $this->preparePatcomData($input, $now, 'create');
|
2025-08-04 10:26:26 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
// Validation rules
|
|
|
|
|
$rulesPatient = [
|
2025-08-08 13:49:18 +07:00
|
|
|
'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]',
|
|
|
|
|
'DeathIndicator' => 'required',
|
|
|
|
|
'Gender' => 'required'
|
2025-07-23 11:03:46 +07:00
|
|
|
];
|
2025-09-08 15:56:38 +07:00
|
|
|
$rulesPatidt = ['Identifier' => 'required|is_unique[patidt.Identifier]'];
|
|
|
|
|
//$rulesPatatt = ['Address' => 'required|is_unique[patatt.Address]'];
|
2025-07-23 11:03:46 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
// Validate patient
|
|
|
|
|
if (!$this->validateData($dataPatient, $rulesPatient)) {
|
|
|
|
|
return $this->validationError('patient', $this->validator->getErrors());
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
2025-09-08 15:56:38 +07:00
|
|
|
// Validate patidt
|
|
|
|
|
if (!$this->validateData($dataPatidt, $rulesPatidt)) {
|
|
|
|
|
return $this->validationError('patidt', $this->validator->getErrors());
|
2025-08-08 13:49:18 +07:00
|
|
|
}
|
2025-09-08 15:56:38 +07:00
|
|
|
/* Validate patatt (if exists, validate only the first row)
|
|
|
|
|
if (!empty($dataPatatt) && !$this->validateData($dataPatatt[0], $rulesPatatt)) {
|
|
|
|
|
return $this->validationError('patatt', $this->validator->getErrors());
|
|
|
|
|
}
|
|
|
|
|
*/
|
2025-08-08 13:49:18 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
|
2025-08-08 13:49:18 +07:00
|
|
|
$this->db->transStart();
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
|
2025-08-08 13:49:18 +07:00
|
|
|
$this->db->table('patient')->insert($dataPatient);
|
|
|
|
|
$newInternalPatientId = $this->db->insertID();
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
|
2025-09-02 13:44:59 +07:00
|
|
|
$dataPatidt['InternalPID'] = $newInternalPatientId;
|
|
|
|
|
$this->db->table('patidt')->insert($dataPatidt);
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
|
|
|
|
|
if (!empty($dataPatatt)) {
|
|
|
|
|
foreach ($dataPatatt as &$row) {
|
|
|
|
|
$row['InternalPID'] = $newInternalPatientId;
|
2025-09-02 13:44:59 +07:00
|
|
|
}
|
2025-09-08 15:56:38 +07:00
|
|
|
$this->db->table('patatt')->upsertBatch($dataPatatt);
|
2025-09-02 13:44:59 +07:00
|
|
|
}
|
2025-09-08 15:56:38 +07:00
|
|
|
|
2025-09-02 13:44:59 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
if (!empty($dataPatcom['Comment'])) {
|
2025-09-04 11:05:13 +07:00
|
|
|
$dataPatcom['InternalPID'] = $newInternalPatientId;
|
|
|
|
|
$this->db->table('patcom')->insert($dataPatcom);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-08 14:02:56 +07:00
|
|
|
$dbError = $this->db->error();
|
|
|
|
|
if (!empty($dbError['message'])) {
|
|
|
|
|
$this->db->transRollback();
|
|
|
|
|
return $this->failServerError('Insert patient failed: ' . $dbError['message']);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-08 13:49:18 +07:00
|
|
|
$this->db->transComplete();
|
|
|
|
|
|
|
|
|
|
if ($this->db->transStatus() === false) {
|
2025-09-08 15:56:38 +07:00
|
|
|
$dbError = $this->db->error();
|
2025-08-08 13:59:24 +07:00
|
|
|
return $this->failServerError(
|
2025-08-08 14:02:56 +07:00
|
|
|
'Failed to create patient data (transaction rolled back): ' . ($dbError['message'] ?? 'Unknown database error')
|
2025-08-08 13:59:24 +07:00
|
|
|
);
|
2025-08-08 13:49:18 +07:00
|
|
|
}
|
2025-07-23 11:03:46 +07:00
|
|
|
|
|
|
|
|
return $this->respondCreated([
|
2025-08-08 13:49:18 +07:00
|
|
|
'status' => 'success',
|
2025-07-23 11:03:46 +07:00
|
|
|
'message' => 'Patient created successfully',
|
2025-08-08 13:49:18 +07:00
|
|
|
'data' => $newInternalPatientId
|
2025-07-23 11:03:46 +07:00
|
|
|
], 201);
|
|
|
|
|
|
|
|
|
|
} catch (\Exception $e) {
|
2025-08-08 13:49:18 +07:00
|
|
|
$this->db->transRollback();
|
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
private function preparePatientData(array $input, string $now, 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
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Only set CreateDate when creating
|
|
|
|
|
if ($mode === 'create') {
|
|
|
|
|
$data["CreateDate"] = $now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function preparePatidtData(array $input, string $now, string $mode = 'create'): array {
|
|
|
|
|
$data = [
|
|
|
|
|
"IdentifierType" => $input['Identity']['IdentifierType'] ?? null,
|
|
|
|
|
"Identifier" => $input['Identity']['Identifier'] ?? null,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($mode === 'create') {
|
|
|
|
|
$data["CreateDate"] = $now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function preparePatattData(array $input, string $now, string $mode = 'create'): array {
|
|
|
|
|
if (empty($input['Attachments'])) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return array_map(function ($attachment) use ($now, $mode) {
|
|
|
|
|
$row = [
|
|
|
|
|
"Address" => $attachment['Address'] ?? null,
|
|
|
|
|
];
|
|
|
|
|
if ($mode === 'create') {
|
|
|
|
|
$row["CreateDate"] = $now;
|
|
|
|
|
}
|
|
|
|
|
return $row;
|
|
|
|
|
}, $input['Attachments']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function preparePatcomData(array $input, string $now, string $mode = 'create'): array {
|
|
|
|
|
$data = [
|
|
|
|
|
"Comment" => $input['Comment'] ?? null,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if ($mode === 'create') {
|
|
|
|
|
$data["CreateDate"] = $now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private function validationError(string $context, array $errors)
|
|
|
|
|
{
|
|
|
|
|
return $this->respond([
|
|
|
|
|
'status' => 'error',
|
|
|
|
|
'message' => "Validation failed ({$context})",
|
|
|
|
|
'errors' => $errors
|
|
|
|
|
], 400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-08-01 22:33:41 +07:00
|
|
|
// OK - Done
|
2025-08-01 22:18:45 +07:00
|
|
|
public function update($InternalPID = null) {
|
2025-07-23 11:03:46 +07:00
|
|
|
try {
|
2025-09-08 15:56:38 +07:00
|
|
|
$now = $this->now;
|
|
|
|
|
if (!$InternalPID || !is_numeric($InternalPID)) { return $this->respond(['status' => 'error', 'message' => 'Invalid or missing InternalPID'], 400); }
|
2025-08-01 22:33:41 +07:00
|
|
|
|
2025-07-23 11:03:46 +07:00
|
|
|
$input = $this->request->getJSON(true);
|
2025-09-08 15:56:38 +07:00
|
|
|
if (!$input) { return $this->respond(['status' => 'error', 'message' => 'Invalid JSON input'], 400); }
|
2025-08-12 09:19:10 +07:00
|
|
|
|
|
|
|
|
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRowArray();
|
2025-09-08 15:56:38 +07:00
|
|
|
if (!$patient) { return $this->respond(['status' => 'error', 'message' => 'Patient not found'], 404); }
|
2025-07-02 16:10:37 +07:00
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
$dataPatient = $this->preparePatientData($input, $now, 'update');
|
|
|
|
|
$dataPatidt = $this->preparePatidtData($input, $now, 'update');
|
|
|
|
|
$dataPatcom = $this->preparePatcomData($input, $now, 'update');
|
|
|
|
|
$dataPatatt = $this->preparePatattData($input, $now, 'update');
|
2025-08-04 10:26:26 +07:00
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
// Atur aturan validasi dengan pengecualian is_unique untuk InternalPID ini
|
2025-08-11 14:12:07 +07:00
|
|
|
$rulesDataPatient = [
|
2025-08-12 09:19:10 +07:00
|
|
|
'PatientID' => "required|max_length[50]|is_unique[patient.PatientID,InternalPID,{$InternalPID}]",
|
2025-08-11 14:12:07 +07:00
|
|
|
'AlternatePID' => 'permit_empty|max_length[50]',
|
|
|
|
|
'NameFirst' => 'required|min_length[1]|max_length[255]',
|
2025-08-12 09:19:10 +07:00
|
|
|
'EmailAddress1' => "required|is_unique[patient.EmailAddress1,InternalPID,{$InternalPID}]",
|
2025-08-11 14:12:07 +07:00
|
|
|
'Gender' => 'required'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$rulesDataPatidt = [
|
2025-08-12 09:19:10 +07:00
|
|
|
'Identifier' => "required|is_unique[patidt.Identifier,InternalPID,{$InternalPID}]"
|
2025-08-01 13:37:13 +07:00
|
|
|
];
|
2025-08-12 09:19:10 +07:00
|
|
|
|
|
|
|
|
// Validasi
|
|
|
|
|
if (!$this->validateData($dataPatient, $rulesDataPatient)) {
|
|
|
|
|
return $this->respond([
|
|
|
|
|
'status' => 'error',
|
|
|
|
|
'message' => 'Validation failed (patient)',
|
|
|
|
|
'errors' => $this->validator->getErrors()
|
|
|
|
|
], 400);
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
if (!$this->validateData($dataPatidt, $rulesDataPatidt)) {
|
|
|
|
|
return $this->respond([
|
|
|
|
|
'status' => 'error',
|
|
|
|
|
'message' => 'Validation failed (patidt)',
|
|
|
|
|
'errors' => $this->validator->getErrors()
|
|
|
|
|
], 400);
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
$this->db->transStart();
|
2025-07-23 11:03:46 +07:00
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
$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']);
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
$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']);
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 15:56:38 +07:00
|
|
|
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)->delete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!empty($dataPatcom['Comment'])) {
|
|
|
|
|
$dataPatcom['InternalPID'] = $InternalPID;
|
|
|
|
|
$dataPatcom['CreateDate'] = $this->now;
|
|
|
|
|
$this->db->table('patcom')->upsert($dataPatcom);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
$this->db->transComplete();
|
2025-07-02 16:10:37 +07:00
|
|
|
|
2025-08-12 09:19:10 +07:00
|
|
|
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',
|
2025-07-23 11:03:46 +07:00
|
|
|
'message' => 'Patient updated successfully',
|
2025-08-12 09:19:10 +07:00
|
|
|
'data' => $InternalPID
|
|
|
|
|
], 200);
|
2025-07-02 16:10:37 +07:00
|
|
|
|
2025-07-23 11:03:46 +07:00
|
|
|
} catch (\Exception $e) {
|
2025-08-12 09:19:10 +07:00
|
|
|
$this->db->transRollback();
|
|
|
|
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
|
|
|
|
}
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|
2025-07-23 11:03:46 +07:00
|
|
|
|
2025-08-01 22:33:41 +07:00
|
|
|
// OK - Done
|
2025-08-01 22:18:45 +07:00
|
|
|
public function delete($InternalPID = null) {
|
2025-07-23 11:03:46 +07:00
|
|
|
|
|
|
|
|
try {
|
2025-08-01 22:33:41 +07:00
|
|
|
|
|
|
|
|
$InternalPID = (int) $InternalPID;
|
2025-07-23 11:03:46 +07:00
|
|
|
|
2025-08-01 22:18:45 +07:00
|
|
|
if (!$InternalPID) {
|
2025-07-23 11:03:46 +07:00
|
|
|
return $this->failValidationError('Patient ID is required.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cari data pasien
|
2025-08-01 22:26:27 +07:00
|
|
|
$patient = $this->db->table('patient')->where('InternalPID', $InternalPID)->get()->getRow();
|
2025-07-23 11:03:46 +07:00
|
|
|
|
|
|
|
|
if (!$patient) {
|
2025-08-01 22:18:45 +07:00
|
|
|
return $this->failNotFound("Patient ID with {$InternalPID} not found.");
|
2025-07-23 11:03:46 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-05 10:03:33 +07:00
|
|
|
// Update kolom DelDate sebagai soft delete
|
|
|
|
|
$this->db->table('patient')->where('InternalPID', $InternalPID)->update(['DelDate' => date('Y-m-d H:i:s')]);
|
2025-07-23 11:03:46 +07:00
|
|
|
|
|
|
|
|
// Mengembalikan 200
|
|
|
|
|
return $this->respondDeleted([
|
|
|
|
|
'status' => 'success',
|
2025-08-01 22:18:45 +07:00
|
|
|
'message' => "Patient ID with {$InternalPID} deleted successfully."
|
2025-07-23 11:03:46 +07:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
return $this->failServerError("Internal server error: " . $e->getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-14 15:28:16 +07:00
|
|
|
// OK - Done
|
|
|
|
|
public function patientCheck() {
|
|
|
|
|
|
2025-08-14 09:17:15 +07:00
|
|
|
try {
|
2025-08-14 15:28:16 +07:00
|
|
|
|
|
|
|
|
$PatientID = $this->request->getVar('PatientID');
|
|
|
|
|
$EmailAddress1 = $this->request->getVar('EmailAddress1');
|
|
|
|
|
|
|
|
|
|
if ($PatientID!=null){
|
|
|
|
|
$tableName = 'PatientID';
|
|
|
|
|
$searchName = $PatientID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($EmailAddress1!=null){
|
|
|
|
|
$tableName = 'EmailAddress1';
|
|
|
|
|
$searchName = $EmailAddress1;
|
2025-08-14 09:17:15 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$patient = $this->db->table('patient')
|
2025-08-14 15:28:16 +07:00
|
|
|
->where($tableName, $searchName)
|
2025-08-14 09:17:15 +07:00
|
|
|
->get()
|
|
|
|
|
->getRowArray();
|
|
|
|
|
|
|
|
|
|
if (!$patient) {
|
|
|
|
|
return $this->respond([
|
|
|
|
|
'status' => 'success',
|
2025-08-14 15:28:16 +07:00
|
|
|
'message' => "$tableName not found.",
|
2025-08-14 09:17:15 +07:00
|
|
|
'data' => true,
|
|
|
|
|
], 200);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->respond([
|
|
|
|
|
'status' => 'success',
|
2025-08-14 15:28:16 +07:00
|
|
|
'message' => "$tableName already exists.",
|
2025-08-14 09:17:15 +07:00
|
|
|
'data' => false,
|
|
|
|
|
], 200);
|
|
|
|
|
|
2025-08-14 15:28:16 +07:00
|
|
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
// Error Server Mengembalikan 500
|
|
|
|
|
return $this->failServerError('Something went wrong.'.$e->getMessage());
|
2025-08-14 09:17:15 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-08-12 11:31:29 +07:00
|
|
|
// Ubah ke format Years Months Days
|
2025-08-11 16:14:26 +07:00
|
|
|
private function calculateAgeFromBirthdate($birthdate) {
|
2025-08-11 16:15:40 +07:00
|
|
|
$dob = new \DateTime($birthdate);
|
|
|
|
|
$today = new \DateTime();
|
2025-08-11 16:14:26 +07:00
|
|
|
$diff = $today->diff($dob);
|
|
|
|
|
|
2025-08-11 20:58:31 +07:00
|
|
|
$formattedAge = "";
|
|
|
|
|
if ($diff->y > 0){
|
2025-08-12 11:03:03 +07:00
|
|
|
$formattedAge .= "{$diff->y} Years ";
|
2025-08-11 20:58:31 +07:00
|
|
|
}
|
|
|
|
|
if ($diff->m > 0){
|
2025-08-12 11:03:03 +07:00
|
|
|
$formattedAge .= "{$diff->m} Months ";
|
2025-08-11 20:58:31 +07:00
|
|
|
}
|
|
|
|
|
if ($diff->d > 0){
|
2025-08-12 11:03:03 +07:00
|
|
|
$formattedAge .= "{$diff->d} Days";
|
2025-08-11 20:58:31 +07:00
|
|
|
}
|
|
|
|
|
|
2025-08-11 16:14:26 +07:00
|
|
|
return $formattedAge;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-12 11:31:29 +07:00
|
|
|
// Ubah ke format Y-m-d H:i
|
|
|
|
|
private function formatedDate($dateString) {
|
2025-08-12 11:03:03 +07:00
|
|
|
$date = \DateTime::createFromFormat('Y-m-d H:i', $dateString);
|
|
|
|
|
|
|
|
|
|
if (!$date) {
|
|
|
|
|
$timestamp = strtotime($dateString);
|
|
|
|
|
if ($timestamp) {
|
|
|
|
|
return date('Y-m-d H:i', $timestamp);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $date->format('Y-m-d H:i');
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-12 11:31:29 +07:00
|
|
|
// Ubah ke format j M Y
|
|
|
|
|
private function formatedDateForDisplay($dateString) {
|
2025-08-12 11:03:03 +07:00
|
|
|
$date = \DateTime::createFromFormat('Y-m-d H:i', $dateString);
|
|
|
|
|
|
|
|
|
|
if (!$date) {
|
|
|
|
|
$timestamp = strtotime($dateString);
|
|
|
|
|
if ($timestamp) {
|
|
|
|
|
return date('j M Y', $timestamp);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $date->format('j M Y');
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-02 16:10:37 +07:00
|
|
|
}
|