diff --git a/app/Controllers/Patient.php b/app/Controllers/Patient.php index 1135a20..2b17d2f 100644 --- a/app/Controllers/Patient.php +++ b/app/Controllers/Patient.php @@ -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; } diff --git a/app/Libraries/Abdm/M3HiuDocumentRepository.php b/app/Libraries/Abdm/M3HiuDocumentRepository.php index 6ac6310..47ea0fa 100644 --- a/app/Libraries/Abdm/M3HiuDocumentRepository.php +++ b/app/Libraries/Abdm/M3HiuDocumentRepository.php @@ -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')) { diff --git a/app/Views/billing/Patient_Profile_Opd_V.php b/app/Views/billing/Patient_Profile_Opd_V.php index e1f878d..cd86b34 100644 --- a/app/Views/billing/Patient_Profile_Opd_V.php +++ b/app/Views/billing/Patient_Profile_Opd_V.php @@ -348,6 +348,7 @@ if ($patientPhotoPath === '') { Status + Request ID HI Types Requested By Requested On @@ -356,7 +357,7 @@ if ($patientPhotoPath === '') { - No consent requests yet. + No consent requests yet. @@ -364,7 +365,7 @@ if ($patientPhotoPath === '') {
-
+
@@ -376,15 +377,17 @@ if ($patientPhotoPath === '') { Date Title Care Context + Org / Hospital + Request ID - No records loaded. + No records loaded.
-
+
Select a fetched document to view details.
@@ -677,7 +680,7 @@ $(function() { function renderAbdmRequestsTable(requests) { if (!requests || !requests.length) { - $('#abdmRequestsTable tbody').html('No consent requests yet.'); + $('#abdmRequestsTable tbody').html('No consent requests yet.'); 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 += '' + '' + escHtml(status || 'UNKNOWN') + '' + + '' + escHtml(requestId) + '' + '' + escHtml(hiTypesText) + '' + '' + escHtml(consent.requested_by || 'HMS') + '' + '' + fmtConsentTs(consent.requested_on) + '' @@ -714,7 +719,7 @@ $(function() { renderAbdmRequestsTable(currentAbdmRequests); }) .catch(function(err) { - $('#abdmRequestsTable tbody').html('' + escHtml('Failed to load consent request history: ' + (err.message || err)) + ''); + $('#abdmRequestsTable tbody').html('' + escHtml('Failed to load consent request history: ' + (err.message || err)) + ''); }); } @@ -879,17 +884,20 @@ $(function() { function renderAbdmRows(rows) { var html = ''; if (!rows || !rows.length) { - html = 'No ABDM fetched records found.'; + html = 'No ABDM fetched records found.'; $('#abdmDocTable tbody').html(html); $('#abdmDocDetailBox').html('
No records available for this patient.
'); return; } rows.forEach(function(row) { + var reqId = row.consent_request_id || '-'; html += '' + '' + escHtml(fmtDateTime(row.document_date || row.created_at)) + '' + '' + escHtml(row.document_title || '-') + '' + '' + escHtml(row.care_context_reference || '-') + '' + + '' + escHtml(row.organization_name || '-') + '' + + '' + escHtml(reqId) + '' + ''; }); $('#abdmDocTable tbody').html(html); @@ -911,7 +919,8 @@ $(function() { html += '
Date: ' + escHtml(fmtDateTime(item.document_date || item.created_at)) + '
'; html += '
Care Context: ' + escHtml(item.care_context_reference || '-') + '
'; html += '
Doctor: ' + escHtml(item.practitioner_name || '-') + '
'; - html += '
Organization: ' + escHtml(item.organization_name || '-') + '
'; + html += '
Organization: ' + escHtml(item.organization_name || '-') + '
'; + html += '
Consent Request ID: ' + escHtml(item.consent_request_id || '-') + '
'; html += '
'; html += '
Diagnoses
    ';