Show Consent Request ID in Consent Request History and fetched-document list; persist consent_request_id per document

This commit is contained in:
DevSoftTech Server 2026-07-29 03:05:02 +05:30
parent 016c0fdf2f
commit 7129f6e17b
3 changed files with 69 additions and 10 deletions

View File

@ -1169,8 +1169,14 @@ class Patient extends BaseController
$q = trim((string) ($this->request->getGet('q') ?? '')); $q = trim((string) ($this->request->getGet('q') ?? ''));
$docFields = $this->db->getFieldNames('abdm_hiu_documents') ?? [];
$selectCols = ['d.id', 'd.patient_id', 'd.abha_address', 'd.document_title', 'd.document_date', 'd.care_context_reference', 'd.practitioner_name', 'd.organization_name', 'd.bundle_type', 'd.created_at'];
if (in_array('consent_request_id', $docFields, true)) {
$selectCols[] = 'd.consent_request_id';
}
$builder = $this->db->table('abdm_hiu_documents d') $builder = $this->db->table('abdm_hiu_documents d')
->select('d.id, d.patient_id, d.abha_address, d.document_title, d.document_date, d.care_context_reference, d.practitioner_name, d.organization_name, d.bundle_type, d.created_at') ->select(implode(', ', $selectCols))
->orderBy('d.document_date', 'DESC') ->orderBy('d.document_date', 'DESC')
->orderBy('d.id', 'DESC') ->orderBy('d.id', 'DESC')
->limit($limit); ->limit($limit);
@ -2033,7 +2039,12 @@ class Patient extends BaseController
]; ];
if ($consentArtifactRef !== '') { if ($consentArtifactRef !== '') {
$fetchPayload['consentId'] = $consentArtifactRef; $fetchPayload['consentId'] = $consentArtifactRef;
} else { }
// Always include the request id too (when known), purely so any documents
// persisted from this fetch can record which consent request they came
// from. This does not change the actual bridge query for Method 2, which
// is driven only by consentId when both are present.
if ($consentRequestRef !== '') {
$fetchPayload['consentRequestId'] = $consentRequestRef; $fetchPayload['consentRequestId'] = $consentRequestRef;
} }

View File

@ -24,8 +24,21 @@ class M3HiuDocumentRepository
return ['saved' => 0, 'updated' => 0, 'skipped' => 0]; return ['saved' => 0, 'updated' => 0, 'skipped' => 0];
} }
$this->ensureConsentRequestIdColumn();
$requestId = trim((string) ($result['request_id'] ?? $payload['request_id'] ?? $payload['requestId'] ?? '')); $requestId = trim((string) ($result['request_id'] ?? $payload['request_id'] ?? $payload['requestId'] ?? ''));
$abhaAddress = trim((string) ($payload['abha_address'] ?? $result['abha_address'] ?? '')); $abhaAddress = trim((string) ($payload['abha_address'] ?? $result['abha_address'] ?? ''));
// The specific consent request (e.g. Method 1/2's targeted request) that
// triggered this fetch, when known. Method 3 (fetch-all-by-abha-address)
// spans many past consent requests at once, so this is intentionally left
// blank for that broad fetch rather than mis-attributing every document to
// whichever single request happened to be passed in.
$consentRequestId = trim((string) (
$payload['abdm_consent_request_id']
?? $payload['consent_request_id']
?? $payload['consentRequestId']
?? ''
));
$saved = 0; $saved = 0;
$updated = 0; $updated = 0;
@ -104,6 +117,12 @@ class M3HiuDocumentRepository
'updated_at' => $now, 'updated_at' => $now,
]; ];
// Only set (and never blank out on update) when this specific fetch
// actually knew which consent request it belonged to.
if ($consentRequestId !== '') {
$row['consent_request_id'] = $consentRequestId;
}
$existing = $this->db->table('abdm_hiu_documents') $existing = $this->db->table('abdm_hiu_documents')
->select('id') ->select('id')
->where('doc_hash', $docHash) ->where('doc_hash', $docHash)
@ -126,6 +145,26 @@ class M3HiuDocumentRepository
return ['saved' => $saved, 'updated' => $updated, 'skipped' => $skipped]; return ['saved' => $saved, 'updated' => $updated, 'skipped' => $skipped];
} }
/**
* Idempotent backfill so deployments that predate the Consent Request ID
* enrichment (added 2026-07-29) don't fail with "Unknown column" on save.
*/
private function ensureConsentRequestIdColumn(): void
{
$fields = $this->db->getFieldNames('abdm_hiu_documents') ?? [];
if (in_array('consent_request_id', $fields, true)) {
return;
}
try {
$this->db->query('ALTER TABLE abdm_hiu_documents ADD COLUMN consent_request_id VARCHAR(190) NULL AFTER consent_artifact_id');
} catch (\Throwable $e) {
// Best-effort; if the ALTER fails (e.g. concurrent request already
// added it, or insufficient DB privileges) just skip enrichment for
// this call rather than breaking the fetch.
}
}
public function listDocuments(array $filters, int $limit = 100): array public function listDocuments(array $filters, int $limit = 100): array
{ {
if (! $this->db->tableExists('abdm_hiu_documents')) { if (! $this->db->tableExists('abdm_hiu_documents')) {

View File

@ -348,6 +348,7 @@ if ($patientPhotoPath === '') {
<thead> <thead>
<tr> <tr>
<th>Status</th> <th>Status</th>
<th>Request ID</th>
<th>HI Types</th> <th>HI Types</th>
<th>Requested By</th> <th>Requested By</th>
<th>Requested On</th> <th>Requested On</th>
@ -356,7 +357,7 @@ if ($patientPhotoPath === '') {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr><td colspan="6" class="text-muted text-center">No consent requests yet.</td></tr> <tr><td colspan="7" class="text-muted text-center">No consent requests yet.</td></tr>
</tbody> </tbody>
</table> </table>
</div> </div>
@ -364,7 +365,7 @@ if ($patientPhotoPath === '') {
</div> </div>
<div class="row g-3"> <div class="row g-3">
<div class="col-lg-5"> <div class="col-lg-6">
<div class="input-group input-group-sm mb-2"> <div class="input-group input-group-sm mb-2">
<input id="abdmDocSearch" class="form-control" placeholder="Search title, care context, doctor"> <input id="abdmDocSearch" class="form-control" placeholder="Search title, care context, doctor">
<button class="btn btn-outline-secondary" type="button" id="btnSearchAbdmDocs">Search</button> <button class="btn btn-outline-secondary" type="button" id="btnSearchAbdmDocs">Search</button>
@ -376,15 +377,17 @@ if ($patientPhotoPath === '') {
<th>Date</th> <th>Date</th>
<th>Title</th> <th>Title</th>
<th>Care Context</th> <th>Care Context</th>
<th>Org / Hospital</th>
<th>Request ID</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr><td colspan="3" class="text-muted text-center">No records loaded.</td></tr> <tr><td colspan="5" class="text-muted text-center">No records loaded.</td></tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
<div class="col-lg-7"> <div class="col-lg-6">
<div class="border rounded p-3 bg-light" id="abdmDocDetailBox"> <div class="border rounded p-3 bg-light" id="abdmDocDetailBox">
<div class="text-muted">Select a fetched document to view details.</div> <div class="text-muted">Select a fetched document to view details.</div>
</div> </div>
@ -677,7 +680,7 @@ $(function() {
function renderAbdmRequestsTable(requests) { function renderAbdmRequestsTable(requests) {
if (!requests || !requests.length) { if (!requests || !requests.length) {
$('#abdmRequestsTable tbody').html('<tr><td colspan="6" class="text-muted text-center">No consent requests yet.</td></tr>'); $('#abdmRequestsTable tbody').html('<tr><td colspan="7" class="text-muted text-center">No consent requests yet.</td></tr>');
return; return;
} }
@ -687,9 +690,11 @@ $(function() {
var hiTypes = (consent.requested_hi_types && consent.requested_hi_types.length) ? consent.requested_hi_types : (consent.granted_hi_types || []); var hiTypes = (consent.requested_hi_types && consent.requested_hi_types.length) ? consent.requested_hi_types : (consent.granted_hi_types || []);
var hiTypesText = hiTypes.length ? hiTypes.join(', ') : '-'; var hiTypesText = hiTypes.length ? hiTypes.join(', ') : '-';
var canFetch = (status === 'GRANTED' || status === 'COMPLETED'); var canFetch = (status === 'GRANTED' || status === 'COMPLETED');
var requestId = consent.consent_request_id || '-';
html += '<tr>' html += '<tr>'
+ '<td><span class="badge ' + consentStatusBadgeClass(status) + '">' + escHtml(status || 'UNKNOWN') + '</span></td>' + '<td><span class="badge ' + consentStatusBadgeClass(status) + '">' + escHtml(status || 'UNKNOWN') + '</span></td>'
+ '<td class="small text-truncate" style="max-width:160px;" title="' + escHtml(requestId) + '">' + escHtml(requestId) + '</td>'
+ '<td class="small">' + escHtml(hiTypesText) + '</td>' + '<td class="small">' + escHtml(hiTypesText) + '</td>'
+ '<td class="small">' + escHtml(consent.requested_by || 'HMS') + '</td>' + '<td class="small">' + escHtml(consent.requested_by || 'HMS') + '</td>'
+ '<td class="small">' + fmtConsentTs(consent.requested_on) + '</td>' + '<td class="small">' + fmtConsentTs(consent.requested_on) + '</td>'
@ -714,7 +719,7 @@ $(function() {
renderAbdmRequestsTable(currentAbdmRequests); renderAbdmRequestsTable(currentAbdmRequests);
}) })
.catch(function(err) { .catch(function(err) {
$('#abdmRequestsTable tbody').html('<tr><td colspan="6" class="text-danger text-center">' + escHtml('Failed to load consent request history: ' + (err.message || err)) + '</td></tr>'); $('#abdmRequestsTable tbody').html('<tr><td colspan="7" class="text-danger text-center">' + escHtml('Failed to load consent request history: ' + (err.message || err)) + '</td></tr>');
}); });
} }
@ -879,17 +884,20 @@ $(function() {
function renderAbdmRows(rows) { function renderAbdmRows(rows) {
var html = ''; var html = '';
if (!rows || !rows.length) { if (!rows || !rows.length) {
html = '<tr><td colspan="3" class="text-muted text-center">No ABDM fetched records found.</td></tr>'; html = '<tr><td colspan="5" class="text-muted text-center">No ABDM fetched records found.</td></tr>';
$('#abdmDocTable tbody').html(html); $('#abdmDocTable tbody').html(html);
$('#abdmDocDetailBox').html('<div class="text-muted">No records available for this patient.</div>'); $('#abdmDocDetailBox').html('<div class="text-muted">No records available for this patient.</div>');
return; return;
} }
rows.forEach(function(row) { rows.forEach(function(row) {
var reqId = row.consent_request_id || '-';
html += '<tr class="abdm-doc-row" data-id="' + escHtml(row.id) + '">' + html += '<tr class="abdm-doc-row" data-id="' + escHtml(row.id) + '">' +
'<td>' + escHtml(fmtDateTime(row.document_date || row.created_at)) + '</td>' + '<td>' + escHtml(fmtDateTime(row.document_date || row.created_at)) + '</td>' +
'<td>' + escHtml(row.document_title || '-') + '</td>' + '<td>' + escHtml(row.document_title || '-') + '</td>' +
'<td>' + escHtml(row.care_context_reference || '-') + '</td>' + '<td>' + escHtml(row.care_context_reference || '-') + '</td>' +
'<td class="small text-truncate" style="max-width:140px;" title="' + escHtml(row.organization_name || '-') + '">' + escHtml(row.organization_name || '-') + '</td>' +
'<td class="small text-truncate" style="max-width:140px;" title="' + escHtml(reqId) + '">' + escHtml(reqId) + '</td>' +
'</tr>'; '</tr>';
}); });
$('#abdmDocTable tbody').html(html); $('#abdmDocTable tbody').html(html);
@ -911,7 +919,8 @@ $(function() {
html += '<div class="small text-muted mb-2">Date: ' + escHtml(fmtDateTime(item.document_date || item.created_at)) + '</div>'; html += '<div class="small text-muted mb-2">Date: ' + escHtml(fmtDateTime(item.document_date || item.created_at)) + '</div>';
html += '<div class="small mb-2">Care Context: <strong>' + escHtml(item.care_context_reference || '-') + '</strong></div>'; html += '<div class="small mb-2">Care Context: <strong>' + escHtml(item.care_context_reference || '-') + '</strong></div>';
html += '<div class="small mb-2">Doctor: <strong>' + escHtml(item.practitioner_name || '-') + '</strong></div>'; html += '<div class="small mb-2">Doctor: <strong>' + escHtml(item.practitioner_name || '-') + '</strong></div>';
html += '<div class="small mb-3">Organization: <strong>' + escHtml(item.organization_name || '-') + '</strong></div>'; html += '<div class="small mb-2">Organization: <strong>' + escHtml(item.organization_name || '-') + '</strong></div>';
html += '<div class="small mb-3">Consent Request ID: <strong>' + escHtml(item.consent_request_id || '-') + '</strong></div>';
html += '<div class="row g-2">'; html += '<div class="row g-2">';
html += '<div class="col-md-4"><div class="border rounded p-2 h-100"><div class="fw-semibold small mb-1">Diagnoses</div><ul class="mb-0 small abdm-doc-detail-list">'; html += '<div class="col-md-4"><div class="border rounded p-2 h-100"><div class="fw-semibold small mb-1">Diagnoses</div><ul class="mb-0 small abdm-doc-detail-list">';