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'); } }