fix(abdm): sanitize care context display, fix discharge care_context_reference and bundle generation, fix taskboard sync patientId
This commit is contained in:
parent
f7761218d0
commit
5130c6b18a
|
|
@ -2218,7 +2218,8 @@ class AbdmGateway extends BaseController
|
||||||
$dateClean = str_replace('-', '', $visitDate);
|
$dateClean = str_replace('-', '', $visitDate);
|
||||||
$ccRef = $prefix . '-' . $labReqId . '-' . $dateClean;
|
$ccRef = $prefix . '-' . $labReqId . '-' . $dateClean;
|
||||||
}
|
}
|
||||||
$careContextDisplay = ($isImaging ? 'Radiology Report - ' : 'Diagnostic Report - ') . ($testTitle !== '' ? $testTitle : ($isImaging ? 'Radiology Report' : 'Lab Report')) . ' (' . date('d M Y', strtotime($visitDate)) . ')';
|
$cleanTestTitle = self::sanitizeCareContextDisplay($testTitle !== '' ? $testTitle : ($isImaging ? 'Radiology Report' : 'Lab Report'));
|
||||||
|
$careContextDisplay = self::sanitizeCareContextDisplay(($isImaging ? 'Radiology Report - ' : 'Diagnostic Report - ') . $cleanTestTitle . ' ' . date('d M Y', strtotime($visitDate)));
|
||||||
|
|
||||||
$healthRecordId = $this->storeHealthRecord([
|
$healthRecordId = $this->storeHealthRecord([
|
||||||
'patient_id' => $patientId,
|
'patient_id' => $patientId,
|
||||||
|
|
@ -3190,6 +3191,12 @@ class AbdmGateway extends BaseController
|
||||||
$diagnoses[] = ['text' => $problem, 'code' => ''];
|
$diagnoses[] = ['text' => $problem, 'code' => ''];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (empty($diagnoses) && ! empty($chiefComplaints)) {
|
||||||
|
$diagnoses = $chiefComplaints;
|
||||||
|
}
|
||||||
|
if (empty($diagnoses) && empty($procedures)) {
|
||||||
|
$diagnoses[] = ['text' => 'Medical care and evaluation', 'code' => ''];
|
||||||
|
}
|
||||||
$chiefComplaintNarrative = trim((string) (($this->ipdRows('ipd_discharge_complaint_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
$chiefComplaintNarrative = trim((string) (($this->ipdRows('ipd_discharge_complaint_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
||||||
$diagnosisNarrative = trim((string) (($this->ipdRows('ipd_discharge_diagnosis_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
$diagnosisNarrative = trim((string) (($this->ipdRows('ipd_discharge_diagnosis_remark', ['comp_remark'], $ipdId)[0]['comp_remark'] ?? '')));
|
||||||
|
|
||||||
|
|
@ -3368,9 +3375,13 @@ class AbdmGateway extends BaseController
|
||||||
|
|
||||||
$uniqueSuffix = $isNewRecord ? ('-v' . time()) : '';
|
$uniqueSuffix = $isNewRecord ? ('-v' . time()) : '';
|
||||||
|
|
||||||
|
$ccRef = 'DISCHARGE-' . $ipdId . '-' . str_replace('-', '', (string) $visitDate) . $uniqueSuffix;
|
||||||
|
$ccDisplay = 'DischargeSummaryRecord - ' . date('d M Y', strtotime((string) $visitDate));
|
||||||
|
|
||||||
$source = [
|
$source = [
|
||||||
'record_id' => (string) $ipdId,
|
'record_id' => (string) $ipdId,
|
||||||
'care_context_reference' => 'DISCHARGE-' . $ipdId . '-S' . $ipdId . '-' . $visitDate . $uniqueSuffix,
|
'care_context_reference' => $ccRef,
|
||||||
|
'care_context_display' => $ccDisplay,
|
||||||
'bundle_identifier' => 'discharge-' . (trim((string) ($ipdRow['ipd_code'] ?? '')) ?: (string) $ipdId) . $uniqueSuffix,
|
'bundle_identifier' => 'discharge-' . (trim((string) ($ipdRow['ipd_code'] ?? '')) ?: (string) $ipdId) . $uniqueSuffix,
|
||||||
'session_id' => (string) $ipdId,
|
'session_id' => (string) $ipdId,
|
||||||
'visit_date' => $visitDate,
|
'visit_date' => $visitDate,
|
||||||
|
|
@ -3379,6 +3390,9 @@ class AbdmGateway extends BaseController
|
||||||
'doctor_name' => $doctorName,
|
'doctor_name' => $doctorName,
|
||||||
'discharge_status' => $dischargeStatus,
|
'discharge_status' => $dischargeStatus,
|
||||||
'problem' => trim((string) ($ipdRow['problem'] ?? '')),
|
'problem' => trim((string) ($ipdRow['problem'] ?? '')),
|
||||||
|
'diagnoses' => $diagnoses,
|
||||||
|
'conditions' => $diagnoses,
|
||||||
|
'chief_complaints' => $chiefComplaints,
|
||||||
'doctor' => [
|
'doctor' => [
|
||||||
'id' => $doctorId > 0 ? (string) $doctorId : '',
|
'id' => $doctorId > 0 ? (string) $doctorId : '',
|
||||||
'name' => $doctorName,
|
'name' => $doctorName,
|
||||||
|
|
@ -6398,7 +6412,8 @@ class AbdmGateway extends BaseController
|
||||||
$visitDate = date('Y-m-d', strtotime((string) $reportedDate));
|
$visitDate = date('Y-m-d', strtotime((string) $reportedDate));
|
||||||
$dateStr = date('d M Y', strtotime($visitDate));
|
$dateStr = date('d M Y', strtotime($visitDate));
|
||||||
$ccRef = $prefix . '-' . $taskEntityId . '-' . str_replace('-', '', $visitDate);
|
$ccRef = $prefix . '-' . $taskEntityId . '-' . str_replace('-', '', $visitDate);
|
||||||
$display = ($isImaging ? 'Radiology Report - ' : 'Diagnostic Report - ') . $title . ' (' . $dateStr . ')';
|
$cleanTitle = self::sanitizeCareContextDisplay($title);
|
||||||
|
$display = self::sanitizeCareContextDisplay(($isImaging ? 'Radiology Report - ' : 'Diagnostic Report - ') . $cleanTitle . ' ' . $dateStr);
|
||||||
|
|
||||||
$hasFindings = trim((string) ($labReq['Report_Data'] ?? '')) !== '' || trim((string) ($labReq['report_data_Impression'] ?? '')) !== '';
|
$hasFindings = trim((string) ($labReq['Report_Data'] ?? '')) !== '' || trim((string) ($labReq['report_data_Impression'] ?? '')) !== '';
|
||||||
$statusVal = (int) ($labReq['status'] ?? 0);
|
$statusVal = (int) ($labReq['status'] ?? 0);
|
||||||
|
|
@ -6711,7 +6726,8 @@ class AbdmGateway extends BaseController
|
||||||
$visitDate = date('Y-m-d', strtotime((string) $reportedDate));
|
$visitDate = date('Y-m-d', strtotime((string) $reportedDate));
|
||||||
$dateStr = date('d M Y', strtotime($visitDate));
|
$dateStr = date('d M Y', strtotime($visitDate));
|
||||||
$ccRef = $prefix . '-' . $lr['id'] . '-' . str_replace('-', '', $visitDate);
|
$ccRef = $prefix . '-' . $lr['id'] . '-' . str_replace('-', '', $visitDate);
|
||||||
$display = ($isImaging ? 'Radiology Report - ' : 'Diagnostic Report - ') . $title . ' (' . $dateStr . ')';
|
$cleanTitle = self::sanitizeCareContextDisplay($title);
|
||||||
|
$display = self::sanitizeCareContextDisplay(($isImaging ? 'Radiology Report - ' : 'Diagnostic Report - ') . $cleanTitle . ' ' . $dateStr);
|
||||||
|
|
||||||
$hasFindings = trim((string) ($lr['Report_Data'] ?? '')) !== '' || trim((string) ($lr['report_data_Impression'] ?? '')) !== '';
|
$hasFindings = trim((string) ($lr['Report_Data'] ?? '')) !== '' || trim((string) ($lr['report_data_Impression'] ?? '')) !== '';
|
||||||
$statusVal = (int) ($lr['status'] ?? 0);
|
$statusVal = (int) ($lr['status'] ?? 0);
|
||||||
|
|
@ -11939,6 +11955,17 @@ class AbdmGateway extends BaseController
|
||||||
// Body: { abha_address, link_token_id, patient_ref, display, hi_type, care_contexts[] }
|
// Body: { abha_address, link_token_id, patient_ref, display, hi_type, care_contexts[] }
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
|
public static function sanitizeCareContextDisplay(string $display): string
|
||||||
|
{
|
||||||
|
$display = str_replace('&', 'and', $display);
|
||||||
|
$display = preg_replace('/[^a-zA-Z0-9 \-_.]/', ' ', $display);
|
||||||
|
$display = trim(preg_replace('/\s+/', ' ', (string) $display));
|
||||||
|
if (mb_strlen($display) > 100) {
|
||||||
|
$display = mb_substr($display, 0, 100);
|
||||||
|
}
|
||||||
|
return $display;
|
||||||
|
}
|
||||||
|
|
||||||
public function hipLinkCareContext()
|
public function hipLinkCareContext()
|
||||||
{
|
{
|
||||||
if (ENVIRONMENT !== 'testing' && ! $this->request->isAJAX()) {
|
if (ENVIRONMENT !== 'testing' && ! $this->request->isAJAX()) {
|
||||||
|
|
@ -12015,6 +12042,46 @@ class AbdmGateway extends BaseController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! empty($body['display'])) {
|
||||||
|
$body['display'] = self::sanitizeCareContextDisplay((string) $body['display']);
|
||||||
|
}
|
||||||
|
if (! empty($body['care_contexts']) && is_array($body['care_contexts'])) {
|
||||||
|
foreach ($body['care_contexts'] as &$cc) {
|
||||||
|
if (isset($cc['display'])) {
|
||||||
|
$cc['display'] = self::sanitizeCareContextDisplay((string) $cc['display']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-ensure health record bundle is pushed to bridge for linked discharge care contexts
|
||||||
|
if (! empty($body['care_contexts']) && is_array($body['care_contexts'])) {
|
||||||
|
foreach ($body['care_contexts'] as $ccItem) {
|
||||||
|
$refNo = (string) ($ccItem['referenceNumber'] ?? $ccItem['reference_number'] ?? $ccItem['ref'] ?? $ccItem['careContextId'] ?? '');
|
||||||
|
if (str_starts_with($refNo, 'DISCHARGE-')) {
|
||||||
|
if (preg_match('/^DISCHARGE-(\d+)/', $refNo, $mIpd)) {
|
||||||
|
$targetIpdId = (int) $mIpd[1];
|
||||||
|
if ($targetIpdId > 0 && class_exists('\App\Controllers\Ipd_discharge')) {
|
||||||
|
try {
|
||||||
|
$ipdCtrl = new \App\Controllers\Ipd_discharge();
|
||||||
|
$ipdCtrl->initController($this->request, $this->response, $this->logger);
|
||||||
|
$refIpd = new \ReflectionClass($ipdCtrl);
|
||||||
|
if ($refIpd->hasMethod('enqueueIpdDischargeFhirSync')) {
|
||||||
|
$mSync = $refIpd->getMethod('enqueueIpdDischargeFhirSync');
|
||||||
|
$mSync->setAccessible(true);
|
||||||
|
$ipdRow = $this->db->table('ipd_master')->where('id', $targetIpdId)->get(1)->getRowArray() ?? [];
|
||||||
|
$pRow = $this->db->table('patient_master')->where('id', $patientId)->get(1)->getRowArray() ?? [];
|
||||||
|
$mSync->invoke($ipdCtrl, $targetIpdId, $patientId, $ipdRow, $pRow);
|
||||||
|
}
|
||||||
|
} catch (\Throwable $eIpd) {
|
||||||
|
log_message('warning', 'hipLinkCareContext IPD sync error: ' . $eIpd->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$result = $this->connector->hipLinkCareContext($body);
|
$result = $this->connector->hipLinkCareContext($body);
|
||||||
return $this->response->setJSON($result);
|
return $this->response->setJSON($result);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9420,6 +9420,13 @@ class Ipd_discharge extends BaseController
|
||||||
$chiefComplaintsList[] = ['text' => $complaintRemarkText, 'code' => ''];
|
$chiefComplaintsList[] = ['text' => $complaintRemarkText, 'code' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($conditionRows) && ! empty($chiefComplaintsList)) {
|
||||||
|
$conditionRows = $chiefComplaintsList;
|
||||||
|
}
|
||||||
|
if (empty($conditionRows)) {
|
||||||
|
$conditionRows[] = ['text' => 'Medical care and evaluation', 'code' => ''];
|
||||||
|
}
|
||||||
|
|
||||||
$procedureRows = [];
|
$procedureRows = [];
|
||||||
foreach ($this->byIpdRows('ipd_discharge_surgery', ['surgery_name', 'surgery_date'], 'id ASC', $ipdId) as $row) {
|
foreach ($this->byIpdRows('ipd_discharge_surgery', ['surgery_name', 'surgery_date'], 'id ASC', $ipdId) as $row) {
|
||||||
$text = trim((string) ($row['surgery_name'] ?? ''));
|
$text = trim((string) ($row['surgery_name'] ?? ''));
|
||||||
|
|
@ -9686,8 +9693,13 @@ class Ipd_discharge extends BaseController
|
||||||
$patientPin = trim((string) ($patientRow['p_pin'] ?? $patientRow['pincode'] ?? ''));
|
$patientPin = trim((string) ($patientRow['p_pin'] ?? $patientRow['pincode'] ?? ''));
|
||||||
$dischargeStatus = trim((string) ($ipdRow['discarge_patient_status'] ?? ''));
|
$dischargeStatus = trim((string) ($ipdRow['discarge_patient_status'] ?? ''));
|
||||||
|
|
||||||
|
$ccRef = 'DISCHARGE-' . $ipdId . '-' . str_replace('-', '', (string) $visitDate);
|
||||||
|
$ccDisplay = 'DischargeSummaryRecord - ' . date('d M Y', strtotime((string) $visitDate));
|
||||||
|
|
||||||
$source = [
|
$source = [
|
||||||
'record_id' => (string) $ipdId,
|
'record_id' => (string) $ipdId,
|
||||||
|
'care_context_reference' => $ccRef,
|
||||||
|
'care_context_display' => $ccDisplay,
|
||||||
'bundle_identifier' => 'discharge-' . $ipdNo,
|
'bundle_identifier' => 'discharge-' . $ipdNo,
|
||||||
'session_id' => (string) $ipdId,
|
'session_id' => (string) $ipdId,
|
||||||
'visit_date' => $visitDate,
|
'visit_date' => $visitDate,
|
||||||
|
|
@ -9696,6 +9708,9 @@ class Ipd_discharge extends BaseController
|
||||||
'doctor_name' => trim((string) ($ipdRow['r_doc_name'] ?? '')),
|
'doctor_name' => trim((string) ($ipdRow['r_doc_name'] ?? '')),
|
||||||
'discharge_status' => $dischargeStatus,
|
'discharge_status' => $dischargeStatus,
|
||||||
'problem' => trim((string) ($ipdRow['problem'] ?? '')),
|
'problem' => trim((string) ($ipdRow['problem'] ?? '')),
|
||||||
|
'diagnoses' => $conditionRows,
|
||||||
|
'conditions' => $conditionRows,
|
||||||
|
'chief_complaints' => $chiefComplaintsList,
|
||||||
'organization' => [
|
'organization' => [
|
||||||
'id' => $hfrId,
|
'id' => $hfrId,
|
||||||
'name' => $hospitalName,
|
'name' => $hospitalName,
|
||||||
|
|
@ -9773,6 +9788,30 @@ class Ipd_discharge extends BaseController
|
||||||
|
|
||||||
$outbox = new AbdmSyncOutboxService();
|
$outbox = new AbdmSyncOutboxService();
|
||||||
$outbox->enqueueRecordSync($syncPayload);
|
$outbox->enqueueRecordSync($syncPayload);
|
||||||
|
|
||||||
|
// Also push synchronously to E-Atria bridge so the bundle is immediately accessible to PHR apps
|
||||||
|
try {
|
||||||
|
$connector = new \App\Libraries\Abdm\EAtriaBridgeConnector();
|
||||||
|
$pushData = [
|
||||||
|
'patient_id' => (string) $patientId,
|
||||||
|
'patient_name' => (string) ($gatewayPayload['patient_name'] ?? $patientName),
|
||||||
|
'abha_id' => (string) ($gatewayPayload['abha_id'] ?? $abhaDigits),
|
||||||
|
'abha_address' => (string) ($gatewayPayload['abha_address'] ?? $abhaAddress),
|
||||||
|
'hi_type' => 'DischargeSummaryRecord',
|
||||||
|
'record_type' => 'DischargeSummaryRecord',
|
||||||
|
'visit_date' => (string) ($gatewayPayload['visit_date'] ?? $visitDate),
|
||||||
|
'care_context_reference' => $ccRef,
|
||||||
|
'care_context_display' => $ccDisplay,
|
||||||
|
'notes' => $ccDisplay,
|
||||||
|
'queue_id' => $ccRef,
|
||||||
|
'bundle' => (array) ($gatewayPayload['fhir_bundle'] ?? []),
|
||||||
|
'fhir_bundle' => (array) ($gatewayPayload['fhir_bundle'] ?? []),
|
||||||
|
'record_data' => (array) ($gatewayPayload['fhir_bundle'] ?? []),
|
||||||
|
];
|
||||||
|
$connector->pushRecord($pushData);
|
||||||
|
} catch (\Throwable $pe) {
|
||||||
|
log_message('warning', '[enqueueIpdDischargeFhirSync] Direct bridge push error: ' . $pe->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizeFhirGender(string $gender): string
|
private function normalizeFhirGender(string $gender): string
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,17 @@ class DischargeFhirGenerator extends \App\Libraries\Abdm\Fhir\Generators\Abstrac
|
||||||
$patientRef = 'urn:uuid:patient-' . $patientId;
|
$patientRef = 'urn:uuid:patient-' . $patientId;
|
||||||
$encounterRef = is_array($encounter) ? 'urn:uuid:' . (string) ($encounter['id'] ?? '') : null;
|
$encounterRef = is_array($encounter) ? 'urn:uuid:' . (string) ($encounter['id'] ?? '') : null;
|
||||||
|
|
||||||
$diagnosesList = (array) ($source['diagnoses'] ?? $source['conditions'] ?? []);
|
$diagnosesList = (array) ($source['diagnoses'] ?? $source['conditions'] ?? $source['ui_final_diagnosis'] ?? []);
|
||||||
$chiefComplaintsList = (array) ($source['chief_complaints'] ?? []);
|
$chiefComplaintsList = (array) ($source['chief_complaints'] ?? $source['ui_complaints'] ?? []);
|
||||||
|
|
||||||
|
if (empty($diagnosesList) && empty($chiefComplaintsList)) {
|
||||||
|
$problem = trim((string) ($source['problem'] ?? ''));
|
||||||
|
if ($problem !== '') {
|
||||||
|
$diagnosesList = [['text' => $problem, 'code' => '']];
|
||||||
|
} else {
|
||||||
|
$diagnosesList = [['text' => 'Medical care and evaluation', 'code' => '']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$conditionGroups = [
|
$conditionGroups = [
|
||||||
[
|
[
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,8 @@ class AbdmTaskBoardSyncService
|
||||||
}
|
}
|
||||||
|
|
||||||
$opdId = (int) ($row['opd_id'] ?? 0);
|
$opdId = (int) ($row['opd_id'] ?? 0);
|
||||||
if ($opdId <= 0) {
|
$patientId = (int) ($row['p_id'] ?? 0);
|
||||||
|
if ($opdId <= 0 || $patientId <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -895,6 +896,23 @@ class AbdmTaskBoardSyncService
|
||||||
log_message('warning', '[processIndividualWorkTask] Wellness bundle generation error: ' . $we->getMessage());
|
log_message('warning', '[processIndividualWorkTask] Wellness bundle generation error: ' . $we->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif ($taskType === 'ipd_discharge_publish') {
|
||||||
|
if ($this->db->tableExists('abdm_sync_record')) {
|
||||||
|
$syncRec = $this->db->table('abdm_sync_record')
|
||||||
|
->where('local_record_id', 'ipd-discharge-' . $entityId)
|
||||||
|
->orWhere('care_context_reference', $careContextRef)
|
||||||
|
->get(1)
|
||||||
|
->getRowArray();
|
||||||
|
if (! empty($syncRec['fhir_bundle_json'])) {
|
||||||
|
$decodedBundle = json_decode((string) $syncRec['fhir_bundle_json'], true);
|
||||||
|
if (is_array($decodedBundle) && ! empty($decodedBundle)) {
|
||||||
|
$pushData['bundle'] = $decodedBundle;
|
||||||
|
$pushData['fhir_bundle'] = $decodedBundle;
|
||||||
|
$pushData['record_data'] = $decodedBundle;
|
||||||
|
$bundleJson = (string) $syncRec['fhir_bundle_json'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user