Fix ABDM live fetch and discovery for PrescriptionRecord and WellnessRecord
This commit is contained in:
parent
da61637c56
commit
686513cf27
|
|
@ -4983,10 +4983,11 @@ class AbdmGateway extends BaseController
|
|||
continue;
|
||||
}
|
||||
|
||||
// Strategy 0: Live On-Demand Fresh Generation for OPD Consult Record
|
||||
if (preg_match('/(?:OPD|PRESCRIPTION)-(\d+)(?:-S(\d+))?/i', $ref, $m)) {
|
||||
$targetPatientId = (int) $m[1];
|
||||
$targetSessionId = (int) ($m[2] ?? 0);
|
||||
// Strategy 0: Live On-Demand Fresh Generation for OPD Consult & Prescription Records
|
||||
if (preg_match('/^(OPD|PRESCRIPTION|PRESC)-(\d+)(?:-S(\d+))?/i', $ref, $m)) {
|
||||
$refPrefix = strtoupper($m[1]);
|
||||
$targetPatientId = (int) $m[2];
|
||||
$targetSessionId = (int) ($m[3] ?? 0);
|
||||
$targetOpdId = 0;
|
||||
|
||||
if ($targetSessionId > 0 && $db->tableExists('opd_prescription')) {
|
||||
|
|
@ -5005,14 +5006,21 @@ class AbdmGateway extends BaseController
|
|||
|
||||
if ($targetOpdId > 0) {
|
||||
try {
|
||||
$isPrescriptionReq = in_array($refPrefix, ['PRESC', 'PRESCRIPTION'], true);
|
||||
$targetBundleType = $isPrescriptionReq ? 'PrescriptionRecord' : 'OPConsultRecord';
|
||||
$targetHiType = $isPrescriptionReq ? 'PrescriptionRecord' : 'OPConsultRecord';
|
||||
$targetDisplay = $isPrescriptionReq
|
||||
? ('Prescription - ' . date('d M Y'))
|
||||
: ('Consultation Record - ' . date('d M Y'));
|
||||
|
||||
$opdCtrl = new \App\Controllers\Opd_prescription();
|
||||
$opdCtrl->initController($this->request, $this->response, service('logger'));
|
||||
$regen = $opdCtrl->regenerateFhirBundleInternal($targetOpdId, $targetSessionId);
|
||||
$regen = $opdCtrl->regenerateFhirBundleInternal($targetOpdId, $targetSessionId, $targetBundleType);
|
||||
if (!empty($regen['ok']) && !empty($regen['bundle'])) {
|
||||
$records[] = [
|
||||
'careContextReference' => $ref,
|
||||
'hiType' => 'OPConsultRecord',
|
||||
'display' => 'Consultation Record - ' . date('d M Y'),
|
||||
'hiType' => $targetHiType,
|
||||
'display' => $targetDisplay,
|
||||
'bundle' => $regen['bundle'],
|
||||
];
|
||||
continue;
|
||||
|
|
@ -5047,6 +5055,82 @@ class AbdmGateway extends BaseController
|
|||
}
|
||||
}
|
||||
|
||||
// Strategy 0c: Live On-Demand Fresh Generation for Wellness Record
|
||||
if (preg_match('/^WELLNESS-(?:(\d+)-)?(?:S)?(\d+)/i', $ref, $wMatch)) {
|
||||
$wPart1 = (int) ($wMatch[1] ?? 0);
|
||||
$wPart2 = (int) ($wMatch[2] ?? 0);
|
||||
|
||||
$targetPatientId = 0;
|
||||
$targetSessionId = 0;
|
||||
|
||||
// Check if part2 is a date (e.g. 20261006)
|
||||
$isDatePart2 = ($wPart2 >= 19700101 && $wPart2 <= 21001231);
|
||||
$candidateEntityId = $isDatePart2 ? $wPart1 : $wPart2;
|
||||
$candidatePatientId = $isDatePart2 ? 0 : $wPart1;
|
||||
|
||||
if ($db->tableExists('opd_prescription')) {
|
||||
// Try finding by prescription id
|
||||
if ($candidateEntityId > 0) {
|
||||
$pRow = $db->table('opd_prescription')
|
||||
->select('id, p_id, opd_id')
|
||||
->where('id', $candidateEntityId)
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
if ($pRow) {
|
||||
$targetSessionId = (int) $pRow['id'];
|
||||
$targetPatientId = (int) $pRow['p_id'];
|
||||
}
|
||||
}
|
||||
// If not found, check by session_id or opd_id
|
||||
if ($targetPatientId <= 0 && $candidateEntityId > 0) {
|
||||
$pRow = $db->table('opd_prescription')
|
||||
->select('id, p_id, opd_id')
|
||||
->where('session_id', $candidateEntityId)
|
||||
->orWhere('opd_id', $candidateEntityId)
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
if ($pRow) {
|
||||
$targetSessionId = (int) $pRow['id'];
|
||||
$targetPatientId = (int) $pRow['p_id'];
|
||||
}
|
||||
}
|
||||
// If candidatePatientId is set, or if candidateEntityId was patient_id
|
||||
if ($targetPatientId <= 0) {
|
||||
$testPid = $candidatePatientId > 0 ? $candidatePatientId : $candidateEntityId;
|
||||
if ($testPid > 0) {
|
||||
$pRow = $db->table('opd_prescription')
|
||||
->select('id, p_id, opd_id')
|
||||
->where('p_id', $testPid)
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
if ($pRow) {
|
||||
$targetPatientId = (int) $pRow['p_id'];
|
||||
$targetSessionId = (int) $pRow['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($targetPatientId > 0) {
|
||||
try {
|
||||
$wellnessPayload = $this->buildWellnessRecordPayload($targetPatientId, $targetSessionId, '');
|
||||
if ($wellnessPayload !== null && !empty($wellnessPayload['bundle'])) {
|
||||
$records[] = [
|
||||
'careContextReference' => $ref,
|
||||
'hiType' => 'WellnessRecord',
|
||||
'display' => $wellnessPayload['care_context_display'] ?? ('Wellness Record - ' . date('d M Y')),
|
||||
'bundle' => $wellnessPayload['bundle'],
|
||||
];
|
||||
continue;
|
||||
}
|
||||
} catch (\Throwable $ex) {
|
||||
log_message('warning', 'Live Wellness FHIR generation in recordsFetch failed: ' . $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Strategy A: Check if health_records already has stored FHIR record_data
|
||||
$hrRow = null;
|
||||
if ($db->tableExists('health_records')) {
|
||||
|
|
@ -5100,13 +5184,14 @@ class AbdmGateway extends BaseController
|
|||
// Strategy B: Build compliant FHIR Document Bundle from patient_master & OPD
|
||||
// STRICTLY restricted to OPD/consultation care contexts.
|
||||
// NEVER synthesize dummy consultation records for invoices, discharge, labs, radiology, etc.
|
||||
if (preg_match('/^(?:OPD|PRESCRIPTION|CONSULT)/i', $ref)) {
|
||||
if (preg_match('/^(?:OPD|PRESCRIPTION|PRESC|CONSULT)/i', $ref)) {
|
||||
$bundle = $this->assembleFhirBundleForCareContext($ref);
|
||||
if ($bundle !== null) {
|
||||
$isPresc = (bool) preg_match('/^(?:PRESC|PRESCRIPTION)/i', $ref);
|
||||
$records[] = [
|
||||
'careContextReference' => $ref,
|
||||
'hiType' => 'OPConsultRecord',
|
||||
'display' => 'OPConsultRecord - ' . date('d M Y'),
|
||||
'hiType' => $isPresc ? 'PrescriptionRecord' : 'OPConsultRecord',
|
||||
'display' => ($isPresc ? 'PrescriptionRecord - ' : 'OPConsultRecord - ') . date('d M Y'),
|
||||
'bundle' => $bundle,
|
||||
];
|
||||
}
|
||||
|
|
@ -6292,7 +6377,9 @@ class AbdmGateway extends BaseController
|
|||
if (! empty($wopd)) {
|
||||
$vDate = ! empty($wopd['date_opd_visit']) ? $wopd['date_opd_visit'] : date('Y-m-d');
|
||||
$dateStr = date('d M Y', strtotime((string) $vDate));
|
||||
$ccRef = 'WELLNESS-' . $patientId . '-S' . $taskEntityId . '-' . date('Ymd', strtotime((string) $vDate));
|
||||
$cleanDate = date('Ymd', strtotime((string) $vDate));
|
||||
// Reference format matching task board (e.g. WELLNESS-33723-20261006)
|
||||
$ccRef = 'WELLNESS-' . $taskEntityId . '-' . $cleanDate;
|
||||
$display = 'WellnessRecord - ' . $dateStr;
|
||||
$addContext([
|
||||
'careContextId' => $ccRef,
|
||||
|
|
@ -6386,10 +6473,9 @@ class AbdmGateway extends BaseController
|
|||
}
|
||||
}
|
||||
|
||||
// 4. Query opd_prescription (OPD consultations & prescriptions)
|
||||
// 4. Query opd_prescription (OPD consultations, prescriptions & wellness records)
|
||||
if ($this->db->tableExists('opd_prescription')) {
|
||||
$prescRows = $this->db->table('opd_prescription')
|
||||
->select('id, p_id, date_opd_visit, session_id, p_datetime')
|
||||
->where('p_id', $patientId)
|
||||
->orderBy('id', 'DESC')
|
||||
->limit(30)
|
||||
|
|
@ -6401,10 +6487,12 @@ class AbdmGateway extends BaseController
|
|||
? $pr['date_opd_visit']
|
||||
: date('Y-m-d', strtotime((string) ($pr['p_datetime'] ?? 'now')));
|
||||
$dateStr = date('d M Y', strtotime($visitDate));
|
||||
$cleanDate = str_replace('-', '', $visitDate);
|
||||
$sessionId = ! empty($pr['session_id']) ? $pr['session_id'] : $pr['id'];
|
||||
$ccRef = 'OPD-' . $patientId . '-S' . $sessionId . '-' . str_replace('-', '', $visitDate);
|
||||
$display = 'OPConsultRecord - ' . $dateStr;
|
||||
|
||||
// 4a. Consultation Record
|
||||
$ccRef = 'OPD-' . $patientId . '-S' . $sessionId . '-' . $cleanDate;
|
||||
$display = 'OPConsultRecord - ' . $dateStr;
|
||||
$addContext([
|
||||
'careContextId' => $ccRef,
|
||||
'referenceNumber' => $ccRef,
|
||||
|
|
@ -6414,6 +6502,44 @@ class AbdmGateway extends BaseController
|
|||
'is_fhir_ready' => true,
|
||||
'is_primary' => false,
|
||||
]);
|
||||
|
||||
// 4b. Prescription Record (if prescribed medicines exist)
|
||||
$hasMeds = false;
|
||||
if ($this->db->tableExists('opd_prescrption_prescribed')) {
|
||||
$hasMeds = ($this->db->table('opd_prescrption_prescribed')->where('prescription_id', (int) $pr['id'])->countAllResults() > 0);
|
||||
}
|
||||
if (! $hasMeds && $this->db->tableExists('opd_prescription_prescribed')) {
|
||||
$hasMeds = ($this->db->table('opd_prescription_prescribed')->where('opd_pre_id', (int) $pr['id'])->countAllResults() > 0);
|
||||
}
|
||||
if ($hasMeds) {
|
||||
$prescCcRef = 'PRESC-' . $patientId . '-S' . $sessionId . '-' . $cleanDate;
|
||||
$prescDisplay = 'Prescription - ' . $dateStr;
|
||||
$addContext([
|
||||
'careContextId' => $prescCcRef,
|
||||
'referenceNumber' => $prescCcRef,
|
||||
'display' => $prescDisplay,
|
||||
'record_type' => 'PrescriptionRecord',
|
||||
'patient_id' => $patientId,
|
||||
'is_fhir_ready' => true,
|
||||
'is_primary' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
// 4c. Wellness Record (if vitals exist)
|
||||
$hasVitals = ! empty($pr['bp']) || ! empty($pr['pulse']) || ! empty($pr['temp']) || ! empty($pr['spo2']) || ! empty($pr['weight']) || ! empty($pr['height']);
|
||||
if ($hasVitals) {
|
||||
$wellCcRef = 'WELLNESS-' . $sessionId . '-' . $cleanDate;
|
||||
$wellDisplay = 'Wellness Record - ' . $dateStr;
|
||||
$addContext([
|
||||
'careContextId' => $wellCcRef,
|
||||
'referenceNumber' => $wellCcRef,
|
||||
'display' => $wellDisplay,
|
||||
'record_type' => 'WellnessRecord',
|
||||
'patient_id' => $patientId,
|
||||
'is_fhir_ready' => true,
|
||||
'is_primary' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4844,7 +4844,7 @@ class Opd_prescription extends BaseController
|
|||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function regenerateFhirBundleInternal(int $opdId, int $sessionId): array
|
||||
public function regenerateFhirBundleInternal(int $opdId, int $sessionId, string $bundleType = 'OPConsultRecord'): array
|
||||
{
|
||||
|
||||
if ($opdId <= 0) {
|
||||
|
|
@ -4932,7 +4932,8 @@ class Opd_prescription extends BaseController
|
|||
if ($prescriptionPdf !== null) {
|
||||
$clinicalContext['attachments'][] = $prescriptionPdf;
|
||||
}
|
||||
$clinicalContext['bundle_type'] = 'OPConsultRecord';
|
||||
$normalizedBundleType = in_array($bundleType, ['Prescription', 'PrescriptionRecord'], true) ? 'PrescriptionRecord' : 'OPConsultRecord';
|
||||
$clinicalContext['bundle_type'] = $normalizedBundleType;
|
||||
$bundle = $this->fhirR4Builder->buildOpConsultBundle($patient, $encounter, $medications, $conditions, $clinicalContext);
|
||||
$bundleJson = (string) json_encode($bundle, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
|
|
@ -4947,10 +4948,10 @@ class Opd_prescription extends BaseController
|
|||
}
|
||||
$generatedAt = Time::now('Asia/Kolkata')->toDateTimeString();
|
||||
|
||||
// Overwrite the latest stored bundle for this opd_id / session
|
||||
// Overwrite the latest stored bundle for this opd_id / session and bundle_type
|
||||
$existingBuilder = $this->db->table('opd_fhir_documents')
|
||||
->where('opd_id', $opdId)
|
||||
->whereIn('bundle_type', ['OPConsultRecord', 'MedicationRequestBundle', 'PrescriptionRecord']);
|
||||
->where('bundle_type', $normalizedBundleType);
|
||||
if ($sessionId > 0) {
|
||||
$existingBuilder->where('opd_session_id', $sessionId);
|
||||
}
|
||||
|
|
@ -4960,7 +4961,7 @@ class Opd_prescription extends BaseController
|
|||
$this->db->table('opd_fhir_documents')
|
||||
->where('id', (int) $existing['id'])
|
||||
->update([
|
||||
'bundle_type' => 'OPConsultRecord',
|
||||
'bundle_type' => $normalizedBundleType,
|
||||
'bundle_json' => $bundleJson,
|
||||
'generated_by' => $generatedBy,
|
||||
'generated_at' => $generatedAt,
|
||||
|
|
@ -4970,7 +4971,7 @@ class Opd_prescription extends BaseController
|
|||
$this->db->table('opd_fhir_documents')->insert([
|
||||
'opd_id' => $opdId,
|
||||
'opd_session_id' => $sessionId,
|
||||
'bundle_type' => 'OPConsultRecord',
|
||||
'bundle_type' => $normalizedBundleType,
|
||||
'bundle_json' => $bundleJson,
|
||||
'generated_by' => $generatedBy,
|
||||
'generated_at' => $generatedAt,
|
||||
|
|
@ -4982,7 +4983,9 @@ class Opd_prescription extends BaseController
|
|||
'ok' => 1,
|
||||
'message' => 'FHIR bundle regenerated successfully',
|
||||
'document_id' => $documentId,
|
||||
'bundle_type' => $normalizedBundleType,
|
||||
'bundle' => $bundle,
|
||||
'medications' => $medications,
|
||||
'generated_at' => $generatedAt,
|
||||
'entry_count' => isset($bundle['entry']) ? count($bundle['entry']) : 0,
|
||||
];
|
||||
|
|
@ -11830,6 +11833,45 @@ class Opd_prescription extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
// Also generate and store PrescriptionRecord FHIR bundle if medicines were prescribed
|
||||
$prescBundleJson = null;
|
||||
if (! empty($medications)) {
|
||||
$prescContext = $clinicalContext;
|
||||
$prescContext['bundle_type'] = 'PrescriptionRecord';
|
||||
$prescBundle = $this->fhirR4Builder->buildOpConsultBundle($patient, $encounter, $medications, $conditions, $prescContext);
|
||||
$prescBundleJson = (string) json_encode($prescBundle, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$existingPrescDoc = $this->db->table('opd_fhir_documents')
|
||||
->where('opd_id', $opdId)
|
||||
->where('opd_session_id', $sessionId)
|
||||
->where('bundle_type', 'PrescriptionRecord')
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
if (! empty($existingPrescDoc['id'])) {
|
||||
$this->db->table('opd_fhir_documents')
|
||||
->where('id', (int) $existingPrescDoc['id'])
|
||||
->update([
|
||||
'bundle_json' => $prescBundleJson,
|
||||
'generated_by' => $generatedBy,
|
||||
'generated_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
} else {
|
||||
$this->db->table('opd_fhir_documents')->insert([
|
||||
'opd_id' => $opdId,
|
||||
'opd_session_id' => $sessionId,
|
||||
'bundle_type' => 'PrescriptionRecord',
|
||||
'bundle_json' => $prescBundleJson,
|
||||
'generated_by' => $generatedBy,
|
||||
'generated_at' => $now,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $inserted) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -11839,8 +11881,10 @@ class Opd_prescription extends BaseController
|
|||
$patientId = (int) ($patientRow['id'] ?? ($opdRow['p_id'] ?? 0));
|
||||
$visitDateRaw = trim((string) ($opdRow['date_opd_visit'] ?? $opdRow['apointment_date'] ?? ''));
|
||||
$visitDate = $visitDateRaw !== '' ? date('Y-m-d', strtotime($visitDateRaw)) : date('Y-m-d');
|
||||
$careContextRef = 'OPD-' . $patientId . '-S' . $sessionId . '-' . str_replace('-', '', $visitDate);
|
||||
$cleanDate = str_replace('-', '', $visitDate);
|
||||
$careContextRef = 'OPD-' . $patientId . '-S' . $sessionId . '-' . $cleanDate;
|
||||
|
||||
// 1. Upsert OPConsultRecord
|
||||
$existingHr = $this->db->table('health_records')
|
||||
->select('id')
|
||||
->where('care_context_reference', $careContextRef)
|
||||
|
|
@ -11865,6 +11909,74 @@ class Opd_prescription extends BaseController
|
|||
$hrPayload['created_at'] = Time::now('Asia/Kolkata')->toDateTimeString();
|
||||
$this->db->table('health_records')->insert($hrPayload);
|
||||
}
|
||||
|
||||
// 2. Upsert PrescriptionRecord (if medications exist)
|
||||
if (! empty($medications) && ! empty($prescBundleJson)) {
|
||||
$prescCcRef = 'PRESC-' . $patientId . '-S' . $sessionId . '-' . $cleanDate;
|
||||
$existingPrescHr = $this->db->table('health_records')
|
||||
->select('id')
|
||||
->where('care_context_reference', $prescCcRef)
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
$prescHrPayload = [
|
||||
'patient_id' => $patientId > 0 ? $patientId : null,
|
||||
'abha_id' => $abhaAddress !== '' ? $abhaAddress : null,
|
||||
'hi_type' => 'PrescriptionRecord',
|
||||
'entity_type' => 'opd_prescription',
|
||||
'entity_id' => (string) $sessionId,
|
||||
'record_data' => $prescBundleJson,
|
||||
'care_context_reference' => $prescCcRef,
|
||||
'push_status' => 'local_discovery_ready',
|
||||
'updated_at' => Time::now('Asia/Kolkata')->toDateTimeString(),
|
||||
];
|
||||
if (! empty($existingPrescHr)) {
|
||||
$this->db->table('health_records')->where('id', (int) $existingPrescHr['id'])->update($prescHrPayload);
|
||||
} else {
|
||||
$prescHrPayload['created_at'] = Time::now('Asia/Kolkata')->toDateTimeString();
|
||||
$this->db->table('health_records')->insert($prescHrPayload);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Upsert WellnessRecord (if vitals exist)
|
||||
$hasVitals = ! empty($clinicalContext['observations']);
|
||||
if ($hasVitals && class_exists('\App\Controllers\DoctorDocument')) {
|
||||
try {
|
||||
$docCtrl = new \App\Controllers\DoctorDocument();
|
||||
$wSource = $docCtrl->buildWellnessRecordSource($patientId, $sessionId);
|
||||
if (! empty($wSource) && ! empty($wSource['vitals'])) {
|
||||
$wFactory = new \App\Libraries\Abdm\Fhir\FhirGeneratorFactory();
|
||||
$wGen = $wFactory->wellness()->generate($wSource);
|
||||
if (! empty($wGen['bundle'])) {
|
||||
$wellBundleJson = json_encode($wGen['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$wellCcRef = 'WELLNESS-' . $sessionId . '-' . $cleanDate;
|
||||
$existingWellHr = $this->db->table('health_records')
|
||||
->select('id')
|
||||
->where('care_context_reference', $wellCcRef)
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
$wellHrPayload = [
|
||||
'patient_id' => $patientId > 0 ? $patientId : null,
|
||||
'abha_id' => $abhaAddress !== '' ? $abhaAddress : null,
|
||||
'hi_type' => 'WellnessRecord',
|
||||
'entity_type' => 'opd_vitals',
|
||||
'entity_id' => (string) $sessionId,
|
||||
'record_data' => $wellBundleJson,
|
||||
'care_context_reference' => $wellCcRef,
|
||||
'push_status' => 'local_discovery_ready',
|
||||
'updated_at' => Time::now('Asia/Kolkata')->toDateTimeString(),
|
||||
];
|
||||
if (! empty($existingWellHr)) {
|
||||
$this->db->table('health_records')->where('id', (int) $existingWellHr['id'])->update($wellHrPayload);
|
||||
} else {
|
||||
$wellHrPayload['created_at'] = Time::now('Asia/Kolkata')->toDateTimeString();
|
||||
$this->db->table('health_records')->insert($wellHrPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $we) {
|
||||
log_message('warning', '[storePrescriptionFhirBundle] auto wellness error: ' . $we->getMessage());
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
log_message('warning', '[storePrescriptionFhirBundle] auto health_records insert error: ' . $e->getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -517,6 +517,115 @@ class AbdmTaskBoardSyncService
|
|||
}
|
||||
}
|
||||
|
||||
// 5b. If medications exist and we linked OPConsultRecord, also link PrescriptionRecord care context to bridge
|
||||
$sessionId = (int) ($docRow['opd_session_id'] ?? 0);
|
||||
if ($isSuccess && $sessionId > 0) {
|
||||
$hasMeds = false;
|
||||
if ($this->db->tableExists('opd_prescrption_prescribed')) {
|
||||
$hasMeds = ($this->db->table('opd_prescrption_prescribed')->where('prescription_id', $sessionId)->countAllResults() > 0);
|
||||
}
|
||||
if (! $hasMeds && $this->db->tableExists('opd_prescription_prescribed')) {
|
||||
$hasMeds = ($this->db->table('opd_prescription_prescribed')->where('opd_pre_id', $sessionId)->countAllResults() > 0);
|
||||
}
|
||||
if ($hasMeds) {
|
||||
$cleanDate = str_replace('-', '', $visitDate);
|
||||
$prescCcRef = 'PRESC-' . $patientId . '-S' . $sessionId . '-' . $cleanDate;
|
||||
$prescDisplay = 'Prescription - ' . $visitDate;
|
||||
try {
|
||||
$opdCtrl = new \App\Controllers\Opd_prescription();
|
||||
$opdCtrl->initController(\Config\Services::request(), \Config\Services::response(), service('logger'));
|
||||
$prescRegen = $opdCtrl->regenerateFhirBundleInternal($opdId, $sessionId, 'PrescriptionRecord');
|
||||
$prescBundleJson = ! empty($prescRegen['bundle']) ? json_encode($prescRegen['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null;
|
||||
|
||||
$prescPushData = [
|
||||
'patient_id' => (string) $patientId,
|
||||
'patient_name' => $patientName !== '' ? $patientName : ('PATIENT-' . $patientId),
|
||||
'abha_id' => $abhaNumber,
|
||||
'abha_address' => $abhaAddress,
|
||||
'year_of_birth' => $yearOfBirth,
|
||||
'gender' => $gender,
|
||||
'hi_type' => 'PrescriptionRecord',
|
||||
'record_type' => 'PrescriptionRecord',
|
||||
'visit_date' => $visitDate,
|
||||
'care_context_reference' => $prescCcRef,
|
||||
'care_context_display' => $prescDisplay,
|
||||
'notes' => $prescDisplay,
|
||||
'queue_id' => $prescCcRef,
|
||||
];
|
||||
if (! empty($prescRegen['bundle'])) {
|
||||
$prescPushData['bundle'] = $prescRegen['bundle'];
|
||||
$prescPushData['fhir_bundle'] = $prescRegen['bundle'];
|
||||
}
|
||||
$prescRes = $this->connector->pushRecord($prescPushData);
|
||||
$this->recordLinkedState(
|
||||
$patientId,
|
||||
$effectiveAbha,
|
||||
'PrescriptionRecord',
|
||||
'opd_prescription',
|
||||
(string) $sessionId,
|
||||
$prescCcRef,
|
||||
(string) ($prescRes['queue_id'] ?? $prescCcRef),
|
||||
(int) ($prescRes['record_id'] ?? 0),
|
||||
$prescBundleJson
|
||||
);
|
||||
} catch (\Throwable $pe) {
|
||||
log_message('warning', '[linkAndPushOpdRecord] Prescription care context push error: ' . $pe->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 5c. If vitals exist, also link WellnessRecord care context to bridge
|
||||
try {
|
||||
$pRow = $this->db->table('opd_prescription')->where('id', $sessionId)->get(1)->getRowArray();
|
||||
$hasVitals = ! empty($pRow['bp']) || ! empty($pRow['pulse']) || ! empty($pRow['temp']) || ! empty($pRow['spo2']) || ! empty($pRow['weight']);
|
||||
if ($hasVitals && class_exists('\App\Controllers\DoctorDocument')) {
|
||||
$cleanDate = str_replace('-', '', $visitDate);
|
||||
$wellCcRef = 'WELLNESS-' . $sessionId . '-' . $cleanDate;
|
||||
$docCtrl = new \App\Controllers\DoctorDocument();
|
||||
$wSource = $docCtrl->buildWellnessRecordSource($patientId, $sessionId);
|
||||
if (! empty($wSource) && ! empty($wSource['vitals'])) {
|
||||
$wFactory = new \App\Libraries\Abdm\Fhir\FhirGeneratorFactory();
|
||||
$wGen = $wFactory->wellness()->generate($wSource);
|
||||
$wellBundleJson = ! empty($wGen['bundle']) ? json_encode($wGen['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null;
|
||||
$wellDisplay = 'Wellness Record - ' . $visitDate;
|
||||
|
||||
$wellPushData = [
|
||||
'patient_id' => (string) $patientId,
|
||||
'patient_name' => $patientName !== '' ? $patientName : ('PATIENT-' . $patientId),
|
||||
'abha_id' => $abhaNumber,
|
||||
'abha_address' => $abhaAddress,
|
||||
'year_of_birth' => $yearOfBirth,
|
||||
'gender' => $gender,
|
||||
'hi_type' => 'WellnessRecord',
|
||||
'record_type' => 'WellnessRecord',
|
||||
'visit_date' => $visitDate,
|
||||
'care_context_reference' => $wellCcRef,
|
||||
'care_context_display' => $wellDisplay,
|
||||
'notes' => $wellDisplay,
|
||||
'queue_id' => $wellCcRef,
|
||||
];
|
||||
if (! empty($wGen['bundle'])) {
|
||||
$wellPushData['bundle'] = $wGen['bundle'];
|
||||
$wellPushData['fhir_bundle'] = $wGen['bundle'];
|
||||
}
|
||||
$wellRes = $this->connector->pushRecord($wellPushData);
|
||||
$this->recordLinkedState(
|
||||
$patientId,
|
||||
$effectiveAbha,
|
||||
'WellnessRecord',
|
||||
'opd_vitals',
|
||||
(string) $sessionId,
|
||||
$wellCcRef,
|
||||
(string) ($wellRes['queue_id'] ?? $wellCcRef),
|
||||
(int) ($wellRes['record_id'] ?? 0),
|
||||
$wellBundleJson
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $we) {
|
||||
log_message('warning', '[linkAndPushOpdRecord] Wellness care context push error: ' . $we->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if ($isSuccess) {
|
||||
return [
|
||||
'ok' => 1,
|
||||
|
|
@ -794,6 +903,25 @@ class AbdmTaskBoardSyncService
|
|||
'queue_id' => $careContextRef,
|
||||
];
|
||||
|
||||
$bundleJson = null;
|
||||
if ($taskType === 'wellness_record_publish' && class_exists('\App\Controllers\DoctorDocument')) {
|
||||
try {
|
||||
$docCtrl = new \App\Controllers\DoctorDocument();
|
||||
$wSource = $docCtrl->buildWellnessRecordSource($patientId, $entityId);
|
||||
if (! empty($wSource)) {
|
||||
$wFactory = new \App\Libraries\Abdm\Fhir\FhirGeneratorFactory();
|
||||
$wGen = $wFactory->wellness()->generate($wSource);
|
||||
if (! empty($wGen['bundle'])) {
|
||||
$pushData['bundle'] = $wGen['bundle'];
|
||||
$pushData['fhir_bundle'] = $wGen['bundle'];
|
||||
$bundleJson = (string) json_encode($wGen['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $we) {
|
||||
log_message('warning', '[processIndividualWorkTask] Wellness bundle generation error: ' . $we->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->connector->pushRecord($pushData);
|
||||
$ok = (int) ($result['ok'] ?? 0);
|
||||
|
|
@ -812,7 +940,8 @@ class AbdmTaskBoardSyncService
|
|||
(string) $entityId,
|
||||
$careContextRef,
|
||||
$queueId,
|
||||
(int) ($result['record_id'] ?? 0)
|
||||
(int) ($result['record_id'] ?? 0),
|
||||
$bundleJson
|
||||
);
|
||||
|
||||
return ['ok' => 1, 'queue_id' => $queueId];
|
||||
|
|
@ -832,7 +961,8 @@ class AbdmTaskBoardSyncService
|
|||
string $entityId,
|
||||
string $careContextRef,
|
||||
string $queueId,
|
||||
int $bridgeRecordId
|
||||
int $bridgeRecordId,
|
||||
?string $recordData = null
|
||||
): void {
|
||||
$now = Time::now('Asia/Kolkata')->toDateTimeString();
|
||||
|
||||
|
|
@ -854,6 +984,9 @@ class AbdmTaskBoardSyncService
|
|||
'abdm_txn_id' => $queueId,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
if ($recordData !== null && $recordData !== '') {
|
||||
$hrData['record_data'] = $recordData;
|
||||
}
|
||||
if ($bridgeRecordId > 0 && in_array('bridge_record_id', $this->db->getFieldNames('health_records') ?? [], true)) {
|
||||
$hrData['bridge_record_id'] = $bridgeRecordId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -718,10 +718,10 @@ class FhirR4Builder
|
|||
'type' => [
|
||||
'coding' => [[
|
||||
'system' => 'http://snomed.info/sct',
|
||||
'code' => '371530004',
|
||||
'display' => 'Clinical consultation report',
|
||||
'code' => $isOpConsult ? '371530004' : '440545006',
|
||||
'display' => $isOpConsult ? 'Clinical consultation report' : 'Prescription record',
|
||||
]],
|
||||
'text' => 'Clinical Consultation report',
|
||||
'text' => $isOpConsult ? 'Clinical Consultation report' : 'Prescription record',
|
||||
],
|
||||
'subject' => ['reference' => $patientRef, 'display' => 'Patient'],
|
||||
'encounter' => ['reference' => $encounterRef, 'display' => 'Encounter'],
|
||||
|
|
|
|||
|
|
@ -41,9 +41,23 @@ final class CareContextDiscoveryTest extends CIUnitTestCase
|
|||
$db->query("CREATE TABLE IF NOT EXISTS " . $db->prefixTable('opd_prescription') . " (
|
||||
id INTEGER PRIMARY KEY,
|
||||
p_id INTEGER,
|
||||
opd_id INTEGER,
|
||||
date_opd_visit TEXT,
|
||||
session_id INTEGER,
|
||||
p_datetime TEXT
|
||||
p_datetime TEXT,
|
||||
bp TEXT,
|
||||
pulse TEXT,
|
||||
temp TEXT,
|
||||
spo2 TEXT,
|
||||
weight TEXT,
|
||||
height TEXT
|
||||
)");
|
||||
|
||||
$db->query("CREATE TABLE IF NOT EXISTS " . $db->prefixTable('opd_prescrption_prescribed') . " (
|
||||
id INTEGER PRIMARY KEY,
|
||||
prescription_id INTEGER,
|
||||
medicine_name TEXT,
|
||||
dosage_summary TEXT
|
||||
)");
|
||||
|
||||
$db->query("CREATE TABLE IF NOT EXISTS " . $db->prefixTable('opd_master') . " (
|
||||
|
|
@ -442,5 +456,82 @@ final class CareContextDiscoveryTest extends CIUnitTestCase
|
|||
$this->assertTrue($invoiceCtx['is_primary']);
|
||||
$this->assertTrue($invoiceCtx['is_fhir_ready']);
|
||||
}
|
||||
|
||||
public function testDiscoversPrescriptionAndWellnessCareContextsWhenPresent(): void
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
$db->table('opd_prescription')->insert([
|
||||
'id' => 901,
|
||||
'p_id' => 15350,
|
||||
'opd_id' => 15350,
|
||||
'session_id' => 901,
|
||||
'date_opd_visit' => '2026-10-06',
|
||||
'bp' => '120/80',
|
||||
'pulse' => '72',
|
||||
'temp' => '98.4',
|
||||
'spo2' => '98',
|
||||
'weight' => '70',
|
||||
'height' => '175',
|
||||
]);
|
||||
|
||||
$db->table('opd_prescrption_prescribed')->insert([
|
||||
'id' => 101,
|
||||
'prescription_id' => 901,
|
||||
'medicine_name' => 'CAP PANTOP DSR',
|
||||
'dosage_summary' => '1 Tab | OD | 5 days',
|
||||
]);
|
||||
|
||||
$refGateway = new ReflectionClass($this->gateway);
|
||||
$method = $refGateway->getMethod('findCareContextsForPatient');
|
||||
$method->setAccessible(true);
|
||||
|
||||
[$v3, $full] = $method->invoke($this->gateway, 15350, 'P-15350', 'DEVENDER SINGH');
|
||||
|
||||
$refs = array_column($v3, 'referenceNumber');
|
||||
$this->assertContains('OPD-15350-S901-20261006', $refs);
|
||||
$this->assertContains('PRESC-15350-S901-20261006', $refs);
|
||||
$this->assertContains('WELLNESS-901-20261006', $refs);
|
||||
|
||||
$types = array_column($full, 'record_type');
|
||||
$this->assertContains('OPConsultRecord', $types);
|
||||
$this->assertContains('PrescriptionRecord', $types);
|
||||
$this->assertContains('WellnessRecord', $types);
|
||||
}
|
||||
|
||||
public function testDiscoversWellnessTaskBoardCareContext(): void
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
$db->table('opd_prescription')->insert([
|
||||
'id' => 33723,
|
||||
'p_id' => 15350,
|
||||
'opd_id' => 15350,
|
||||
'session_id' => 33723,
|
||||
'date_opd_visit' => '2026-10-06',
|
||||
'bp' => '130/85',
|
||||
'pulse' => '75',
|
||||
]);
|
||||
|
||||
$refGateway = new ReflectionClass($this->gateway);
|
||||
$method = $refGateway->getMethod('findCareContextsForPatient');
|
||||
$method->setAccessible(true);
|
||||
|
||||
[$v3, $full] = $method->invoke(
|
||||
$this->gateway,
|
||||
15350,
|
||||
'P-15350',
|
||||
'DEVENDER SINGH',
|
||||
'wellness_record_publish',
|
||||
'33723'
|
||||
);
|
||||
|
||||
$refs = array_column($v3, 'referenceNumber');
|
||||
$this->assertContains('WELLNESS-33723-20261006', $refs);
|
||||
|
||||
$primary = $full[0];
|
||||
$this->assertSame('WELLNESS-33723-20261006', $primary['careContextId']);
|
||||
$this->assertSame('WellnessRecord', $primary['record_type']);
|
||||
$this->assertTrue($primary['is_primary']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user