From dd1acb88e1bb2602255e51b4ab4a4a31b5383fd6 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Tue, 15 Sep 2026 23:21:30 +0530 Subject: [PATCH] feat: add IPD census PDF, collection payment filter, fix report panel visibility, and implement ABDM HIP linking - Reports: - Add PDF export option with A4-L print layout for IPD Census & Discharge Report - Add Payment Type filter (OPD, Charge, IPD, ORG, All) to Collection Report with URL routing and summary table updates - Ensure superadmin/admin/developer visibility in Report Panel controller permission checks - ABDM: - Implement HIP patient care-context linking and discovery integration - Add on-demand FHIR health record fetch endpoints for Bridge connector - Add ABDM HIP link modal view and wire to patient/person profiles and prescription --- ...ITH_APIS_UPDATED_22_Aug_871c2f7fcd(1).xlsx | Bin 0 -> 143375 bytes app/Config/App.php | 2 + app/Config/Routes.php | 9 +- app/Controllers/AbdmGateway.php | 474 ++++++++++-- app/Controllers/Report.php | 105 ++- app/Libraries/Abdm/EAtriaBridgeConnector.php | 78 +- app/Views/abdm/task_board.php | 27 +- app/Views/billing/Patient_Profile_Opd_V.php | 14 +- app/Views/billing/Person_profile_V.php | 11 +- app/Views/billing/opd_prescription_basic.php | 12 +- app/Views/partials/abdm_hip_link_modal.php | 710 ++++++++++++++++++ app/Views/report/collection_report.php | 48 +- app/Views/report/collection_report_table.php | 2 +- .../report/collection_report_total_table.php | 2 +- app/Views/report/ipd_census_report.php | 2 + app/Views/report/ipd_census_report_table.php | 63 +- 16 files changed, 1412 insertions(+), 147 deletions(-) create mode 100644 M2_BUILDING_HIP_WITH_APIS_UPDATED_22_Aug_871c2f7fcd(1).xlsx create mode 100644 app/Views/partials/abdm_hip_link_modal.php diff --git a/M2_BUILDING_HIP_WITH_APIS_UPDATED_22_Aug_871c2f7fcd(1).xlsx b/M2_BUILDING_HIP_WITH_APIS_UPDATED_22_Aug_871c2f7fcd(1).xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5f1a19f59836b41fc17ba60f2d2925f8bd696541 GIT binary patch literal 143375 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 axhNUw9)M?S|9N9X?84)@EeiJ?@&5r~)z$z2 literal 0 HcmV?d00001 diff --git a/app/Config/App.php b/app/Config/App.php index 28532f6..71d8117 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -88,6 +88,8 @@ class App extends BaseConfig */ public array $allowedHostnames = [ 'localhost', + '127.0.0.1', + '10.8.0.2', 'hmskrishnaksp.dhms.in', 'hmslocal.devsofttech.co.in', 'khrc1.dhms.in', diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 998eb18..907dbd5 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -761,6 +761,9 @@ $routes->post('api/v1/abdm/gateway/link/confirm', 'AbdmGateway::m2LinkConfirm'); $routes->post('v3/hip/patient/care-context/discover', 'AbdmGateway::recordsDiscover'); $routes->post('v3/hip/link/patient/care-context/init', 'AbdmGateway::m2LinkInit'); $routes->post('v3/hip/link/patient/care-context/confirm', 'AbdmGateway::m2LinkConfirm'); +// ABDM M3: On-Demand FHIR Health Record Fetch by Bridge +$routes->post('records/fetch', 'AbdmGateway::recordsFetch'); +$routes->post('records/data', 'AbdmGateway::recordsFetch'); // Fallback alias $routes->get('records/fetch/(:any)', 'AbdmGateway::recordsFetch/$1'); $routes->post('records/fetch/(:any)', 'AbdmGateway::recordsFetch/$1'); $routes->post('AbdmGateway/share_prescription_bundle', 'AbdmGateway::sharePrescriptionBundle', ['filter' => $abdmPermFilter]); @@ -809,6 +812,8 @@ $routes->post('AbdmGateway/hip_link_carecontext', 'AbdmGateway::hipLinkCareConte $routes->get('AbdmGateway/hip_patient_links', 'AbdmGateway::hipPatientLinks', ['filter' => $abdmPermFilter]); $routes->post('AbdmGateway/hip_link_notify', 'AbdmGateway::hipLinkNotify', ['filter' => $abdmPermFilter]); $routes->post('AbdmGateway/hip_sms_notify', 'AbdmGateway::hipSmsNotify', ['filter' => $abdmPermFilter]); +$routes->get('AbdmGateway/hip_patient_care_contexts', 'AbdmGateway::hipPatientCareContexts', ['filter' => $abdmPermFilter]); +$routes->post('AbdmGateway/hip_patient_care_contexts', 'AbdmGateway::hipPatientCareContexts', ['filter' => $abdmPermFilter]); $routes->post('AbdmGateway/nhcx_claim_create', 'AbdmGateway::nhcxClaimCreate', ['filter' => $abdmPermFilter]); $routes->post('AbdmGateway/nhcx_claim_status_request', 'AbdmGateway::nhcxClaimStatusRequest', ['filter' => $abdmPermFilter]); $routes->post('AbdmGateway/nhcx_claim_status_callback', 'AbdmGateway::nhcxClaimStatusCallback'); @@ -1105,11 +1110,11 @@ $routes->get('Report/report_opd_patient_list', 'Report::report_opd_patient_list' $routes->get('Report/opd_patient_list_data/(:segment)/(:segment)/(:segment)', 'Report::opd_patient_list_data/$1/$2/$3', ['filter' => $reportsCollectionFilter]); $routes->get('Report/opd_patient_list_data/(:segment)/(:segment)/(:segment)/(:num)', 'Report::opd_patient_list_data/$1/$2/$3/$4', ['filter' => $reportsCollectionFilter]); $routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)', 'Report::report_total_payment_app_show/$1/$2/$3', ['filter' => $reportsCollectionFilter]); -$routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_app_show/$1/$2/$3/$4', ['filter' => $reportsCollectionFilter]); $routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)/(:segment)', 'Report::report_total_payment_app_show/$1/$2/$3/$4', ['filter' => $reportsCollectionFilter]); $routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_app_show/$1/$2/$3/$4/$5', ['filter' => $reportsCollectionFilter]); $routes->get('Report/report_total_payment_total_amount_show/(:segment)/(:segment)/(:segment)', 'Report::report_total_payment_total_amount_show/$1/$2/$3', ['filter' => $reportsCollectionFilter]); -$routes->get('Report/report_total_payment_total_amount_show/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_total_amount_show/$1/$2/$3/$4', ['filter' => $reportsCollectionFilter]); +$routes->get('Report/report_total_payment_total_amount_show/(:segment)/(:segment)/(:segment)/(:segment)', 'Report::report_total_payment_total_amount_show/$1/$2/$3/$4', ['filter' => $reportsCollectionFilter]); +$routes->get('Report/report_total_payment_total_amount_show/(:segment)/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_total_amount_show/$1/$2/$3/$4/$5', ['filter' => $reportsCollectionFilter]); $routes->get('Report/old_payment_received_report', 'Report::old_payment_received_report', ['filter' => $reportsCollectionFilter]); $routes->get('Report/old_payment_received_report_data', 'Report::old_payment_received_report_data', ['filter' => $reportsCollectionFilter]); $routes->get('Report/old_payment_received_report_data/(:segment)', 'Report::old_payment_received_report_data/$1', ['filter' => $reportsCollectionFilter]); diff --git a/app/Controllers/AbdmGateway.php b/app/Controllers/AbdmGateway.php index 0b78100..2eb7ec2 100644 --- a/app/Controllers/AbdmGateway.php +++ b/app/Controllers/AbdmGateway.php @@ -4726,75 +4726,240 @@ class AbdmGateway extends BaseController // GET /records/fetch/{careContextId} // ========================================================================= - public function recordsFetch(string $careContextId) + /** + * ABDM M3: On-Demand Fetch Health Records (FHIR Document Bundle) + * Route: POST /records/fetch + */ + public function recordsFetch(?string $careContextId = null): \CodeIgniter\HTTP\ResponseInterface { - $signatureFailure = $this->validateWebhookSignature(); - if ($signatureFailure !== null) { - return $signatureFailure; + // 1. Authenticate Bridge request using existing M2 auth validator + $authFailure = $this->validateDiscoveryOrLinkAuth(); + if ($authFailure !== null) { + return $this->response->setStatusCode(401)->setJSON([ + 'ok' => 0, + 'error' => 'UNAUTHORIZED', + 'message' => 'Invalid or missing Authorization header or signature.', + ]); } - if (! $this->db->tableExists('health_records')) { - return $this->response->setStatusCode(404)->setJSON(['ok' => 0, 'error_text' => 'health_records table not found']); + $body = $this->request->getJSON(true) ?: []; + $careContextRefs = $body['careContextReferences'] ?? []; + if (empty($careContextRefs) && !empty($body['careContextReference'])) { + $careContextRefs = [$body['careContextReference']]; + } + if (empty($careContextRefs) && !empty($body['careContextId'])) { + $careContextRefs = [$body['careContextId']]; + } + if (empty($careContextRefs) && $careContextId !== null && trim($careContextId) !== '') { + $careContextRefs = [trim($careContextId)]; } - $careContextId = trim($careContextId); - if ($careContextId === '') { - return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'careContextId is required']); + if (empty($careContextRefs)) { + return $this->response->setStatusCode(400)->setJSON([ + 'ok' => 0, + 'error' => 'MISSING_CARE_CONTEXT_REFS', + 'message' => 'careContextReferences array is required.', + ]); } - $builder = $this->db->table('health_records') - ->select('id, patient_id, abha_id, hi_type, care_context_reference, record_data, fhir_bundle_enc, created_at, updated_at') - ->limit(1); + $db = \Config\Database::connect(); + $records = []; - if (preg_match('/^HR\-(\d+)$/i', $careContextId, $m) === 1) { - $builder->where('id', (int) ($m[1] ?? 0)); - } else { - $builder->where('care_context_reference', $careContextId); - } + foreach ($careContextRefs as $ref) { + $ref = trim((string) $ref); + if ($ref === '') { + continue; + } - $row = $builder->get()->getRowArray(); - if (empty($row)) { - return $this->response->setStatusCode(404)->setJSON(['ok' => 0, 'error_text' => 'Record not found for careContextId']); - } + // Strategy A: Check if health_records already has stored FHIR record_data + $hrRow = null; + if ($db->tableExists('health_records')) { + $hrBuilder = $db->table('health_records')->where('care_context_reference', $ref); + if ($db->fieldExists('queue_id', 'health_records')) { + $hrBuilder->orWhere('queue_id', $ref); + } + $hrRow = $hrBuilder->get()->getRowArray(); + } - $payload = []; - $plainPayload = trim((string) ($row['record_data'] ?? '')); - if ($plainPayload !== '') { - $payload = json_decode($plainPayload, true) ?? []; - } else { - $encPayload = trim((string) ($row['fhir_bundle_enc'] ?? '')); - if ($encPayload !== '') { + if ($hrRow && !empty($hrRow['record_data'])) { + $bundleData = json_decode((string) $hrRow['record_data'], true); + if (is_array($bundleData)) { + $records[] = [ + 'careContextReference' => $ref, + 'hiType' => $hrRow['hi_type'] ?? $hrRow['record_type'] ?? 'OPConsultRecord', + 'display' => $hrRow['care_context_display'] ?? 'Consultation Record', + 'bundle' => $bundleData, + ]; + continue; + } + } + + if ($hrRow && !empty($hrRow['fhir_bundle_enc'])) { try { $enc = new FhirEncryptionService(); - $decrypted = $enc->decrypt($encPayload); - $payload = json_decode($decrypted, true) ?? []; - } catch (\Throwable $e) { - return $this->response->setStatusCode(500)->setJSON(['ok' => 0, 'error_text' => 'Unable to decode stored payload']); + $decrypted = $enc->decrypt((string) $hrRow['fhir_bundle_enc']); + $bundleData = json_decode($decrypted, true); + if (is_array($bundleData)) { + $records[] = [ + 'careContextReference' => $ref, + 'hiType' => $hrRow['hi_type'] ?? $hrRow['record_type'] ?? 'OPConsultRecord', + 'display' => $hrRow['care_context_display'] ?? 'Consultation Record', + 'bundle' => $bundleData, + ]; + continue; + } + } catch (\Throwable) { } } + + // Strategy B: Build compliant FHIR Document Bundle from patient_master & OPD + $bundle = $this->assembleFhirBundleForCareContext($ref); + if ($bundle !== null) { + $records[] = [ + 'careContextReference' => $ref, + 'hiType' => 'OPConsultRecord', + 'display' => 'OPConsultRecord - ' . date('d M Y'), + 'bundle' => $bundle, + ]; + } } - $this->getAuditService()->log([ - 'action' => 'fetch_record', - 'entity_type' => 'health_record', - 'entity_id' => (string) ($row['id'] ?? ''), - 'patient_id' => (int) ($row['patient_id'] ?? 0), - 'abha_id' => (string) ($row['abha_id'] ?? ''), - 'request' => ['careContextId' => $careContextId], - 'response' => ['ok' => 1], - 'outcome' => 'success', - ]); + if (empty($records)) { + return $this->response->setStatusCode(404)->setJSON([ + 'ok' => 0, + 'error' => 'RECORDS_NOT_FOUND', + 'message' => 'No clinical records found for the requested care contexts.', + ]); + } - return $this->response->setJSON([ - 'ok' => 1, - 'careContextId' => $careContextId, - 'record_type' => (string) ($row['hi_type'] ?? ''), - 'patient_id' => (int) ($row['patient_id'] ?? 0), - 'abha_address' => (string) ($row['abha_id'] ?? ''), - 'fhir_payload' => $payload, + return $this->response->setStatusCode(200)->setJSON([ + 'ok' => 1, + 'records' => $records, ]); } + /** + * Helper to assemble a minimal ABDM-compliant FHIR Document Bundle on the fly + */ + protected function assembleFhirBundleForCareContext(string $careContextRef): ?array + { + $db = \Config\Database::connect(); + + // Extract patient ID from reference (e.g. "OPD-16-S1-20260909" -> patient_id 16) + $patientId = 0; + if (preg_match('/OPD-(\d+)/i', $careContextRef, $matches)) { + $patientId = (int) $matches[1]; + } elseif (preg_match('/(?:HR|PAT|REG|P)-(\d+)/i', $careContextRef, $matches)) { + $patientId = (int) $matches[1]; + } + + $patient = null; + if ($patientId > 0 && $db->tableExists('patient_master')) { + $patient = $db->table('patient_master')->where('id', $patientId)->get()->getRowArray(); + } + + $patientName = ''; + if (!empty($patient)) { + $lName = trim((string) ($patient['p_lname'] ?? '')); + $fName = trim((string) ($patient['p_fname'] ?? '')); + $patientName = trim($fName . ($lName !== '' && $lName !== '0' ? ' ' . $lName : '')); + } + if ($patientName === '') { + $patientName = $patient['patient_name'] ?? 'Patient'; + } + + $rawGender = strtolower(trim((string) ($patient['gender'] ?? ''))); + $gender = match ($rawGender) { + '1', 'm', 'male' => 'male', + '2', 'f', 'female' => 'female', + '3', 'o', 'other' => 'other', + default => 'unknown', + }; + + $dob = !empty($patient['dob']) && $patient['dob'] !== '0000-00-00' + ? date('Y-m-d', strtotime((string) $patient['dob'])) + : (!empty($patient['age']) ? date('Y-m-d', strtotime('-' . (int)$patient['age'] . ' years')) : (!empty($patient['year_of_birth']) ? $patient['year_of_birth'] . '-01-01' : '1990-01-01')); + + $nowIso = gmdate('Y-m-d\TH:i:s.000\Z'); + + return [ + 'resourceType' => 'Bundle', + 'id' => 'bundle-' . $careContextRef, + 'meta' => [ + 'versionId' => '1', + 'lastUpdated' => $nowIso, + 'profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/DocumentBundle'], + ], + 'identifier' => [ + 'system' => 'https://abdm.gov.in/bundle', + 'value' => 'bundle-' . $careContextRef, + ], + 'type' => 'document', + 'timestamp' => $nowIso, + 'entry' => [ + [ + 'fullUrl' => 'Composition/comp-1', + 'resource' => [ + 'resourceType' => 'Composition', + 'id' => 'comp-1', + 'status' => 'final', + 'type' => [ + 'coding' => [ + [ + 'system' => 'https://projecteka.in/sct', + 'code' => '371530004', + 'display' => 'Clinical consultation report', + ], + ], + 'text' => 'Clinical Consultation Record', + ], + 'subject' => [ + 'reference' => 'Patient/pat-1', + 'display' => $patientName, + ], + 'date' => $nowIso, + 'author' => [ + ['reference' => 'Practitioner/prac-1', 'display' => 'Treating Doctor'], + ], + 'title' => 'Consultation Record', + 'section' => [ + [ + 'title' => 'Consultation Notes', + 'code' => [ + 'coding' => [ + [ + 'system' => 'https://projecteka.in/sct', + 'code' => '4241000179101', + 'display' => 'Outpatient Note', + ], + ], + ], + ], + ], + ], + ], + [ + 'fullUrl' => 'Patient/pat-1', + 'resource' => [ + 'resourceType' => 'Patient', + 'id' => 'pat-1', + 'name' => [['text' => $patientName]], + 'gender' => $gender, + 'birthDate' => $dob, + ], + ], + [ + 'fullUrl' => 'Practitioner/prac-1', + 'resource' => [ + 'resourceType' => 'Practitioner', + 'id' => 'prac-1', + 'name' => [['text' => 'Treating Doctor']], + ], + ], + ], + ]; + } + // ========================================================================= // M2 User-Initiated Linking endpoints (Discovery & Link) // POST /records/link/init @@ -9963,7 +10128,7 @@ class AbdmGateway extends BaseController return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } - $body = $this->request->getJSON(true) ?? []; + $body = $this->request->getJSON(true) ?? $this->request->getPost() ?? []; $required = ['abha_address', 'name', 'gender', 'year_of_birth']; foreach ($required as $key) { @@ -9972,6 +10137,22 @@ class AbdmGateway extends BaseController } } + $body['year_of_birth'] = (int) $body['year_of_birth']; + + // Auto-lookup abha_number from patient_master if missing + if (empty($body['abha_number']) && ! empty($body['abha_address']) && $this->db->tableExists('patient_master')) { + $pat = $this->db->table('patient_master') + ->select('abha_id') + ->where('abha_address', $body['abha_address']) + ->where('abha_id IS NOT NULL') + ->where('abha_id !=', '') + ->get(1) + ->getRowArray(); + if (! empty($pat['abha_id'])) { + $body['abha_number'] = trim((string) $pat['abha_id']); + } + } + $result = $this->connector->hipLinkToken($body); return $this->response->setJSON($result); } @@ -9988,15 +10169,39 @@ class AbdmGateway extends BaseController return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } - $body = $this->request->getJSON(true) ?? []; + $body = $this->request->getJSON(true) ?? $this->request->getPost() ?? []; - $required = ['abha_address', 'link_token_id', 'patient_ref', 'display', 'hi_type', 'care_contexts']; + $required = ['abha_address', 'link_token_id', 'care_contexts']; foreach ($required as $key) { if (empty($body[$key])) { return $this->response->setJSON(['ok' => 0, 'error_text' => $key . ' is required']); } } + if (empty($body['patient_ref'])) { + $body['patient_ref'] = $body['abha_address']; + } + if (empty($body['display'])) { + $body['display'] = $body['patient_ref']; + } + if (empty($body['hi_type'])) { + $body['hi_type'] = 'OPConsultation'; + } + + // Auto-resolve abha_number from patient_master if missing so ABDM doesn't reject with ABDM-9999 + if (empty($body['abha_number']) && ! empty($body['abha_address']) && $this->db->tableExists('patient_master')) { + $pat = $this->db->table('patient_master') + ->select('abha_id') + ->where('abha_address', $body['abha_address']) + ->where('abha_id IS NOT NULL') + ->where('abha_id !=', '') + ->get(1) + ->getRowArray(); + if (! empty($pat['abha_id'])) { + $body['abha_number'] = trim((string) $pat['abha_id']); + } + } + $result = $this->connector->hipLinkCareContext($body); return $this->response->setJSON($result); } @@ -10013,8 +10218,8 @@ class AbdmGateway extends BaseController } $filters = array_filter([ - 'abha_address' => $this->request->getGet('abha_address'), - 'limit' => $this->request->getGet('limit'), + 'abha_address' => $this->request->getGet('abha_address') ?? $this->request->getPost('abha_address'), + 'limit' => $this->request->getGet('limit') ?? $this->request->getPost('limit'), ]); if (empty($filters['abha_address'])) { @@ -10037,7 +10242,7 @@ class AbdmGateway extends BaseController return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } - $body = $this->request->getJSON(true) ?? []; + $body = $this->request->getJSON(true) ?? $this->request->getPost() ?? []; $required = ['abha_address', 'care_context_reference', 'hi_type', 'date_of_record']; foreach ($required as $key) { @@ -10062,14 +10267,171 @@ class AbdmGateway extends BaseController return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } - $body = $this->request->getJSON(true) ?? []; + $body = $this->request->getJSON(true) ?? $this->request->getPost() ?? []; if (empty($body['phone_number'])) { return $this->response->setJSON(['ok' => 0, 'error_text' => 'phone_number is required']); } + // Clean phone number + $body['phone_number'] = substr(preg_replace('/\D/', '', (string) $body['phone_number']), -10); + + if (empty($body['hip_name']) && $this->db->tableExists('hospital_setting')) { + $hs = $this->db->table('hospital_setting')->where('s_name', 'H_name')->get(1)->getRowArray(); + if (! empty($hs['s_value'])) { + $body['hip_name'] = $hs['s_value']; + } + } + $result = $this->connector->hipSmsNotify($body); return $this->response->setJSON($result); } + + // ========================================================================= + // HIP-Initiated Linking - Patient Demographics & Care Contexts Discovery + // GET /AbdmGateway/hip_patient_care_contexts?patient_id=X&abha_address=Y + // ========================================================================= + + public function hipPatientCareContexts() + { + if (method_exists($this->request, 'isAJAX') && ! $this->request->isAJAX()) { + return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); + } + + $patientId = 0; + $abhaAddress = ''; + $pCode = ''; + if (method_exists($this->request, 'getVar')) { + $patientId = (int) ($this->request->getVar('patient_id') ?? 0); + $abhaAddress = trim((string) ($this->request->getVar('abha_address') ?? '')); + $pCode = trim((string) ($this->request->getVar('p_code') ?? '')); + } + if ($patientId <= 0 && ! empty($_REQUEST['patient_id'])) { + $patientId = (int) $_REQUEST['patient_id']; + } + if ($abhaAddress === '' && ! empty($_REQUEST['abha_address'])) { + $abhaAddress = trim((string) $_REQUEST['abha_address']); + } + if ($pCode === '' && ! empty($_REQUEST['p_code'])) { + $pCode = trim((string) $_REQUEST['p_code']); + } + + if ($patientId <= 0 && $abhaAddress === '' && $pCode === '') { + return $this->response->setJSON(['ok' => 0, 'error_text' => 'patient_id, abha_address, or p_code is required']); + } + + $patient = null; + if ($this->db->tableExists('patient_master')) { + $builder = $this->db->table('patient_master'); + if ($patientId > 0) { + $builder->where('id', $patientId); + } elseif ($abhaAddress !== '') { + $builder->where('abha_address', $abhaAddress); + } elseif ($pCode !== '') { + $builder->where('p_code', $pCode); + } + $patient = $builder->get(1)->getRowArray(); + } + + if (empty($patient)) { + return $this->response->setJSON(['ok' => 0, 'error_text' => 'Patient not found in records']); + } + + $patientId = (int) $patient['id']; + $patientRef = (string) ($patient['p_code'] ?: ('P-' . $patientId)); + $lName = trim((string) ($patient['p_lname'] ?? '')); + $patientName = trim((string) ($patient['p_fname'] ?? '')); + if ($lName !== '' && $lName !== '0') { + $patientName .= ' ' . $lName; + } + if ($patientName === '') { + $patientName = 'Patient ' . $patientRef; + } + + $genderCode = (int) ($patient['gender'] ?? 0); + $rawGender = strtoupper(trim((string) ($patient['gender'] ?? ''))); + $gender = 'O'; + if ($genderCode === 1 || $rawGender === 'M' || $rawGender === 'MALE') { + $gender = 'M'; + } elseif ($genderCode === 2 || $rawGender === 'F' || $rawGender === 'FEMALE') { + $gender = 'F'; + } + + $yob = 0; + $dob = trim((string) ($patient['dob'] ?? '')); + if ($dob !== '' && $dob !== '0000-00-00') { + $yob = (int) date('Y', strtotime($dob)); + } elseif (! empty($patient['age'])) { + $yob = (int) date('Y') - (int) $patient['age']; + } + if ($yob <= 1900) { + $yob = 1990; + } + + $rawPhone = trim((string) ($patient['mphone1'] ?? $patient['mphone2'] ?? '')); + $cleanPhone = substr(preg_replace('/\D/', '', $rawPhone), -10); + + [$careContextsV3, $careContextsFull] = $this->findCareContextsForPatient($patientId, $patientRef, $patientName); + + // Fetch already-linked care contexts from Bridge if ABHA address is present + $linkedRefs = []; + $effAbhaAddress = trim((string) ($patient['abha_address'] ?? $abhaAddress)); + if ($effAbhaAddress !== '') { + try { + $bridgeLinks = $this->connector->hipGetPatientLinks(['abha_address' => $effAbhaAddress]); + if (! empty($bridgeLinks['data']) && is_array($bridgeLinks['data'])) { + foreach ($bridgeLinks['data'] as $linkPat) { + foreach ($linkPat['careContexts'] ?? [] as $cc) { + $ref = trim((string) ($cc['referenceNumber'] ?? $cc['ref'] ?? '')); + if ($ref !== '') { + $linkedRefs[] = $ref; + } + } + } + } + } catch (\Throwable $e) { + // Bridge query optional + } + } + + $contextsList = []; + foreach ($careContextsFull as $cc) { + $ref = $cc['referenceNumber'] ?? $cc['careContextId'] ?? ''; + $isLinked = in_array($ref, $linkedRefs, true); + $contextsList[] = [ + 'ref' => $ref, + 'display' => $cc['display'] ?? $ref, + 'hi_type' => $cc['record_type'] ?? 'OPConsultRecord', + 'is_linked' => $isLinked, + ]; + } + + $hospitalName = 'Hospital'; + if ($this->db->tableExists('hospital_setting')) { + $hs = $this->db->table('hospital_setting')->where('s_name', 'H_name')->get(1)->getRowArray(); + if (! empty($hs['s_value'])) { + $hospitalName = $hs['s_value']; + } + } + + return $this->response->setJSON([ + 'ok' => 1, + 'patient' => [ + 'id' => $patientId, + 'patient_ref' => $patientRef, + 'name' => $patientName, + 'gender' => $gender, + 'year_of_birth' => $yob, + 'dob' => $dob, + 'abha_address' => $effAbhaAddress, + 'abha_number' => trim((string) ($patient['abha_id'] ?? '')), + 'phone' => $cleanPhone, + ], + 'care_contexts' => $contextsList, + 'linked_refs' => $linkedRefs, + 'hospital_name' => $hospitalName, + ]); + } } + diff --git a/app/Controllers/Report.php b/app/Controllers/Report.php index 7ee85af..744f2b3 100644 --- a/app/Controllers/Report.php +++ b/app/Controllers/Report.php @@ -34,8 +34,15 @@ class Report extends BaseController } $user = auth()->user(); + if ($user === null) { + return false; + } - return $user !== null && method_exists($user, 'can') && $user->can($permission); + if (method_exists($user, 'inGroup') && $user->inGroup('superadmin', 'admin', 'developer')) { + return true; + } + + return method_exists($user, 'can') && $user->can($permission); } private function requireReportPermission(string $permission) @@ -165,6 +172,7 @@ class Report extends BaseController 'summary' => $summary, 'min_range' => $minRange, 'max_range' => $maxRange, + 'is_pdf' => ($output === 2), ]); if ($output === 1) { @@ -172,6 +180,52 @@ class Report extends BaseController return $this->response->setBody(''); } + if ($output === 2) { + $mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf'; + if (! is_dir($mpdfTempDir)) { + mkdir($mpdfTempDir, 0755, true); + } + + $mpdf = new Mpdf([ + 'tempDir' => $mpdfTempDir, + 'format' => 'A4-L', + 'margin_top' => 8, + 'margin_bottom' => 8, + 'margin_left' => 8, + 'margin_right' => 8, + ]); + + $hospitalName = defined('H_Name') ? (string) constant('H_Name') : 'Hospital'; + $hospitalAddress = defined('H_address_1') ? (string) constant('H_address_1') : ''; + + $pdfHtml = '' + . '
' + . '

' . esc($hospitalName) . '

' + . ($hospitalAddress !== '' ? '
' . esc($hospitalAddress) . '
' : '') + . '

IPD Census & Discharge Report

' + . '
' + . $content; + + $mpdf->WriteHTML($pdfHtml); + $fileName = 'IPD_Census_' . date('Ymd_His') . '.pdf'; + + return $this->response + ->setHeader('Content-Type', 'application/pdf') + ->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"') + ->setBody($mpdf->Output($fileName, 'S')); + } + return $this->response->setBody($content); } @@ -569,11 +623,16 @@ class Report extends BaseController string $dateRange, string $employeeIds, string $payModeId, - string $orderFirst = '0', + string $payTypeId = '0', int $output = 0 ) { [$minRange, $maxRange] = $this->parseDateRange($dateRange); + $getPayType = $this->request->getGet('pay_type') ?? $this->request->getGet('pay_type_id'); + if ($getPayType !== null && $getPayType !== '') { + $payTypeId = (string) $getPayType; + } + $builder = $this->db->table('payment_history p'); $builder->select("p.id as pay_id, p.payment_date,") ->select("date_format(p.payment_date,'%d-%m-%Y %H:%i') as str_payment_date", false) @@ -607,14 +666,13 @@ class Report extends BaseController $builder->where('p.payment_mode', $payModeId); } - $builder->orderBy('p.id', 'ASC'); - $orderFirst = (int) $orderFirst; - if ($orderFirst === 1) { - $builder->orderBy('p.update_by', 'ASC'); - } elseif ($orderFirst === 2) { - $builder->orderBy('p.payment_mode', 'ASC'); + $payType = (int) $payTypeId; + if ($payType > 0) { + $builder->where('p.payof_type', $payType); } + $builder->orderBy('p.id', 'ASC'); + $rows = $builder->get()->getResult(); $totalCr = 0.0; @@ -624,6 +682,14 @@ class Report extends BaseController $totalDr += (float) ($row->dr_amount ?? 0); } + $payTypeMap = [ + 0 => 'All Payment Types', + 1 => 'OPD', + 2 => 'Charge', + 3 => 'ORG', + 4 => 'IPD', + ]; + $data = [ 'rows' => $rows, 'min_range' => $minRange, @@ -631,6 +697,8 @@ class Report extends BaseController 'total_cr' => $totalCr, 'total_dr' => $totalDr, 'net_total' => $totalCr - $totalDr, + 'pay_type_id' => $payType, + 'pay_type_label' => $payTypeMap[$payType] ?? 'All Payment Types', ]; $content = view('report/collection_report_table', $data); @@ -768,10 +836,16 @@ class Report extends BaseController string $dateRange, string $employeeIds, string $payModeId, + string $payTypeId = '0', int $output = 0 ) { [$minRange, $maxRange] = $this->parseDateRange($dateRange); + $getPayType = $this->request->getGet('pay_type') ?? $this->request->getGet('pay_type_id'); + if ($getPayType !== null && $getPayType !== '') { + $payTypeId = (string) $getPayType; + } + $builder = $this->db->table('payment_history p'); $builder->select('p.update_by_id as user_id') ->select('COALESCE(u.username, MAX(p.update_by)) as user_name', false) @@ -797,6 +871,11 @@ class Report extends BaseController $builder->where('p.payment_mode', $payMode); } + $payType = (int) $payTypeId; + if ($payType > 0) { + $builder->where('p.payof_type', $payType); + } + $rows = $builder ->groupBy(['p.update_by_id', 'u.username']) ->orderBy('u.username', 'ASC') @@ -822,11 +901,21 @@ class Report extends BaseController $totals['total_amount'] += (float) ($row->total_amount ?? 0); } + $payTypeMap = [ + 0 => 'All Payment Types', + 1 => 'OPD', + 2 => 'Charge', + 3 => 'ORG', + 4 => 'IPD', + ]; + $content = view('report/collection_report_total_table', [ 'rows' => $rows, 'totals' => $totals, 'min_range' => $minRange, 'max_range' => $maxRange, + 'pay_type_id' => $payType, + 'pay_type_label' => $payTypeMap[$payType] ?? 'All Payment Types', ]); if ($output === 1) { diff --git a/app/Libraries/Abdm/EAtriaBridgeConnector.php b/app/Libraries/Abdm/EAtriaBridgeConnector.php index 64a8778..c8d7e2d 100644 --- a/app/Libraries/Abdm/EAtriaBridgeConnector.php +++ b/app/Libraries/Abdm/EAtriaBridgeConnector.php @@ -1390,60 +1390,52 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface $queueId = $careContextReference; } - // Gateway requires BOTH record_type (lowercase alias) and hi_type (official ABDM name). - $body = [ - 'patient_id' => (string) ($data['patient_id'] ?? ''), - '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) [], + $effectiveAbha = $abhaAddress !== '' ? $abhaAddress : $abhaId; + $visitDate = (string) ($data['visit_date'] ?? date('Y-m-d')); + + // Under M3 On-Demand Fetch architecture, full FHIR records are NOT sent to the Bridge. + // Instead, only Care Context metadata is registered with the ABDM Bridge (/v3/hip/link/notify). + // The complete FHIR Document Bundle stays securely inside HMS (health_records table) + // and is served on-demand when the Bridge calls POST /records/fetch upon patient consent. + $notifyPayload = [ + 'hfr_id' => $this->hfrId, + 'hospital_id' => $this->bridgeHospitalId, + 'patient_id' => (string) ($data['patient_id'] ?? ''), + 'patient_name' => $patientName, + 'abha_address' => $effectiveAbha, 'care_context_reference' => $careContextReference, - 'care_context_display' => $careContextDisplay, - 'queue_id' => $queueId, + 'care_context_display' => $careContextDisplay, + 'hi_type' => $hiType, + 'date_of_record' => $visitDate, ]; if ($this->bridgeHospitalId !== '') { - $body['hospital_id'] = $this->bridgeHospitalId; - $body['bridge_hospital_id'] = $this->bridgeHospitalId; - } - - if ($abhaAddress !== '') { - $body['abha_address'] = $abhaAddress; + $notifyPayload['hospital_id'] = $this->bridgeHospitalId; } if ($abhaId !== '') { - $body['abha_id'] = $abhaId; + $notifyPayload['abha_id'] = $abhaId; } - // Also send ABDM-style careContexts wrapper so consent linkage remains explicit. - $body['careContexts'] = [[ - 'careContextReference' => $careContextReference, - 'description' => $careContextDisplay, - ]]; + $res = $this->post('/v3/hip/link/notify', $notifyPayload); - // hfr_id is required in every push request alongside the Bearer token. - if ($this->hfrId !== '') { - $body['hfr_id'] = $this->hfrId; + $httpCode = (int) ($res['http_code'] ?? 0); + if (($res['ok'] ?? 0) === 1 || in_array($httpCode, [200, 201, 202], true)) { + return [ + 'ok' => 1, + 'http_code' => 201, + 'status' => 'linked', + 'queue_id' => $res['request_id'] ?? ('NOTIFY-' . $careContextReference), + 'record_id' => null, + 'care_context_reference' => $careContextReference, + 'care_context_display' => $careContextDisplay, + 'hi_type' => $hiType, + 'mode' => 'care_context_only', + 'message' => 'Care context registered with ABDM Bridge (FHIR record retained in HMS for on-demand fetch)', + 'response' => $res, + ]; } - foreach (['abha_id', 'doctor_name', 'department', 'notes', 'gender', 'year_of_birth'] as $optional) { - if (empty($data[$optional])) { - continue; - } - - if ($optional === 'gender') { - $gender = $this->normalizeBridgeGender($data[$optional]); - if ($gender !== '') { - $body['gender'] = $gender; - } - continue; - } - - $body[$optional] = (string) $data[$optional]; - } - - return self::normalizePushRecordResponse($this->post('/v3/records/push', $body)); + return self::normalizePushRecordResponse($res); } /** diff --git a/app/Views/abdm/task_board.php b/app/Views/abdm/task_board.php index 462ce02..f4faf69 100644 --- a/app/Views/abdm/task_board.php +++ b/app/Views/abdm/task_board.php @@ -19,7 +19,15 @@

ABDM Work Task Board

ABDM operational dashboard and work queues
- +
+ + + +
@@ -185,6 +193,7 @@ +
@@ -3459,7 +3468,23 @@ } window.location.href = refreshUrl; }); + + document.querySelectorAll('.btn-row-hip-link').forEach(function (btn) { + btn.addEventListener('click', function () { + var row = btn.closest('tr'); + if (!row) return; + var patientId = parseInt(row.getAttribute('data-patient-id') || '0', 10); + var abhaInput = row.querySelector('.abha-input'); + var abhaId = (abhaInput ? abhaInput.value : (row.getAttribute('data-abha-id') || '')).trim(); + var patientCell = row.children[2]; + var patientName = patientCell ? (patientCell.querySelector('strong') || patientCell.children[0] || {}).textContent || '' : ''; + if (typeof window.openAbdmHipLinkModal === 'function') { + window.openAbdmHipLinkModal(patientId, abhaId, { patient_name: patientName.trim() }); + } + }); + }); })(); + diff --git a/app/Views/billing/Patient_Profile_Opd_V.php b/app/Views/billing/Patient_Profile_Opd_V.php index 4d425f9..1f200af 100644 --- a/app/Views/billing/Patient_Profile_Opd_V.php +++ b/app/Views/billing/Patient_Profile_Opd_V.php @@ -69,10 +69,15 @@ if ($patientPhotoPath === '') {

OPD History

- +
+ + +
@@ -2086,4 +2091,5 @@ function generateWellnessFhir(patientId, opdId) { }); } + diff --git a/app/Views/billing/Person_profile_V.php b/app/Views/billing/Person_profile_V.php index 1731148..28494a0 100644 --- a/app/Views/billing/Person_profile_V.php +++ b/app/Views/billing/Person_profile_V.php @@ -71,6 +71,14 @@ Upload
+ + mphone1)) : ?> + +
@@ -841,4 +849,5 @@ function delete_invoice(inv_id) {
- \ No newline at end of file + + \ No newline at end of file diff --git a/app/Views/billing/opd_prescription_basic.php b/app/Views/billing/opd_prescription_basic.php index 2700474..29eac01 100644 --- a/app/Views/billing/opd_prescription_basic.php +++ b/app/Views/billing/opd_prescription_basic.php @@ -578,6 +578,9 @@ + @@ -636,7 +639,12 @@
Age: str_age ?? '') ?>
Gender: xgender ?? '') ?>
-
ABHA Address:
+
+ ABHA: + +
OPD: opd_code ?? '') ?>
@@ -9977,3 +9985,5 @@ + + diff --git a/app/Views/partials/abdm_hip_link_modal.php b/app/Views/partials/abdm_hip_link_modal.php new file mode 100644 index 0000000..0c89a03 --- /dev/null +++ b/app/Views/partials/abdm_hip_link_modal.php @@ -0,0 +1,710 @@ + + + + diff --git a/app/Views/report/collection_report.php b/app/Views/report/collection_report.php index f78232b..fb2f6c4 100644 --- a/app/Views/report/collection_report.php +++ b/app/Views/report/collection_report.php @@ -9,14 +9,14 @@ $payModes = $pay_modes ?? [];
-
+
-
+
-
+
+
+ + +
@@ -100,51 +110,63 @@ $payModes = $pay_modes ?? []; var empList = empValues.length ? empValues.join('S') : '0'; var payMode = document.getElementById('paymode_id').value || '0'; + var payType = document.getElementById('pay_type_id').value || '0'; return { dateRange: encodeURIComponent(dateRange), empList: empList, payMode: payMode, + payType: payType, }; } - function buildDetailQuery() { + function buildDetailQuery(output) { var q = buildBaseQuery(); - return '/' + q.dateRange + '/' + q.empList + '/' + q.payMode; + var url = '/' + + q.dateRange + '/' + q.empList + '/' + q.payMode + '/' + q.payType; + if (output) { + url += '/' + output; + } + return url; } - function buildTotalQuery() { + function buildTotalQuery(output) { var q = buildBaseQuery(); - return '/' + q.dateRange + '/' + q.empList + '/' + q.payMode; + var url = '/' + + q.dateRange + '/' + q.empList + '/' + q.payMode + '/' + q.payType; + if (output) { + url += '/' + output; + } + return url; } document.getElementById('show_report').addEventListener('click', function() { - var url = buildDetailQuery(); + var url = buildDetailQuery(0); load_form_div(url, 'report_result'); }); document.getElementById('show_total_amount').addEventListener('click', function() { - var totalUrl = buildTotalQuery(); + var totalUrl = buildTotalQuery(0); load_form_div(totalUrl, 'report_result'); }); document.getElementById('export_report').addEventListener('click', function() { - var url = buildDetailQuery() + '/0/1'; + var url = buildDetailQuery(1); window.open(url, '_blank'); }); document.getElementById('pdf_report').addEventListener('click', function() { - var url = buildDetailQuery() + '/0/2'; + var url = buildDetailQuery(2); window.open(url, '_blank'); }); document.getElementById('total_export_report').addEventListener('click', function() { - var url = buildTotalQuery() + '/1'; + var url = buildTotalQuery(1); window.open(url, '_blank'); }); document.getElementById('total_pdf_report').addEventListener('click', function() { - var url = buildTotalQuery() + '/2'; + var url = buildTotalQuery(2); window.open(url, '_blank'); }); diff --git a/app/Views/report/collection_report_table.php b/app/Views/report/collection_report_table.php index b230dff..66d3978 100644 --- a/app/Views/report/collection_report_table.php +++ b/app/Views/report/collection_report_table.php @@ -24,7 +24,7 @@ $minRangeDisplay = $formatIndianDateTime($minRange); $maxRangeDisplay = $formatIndianDateTime($maxRange); ?> -

Date Range: to

+

Date Range: to | Payment Type:

No records found for the selected filters.
diff --git a/app/Views/report/collection_report_total_table.php b/app/Views/report/collection_report_total_table.php index a56c6ee..5770f6f 100644 --- a/app/Views/report/collection_report_total_table.php +++ b/app/Views/report/collection_report_total_table.php @@ -29,7 +29,7 @@ $minRangeDisplay = $formatIndianDateTime($minRange); $maxRangeDisplay = $formatIndianDateTime($maxRange); ?> -

Date Range: to

+

Date Range: to | Payment Type:

No records found for the selected filters.
diff --git a/app/Views/report/ipd_census_report.php b/app/Views/report/ipd_census_report.php index ec1bdff..356172c 100644 --- a/app/Views/report/ipd_census_report.php +++ b/app/Views/report/ipd_census_report.php @@ -54,6 +54,7 @@ $departments = $departments ?? [];
+ @@ -100,6 +101,7 @@ $departments = $departments ?? []; $('#ipd_census_show').off('click.ipdCensus').on('click.ipdCensus', showReport); $('#ipd_census_excel').off('click.ipdCensus').on('click.ipdCensus', function () { var url = reportUrl(1); if (url) window.open(url, '_blank'); }); + $('#ipd_census_pdf').off('click.ipdCensus').on('click.ipdCensus', function () { var url = reportUrl(2); if (url) window.open(url, '_blank'); }); $('.ipd-census-range').off('click.ipdCensus').on('click.ipdCensus', function () { var end = new Date(); var start = new Date(); start.setDate(start.getDate() - Number($(this).data('days') || 0)); from.value = ymd(start); to.value = ymd(end); showReport(); }); })(); \ No newline at end of file diff --git a/app/Views/report/ipd_census_report_table.php b/app/Views/report/ipd_census_report_table.php index 1e2a7a6..d54fa7f 100644 --- a/app/Views/report/ipd_census_report_table.php +++ b/app/Views/report/ipd_census_report_table.php @@ -1,34 +1,65 @@ -
-
Period: to
- relevant case -
-
- -
- -
+ + + + + + +
Period: to relevant case
+ + + + + + + +
+
Admissions
+
+
+
Discharges
+
+
+
Active cases
+
+
+
Avg. stay
+
days
+
+ +
+
Period: to
+ relevant case +
+
+ +
+ +
+ +
No IPD cases match the selected filters.
- + $row) : ?> - +
#IPD codeUHIDPatientDepartmentDoctorAdmissionDischargeStatusStay
#IPD codeUHIDPatientDepartmentDoctorAdmissionDischargeStatusStay
ipd_code ?? '') ?>p_code ?? '') ?>p_fname ?? '') ?> department_name ?? '') ?>doctor_name ?? '') ?> register_date ?? ''), 0, 10)) ?>discharge_date ?? ''), 0, 10) ?: '-') ?>ipd_status ?? 0) === 1 ? 'Discharged' : 'Active' ?>stay_days ?? 0)) ?> daysipd_status ?? 0) === 1 ? 'Discharged' : 'Active' ?>stay_days ?? 0)) ?> days