fix(abdm): unify immunization payload, resolve CC IMM-53, add on-demand fetch and sync bundle
This commit is contained in:
parent
91d7fe77d2
commit
75e3a820cc
|
|
@ -241,9 +241,13 @@ class AbdmFhirInspector extends BaseController
|
||||||
return $gw->invoiceFhirPreview();
|
return $gw->invoiceFhirPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Immunization: IMM-{id}
|
// Immunization: IMM-{id} or IMM-{patientId}-V{id}-{date}
|
||||||
if (preg_match('/^IMM-(\d+)/i', $ref, $m)) {
|
if (preg_match('/^IMM-(?:PAT-(\d+)|(?:(\d+)-V)?(\d+))/i', $ref, $m)) {
|
||||||
$immId = (int) $m[1];
|
$immId = (int) (! empty($m[3]) ? $m[3] : (! empty($m[2]) ? $m[2] : ($m[1] ?? 0)));
|
||||||
|
if ($patientId <= 0 && $this->db->tableExists('immunization_records')) {
|
||||||
|
$immRec = $this->db->table('immunization_records')->select('patient_id')->where('id', $immId)->get(1)->getRowArray();
|
||||||
|
$patientId = (int) ($immRec['patient_id'] ?? 0);
|
||||||
|
}
|
||||||
$gw = new \App\Controllers\AbdmGateway();
|
$gw = new \App\Controllers\AbdmGateway();
|
||||||
$gw->initController($this->request, $this->response, service('logger'));
|
$gw->initController($this->request, $this->response, service('logger'));
|
||||||
$_GET['record_id'] = $immId;
|
$_GET['record_id'] = $immId;
|
||||||
|
|
|
||||||
|
|
@ -2581,15 +2581,16 @@ class AbdmGateway extends BaseController
|
||||||
|
|
||||||
public function immunizationFhirPreview()
|
public function immunizationFhirPreview()
|
||||||
{
|
{
|
||||||
if (! $this->request->isAJAX()) {
|
|
||||||
return $this->response->setStatusCode(403)->setJSON(['status' => 'error', 'message' => 'AJAX only']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$patientId = (int) ($this->request->getGet('patient_id') ?? $this->request->getPost('patient_id') ?? 0);
|
$patientId = (int) ($this->request->getGet('patient_id') ?? $this->request->getPost('patient_id') ?? 0);
|
||||||
$recordId = (int) ($this->request->getGet('record_id') ?? $this->request->getPost('record_id') ?? 0);
|
$recordId = (int) ($this->request->getGet('record_id') ?? $this->request->getPost('record_id') ?? 0);
|
||||||
$abhaId = trim((string) ($this->request->getGet('abha_id') ?? $this->request->getPost('abha_id') ?? ''));
|
$abhaId = trim((string) ($this->request->getGet('abha_id') ?? $this->request->getPost('abha_id') ?? ''));
|
||||||
$forceNewRecord = (int) ($this->request->getGet('force_new_record') ?? $this->request->getGet('force_rebuild') ?? $this->request->getPost('force_new_record') ?? 0) === 1;
|
$forceNewRecord = (int) ($this->request->getGet('force_new_record') ?? $this->request->getGet('force_rebuild') ?? $this->request->getPost('force_new_record') ?? 0) === 1;
|
||||||
|
|
||||||
|
if ($patientId <= 0 && $recordId > 0 && $this->db->tableExists('immunization_records')) {
|
||||||
|
$immRec = $this->db->table('immunization_records')->select('patient_id')->where('id', $recordId)->get(1)->getRowArray();
|
||||||
|
$patientId = (int) ($immRec['patient_id'] ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
if ($patientId <= 0) {
|
if ($patientId <= 0) {
|
||||||
return $this->response->setStatusCode(400)->setJSON([
|
return $this->response->setStatusCode(400)->setJSON([
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
|
|
@ -3974,10 +3975,14 @@ class AbdmGateway extends BaseController
|
||||||
'care_context_reference' => $ccRef,
|
'care_context_reference' => $ccRef,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$vaccineDisplay = ! empty($records[0]['vaccine_name']) ? trim((string) $records[0]['vaccine_name']) : 'Vaccine';
|
||||||
|
$dateStr = date('d M Y', strtotime($visitDate));
|
||||||
|
$ccDisplay = 'ImmunizationRecord - ' . $vaccineDisplay . ' (' . $dateStr . ')';
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'bundle' => $bundle,
|
'bundle' => $bundle,
|
||||||
'care_context_reference' => $ccRef,
|
'care_context_reference' => $ccRef,
|
||||||
'care_context_display' => 'Immunization Record - ' . $visitDate,
|
'care_context_display' => $ccDisplay,
|
||||||
'patient_name' => $patient['name'],
|
'patient_name' => $patient['name'],
|
||||||
'doctor_name' => (string) ($practitioner['name'] ?? ''),
|
'doctor_name' => (string) ($practitioner['name'] ?? ''),
|
||||||
'year_of_birth' => $this->resolvePatientBirthYear($patientRow, str_contains($rawAbha, '@') ? $rawAbha : '', str_contains($rawAbha, '@') ? '' : $rawAbha),
|
'year_of_birth' => $this->resolvePatientBirthYear($patientRow, str_contains($rawAbha, '@') ? $rawAbha : '', str_contains($rawAbha, '@') ? '' : $rawAbha),
|
||||||
|
|
@ -5371,6 +5376,60 @@ class AbdmGateway extends BaseController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strategy 0e: Live On-Demand Fresh Generation for Immunization Record (IMM-{id})
|
||||||
|
if (preg_match('/^IMM-(?:PAT-(\d+)|(?:(\d+)-V)?(\d+))/i', $ref, $immM)) {
|
||||||
|
$immTargetId = (int) (! empty($immM[3]) ? $immM[3] : (! empty($immM[2]) ? $immM[2] : ($immM[1] ?? 0)));
|
||||||
|
$immPatientId = (int) (! empty($immM[1]) ? $immM[1] : (! empty($immM[2]) ? $immM[2] : 0));
|
||||||
|
try {
|
||||||
|
$immPayload = $this->buildImmunizationGatewayPayload($immPatientId, $immTargetId, '', false);
|
||||||
|
if ($immPayload !== null && ! empty($immPayload['bundle'])) {
|
||||||
|
$vaccineName = 'Vaccine';
|
||||||
|
if (! empty($immPayload['records'][0]['vaccine_name'])) {
|
||||||
|
$vaccineName = trim((string) $immPayload['records'][0]['vaccine_name']);
|
||||||
|
}
|
||||||
|
$dateStr = date('d M Y', strtotime((string) ($immPayload['visit_date'] ?? date('Y-m-d'))));
|
||||||
|
$immDisplay = 'ImmunizationRecord - ' . $vaccineName . ' (' . $dateStr . ')';
|
||||||
|
|
||||||
|
$records[] = [
|
||||||
|
'careContextReference' => $ref,
|
||||||
|
'hiType' => 'ImmunizationRecord',
|
||||||
|
'display' => $immDisplay,
|
||||||
|
'bundle' => $immPayload['bundle'],
|
||||||
|
];
|
||||||
|
// Persist or cache to health_records for rapid subsequent fetches
|
||||||
|
if ($db->tableExists('health_records')) {
|
||||||
|
$exHr = $db->table('health_records')->where('care_context_reference', $ref)->get(1)->getRowArray();
|
||||||
|
if ($exHr) {
|
||||||
|
if (empty($exHr['record_data'])) {
|
||||||
|
$db->table('health_records')->where('id', (int) $exHr['id'])->update([
|
||||||
|
'record_data' => json_encode($immPayload['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||||
|
'push_status' => 'linked',
|
||||||
|
'updated_at' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$resolvedPatId = $immPatientId > 0 ? $immPatientId : (int) ($immPayload['records'][0]['patient_id'] ?? 0);
|
||||||
|
$db->table('health_records')->insert([
|
||||||
|
'patient_id' => $resolvedPatId,
|
||||||
|
'abha_id' => (string) ($immPayload['records'][0]['abha_id'] ?? $this->resolvePatientAbhaIdentifier($resolvedPatId)),
|
||||||
|
'hi_type' => 'ImmunizationRecord',
|
||||||
|
'entity_type' => 'immunization',
|
||||||
|
'entity_id' => (string) $immTargetId,
|
||||||
|
'care_context_reference' => $ref,
|
||||||
|
'record_data' => json_encode($immPayload['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||||
|
'push_status' => 'linked',
|
||||||
|
'created_at' => date('Y-m-d H:i:s'),
|
||||||
|
'updated_at' => date('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} catch (\Throwable $ex) {
|
||||||
|
log_message('warning', 'Live Immunization FHIR generation in recordsFetch failed: ' . $ex->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Strategy A: Check if health_records already has stored FHIR record_data
|
// Strategy A: Check if health_records already has stored FHIR record_data
|
||||||
$hrRow = null;
|
$hrRow = null;
|
||||||
if ($db->tableExists('health_records')) {
|
if ($db->tableExists('health_records')) {
|
||||||
|
|
@ -7494,6 +7553,15 @@ class AbdmGateway extends BaseController
|
||||||
$ccRef = ! empty($imm['abdm_care_context_reference'])
|
$ccRef = ! empty($imm['abdm_care_context_reference'])
|
||||||
? trim((string) $imm['abdm_care_context_reference'])
|
? trim((string) $imm['abdm_care_context_reference'])
|
||||||
: ('IMM-' . $imm['id']);
|
: ('IMM-' . $imm['id']);
|
||||||
|
if (empty($imm['abdm_care_context_reference'])) {
|
||||||
|
$this->db->table('immunization_records')
|
||||||
|
->where('id', (int) $imm['id'])
|
||||||
|
->groupStart()
|
||||||
|
->where('abdm_care_context_reference', null)
|
||||||
|
->orWhere('abdm_care_context_reference', '')
|
||||||
|
->groupEnd()
|
||||||
|
->update(['abdm_care_context_reference' => $ccRef]);
|
||||||
|
}
|
||||||
$display = 'ImmunizationRecord - ' . ($imm['vaccine_name'] ?? 'Vaccine') . ' (' . $dateStr . ')';
|
$display = 'ImmunizationRecord - ' . ($imm['vaccine_name'] ?? 'Vaccine') . ' (' . $dateStr . ')';
|
||||||
|
|
||||||
$addContext([
|
$addContext([
|
||||||
|
|
@ -10326,95 +10394,48 @@ class AbdmGateway extends BaseController
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$immRows = [];
|
if ($patientId <= 0 && $recordId > 0 && $this->db->tableExists('immunization_records')) {
|
||||||
if ($this->db->tableExists('immunization_records')) {
|
$rec = $this->db->table('immunization_records')->select('patient_id')->where('id', $recordId)->get(1)->getRowArray();
|
||||||
$builder = $this->db->table('immunization_records');
|
$patientId = (int) ($rec['patient_id'] ?? 0);
|
||||||
if ($recordId > 0) {
|
|
||||||
$builder->where('id', $recordId);
|
|
||||||
} elseif ($patientId > 0) {
|
|
||||||
$builder->where('patient_id', $patientId)->orderBy('id', 'DESC')->limit(10);
|
|
||||||
}
|
|
||||||
$immRows = $builder->get()->getResultArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($immRows)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$firstRow = $immRows[0];
|
|
||||||
if ($patientId <= 0) {
|
if ($patientId <= 0) {
|
||||||
$patientId = (int) ($firstRow['patient_id'] ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
$patientRow = $this->loadPatientRow($patientId);
|
|
||||||
if (empty($patientRow)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($abhaId === '') {
|
$gatewayPayload = $this->buildImmunizationGatewayPayload($patientId, $recordId, $abhaId, false);
|
||||||
$abhaId = $this->resolvePatientAbhaIdentifier($patientId);
|
if ($gatewayPayload === null) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$vaccines = [];
|
$vaccineName = 'Vaccine';
|
||||||
$visitDate = date('Y-m-d');
|
if (! empty($gatewayPayload['records'][0]['vaccine_name'])) {
|
||||||
foreach ($immRows as $row) {
|
$vaccineName = trim((string) $gatewayPayload['records'][0]['vaccine_name']);
|
||||||
$vaccineName = trim((string) ($row['vaccine_name'] ?? $row['vaccine_display'] ?? ''));
|
|
||||||
if ($vaccineName === '' && ! empty($row['vaccine_master_id']) && $this->db->tableExists('immunization_vaccine_master')) {
|
|
||||||
$vm = $this->db->table('immunization_vaccine_master')->where('id', (int) $row['vaccine_master_id'])->get(1)->getRowArray();
|
|
||||||
$vaccineName = trim((string) ($vm['vaccine_name'] ?? ''));
|
|
||||||
}
|
|
||||||
if ($vaccineName === '') {
|
|
||||||
$vaccineName = 'Vaccine Dose';
|
|
||||||
}
|
|
||||||
$occDate = ! empty($row['given_date']) ? (string) $row['given_date'] : (! empty($row['scheduled_date']) ? (string) $row['scheduled_date'] : date('Y-m-d H:i:s'));
|
|
||||||
$visitDate = date('Y-m-d', strtotime($occDate));
|
|
||||||
$vaccines[] = [
|
|
||||||
'vaccine_name' => $vaccineName,
|
|
||||||
'name' => $vaccineName,
|
|
||||||
'snomed_code' => trim((string) ($row['vaccine_code'] ?? '')),
|
|
||||||
'occurrence_date' => date(DATE_ATOM, strtotime($occDate)),
|
|
||||||
'status' => trim((string) ($row['status'] ?? 'completed')),
|
|
||||||
'lot_number' => trim((string) ($row['lot_number'] ?? '')),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
$dateStr = date('d M Y', strtotime((string) ($gatewayPayload['visit_date'] ?? date('Y-m-d'))));
|
||||||
|
$ccDisplay = 'ImmunizationRecord - ' . $vaccineName . ' (' . $dateStr . ')';
|
||||||
|
$ccRef = (string) ($gatewayPayload['care_context_reference'] ?? ('IMM-' . $recordId));
|
||||||
|
|
||||||
$primaryRecordId = (int) ($firstRow['id'] ?? $recordId);
|
if ($recordId > 0 && $this->db->tableExists('immunization_records')) {
|
||||||
$cleanDate = date('Ymd', strtotime($visitDate));
|
$this->db->table('immunization_records')
|
||||||
$ccRef = 'IMM-' . $patientId . '-V' . $primaryRecordId . '-' . $cleanDate;
|
->where('id', $recordId)
|
||||||
$ccDisplay = 'Immunization - ' . date('d/m/Y', strtotime($visitDate));
|
->groupStart()
|
||||||
|
->where('abdm_care_context_reference', null)
|
||||||
$source = [
|
->orWhere('abdm_care_context_reference', '')
|
||||||
'record_id' => (string) $primaryRecordId,
|
->groupEnd()
|
||||||
'visit_date' => $visitDate,
|
->update(['abdm_care_context_reference' => $ccRef]);
|
||||||
'completed_at' => date(DATE_ATOM, strtotime($visitDate)),
|
}
|
||||||
'patient' => [
|
|
||||||
'id' => (string) $patientId,
|
|
||||||
'name' => $this->patientDisplayName($patientRow),
|
|
||||||
'gender' => strtolower(trim((string) ($patientRow['gender'] ?? 'unknown'))),
|
|
||||||
'birth_date' => ! empty($patientRow['dob']) ? date('Y-m-d', strtotime((string) $patientRow['dob'])) : '',
|
|
||||||
'abha_id' => preg_replace('/\D/', '', $abhaId),
|
|
||||||
'abha_address' => str_contains($abhaId, '@') ? $abhaId : '',
|
|
||||||
],
|
|
||||||
'immunizations' => $vaccines,
|
|
||||||
'vaccines' => $vaccines,
|
|
||||||
'hfr_id' => $this->connector->getHfrId() ?: 'HFR-IN-HMS',
|
|
||||||
];
|
|
||||||
|
|
||||||
$factory = new FhirGeneratorFactory();
|
|
||||||
$generatorOutput = $factory->immunization()->generate($source);
|
|
||||||
$adapter = new \App\Libraries\Abdm\Fhir\Support\GatewayPayloadAdapter();
|
|
||||||
$gatewayPayload = $adapter->toGatewayPayload($generatorOutput, $source, (string) ($source['hfr_id']));
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'hi_type' => 'ImmunizationRecord',
|
'hi_type' => 'ImmunizationRecord',
|
||||||
'entity_type' => 'immunization',
|
'entity_type' => 'immunization',
|
||||||
'entity_id' => (string) $primaryRecordId,
|
'entity_id' => (string) ($recordId > 0 ? $recordId : $patientId),
|
||||||
'patient_id' => $patientId,
|
'patient_id' => $patientId,
|
||||||
'patient_name' => $this->patientDisplayName($patientRow),
|
'patient_name' => (string) ($gatewayPayload['patient_name'] ?? ('PATIENT-' . $patientId)),
|
||||||
'visit_date' => $visitDate,
|
'visit_date' => (string) ($gatewayPayload['visit_date'] ?? date('Y-m-d')),
|
||||||
'care_context_reference' => $ccRef,
|
'care_context_reference' => $ccRef,
|
||||||
'care_context_display' => $ccDisplay,
|
'care_context_display' => $ccDisplay,
|
||||||
'bundle' => (array) ($gatewayPayload['fhir_bundle'] ?? []),
|
'bundle' => (array) ($gatewayPayload['bundle'] ?? []),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -831,9 +831,11 @@ class AbdmTaskBoardSyncService
|
||||||
$cleanVisitDate = str_replace('-', '', $visitDate);
|
$cleanVisitDate = str_replace('-', '', $visitDate);
|
||||||
$careContextRef = $prefix . $entityId . '-' . $cleanVisitDate;
|
$careContextRef = $prefix . $entityId . '-' . $cleanVisitDate;
|
||||||
if ($taskType === 'immunization_record_publish' && $this->db->tableExists('immunization_records')) {
|
if ($taskType === 'immunization_record_publish' && $this->db->tableExists('immunization_records')) {
|
||||||
$immRec = $this->db->table('immunization_records')->select('abdm_care_context_reference')->where('id', (int) $entityId)->get(1)->getRowArray();
|
$immRec = $this->db->table('immunization_records')->select('abdm_care_context_reference, vaccine_name')->where('id', (int) $entityId)->get(1)->getRowArray();
|
||||||
if (! empty($immRec['abdm_care_context_reference'])) {
|
if (! empty($immRec['abdm_care_context_reference'])) {
|
||||||
$careContextRef = trim((string) $immRec['abdm_care_context_reference']);
|
$careContextRef = trim((string) $immRec['abdm_care_context_reference']);
|
||||||
|
} else {
|
||||||
|
$careContextRef = 'IMM-' . $entityId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($taskType === 'wellness_record_publish' && $this->db->tableExists('patient_wellness_records')) {
|
if ($taskType === 'wellness_record_publish' && $this->db->tableExists('patient_wellness_records')) {
|
||||||
|
|
@ -846,7 +848,12 @@ class AbdmTaskBoardSyncService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$careContextDisplay = $hiType . ' ' . $visitDate;
|
|
||||||
|
if ($taskType === 'immunization_record_publish' && ! empty($immRec['vaccine_name'])) {
|
||||||
|
$careContextDisplay = 'ImmunizationRecord - ' . trim((string) $immRec['vaccine_name']) . ' (' . date('d M Y', strtotime($visitDate)) . ')';
|
||||||
|
} else {
|
||||||
|
$careContextDisplay = $hiType . ' ' . $visitDate;
|
||||||
|
}
|
||||||
|
|
||||||
$pushData = [
|
$pushData = [
|
||||||
'patient_id' => (string) $patientId,
|
'patient_id' => (string) $patientId,
|
||||||
|
|
@ -913,6 +920,21 @@ class AbdmTaskBoardSyncService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif ($taskType === 'immunization_record_publish') {
|
||||||
|
if (empty($pushData['bundle']) && class_exists('\App\Controllers\AbdmGateway')) {
|
||||||
|
try {
|
||||||
|
$gw = new \App\Controllers\AbdmGateway();
|
||||||
|
$immPayload = $gw->buildImmunizationRecordPayload((int) $entityId, $patientId, $abhaAddress !== '' ? $abhaAddress : $abhaNumber);
|
||||||
|
if (! empty($immPayload['bundle'])) {
|
||||||
|
$pushData['bundle'] = $immPayload['bundle'];
|
||||||
|
$pushData['fhir_bundle'] = $immPayload['bundle'];
|
||||||
|
$pushData['record_data'] = $immPayload['bundle'];
|
||||||
|
$bundleJson = (string) json_encode($immPayload['bundle'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
}
|
||||||
|
} catch (\Throwable $ie) {
|
||||||
|
log_message('warning', '[processIndividualWorkTask] Immunization bundle generation error: ' . $ie->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user