diff --git a/app/Controllers/Patient.php b/app/Controllers/Patient.php
index 76eee82..1504756 100644
--- a/app/Controllers/Patient.php
+++ b/app/Controllers/Patient.php
@@ -3035,11 +3035,11 @@ class Patient extends BaseController
$phase = 'DENIED';
$priority = 300;
} elseif ($status === 'FAILED' && $httpCode === 404 && stripos($errorText, 'consent record not found') !== false) {
- $phase = 'REQUESTED';
- $priority = 80;
+ $phase = 'FAILED';
+ $priority = 280;
} elseif ($status === 'FAILED') {
- $phase = 'PENDING';
- $priority = 100;
+ $phase = 'FAILED';
+ $priority = 260;
} elseif (in_array($state, ['REQUESTED', 'PENDING', 'STATUS_CHECKED'], true)) {
$phase = 'REQUESTED';
$priority = 180;
@@ -3053,7 +3053,9 @@ class Patient extends BaseController
} elseif ($phase === 'DENIED') {
$message = 'Consent was denied/revoked/expired in previous attempt.';
} elseif ($status === 'FAILED' && $httpCode === 404) {
- $message = 'Consent status was not found on bridge in previous check. Retry after a short delay.';
+ $message = 'Last consent request was not found on bridge. Start a new consent request.';
+ } elseif ($phase === 'FAILED') {
+ $message = 'Last consent request failed. Start a new consent request.';
}
if ($best === null || $priority > $bestPriority) {
@@ -3105,9 +3107,10 @@ class Patient extends BaseController
$snapshot['operation'] = (string) ($best['operation'] ?? '');
$snapshot['status'] = (string) ($best['status'] ?? '');
$snapshot['restart_required'] = (bool) (
- ($snapshot['phase'] === 'REQUESTED')
- && ($snapshot['status'] === 'failed')
- && stripos((string) ($snapshot['message'] ?? ''), 'not found on bridge') !== false
+ ($snapshot['phase'] === 'FAILED')
+ || (($snapshot['phase'] === 'REQUESTED')
+ && ($snapshot['status'] === 'failed')
+ && stripos((string) ($snapshot['message'] ?? ''), 'not found on bridge') !== false)
);
return $snapshot;
diff --git a/app/Views/billing/Patient_Profile_Opd_V.php b/app/Views/billing/Patient_Profile_Opd_V.php
index 7dbf779..8fb705e 100644
--- a/app/Views/billing/Patient_Profile_Opd_V.php
+++ b/app/Views/billing/Patient_Profile_Opd_V.php
@@ -309,11 +309,23 @@ if ($patientPhotoPath === '') {
= $abhaVerifiedStatus !== '' ? esc($abhaVerifiedStatus) : 'UNVERIFIED' ?>
+ |
+ Last Consent: Unknown
+ ?
+
@@ -410,6 +422,43 @@ $(function() {
var autoFlowMaxAttempts = 15;
var autoFlowNeedsFreshRequest = false;
+ function updateConsentBadge(phase, needsFresh) {
+ var text = (phase || '').toString().toUpperCase();
+ var $badge = $('#abdmLastConsentBadge');
+ if (!$badge.length) {
+ return;
+ }
+
+ $badge.removeClass('bg-secondary bg-success bg-info bg-warning bg-danger');
+ if (needsFresh) {
+ $badge.addClass('bg-danger').text('Failed - New Required');
+ return;
+ }
+
+ if (text === 'COMPLETED') {
+ $badge.addClass('bg-success').text('Completed');
+ } else if (text === 'GRANTED') {
+ $badge.addClass('bg-info').text('Granted');
+ } else if (text === 'REQUESTED' || text === 'PENDING') {
+ $badge.addClass('bg-warning').text('Pending');
+ } else if (text === 'FAILED' || text === 'DENIED') {
+ $badge.addClass('bg-danger').text('Failed');
+ } else {
+ $badge.addClass('bg-secondary').text('Unknown');
+ }
+ }
+
+ function applyConsentButtonState() {
+ var $newBtn = $('#btnNewAbdmConsent');
+ var canUse = autoFlowNeedsFreshRequest;
+ $newBtn.toggle(canUse);
+ if (canUse) {
+ $('#btnAutoAbdmFlow').text('Retry Sync');
+ } else {
+ $('#btnAutoAbdmFlow').text('Start ABDM Sync');
+ }
+ }
+
var zoom = 1;
var minZoom = 0.5;
var maxZoom = 3;
@@ -621,8 +670,12 @@ $(function() {
setFlowProgress(2);
} else if (lastPhase === 'REQUESTED' || lastPhase === 'PENDING') {
setFlowProgress(1);
+ } else if (lastPhase === 'FAILED' || lastPhase === 'DENIED') {
+ setFlowProgress(0);
}
+ updateConsentBadge(lastPhase, autoFlowNeedsFreshRequest);
+
var baseMsg = 'Loaded ' + currentAbdmRows.length + ' fetched ABDM record(s).';
if (lastSync && (lastSync.message || '').toString().trim() !== '') {
baseMsg = (lastSync.message || '').toString();
@@ -635,6 +688,7 @@ $(function() {
}
$('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text(baseMsg);
+ applyConsentButtonState();
})
.catch(function(err) {
$('#abdmStatusBox').removeClass('text-muted').addClass('text-danger').text('ABDM load failed: ' + (err.message || err));
@@ -706,17 +760,21 @@ $(function() {
} else if (phase === 'REQUESTED' || phase === 'PENDING') {
setFlowProgress(1);
}
+ updateConsentBadge(phase, autoFlowNeedsFreshRequest);
$('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text(info + (autoFlowRequestId ? (' | Request ID: ' + autoFlowRequestId) : ''));
if (resetRequestId) {
autoFlowNeedsFreshRequest = true;
autoFlowRequestId = '';
- if (autoFlowAttempts < autoFlowMaxAttempts) {
- autoFlowAttempts += 1;
- autoFlowTimer = setTimeout(runAutoFlowStep, 1200);
- return;
- }
+ stopAutoFlowLoop();
+ $('#btnAutoAbdmFlow').prop('disabled', false);
+ updateConsentBadge('FAILED', true);
+ applyConsentButtonState();
+ $('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text(
+ 'Previous consent request is stale/failed. Click "New Consent Request" to start a fresh request.'
+ );
+ return;
}
var shouldPoll = Number(data.poll_again || 0) === 1;
@@ -727,13 +785,15 @@ $(function() {
}
$('#btnAutoAbdmFlow').prop('disabled', false).text('One-Click Sync');
+ applyConsentButtonState();
if (phase === 'COMPLETED') {
loadAbdmDocs();
}
})
.catch(function(err) {
stopAutoFlowLoop();
- $('#btnAutoAbdmFlow').prop('disabled', false).text('One-Click Sync');
+ $('#btnAutoAbdmFlow').prop('disabled', false);
+ applyConsentButtonState();
$('#abdmStatusBox').removeClass('text-muted').addClass('text-danger').text('Auto flow failed: ' + (err.message || err));
});
}
@@ -794,10 +854,25 @@ $(function() {
runAutoFlowStep();
});
+ $(document).off('click.abdmOpd', '#btnNewAbdmConsent').on('click.abdmOpd', '#btnNewAbdmConsent', function() {
+ autoFlowNeedsFreshRequest = false;
+ autoFlowRequestId = '';
+ autoFlowAttempts = 0;
+ stopAutoFlowLoop();
+ updateConsentBadge('IDLE', false);
+ applyConsentButtonState();
+ $('#abdmStatusBox').removeClass('text-danger').addClass('text-muted').text('Fresh consent request context prepared. Click "Start ABDM Sync".');
+ });
+
$(document).off('shown.bs.tab.abdmOpd', '[data-bs-target="#opd-abdm-tab"]').on('shown.bs.tab.abdmOpd', '[data-bs-target="#opd-abdm-tab"]', function() {
if (!currentAbdmRows.length) {
loadAbdmDocs();
}
});
+
+ $('[data-bs-toggle="tooltip"]').tooltip();
+
+ applyConsentButtonState();
+ updateConsentBadge('IDLE', false);
});
diff --git a/app/Views/billing/ipd/ayushman_claim_sheet.php b/app/Views/billing/ipd/ayushman_claim_sheet.php
index 37a4f41..ffe59e8 100644
--- a/app/Views/billing/ipd/ayushman_claim_sheet.php
+++ b/app/Views/billing/ipd/ayushman_claim_sheet.php
@@ -48,11 +48,22 @@ $canUseM3 = $patientId > 0 && $abhaAddress !== '' && $abhaLooksVerified;
ABHA Number: = $abhaNumber !== '' ? esc($abhaNumber) : 'Not available' ?>
| ABHA Address: = $abhaAddress !== '' ? esc($abhaAddress) : 'Not available' ?>
| Status: = $abhaLooksVerified ? 'Verified' : 'Not verified in HMS' ?>
+ | Last Consent: Unknown
+ ?
+
@@ -145,6 +156,38 @@ $canUseM3 = $patientId > 0 && $abhaAddress !== '' && $abhaLooksVerified;
var pollTimer = null;
var pollAttempts = 0;
var maxPollAttempts = 15;
+ var needsFreshRequest = false;
+
+ function updateConsentBadge(phase, needsFresh) {
+ var text = (phase || '').toString().toUpperCase();
+ var $badge = $('#ayushmanLastConsentBadge');
+ if (!$badge.length) {
+ return;
+ }
+
+ $badge.removeClass('bg-secondary bg-success bg-info bg-warning bg-danger');
+ if (needsFresh) {
+ $badge.addClass('bg-danger').text('Failed - New Required');
+ return;
+ }
+
+ if (text === 'COMPLETED') {
+ $badge.addClass('bg-success').text('Completed');
+ } else if (text === 'GRANTED') {
+ $badge.addClass('bg-info').text('Granted');
+ } else if (text === 'REQUESTED' || text === 'PENDING') {
+ $badge.addClass('bg-warning').text('Pending');
+ } else if (text === 'FAILED' || text === 'DENIED') {
+ $badge.addClass('bg-danger').text('Failed');
+ } else {
+ $badge.addClass('bg-secondary').text('Unknown');
+ }
+ }
+
+ function applyConsentButtons() {
+ $('#btnAyushmanNewConsent').toggle(needsFreshRequest);
+ $('#btnAyushmanFetchAbdmM3').text(needsFreshRequest ? 'Retry ABDM M3 Sync' : 'Fetch From ABDM M3');
+ }
function esc(value) {
return $('').text(value == null ? '' : String(value)).html();
@@ -238,6 +281,18 @@ $canUseM3 = $patientId > 0 && $abhaAddress !== '' && $abhaLooksVerified;
}
var rows = Array.isArray(data.items) ? data.items : [];
renderRows(rows);
+
+ var lastSync = data.last_sync || null;
+ if (lastSync) {
+ var lastPhase = (lastSync.phase || '').toString().toUpperCase();
+ needsFreshRequest = !!lastSync.restart_required;
+ if (!needsFreshRequest && (lastSync.request_id || '').toString().trim() !== '') {
+ currentRequestId = (lastSync.request_id || '').toString().trim();
+ }
+ updateConsentBadge(lastPhase, needsFreshRequest);
+ applyConsentButtons();
+ }
+
setStatus('Loaded ' + rows.length + ' fetched ABDM record(s).', false);
})
.catch(function (error) {
@@ -286,7 +341,20 @@ $canUseM3 = $patientId > 0 && $abhaAddress !== '' && $abhaLooksVerified;
currentRequestId = (data.request_id || currentRequestId || '').toString();
var phase = (data.phase || '').toString();
var message = (data.message || ('Phase: ' + (phase || 'UNKNOWN'))).toString();
+ var resetRequestId = parseInt(data.reset_request_id || 0, 10) === 1;
setStatus(message + (currentRequestId ? (' | Request ID: ' + currentRequestId) : ''), false);
+ updateConsentBadge(phase, needsFreshRequest);
+
+ if (resetRequestId) {
+ needsFreshRequest = true;
+ currentRequestId = '';
+ stopPolling();
+ $('#btnAyushmanFetchAbdmM3').prop('disabled', false);
+ updateConsentBadge('FAILED', true);
+ applyConsentButtons();
+ setStatus('Previous consent request is stale/failed. Click "New Consent Request" and run sync again.', false);
+ return;
+ }
if (parseInt(data.poll_again || 0, 10) === 1 && pollAttempts < maxPollAttempts) {
pollAttempts += 1;
@@ -294,14 +362,16 @@ $canUseM3 = $patientId > 0 && $abhaAddress !== '' && $abhaLooksVerified;
return;
}
- $('#btnAyushmanFetchAbdmM3').prop('disabled', false).text('Fetch From ABDM M3');
+ $('#btnAyushmanFetchAbdmM3').prop('disabled', false);
+ applyConsentButtons();
if (phase === 'COMPLETED') {
loadDocs();
}
})
.catch(function (error) {
stopPolling();
- $('#btnAyushmanFetchAbdmM3').prop('disabled', false).text('Fetch From ABDM M3');
+ $('#btnAyushmanFetchAbdmM3').prop('disabled', false);
+ applyConsentButtons();
setStatus('M3 fetch failed: ' + (error.message || error), true);
});
}
@@ -331,6 +401,21 @@ $canUseM3 = $patientId > 0 && $abhaAddress !== '' && $abhaLooksVerified;
setStatus('Starting ABDM M3 consent and data fetch flow...', false);
runM3AutoFlow();
});
+
+ $(document).off('click.ayushmanAbdm', '#btnAyushmanNewConsent').on('click.ayushmanAbdm', '#btnAyushmanNewConsent', function () {
+ needsFreshRequest = false;
+ currentRequestId = '';
+ pollAttempts = 0;
+ stopPolling();
+ updateConsentBadge('IDLE', false);
+ applyConsentButtons();
+ setStatus('Fresh consent request context prepared. Click "Fetch From ABDM M3" to create a new request.', false);
+ });
+
+ $('[data-bs-toggle="tooltip"]').tooltip();
+
+ applyConsentButtons();
+ updateConsentBadge('IDLE', false);
})();