clqms-be/app/Models/PatientModel.php
2025-10-01 15:38:58 +07:00

281 lines
8.7 KiB
PHP

<?php
namespace App\Models;
use CodeIgniter\Model;
use CodeIgniter\Database\RawSql;
class PatientModel extends Model {
protected $table = 'patient';
protected $primaryKey = 'InternalPID';
protected $allowedFields = ['PatientID', 'AlternatePID', 'Prefix', 'NameFirst', 'NameMiddle', 'NameMaiden', 'NameLast', 'Suffix', 'NameAlias', 'Gender', 'PlaceOfBirth', 'Street_1', 'Street_2', 'Street_3',
'City', 'Province', 'ZIP', 'EmailAddress1', 'EmailAddress2', 'Phone', 'MobilePhone', 'Custodian', 'AccountNumber', 'Country', 'Race', 'MaritalStatus', 'Religion', 'Ethnic', 'Citizenship',
'DeathIndicator', 'DeathDateTime', 'LinkTo' ];
public function getPatients($filters = []) {
$qname = "LOWER(CONCAT_WS(' ', IFNULL(Prefix,''), IFNULL(NameFirst,''), IFNULL(NameMiddle,''), IFNULL(NameLast,''), IFNULL(NameMaiden,''), IFNULL(Suffix,'')))";
$builder = $this->db->table($this->table);
$builder->select("InternalPID, PatientID, $qname as FullName, Gender, Birthdate, EmailAddress1 as Email, MobilePhone");
if (!empty($filters['Name'])) {
$rawSql = new RawSql($qname);
$builder->like($rawSql, $filters['Name'], 'both');
}
if (!empty($filters['InternalPID'])) {
$builder->where('InternalPID', $filters['InternalPID']);
}
if (!empty($filters['PatientID'])) {
$builder->like('PatientID', $filters['PatientID'], 'both');
}
if (!empty($filters['Birthdate'])) {
$builder->where('Birthdate', $filters['Birthdate']);
}
return $builder->get()->getResultArray();
}
public function getPatient($InternalPID) {
$rows = $this->db->table('patient p')
->select("
p.*,
country.VDesc as Country,
race.VDesc as Race,
religion.VDesc as Religion,
ethnic.VDesc as Ethnic,
patcom.Comment as Comment,
patidt.IdentifierType,
patidt.Identifier,
patatt.Address
")
->join('valueset country', 'country.VID = p.Country', 'left')
->join('valueset race', 'race.VID = p.Race', 'left')
->join('valueset religion', 'religion.VID = p.Religion', 'left')
->join('valueset ethnic', 'ethnic.VID = p.Ethnic', 'left')
->join('patcom', 'patcom.InternalPID = p.InternalPID', 'left')
->join('patidt', 'patidt.InternalPID = p.InternalPID', 'left')
->join('patatt', 'patatt.InternalPID = p.InternalPID and patatt.DelDate is null', 'left')
->where('p.InternalPID', (int) $InternalPID)
->get()
->getResultArray();
if (empty($rows)) { return null; }
$patient = $rows[0];
unset($patient['Address']);
if (method_exists($this, 'transformPatientData')) { $patient = $this->transformPatientData($patient); }
// Default nested structures
$patient['PatIdt'] = null;
$patient['PatAtt'] = [];
foreach ($rows as $row) {
if ($row['IdentifierType'] && $row['Identifier'] && !$patient['PatIdt']) {
$patient['PatIdt'] = [
'IdentifierType' => $row['IdentifierType'],
'Identifier' => $row['Identifier'],
];
}
if ($row['Address']) {
$patient['PatAtt'][] = ['Address' => $row['Address']];
}
}
if (empty($patient['PatIdt'])) { $patient['PatIdt'] = null; }
if (empty($patient['PatAtt'])) { $patient['PatAtt'] = null; }
return $patient;
}
public function createPatient($input) {
$db = \Config\Database::connect();
$patidt = $input['PatIdt'] ?? [];
$patatt = $input['PatAtt'] ?? [];
$patcom['Comment'] = $input['Comment'] ?? [];
try {
$db->transStart();
$this->insert($input);
$newInternalPID = $this->getInsertID();
if (!empty($patidt)) {
$patidt['InternalPID'] = $newInternalPID;
$db->table('patidt')->insert($patidt);
}
if (!empty($patcom['Comment'])) {
$patcom['InternalPID'] = $newInternalPID;
$db->table('patcom')->insert($patcom);
}
/*
if (!empty($patatt)) {
foreach ($patatt as &$row) {
$row['InternalPID'] = $newInternalPID;
}
$db->table('patatt')->upsertBatch($patatt);
}
*/
$db->transComplete();
if ($db->transStatus() === false) {
$error = $db->error();
throw new \Exception('Transaction failed: ' . ($error['message'] ?? 'Unknown DB error'));
}
return $newInternalPID;
} catch (\Exception $e) {
$db->transRollback();
throw $e;
}
}
public function updatePatient($input) {
$db = \Config\Database::connect();
$patidt = $input['PatIdt'] ?? [];
$patatt = $input['PatAtt'] ?? [];
$patcom['Comment'] = $input['Comment'] ?? [];
try {
$db->transStart();
$InternalPID = $input['InternalPID'];
$this->where('InternalPID',$InternalPID)->set($input)->update();
if (!empty($patidt)) {
$exists = $db->table('patidt')->where('InternalPID', $InternalPID)->get()->getRowArray();
if ($exists) {
$db->table('patidt')->where('InternalPID', $InternalPID)->update($patidt);
} else {
$patidt['InternalPID'] = $InternalPID;
$db->table('patidt')->insert($patidt);
}
} else {
$db->table('patidt')->where('InternalPID', $InternalPID)->delete();
}
if (!empty($patcom)) {
$exists = $db->table('patcom')->where('InternalPID', $InternalPID)->get()->getRowArray();
if ($exists) {
$db->table('patcom')->where('InternalPID', $InternalPID)->update($patcom);
} else {
$patidt['InternalPID'] = $InternalPID;
$db->table('patcom')->insert($patcom);
}
} else {
$db->table('patcom')->where('InternalPID', $InternalPID)->delete();
}
/*
if (!empty($patatt)) {
$db->table('patatt')->where('InternalPID', $InternalPID)->delete();
foreach ($patatt as $row) {
$row['InternalPID'] = $InternalPID;
$db->table('patatt')->insert($row);
}
} else {
$db->table('patatt')->where('InternalPID', $InternalPID)->delete();
}
*/
$db->transComplete();
if ($db->transStatus() === false) {
throw new \Exception('Failed to sync patient relations');
}
return $InternalPID;
} catch (\Exception $e) {
$db->transRollback();
throw $e;
}
}
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; }
$ids = array_filter(explode(',', $linkTo));
return $this->db->table('patient')
->select('InternalPID, PatientID')
->whereIn('InternalPID', $ids)
->get()
->getResultArray() ?: null;
}
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;
}
// Conversion to (Years Months Days)
private function calculateAgeFromBirthdate($birthdate) {
$dob = new \DateTime($birthdate);
$today = new \DateTime();
$diff = $today->diff($dob);
$formattedAge = "";
if ($diff->y > 0){
$formattedAge .= "{$diff->y} Years ";
}
if ($diff->m > 0){
$formattedAge .= "{$diff->m} Months ";
}
if ($diff->d > 0){
$formattedAge .= "{$diff->d} Days";
}
return $formattedAge;
}
// Conversion Time to Format Y-m-d H:i
private function formatedDate($dateString) {
$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');
}
// Conversion Time to Format j M Y
private function formatedDateForDisplay($dateString) {
$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');
}
}