diff --git a/app/Controllers/AbdmGateway.php b/app/Controllers/AbdmGateway.php index 5647ed3..cc9060e 100644 --- a/app/Controllers/AbdmGateway.php +++ b/app/Controllers/AbdmGateway.php @@ -823,11 +823,13 @@ class AbdmGateway extends BaseController 'patient_name' => $patName, 'abha_id' => $abhaId, 'hi_type' => 'DischargeSummaryRecord', - 'record_type' => 'discharge_summary', + 'record_type' => 'DischargeSummaryRecord', 'visit_date' => $visitDate, 'doctor_name' => $doctorName, 'care_context_reference' => $ccRef, + 'care_context_display' => 'Discharge Summary - ' . ($ipdCode !== '' ? 'IPD#' . $ipdCode : 'IPD#' . $ipdId), 'notes' => 'Discharge Summary - ' . ($ipdCode !== '' ? 'IPD#' . $ipdCode : 'IPD#' . $ipdId), + 'queue_id' => 'IPD-' . $ipdId . '-' . $visitDate, 'record_data' => $bundle, ]); $queueId = (string) ($result['queue_id'] ?? ''); @@ -1014,10 +1016,12 @@ class AbdmGateway extends BaseController 'patient_name' => $patName, 'abha_id' => $abhaId, 'hi_type' => 'DiagnosticReportRecord', - 'record_type' => 'lab_report', + 'record_type' => 'DiagnosticReportRecord', 'visit_date' => $visitDate, 'care_context_reference' => $ccRef, + 'care_context_display' => $testTitle !== '' ? $testTitle : 'Lab Report', 'notes' => $testTitle !== '' ? $testTitle : 'Lab Report', + 'queue_id' => 'LAB-' . $labReqId . '-' . $visitDate, 'record_data' => $bundle, ]); $queueId = (string) ($result['queue_id'] ?? ''); @@ -1769,7 +1773,9 @@ class AbdmGateway extends BaseController 'doctor_name' => $doctorName, 'department' => $department, 'care_context_reference' => trim((string) ($hr['care_context_reference'] ?? '')), + 'care_context_display' => trim((string) ($storedPayload['care_context_display'] ?? '')), 'notes' => trim((string) ($storedPayload['care_context_display'] ?? '')), + 'queue_id' => trim((string) ($hr['care_context_reference'] ?? '')), 'record_data' => $fhirBundle, ]); $queueId = $result['queue_id'] ?? null; @@ -2958,17 +2964,19 @@ class AbdmGateway extends BaseController } /** - * Maps HMS internal ABDM hi_type strings to bridge API record_type enum values. - * Bridge accepts: prescription | lab_report | discharge_summary | wellness_record | health_document + * Maps HMS inputs to official ABDM HI record types. */ private function mapHiTypeToRecordType(string $hiType): string { return match (strtolower($hiType)) { - 'opconsultrecord', 'prescriptionrecord' => 'prescription', - 'diagnosticreportrecord' => 'lab_report', - 'dischargesummaryrecord' => 'discharge_summary', - 'wellnessrecord' => 'wellness_record', - default => 'health_document', + 'opconsultrecord', 'prescriptionrecord', 'prescription' => 'PrescriptionRecord', + 'diagnosticreportrecord', 'lab_report', 'diagnosticreport' => 'DiagnosticReportRecord', + 'dischargesummaryrecord', 'discharge_summary', 'dischargesummary' => 'DischargeSummaryRecord', + 'wellnessrecord' => 'WellnessRecord', + 'immunizationrecord' => 'ImmunizationRecord', + 'invoicerecord' => 'InvoiceRecord', + 'healthdocumentrecord', 'health_document' => 'HealthDocumentRecord', + default => 'HealthDocumentRecord', }; } diff --git a/app/Controllers/Opd_prescription.php b/app/Controllers/Opd_prescription.php index 90a1b53..0a2dbd5 100644 --- a/app/Controllers/Opd_prescription.php +++ b/app/Controllers/Opd_prescription.php @@ -5281,28 +5281,39 @@ class Opd_prescription extends BaseController } } + if ($abhaId === '') { + return $this->response->setJSON([ + 'ok' => 0, + 'error_text' => 'ABHA address is required before pushing to ABDM. Update the patient record first.', + 'csrfName' => csrf_token(), + 'csrfHash' => csrf_hash(), + ]); + } + try { $connector = new \App\Libraries\Abdm\EAtriaBridgeConnector(); $visitLabel = $visitDate !== '' ? date('d M Y', strtotime($visitDate)) : date('d M Y'); - $displayLabel = 'OPD Consultation - ' . $visitLabel . ($doctorName !== '' ? ' - Dr. ' . $doctorName : ''); + $displayLabel = 'OPD Visit ' . $visitLabel . ($doctorName !== '' ? ' - Dr. ' . $doctorName : ''); // care_context_reference must be unique per visit in ABDM spec. - // Use OPD-{id}-{date} so different visit dates generate distinct care contexts. - $ccRef = 'OPD-' . $opdId . '-' . ($visitDate !== '' ? $visitDate : date('Y-m-d')); + // Use OPD-{id}-{session} so the reference stays stable for a specific saved record. + $ccRef = 'OPD-' . $opdId . '-' . $recordId; $pushData = [ 'patient_id' => (string) $patientId, 'patient_name' => $patientName, - 'record_type' => 'prescription', + 'record_type' => 'PrescriptionRecord', + 'hi_type' => 'PrescriptionRecord', 'visit_date' => $visitDate, + 'hospital_id' => (string) $opdId, 'care_context_reference' => $ccRef, + 'care_context_display' => $displayLabel, 'notes' => $displayLabel, + 'queue_id' => 'OPD-' . $opdId . '-' . $recordId, + 'abha_address' => $abhaId, 'record_data' => $bundle, ]; - if ($abhaId !== '') { - $pushData['abha_address'] = $abhaId; - } if ($doctorName !== '') { $pushData['doctor_name'] = $doctorName; } diff --git a/app/Libraries/Abdm/EAtriaBridgeConnector.php b/app/Libraries/Abdm/EAtriaBridgeConnector.php index a411ea1..105d548 100644 --- a/app/Libraries/Abdm/EAtriaBridgeConnector.php +++ b/app/Libraries/Abdm/EAtriaBridgeConnector.php @@ -21,6 +21,7 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface private string $baseUrl; private string $token; private string $hfrId; + private string $hospitalId; private int $timeoutSec; public function __construct() @@ -30,6 +31,7 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface $this->baseUrl = rtrim((string) ($config->eatriaBridgeUrl ?? 'https://abdm-bridge.e-atria.in/api'), '/'); $this->token = (string) ($config->eatriaBridgeToken ?? ''); $this->hfrId = ''; + $this->hospitalId = ''; $this->timeoutSec = (int) ($config->eatriaBridgeTimeoutSec ?? 30); // DB (Admin Panel → ABDM Gateway Config) is the authoritative source for @@ -41,7 +43,7 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface if ($db->tableExists('hospital_setting')) { $rows = $db->table('hospital_setting') ->select('s_name, s_value') - ->whereIn('s_name', ['EATRIA_BRIDGE_TOKEN', 'EATRIA_BRIDGE_URL', 'ABDM_HFR_ID']) + ->whereIn('s_name', ['EATRIA_BRIDGE_TOKEN', 'EATRIA_BRIDGE_URL', 'ABDM_HFR_ID', 'ABDM_BRIDGE_HOSPITAL_ID', 'HOSPITAL_ID']) ->get() ->getResultArray(); @@ -56,6 +58,11 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface if (! empty($dbSettings['ABDM_HFR_ID'])) { $this->hfrId = trim($dbSettings['ABDM_HFR_ID']); } + if (! empty($dbSettings['ABDM_BRIDGE_HOSPITAL_ID'])) { + $this->hospitalId = trim($dbSettings['ABDM_BRIDGE_HOSPITAL_ID']); + } elseif (! empty($dbSettings['HOSPITAL_ID'])) { + $this->hospitalId = trim($dbSettings['HOSPITAL_ID']); + } } } catch (\Throwable $e) { // DB unavailable — continue with config/env values @@ -351,59 +358,75 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface public function pushRecord(array $data): array { - // Normalize to gateway-enforced HI types for /v3/records/push. - // Runtime valid_types include *Record variants. + $recordTypeRaw = (string) ($data['record_type'] ?? ''); $hiTypeRaw = (string) ($data['hi_type'] ?? ''); - $hiType = match ($hiTypeRaw) { - 'OPConsultRecord', 'OPConsultation' => 'OPConsultRecord', - 'PrescriptionRecord', 'Prescription' => 'PrescriptionRecord', - 'DiagnosticReportRecord', 'DiagnosticReport' => 'DiagnosticReportRecord', - 'DischargeSummaryRecord', 'DischargeSummary' => 'DischargeSummaryRecord', - 'WellnessRecord' => 'WellnessRecord', - 'ImmunizationRecord' => 'ImmunizationRecord', - 'InvoiceRecord' => 'InvoiceRecord', - 'HealthDocumentRecord' => 'HealthDocumentRecord', - '' => '', - default => $hiTypeRaw, + + $normalizeHiType = static function (string $value): string { + return match ($value) { + 'OPConsultation', 'OPConsultRecord', 'Prescription', 'PrescriptionRecord' => 'PrescriptionRecord', + 'DiagnosticReport', 'DiagnosticReportRecord', 'Lab_Report', 'lab_report' => 'DiagnosticReportRecord', + 'DischargeSummary', 'DischargeSummaryRecord' => 'DischargeSummaryRecord', + 'ImmunizationRecord' => 'ImmunizationRecord', + 'WellnessRecord' => 'WellnessRecord', + 'HealthDocumentRecord' => 'HealthDocumentRecord', + 'InvoiceRecord' => 'InvoiceRecord', + default => '', + }; }; - // Bridge internal record_type enum (sent alongside hi_type for categorisation) - $recordTypeIn = (string) ($data['record_type'] ?? ''); - $validRecordTypes = ['prescription', 'lab_report', 'discharge_summary', 'wellness_record', 'health_document']; - if (in_array($recordTypeIn, $validRecordTypes, true)) { - $recordType = $recordTypeIn; - } else { - // Derive record_type from hi_type - $recordType = match ($hiType) { - 'OPConsultation', 'Prescription' => 'prescription', - 'DiagnosticReport' => 'lab_report', - 'DischargeSummary' => 'discharge_summary', - 'WellnessRecord', 'ImmunizationRecord' => 'wellness_record', - default => 'health_document', - }; + $normalizeRecordType = static function (string $value) use ($normalizeHiType): string { + return $normalizeHiType($value); + }; + + $recordType = $normalizeRecordType($recordTypeRaw); + if ($recordType === '') { + $recordType = $normalizeRecordType($hiTypeRaw); + } + if ($recordType === '') { + $recordType = 'HealthDocumentRecord'; } - // Derive hi_type from record_type if still empty. - // Gateway requires hi_type with the exact ABDM HI type name. + $hiType = $normalizeHiType($hiTypeRaw); if ($hiType === '') { - $hiType = match ($recordType) { - 'prescription' => 'OPConsultRecord', - 'lab_report' => 'DiagnosticReportRecord', - 'discharge_summary' => 'DischargeSummaryRecord', - 'wellness_record' => 'WellnessRecord', - default => 'HealthDocumentRecord', - }; + $hiType = $recordType; + } + + $patientName = trim((string) ($data['patient_name'] ?? '')); + $abhaAddress = trim((string) ($data['abha_address'] ?? '')); + $abhaId = trim((string) ($data['abha_id'] ?? '')); + $careContextReference = trim((string) ($data['care_context_reference'] ?? '')); + $careContextDisplay = trim((string) ($data['care_context_display'] ?? $data['notes'] ?? '')); + $queueId = trim((string) ($data['queue_id'] ?? '')); + + if ($patientName === '') { + return ['ok' => 0, 'http_code' => 0, 'error_text' => 'patient_name is required']; + } + if ($abhaAddress === '') { + return ['ok' => 0, 'http_code' => 0, 'error_text' => 'abha_address is required before pushing health record']; + } + if ($careContextReference === '') { + return ['ok' => 0, 'http_code' => 0, 'error_text' => 'care_context_reference is required']; + } + if ($careContextDisplay === '') { + $careContextDisplay = $recordType; + } + if ($queueId === '') { + $queueId = $careContextReference; } // Gateway requires BOTH record_type (lowercase alias) and hi_type (official ABDM name). $body = [ 'patient_id' => (string) ($data['patient_id'] ?? ''), - 'patient_name' => (string) ($data['patient_name'] ?? ''), + 'patient_name' => $patientName, 'record_type' => $recordType, 'hi_type' => $hiType, 'visit_date' => (string) ($data['visit_date'] ?? date('Y-m-d')), 'record_data' => $data['record_data'] ?? $data['bundle'] ?? (object) [], 'fhir_bundle' => $data['record_data'] ?? $data['bundle'] ?? (object) [], + 'care_context_reference' => $careContextReference, + 'care_context_display' => $careContextDisplay, + 'abha_address' => $abhaAddress, + 'queue_id' => $queueId, ]; // hfr_id is required in every push request alongside the Bearer token. @@ -411,7 +434,11 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface $body['hfr_id'] = $this->hfrId; } - foreach (['abha_id', 'abha_address', 'doctor_name', 'department', 'care_context_reference', 'care_context_display', 'notes', 'queue_id', 'gender', 'year_of_birth'] as $optional) { + if ($this->hospitalId !== '') { + $body['hospital_id'] = $this->hospitalId; + } + + foreach (['abha_id', 'doctor_name', 'department', 'notes', 'gender', 'year_of_birth'] as $optional) { if (! empty($data[$optional])) { $body[$optional] = (string) $data[$optional]; }