fix(abdm): generate and publish OPD consultations as OPConsultRecord and support dynamic hi_type

This commit is contained in:
DevSoftTech Server 2026-09-28 02:46:10 +05:30
parent b28b51965c
commit 90e63d2d58
5 changed files with 55 additions and 18 deletions

View File

@ -1529,11 +1529,20 @@ class AbdmGateway extends BaseController
]);
}
$requestedHiType = trim((string) ($this->request->getPost('hi_type') ?? ''));
$bundleType = trim((string) ($bundleRow['bundle_type'] ?? 'OPConsultRecord'));
$hiType = match ($bundleType) {
'MedicationRequestBundle', 'Prescription', 'PrescriptionRecord' => 'PrescriptionRecord',
default => 'OPConsultRecord',
};
if ($requestedHiType !== '') {
$hiType = match ($requestedHiType) {
'OPConsultation', 'OPConsultRecord' => 'OPConsultRecord',
'MedicationRequestBundle', 'Prescription', 'PrescriptionRecord' => 'PrescriptionRecord',
default => $requestedHiType,
};
} else {
$hiType = match ($bundleType) {
'OPConsultRecord', 'OPConsultation' => 'OPConsultRecord',
default => 'PrescriptionRecord',
};
}
$consentHandleResolved = is_array($consent) ? trim((string) ($consent['consent_handle'] ?? '')) : '';
$consentExternalId = is_array($consent) ? $this->resolveConsentExternalId($consent) : '';
$sessionForRef = $sessionId > 0 ? $sessionId : (int) ($bundleRow['opd_session_id'] ?? 0);
@ -1564,7 +1573,7 @@ class AbdmGateway extends BaseController
}
$careContextDisplay = $hiType === 'PrescriptionRecord'
? 'Prescription - ' . $visitDate
: 'OPD Visit - ' . $visitDate;
: 'Consultation Record - ' . $visitDate;
$payload = [
'opd_id' => $opdId,

View File

@ -4931,7 +4931,8 @@ class Opd_prescription extends BaseController
if ($prescriptionPdf !== null) {
$clinicalContext['attachments'][] = $prescriptionPdf;
}
$bundle = $this->fhirR4Builder->buildPrescriptionBundle($patient, $encounter, $medications, $conditions, $clinicalContext);
$clinicalContext['bundle_type'] = 'OPConsultRecord';
$bundle = $this->fhirR4Builder->buildOpConsultBundle($patient, $encounter, $medications, $conditions, $clinicalContext);
$bundleJson = (string) json_encode($bundle, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$user = function_exists('auth') ? auth()->user() : null;
@ -4951,7 +4952,7 @@ class Opd_prescription extends BaseController
$this->db->table('opd_fhir_documents')
->where('id', (int) $existing['id'])
->update([
'bundle_type' => 'PrescriptionRecord',
'bundle_type' => 'OPConsultRecord',
'bundle_json' => $bundleJson,
'generated_by' => $generatedBy,
'generated_at' => $generatedAt,
@ -4961,7 +4962,7 @@ class Opd_prescription extends BaseController
$this->db->table('opd_fhir_documents')->insert([
'opd_id' => $opdId,
'opd_session_id' => $sessionId,
'bundle_type' => 'PrescriptionRecord',
'bundle_type' => 'OPConsultRecord',
'bundle_json' => $bundleJson,
'generated_by' => $generatedBy,
'generated_at' => $generatedAt,
@ -5587,6 +5588,7 @@ class Opd_prescription extends BaseController
'opd_session_id' => $sessionId,
'patient_id' => $patientId,
'abha_id' => $abhaId,
'hi_type' => (string) ($this->request->getPost('hi_type') ?: ($bundleRow['bundle_type'] ?? 'OPConsultRecord')),
'consent_handle' => (string) ($this->request->getPost('consent_handle') ?? ''),
'push_to_gateway' => $pushToGateway ? 1 : 0,
csrf_token() => csrf_hash(),
@ -11732,12 +11734,13 @@ class Opd_prescription extends BaseController
$medications = $this->getPrescriptionMedicines($sessionId);
$conditions = $this->getPrescriptionConditions($sessionId);
$clinicalContext = $this->getPrescriptionClinicalContext($sessionId, $opdRow);
$clinicalContext['bundle_type'] = 'OPConsultRecord';
$clinicalContext['attachments'] = $this->collectOpdFhirAttachments($opdId);
$prescriptionPdf = $this->buildPrescriptionDigitalSharePdf($patientRow, $opdRow, $sessionId, $medications, $conditions, $clinicalContext);
if ($prescriptionPdf !== null) {
$clinicalContext['attachments'][] = $prescriptionPdf;
}
$bundle = $this->fhirR4Builder->buildPrescriptionBundle($patient, $encounter, $medications, $conditions, $clinicalContext);
$bundle = $this->fhirR4Builder->buildOpConsultBundle($patient, $encounter, $medications, $conditions, $clinicalContext);
$bundleJson = (string) json_encode($bundle, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$userId = null;
@ -11753,7 +11756,7 @@ class Opd_prescription extends BaseController
$inserted = (bool) $this->db->table('opd_fhir_documents')->insert([
'opd_id' => $opdId,
'opd_session_id' => $sessionId,
'bundle_type' => 'PrescriptionRecord',
'bundle_type' => 'OPConsultRecord',
'bundle_json' => $bundleJson,
'generated_by' => $generatedBy,
'generated_at' => Time::now('Asia/Kolkata')->toDateTimeString(),

View File

@ -321,14 +321,14 @@ class AbdmTaskBoardSyncService
$bundle = ['raw' => $bundleJson];
}
$bundleType = trim((string) ($docRow['bundle_type'] ?? 'PrescriptionRecord'));
$bundleType = trim((string) ($docRow['bundle_type'] ?? 'OPConsultRecord'));
$hiType = match ($bundleType) {
'OPConsultRecord' => 'OPConsultRecord',
default => 'PrescriptionRecord',
'PrescriptionRecord' => 'PrescriptionRecord',
default => 'OPConsultRecord',
};
$careContextDisplay = $hiType === 'PrescriptionRecord'
? 'Prescription - ' . $visitDate
: 'OPD Visit - ' . $visitDate;
: 'Consultation Record - ' . $visitDate;
$now = Time::now('Asia/Kolkata')->toDateTimeString();

View File

@ -11,7 +11,22 @@ class FhirR4Builder
* @param array<string, mixed> $encounter
* @param array<int, array<string, mixed>> $medications
* @param array<int, array<string, mixed>> $conditions
* @param array<string, mixed> $context
* @param array<string, mixed> $context
*
* @return array<string, mixed>
*/
public function buildOpConsultBundle(array $patient, array $encounter, array $medications, array $conditions = [], array $context = []): array
{
$context['bundle_type'] = 'OPConsultRecord';
return $this->buildPrescriptionBundle($patient, $encounter, $medications, $conditions, $context);
}
/**
* @param array<string, mixed> $patient
* @param array<string, mixed> $encounter
* @param array<int, array<string, mixed>> $medications
* @param array<int, array<string, mixed>> $conditions
* @param array<string, mixed> $context
*
* @return array<string, mixed>
*/
@ -684,10 +699,19 @@ class FhirR4Builder
}
// ── Composition (first entry per ABDM spec) ───────────────────────────
$requestedBundleType = trim((string) ($context['bundle_type'] ?? $context['record_type'] ?? 'PrescriptionRecord'));
$isOpConsult = in_array($requestedBundleType, ['OPConsultRecord', 'OPConsultation'], true);
$compositionProfile = $isOpConsult
? 'https://nrces.in/ndhm/fhir/r4/StructureDefinition/OPConsultRecord'
: 'https://nrces.in/ndhm/fhir/r4/StructureDefinition/PrescriptionRecord';
$compositionTitle = $isOpConsult ? 'OP Consultation Record' : 'Prescription Record';
$bundlePrefix = $isOpConsult ? 'OPCONSULT-' : 'PRESCRIPTION-';
$composition = [
'resourceType' => 'Composition',
'id' => $compositionUuid,
'meta' => ['profile' => ['https://nrces.in/ndhm/fhir/r4/StructureDefinition/PrescriptionRecord']],
'meta' => ['profile' => [$compositionProfile]],
'language' => 'en-IN',
'identifier' => ['system' => 'https://ndhm.in/phr', 'value' => $compositionUuid],
'status' => 'final',
@ -705,7 +729,7 @@ class FhirR4Builder
'author' => $practitionerRef !== ''
? [['reference' => $practitionerRef, 'display' => 'Practitioner']]
: [['display' => 'Unknown']],
'title' => 'Prescription Record',
'title' => $compositionTitle,
'section' => $compositionSections,
];
if ($organizationRef !== '') {
@ -724,7 +748,7 @@ class FhirR4Builder
? 'https://' . strtolower(preg_replace('/[^A-Za-z0-9]/', '', $hfrId)) . '.hfr.abdm.gov.in'
: 'https://hfr.abdm.gov.in';
$bundleIdValue = $hfrId !== ''
? 'PRESCRIPTION-' . ($encounter['id'] ?? $bundleUuid) . '-' . date('Y-m-d')
? $bundlePrefix . ($encounter['id'] ?? $bundleUuid) . '-' . date('Y-m-d')
: $bundleUuid;
return $this->sanitizeBundle([

View File

@ -3300,6 +3300,7 @@
btn.textContent = 'Submitting...';
var body = new URLSearchParams({ opd_id: _fhirOpdId, opd_session_id: _fhirSessionId });
body.append('push_to_gateway', '1');
body.append('hi_type', 'OPConsultRecord');
body.append(csrfName, csrfHash);
var submitTimeoutMs = 150000;
var submitController = new AbortController();