select("InternalPID, PatientID, $qname as FullName, Gender, Birthdate, EmailAddress1 as Email, MobilePhone"); if (!empty($filters['Name'])) { $this->like($qname, $filters['Name'], 'both'); } if (!empty($filters['InternalPID'])) { $this->where('InternalPID', $filters['InternalPID']); } if (!empty($filters['PatientID'])) { $this->like('PatientID', $filters['PatientID'], 'both'); } if (!empty($filters['Birthdate'])) { $this->where('Birthdate', $filters['Birthdate']); } return $this->findAll(); } public function getPatient($InternalPID) { $rows = $this->select(" patient.*, country.VDesc as Country, country.VID as CountryVID, race.VDesc as Race, race.VID as RaceVID, religion.VDesc as Religion, religion.VID as ReligionVID, ethnic.VDesc as Ethnic, ethnic.VID as EthnicVID, gender.VDesc as Gender, gender.VID as GenderVID, deathindicator.VDesc as DeathIndicator, deathindicator.VID as DeathIndicatorVID, maritalstatus.VDesc as MaritalStatus, maritalstatus.VID as MaritalStatusVID, patcom.Comment as Comment, patidt.IdentifierType, patidt.Identifier, patatt.Address, zones1.zonename as Province, zones2.zonename as City ") ->join('valueset country', 'country.VID = patient.Country', 'left') ->join('valueset race', 'race.VID = patient.Race', 'left') ->join('valueset religion', 'religion.VID = patient.Religion', 'left') ->join('valueset ethnic', 'ethnic.VID = patient.Ethnic', 'left') ->join('valueset gender', 'gender.VID = patient.Gender', 'left') ->join('valueset deathindicator', 'deathindicator.VID = patient.DeathIndicator', 'left') ->join('valueset maritalstatus', 'maritalstatus.VID = patient.MaritalStatus', 'left') ->join('patcom', 'patcom.InternalPID = patient.InternalPID', 'left') ->join('patidt', 'patidt.InternalPID = patient.InternalPID', 'left') ->join('patatt', 'patatt.InternalPID = patient.InternalPID and patatt.DelDate is null', 'left') ->join('zones zones1', 'zones1.zoneid = patient.Province', 'left') ->join('zones zones2', 'zones2.zoneid = patient.City', 'left') ->where('patient.InternalPID', (int) $InternalPID) ->findAll(); if (empty($rows)) { return null; } $patient = $rows[0]; if (method_exists($this, 'transformPatientData')) { $patient = $this->transformPatientData($patient); } unset($patient['Address']); unset($patient['IdentifierType']); unset($patient['Identifier']); unset($patient['Comment']); // 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(); $modelPatAtt = new PatAttModel(); $modelPatCom = new PatComModel(); $modelPatIdt = new PatIdtModel(); $input['LinkTo'] = empty($input['LinkTo']) ? null : $input['LinkTo']; $db->transBegin(); try { // Insert Data ke Tabel Patient, get ID dan cek apa ada error $this->insert($input); $newInternalPID = $this->getInsertID(); $this->checkDbError($db, 'Insert patient'); // Insert Data ke Tabel PatIdt if (!empty($input['PatIdt'])) { $modelPatIdt->createPatIdt($input['PatIdt'], $newInternalPID); $this->checkDbError($db, 'Insert PatIdt'); } // Insert Data ke Tabel PatCom if (!empty($input['PatCom'])) { $modelPatCom->createPatCom($input['PatCom'], $newInternalPID); $this->checkDbError($db, 'Insert PatCom'); } // Insert Data ke Tabel PatAtt if (!empty($input['PatAtt'])) { $modelPatAtt->createPatAtt($input['PatAtt'], $newInternalPID); $this->checkDbError($db, 'Insert PatAtt'); } $db->transCommit(); return $newInternalPID; } catch (\Exception $e) { $db->transRollback(); throw $e; } } public function updatePatient($input) { $db = \Config\Database::connect(); $modelPatIdt = new PatIdtModel(); $modelPatCom = new PatComModel(); $modelPatAtt = new PatAttModel(); $input['LinkTo'] = empty($input['LinkTo']) ? null : $input['LinkTo']; $db->transBegin(); try { // Update Patient $InternalPID = $input['InternalPID']; $this->where('InternalPID',$InternalPID)->set($input)->update(); $this->checkDbError($db, 'Update patient'); // Update Patidt if (!empty($input['PatIdt'])) { $modelPatIdt->updatePatIdt($input['PatIdt'], $InternalPID); $this->checkDbError($db, 'Update patIdt'); } else { $modelPatIdt->deletePatIdt($InternalPID); $this->checkDbError($db, 'Update patidt'); } // Update Patcom if (!empty($input['PatCom'])) { $modelPatCom->updatePatCom($input['PatCom'], $InternalPID); $this->checkDbError($db, 'Update PatCom'); } else { $modelPatCom->deletePatCom($InternalPID); $this->checkDbError($db, 'Update patcom'); } // Update Patatt if (!empty($input['PatAtt'])) { $modelPatAtt->updatePatAtt($input['PatAtt'], $InternalPID); $this->checkDbError($db, 'Update PatAtt'); } else { $modelPatAtt->deletePatAtt($InternalPID); $this->checkDbError($db, 'Update/Delete patatt'); } $db->transCommit(); return $InternalPID; } catch (\Exception $e) { $db->transRollback(); throw $e; } } private function transformPatientData(array $patient): array { $patient["Age"] = $this->calculateAgeFromBirthdate($patient["Birthdate"], $patient["TimeOfDeath"]); $patient["TimeOfDeath"] = $this->formattedDate($patient["TimeOfDeath"]); $patient["CreateDate"] = $this->formattedDate($patient["CreateDate"]); $patient["BirthdateConversion"] = $this->formatedDateForDisplay($patient["Birthdate"]); $patient["LinkTo"] = $this->getLinkedPatients($patient['LinkTo']); $patient["Custodian"] = $this->getCustodian($patient['Custodian']); $patient['PatCom'] = $patient['Comment']; 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->select('InternalPID, PatientID') ->where('InternalPID', (int) $custodianId) ->first() ?: null; } // Conversion to (Years Months Days) - For Age private function calculateAgeFromBirthdate($birthdate, $deathdate) { $dob = new \DateTime($birthdate); // Cek DeathTime if ($deathdate == null) { $today = new \DateTime(); } else { $deathdate = new \DateTime($deathdate); $today = $deathdate; } $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\TH:i:s\Z private function formattedDate(?string $dateString): ?string { try { if (empty($dateString)) {return null;} $dt = new \DateTime($dateString, new \DateTimeZone("UTC")); return $dt->format('Y-m-d\TH:i:s\Z'); // ISO 8601 UTC } catch (\Exception $e) { return null; } } // Conversion Time to Format j M Y - For BirthdateConversion 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'); } // Check Error and Send Spesific Messages private function checkDbError($db, string $context) { $error = $db->error(); if (!empty($error['code'])) { throw new \Exception( "{$context} failed: {$error['code']} - {$error['message']}" ); } } // Preventif 0000-00-00 private function isValidDateTime($datetime) { if (empty($datetime) || $datetime=="") {return null; } try { // Kalau input hanya Y-m-d (tanpa jam) if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $datetime)) { $dt = \DateTime::createFromFormat('Y-m-d', $datetime); return $dt ? $dt->format('Y-m-d') : null; // hanya tanggal } // Selain itu (ISO 8601 atau datetime lain), format ke Y-m-d H:i:s $dt = new \DateTime($datetime); return $dt->format('Y-m-d H:i:s'); } catch (\Exception $e) { return null; } } }