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') ?? ''));
$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')
->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.id', 'DESC')
->limit($limit);
@ -2033,7 +2039,12 @@ class Patient extends BaseController
];
if ($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;
}

View File

@ -24,8 +24,21 @@ class M3HiuDocumentRepository
return ['saved' => 0, 'updated' => 0, 'skipped' => 0];
}
$this->ensureConsentRequestIdColumn();
$requestId = trim((string) ($result['request_id'] ?? $payload['request_id'] ?? $payload['requestId'] ?? ''));
$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;
$updated = 0;
@ -104,6 +117,12 @@ class M3HiuDocumentRepository
'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')
->select('id')
->where('doc_hash', $docHash)
@ -126,6 +145,26 @@ class M3HiuDocumentRepository
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
{
if (! $this->db->tableExists('abdm_hiu_documents')) {

View File

@ -348,6 +348,7 @@ if ($patientPhotoPath === '') {
<thead>
<tr>
<th>Status</th>
<th>Request ID</th>
<th>HI Types</th>
<th>Requested By</th>
<th>Requested On</th>
@ -356,7 +357,7 @@ if ($patientPhotoPath === '') {
</tr>
</thead>
<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>
</table>
</div>
@ -364,7 +365,7 @@ if ($patientPhotoPath === '') {
</div>
<div class="row g-3">
<div class="col-lg-5">
<div class="col-lg-6">
<div class="input-group input-group-sm mb-2">
<input id="abdmDocSearch" class="form-control" placeholder="Search title, care context, doctor">
<button class="btn btn-outline-secondary" type="button" id="btnSearchAbdmDocs">Search</button>
@ -376,15 +377,17 @@ if ($patientPhotoPath === '') {
<th>Date</th>
<th>Title</th>
<th>Care Context</th>
<th>Org / Hospital</th>
<th>Request ID</th>
</tr>
</thead>
<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>
</table>
</div>
</div>
<div class="col-lg-7">
<div class="col-lg-6">
<div class="border rounded p-3 bg-light" id="abdmDocDetailBox">
<div class="text-muted">Select a fetched document to view details.</div>
</div>
@ -677,7 +680,7 @@ $(function() {
function renderAbdmRequestsTable(requests) {
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;
}
@ -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 hiTypesText = hiTypes.length ? hiTypes.join(', ') : '-';
var canFetch = (status === 'GRANTED' || status === 'COMPLETED');
var requestId = consent.consent_request_id || '-';
html += '<tr>'
+ '<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(consent.requested_by || 'HMS') + '</td>'
+ '<td class="small">' + fmtConsentTs(consent.requested_on) + '</td>'
@ -714,7 +719,7 @@ $(function() {
renderAbdmRequestsTable(currentAbdmRequests);
})
.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) {
var html = '';
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);
$('#abdmDocDetailBox').html('<div class="text-muted">No records available for this patient.</div>');
return;
}
rows.forEach(function(row) {
var reqId = row.consent_request_id || '-';
html += '<tr class="abdm-doc-row" data-id="' + escHtml(row.id) + '">' +
'<td>' + escHtml(fmtDateTime(row.document_date || row.created_at)) + '</td>' +
'<td>' + escHtml(row.document_title || '-') + '</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>';
});
$('#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 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-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="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">';