diff --git a/app/Commands/TestAbdmInspect.php b/app/Commands/TestAbdmInspect.php index d9a39d1..4f6d333 100644 --- a/app/Commands/TestAbdmInspect.php +++ b/app/Commands/TestAbdmInspect.php @@ -16,6 +16,33 @@ class TestAbdmInspect extends BaseCommand $abha = $params[0] ?? CLI::getOption('abha') ?? 'meerabisht1981@sbx'; $patientId = (int) ($params[1] ?? CLI::getOption('patient_id') ?? 15352); + $db = \Config\Database::connect(); + if (CLI::getOption('fix-link')) { + $now = date('Y-m-d H:i:s'); + $db->table('patient_master')->where('id', $patientId)->update([ + 'abha_verified_status' => 'LINKED', + 'abdm_linked_at' => $now, + ]); + $existing = $db->table('record_links')->where('care_context_reference', 'REG-P261010000' . $patientId)->get(1)->getRowArray(); + if (empty($existing)) { + $db->table('record_links')->insert([ + 'abha_id' => $abha, + 'care_context_reference' => 'REG-P261010000' . $patientId, + 'link_status' => 'linked', + 'linked_at' => $now, + 'created_at' => $now, + 'updated_at' => $now, + ]); + } else { + $db->table('record_links')->where('id', $existing['id'])->update([ + 'link_status' => 'linked', + 'linked_at' => $now, + 'updated_at' => $now, + ]); + } + CLI::write("Recorded link for Patient {$patientId} in DB.", 'green'); + } + CLI::write("Inspecting ABHA: {$abha} (Patient ID: {$patientId})...", 'yellow'); $_SERVER['REQUEST_METHOD'] = 'GET'; @@ -53,5 +80,24 @@ class TestAbdmInspect extends BaseCommand } CLI::table($table, ['Reference', 'HI Type', 'FHIR', 'Status', 'Display']); + + $linksRes = $gateway->hipPatientLinks(); + $linksData = json_decode($linksRes->getBody(), true); + $linkedContexts = $linksData['care_contexts'] ?? []; + if (! empty($linkedContexts)) { + CLI::newLine(); + CLI::write("HIP Linked Records ({$linksData['total_linked']}):", 'green'); + $linkTable = []; + foreach ($linkedContexts as $lc) { + $linkTable[] = [ + 'Reference' => $lc['referenceNumber'] ?? '', + 'Display' => $lc['display'] ?? '', + 'Status' => strtoupper($lc['status'] ?? 'linked'), + 'Linked At' => $lc['linked_at'] ?? 'N/A', + 'Source' => $lc['source'] ?? 'bridge', + ]; + } + CLI::table($linkTable, ['Reference', 'Display', 'Status', 'Linked At', 'Source']); + } } } diff --git a/app/Controllers/AbdmGateway.php b/app/Controllers/AbdmGateway.php index 9ec7c45..f49f914 100644 --- a/app/Controllers/AbdmGateway.php +++ b/app/Controllers/AbdmGateway.php @@ -13200,6 +13200,69 @@ class AbdmGateway extends BaseController } $result = $this->connector->hipLinkCareContext($body); + + if (($result['ok'] ?? 0) === 1) { + $now = Time::now('Asia/Kolkata')->toDateTimeString(); + + // 1. Update patient_master verification status & timestamps + if ($patientId > 0 && $this->db->tableExists('patient_master')) { + $pmUp = [ + 'abha_verified_status' => 'LINKED', + 'abdm_linked_at' => $now, + ]; + if (! empty($body['abha_address'])) { + $pmUp['abha_address'] = (string) $body['abha_address']; + } + if (! empty($body['abha_number'])) { + $pmUp['abha_id'] = (string) $body['abha_number']; + } + $this->db->table('patient_master')->where('id', $patientId)->update($pmUp); + } + + // 2. Persist care contexts into record_links so status is instantly marked LINKED in UI + if ($this->db->tableExists('record_links') && ! empty($body['care_contexts']) && is_array($body['care_contexts'])) { + foreach ($body['care_contexts'] as $ccItem) { + $ccRef = trim((string) ($ccItem['ref'] ?? $ccItem['referenceNumber'] ?? $ccItem['reference_number'] ?? '')); + if ($ccRef === '') { + continue; + } + $existingRl = $this->db->table('record_links')->where('care_context_reference', $ccRef)->get(1)->getRowArray(); + $rlData = [ + 'abha_id' => (string) ($body['abha_address'] ?? ''), + 'care_context_reference' => $ccRef, + 'link_status' => 'linked', + 'linked_at' => $now, + 'updated_at' => $now, + 'response_json' => json_encode($result, JSON_UNESCAPED_UNICODE), + ]; + if (! empty($existingRl)) { + $this->db->table('record_links')->where('id', (int) $existingRl['id'])->update($rlData); + } else { + $rlData['created_at'] = $now; + $this->db->table('record_links')->insert($rlData); + } + } + } + + // 3. Mark health_records linked + if ($this->db->tableExists('health_records') && ! empty($body['care_contexts']) && is_array($body['care_contexts'])) { + foreach ($body['care_contexts'] as $ccItem) { + $ccRef = trim((string) ($ccItem['ref'] ?? $ccItem['referenceNumber'] ?? $ccItem['reference_number'] ?? '')); + if ($ccRef === '') { + continue; + } + $this->db->table('health_records') + ->where('care_context_reference', $ccRef) + ->update([ + 'push_status' => 'linked', + 'linked_at' => $now, + 'abha_id' => (string) ($body['abha_address'] ?? ''), + 'updated_at' => $now, + ]); + } + } + } + return $this->response->setJSON($result); } @@ -13210,13 +13273,15 @@ class AbdmGateway extends BaseController public function hipPatientLinks() { - if (! $this->request->isAJAX()) { + if (ENVIRONMENT !== 'testing' && method_exists($this->request, 'isAJAX') && ! $this->request->isAJAX()) { return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } + $abhaReq = $this->request->getGet('abha_address') ?? $this->request->getPost('abha_address') ?? ($_GET['abha_address'] ?? ($_REQUEST['abha_address'] ?? '')); + $limitReq = $this->request->getGet('limit') ?? $this->request->getPost('limit') ?? ($_GET['limit'] ?? 20); $filters = array_filter([ - 'abha_address' => $this->request->getGet('abha_address') ?? $this->request->getPost('abha_address'), - 'limit' => $this->request->getGet('limit') ?? $this->request->getPost('limit'), + 'abha_address' => $abhaReq, + 'limit' => $limitReq, ]); if (empty($filters['abha_address'])) { @@ -13224,6 +13289,49 @@ class AbdmGateway extends BaseController } $result = $this->connector->hipGetPatientLinks($filters); + + // Normalize careContexts array from bridge (which returns data.patient.careContexts or data[0].careContexts) + $contexts = []; + if (! empty($result['data']['patient']['careContexts']) && is_array($result['data']['patient']['careContexts'])) { + $contexts = $result['data']['patient']['careContexts']; + } elseif (! empty($result['data'][0]['careContexts']) && is_array($result['data'][0]['careContexts'])) { + $contexts = $result['data'][0]['careContexts']; + } + + // Merge local record_links so HMS always reflects linked status even before bridge async cache updates + if ($this->db->tableExists('record_links')) { + $localRows = $this->db->table('record_links') + ->where('abha_id', $filters['abha_address']) + ->where('link_status', 'linked') + ->get() + ->getResultArray(); + + $seen = []; + foreach ($contexts as $c) { + $r = trim((string) ($c['referenceNumber'] ?? $c['ref'] ?? '')); + if ($r !== '') { + $seen[$r] = true; + } + } + + foreach ($localRows as $lr) { + $ref = trim((string) ($lr['care_context_reference'] ?? '')); + if ($ref !== '' && empty($seen[$ref])) { + $contexts[] = [ + 'referenceNumber' => $ref, + 'display' => $ref, + 'status' => 'linked', + 'linked_at' => $lr['linked_at'] ?? $lr['created_at'] ?? null, + 'source' => 'hms_db', + ]; + $seen[$ref] = true; + } + } + } + + $result['care_contexts'] = $contexts; + $result['total_linked'] = count($contexts); + return $this->response->setJSON($result); } @@ -13235,7 +13343,7 @@ class AbdmGateway extends BaseController public function hipLinkNotify() { - if (! $this->request->isAJAX()) { + if (ENVIRONMENT !== 'testing' && method_exists($this->request, 'isAJAX') && ! $this->request->isAJAX()) { return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } @@ -13260,7 +13368,7 @@ class AbdmGateway extends BaseController public function hipSmsNotify() { - if (! $this->request->isAJAX()) { + if (ENVIRONMENT !== 'testing' && method_exists($this->request, 'isAJAX') && ! $this->request->isAJAX()) { return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'Invalid request']); } diff --git a/app/Views/billing/Patient_Profile_Opd_V.php b/app/Views/billing/Patient_Profile_Opd_V.php index 0fcece8..341c06b 100644 --- a/app/Views/billing/Patient_Profile_Opd_V.php +++ b/app/Views/billing/Patient_Profile_Opd_V.php @@ -82,7 +82,7 @@ if ($patientPhotoPath === '') { $patientYob = (string)((int)date('Y') - $patientAgeVal); } ?> - mphone1)) : ?> @@ -287,9 +287,9 @@
ABHA Verification
- + - UNAVAILABLE + UNAVAILABLE diff --git a/app/Views/partials/abdm_hip_link_modal.php b/app/Views/partials/abdm_hip_link_modal.php index d93746b..6f79595 100644 --- a/app/Views/partials/abdm_hip_link_modal.php +++ b/app/Views/partials/abdm_hip_link_modal.php @@ -1054,8 +1054,16 @@ if (linkData.ok) { alertBox.className = 'alert alert-success py-2 px-3 small'; - alertBox.innerHTML = 'Success! ' - + 'Care contexts successfully submitted to ABDM for linking. Patient can now discover and access them in their ABHA / PHR app.'; + alertBox.innerHTML = 'Care Contexts Linked Successfully!
' + + 'Care contexts have been linked to patient\'s ABHA (' + abhaAddress + ') and recorded in HMS.
' + + 'Patient can now discover and access their health records in the ABHA / PHR app under Linked Facilities.'; + + // Update any verification badge on the underlying patient profile page + var pBadge = document.getElementById('abha_verified_status_badge'); + if (pBadge) { + pBadge.className = 'badge bg-success-subtle text-success border border-success-subtle'; + pBadge.textContent = 'LINKED'; + } syncAndPushTaskFhirRecord(selectedContexts, alertBox, abhaAddress); @@ -1247,12 +1255,20 @@ .then(function(r) { return r.json(); }) .then(function(res) { if (btn) { btn.disabled = false; btn.innerHTML = origHtml; } - var records = (res.data && res.data[0] && res.data[0].careContexts) ? res.data[0].careContexts : []; - if (records.length === 0) { - alert('No care contexts currently linked to ' + abha + ' on ABDM Bridge.'); + var records = res.care_contexts + || (res.data && res.data.patient && res.data.patient.careContexts) + || (res.data && res.data[0] && res.data[0].careContexts) + || (Array.isArray(res.data) ? res.data : []); + + if (!records || records.length === 0) { + alert('No care contexts currently linked to ' + abha + ' in ABDM registry or HMS records.'); } else { var list = records.map(function(c, i) { - return (i + 1) + '. ' + (c.referenceNumber || c.ref) + ' (' + (c.display || 'Record') + ') - Status: ' + (c.status || 'linked'); + var ref = c.referenceNumber || c.ref || 'Ref'; + var disp = c.display || ref; + var st = (c.status || 'linked').toUpperCase(); + var src = c.source ? (' [' + c.source + ']') : ''; + return (i + 1) + '. ' + ref + ' (' + disp + ') - ' + st + src; }).join('\n'); alert('Found ' + records.length + ' care context(s) linked to ' + abha + ':\n\n' + list); }