From a1127522effb5754c0fb1ed8fc5c24dd02a3d1b0 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Tue, 28 Jul 2026 02:48:02 +0530 Subject: [PATCH] ABDM M3: flatten nested consent.status from bridge (root cause fix) and redesign OPD Fetch ABDM Records UI --- app/Libraries/Abdm/M3HiuGatewayClient.php | 17 ++++ app/Views/billing/Patient_Profile_Opd_V.php | 107 +++++++++++--------- 2 files changed, 76 insertions(+), 48 deletions(-) diff --git a/app/Libraries/Abdm/M3HiuGatewayClient.php b/app/Libraries/Abdm/M3HiuGatewayClient.php index 6ba1f44..df25ebc 100644 --- a/app/Libraries/Abdm/M3HiuGatewayClient.php +++ b/app/Libraries/Abdm/M3HiuGatewayClient.php @@ -335,6 +335,23 @@ class M3HiuGatewayClient $response['abdm_consent_artifact_id'] = $abdmConsentId; } + // Per bridge contract, consent status/date_range/expiry come back nested + // under `consent{}` (e.g. { consent: { status: "GRANTED", ... } }) rather + // than at the top level. Flatten them so resolveState()/snapshot logic + // (which reads $response['consent_status']) can see the real value — + // otherwise GRANTED consents keep getting misclassified as pending. + $abdmConsentStatus = $this->findFirstValueByKeys($response, ['status']); + if ($abdmConsentStatus !== '') { + $response['consent_status'] = strtoupper($abdmConsentStatus); + } + if (isset($response['consent']) && is_array($response['consent'])) { + foreach (['date_range', 'dateRange', 'expiry', 'purpose', 'hi_types', 'abha_address', 'granted_at'] as $flattenKey) { + if (! isset($response[$flattenKey]) && isset($response['consent'][$flattenKey])) { + $response[$flattenKey] = $response['consent'][$flattenKey]; + } + } + } + if (! isset($response['transaction_id'])) { $response['transaction_id'] = (string) ($response['transactionId'] ?? $cleanQuery['transaction_id'] ?? ''); } diff --git a/app/Views/billing/Patient_Profile_Opd_V.php b/app/Views/billing/Patient_Profile_Opd_V.php index acf6612..79465b8 100644 --- a/app/Views/billing/Patient_Profile_Opd_V.php +++ b/app/Views/billing/Patient_Profile_Opd_V.php @@ -295,49 +295,57 @@ if ($patientPhotoPath === '') {
-
-
-
ABHA Context
-
- ABHA ID: -  |  - ABHA Address: -  |  - Status: - - VERIFIED - - - -  |  - Last Consent: Unknown - ? +
+
+
+
+
ABDM M3 — Fetch Patient Health Records
+
+ ABHA Address: +  |  + ABHA Status: + + VERIFIED + + + +
+
+
+ +
+ +
+
-
-
- - -
-
-
Click "Refresh Fetched Data" to load ABDM records mapped to this patient.
+ +
+ ABHA must be linked and verified for this patient before ABDM records can be requested. Verify ABHA from the patient's profile first. +
+ +
+ One click sends a consent request to the patient's ABHA (PHR) app. Once the patient approves it there, HMS automatically fetches their health records — no need to click again. +
+ -
-
- 1. Requested - 2. Granted - 3. Fetched -
-
-
+
+
+ 1. Consent Requested + 2. Consent Granted + 3. Records Fetched +
+
+
+
+
+ Unknown + Click "Fetch ABDM Records" to request and load the patient's ABDM health records. +
+
@@ -420,6 +428,7 @@ $(function() { var autoFlowAttempts = 0; var autoFlowMaxAttempts = 15; var autoFlowNeedsFreshRequest = false; + var autoFlowRunning = false; function updateConsentBadge(phase, needsFresh) { var text = (phase || '').toString().toUpperCase(); @@ -448,7 +457,9 @@ $(function() { } function applyConsentButtonState() { - $('#btnAutoAbdmFlow').text(autoFlowTimer ? 'Fetching...' : 'Fetch Request'); + $('#btnAutoAbdmFlow').prop('disabled', autoFlowRunning); + $('#btnAutoAbdmFlow .abdm-btn-spinner').toggleClass('d-none', !autoFlowRunning); + $('#btnAutoAbdmFlowLabel').text(autoFlowRunning ? 'Fetching...' : 'Fetch ABDM Records'); } var zoom = 1; @@ -760,7 +771,7 @@ $(function() { autoFlowRequestId = ''; stopAutoFlowLoop(); updateConsentBadge('FAILED', false); - $('#btnAutoAbdmFlow').prop('disabled', false); + autoFlowRunning = false; applyConsentButtonState(); $('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text('Previous request is still being processed. Please wait for the first request to finish before starting a new one.'); return; @@ -773,7 +784,7 @@ $(function() { return; } - $('#btnAutoAbdmFlow').prop('disabled', false); + autoFlowRunning = false; applyConsentButtonState(); if (phase === 'COMPLETED') { loadAbdmDocs(); @@ -781,7 +792,7 @@ $(function() { }) .catch(function(err) { stopAutoFlowLoop(); - $('#btnAutoAbdmFlow').prop('disabled', false); + autoFlowRunning = false; applyConsentButtonState(); $('#abdmStatusBox').removeClass('text-muted').addClass('text-danger').text('Auto flow failed: ' + (err.message || err)); }); @@ -827,8 +838,7 @@ $(function() { }); $(document).off('click.abdmOpd', '#btnAutoAbdmFlow').on('click.abdmOpd', '#btnAutoAbdmFlow', function() { - var $btn = $(this); - if ($btn.prop('disabled')) { + if (autoFlowRunning) { return; } stopAutoFlowLoop(); @@ -838,8 +848,9 @@ $(function() { autoFlowNeedsFreshRequest = false; } setFlowProgress(1); - $btn.prop('disabled', true).text('Sync Running...'); - $('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text('Starting one-click sync flow...'); + autoFlowRunning = true; + applyConsentButtonState(); + $('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text('Sending consent request to patient\'s ABHA app...'); runAutoFlowStep(); });