feat(abdm-m2): add HIP link modal and care context discovery on patient registration

This commit is contained in:
DevSoftTech Server 2026-09-29 23:48:33 +05:30
parent 6bd24303e3
commit a33b376ecd
3 changed files with 103 additions and 4 deletions

View File

@ -6225,6 +6225,39 @@ class AbdmGateway extends BaseController
}
}
// 4b. Query opd_master (OPD consultation appointments/visits not already in prescriptions)
if ($this->db->tableExists('opd_master')) {
$opdMasterRows = $this->db->table('opd_master')
->select('opd_id, p_id, apointment_date, opd_book_date, doc_name')
->where('p_id', $patientId)
->orderBy('opd_id', 'DESC')
->limit(30)
->get()
->getResultArray();
foreach ($opdMasterRows as $om) {
$visitRaw = ! empty($om['apointment_date']) && $om['apointment_date'] !== '0000-00-00 00:00:00'
? $om['apointment_date']
: (! empty($om['opd_book_date']) ? $om['opd_book_date'] : date('Y-m-d'));
$visitDate = date('Y-m-d', strtotime((string) $visitRaw));
$dateStr = date('d M Y', strtotime($visitDate));
$opdId = (int) $om['opd_id'];
$ccRef = 'OPD-' . $patientId . '-S' . $opdId . '-' . str_replace('-', '', $visitDate);
$docName = trim((string) ($om['doc_name'] ?? ''));
$display = 'OPConsultRecord - ' . ($docName !== '' ? 'Dr. ' . $docName . ' - ' : '') . $dateStr;
$addContext([
'careContextId' => $ccRef,
'referenceNumber' => $ccRef,
'display' => $display,
'record_type' => 'OPConsultRecord',
'patient_id' => $patientId,
'is_fhir_ready' => true,
'is_primary' => false,
]);
}
}
// 5. Query ipd_master (Discharge summaries)
if ($this->db->tableExists('ipd_master')) {
$ipdRows = $this->db->table('ipd_master')
@ -10917,7 +10950,16 @@ class AbdmGateway extends BaseController
if ($patientId > 0) {
$builder->where('id', $patientId);
} elseif ($abhaAddress !== '') {
$builder->where('abha_address', $abhaAddress);
$cleanAbha = preg_replace('/\D/', '', $abhaAddress);
if (strlen($cleanAbha) === 14) {
$builder->groupStart()
->where('abha_address', $abhaAddress)
->orWhere('abha_id', $cleanAbha)
->orWhere('abha_id', $abhaAddress)
->groupEnd();
} else {
$builder->where('abha_address', $abhaAddress);
}
} elseif ($pCode !== '') {
$builder->where('p_code', $pCode);
}

View File

@ -45,6 +45,7 @@
<?= view('partials/abha_create_modal') ?>
<?= view('partials/abha_qr_modal') ?>
<?= view('partials/abha_mobile_modal') ?>
<?= view('partials/abdm_hip_link_modal') ?>
<section class="content">
<div class="row">
<div class="col-md-12">
@ -105,6 +106,7 @@
<input class="form-control" name="input_abha_id" id="input_abha_id"
placeholder="14-digit ABHA ID" type="text" autocomplete="off"
maxlength="14" data-inputmask='"mask": "99999999999999"' data-mask>
<input type="hidden" name="input_abha_address" id="input_abha_address" value="">
<div id="abha_id_feedback" class="mt-1" style="display:none;"></div>
</div>
</div>
@ -410,7 +412,7 @@
</div>
<div class="row g-3 py-3 px-2">
<div class="col-lg-4">
<div class="col-xl-3 col-md-6">
<div class="card h-100 border-primary">
<div class="card-body d-flex flex-column">
<div class="d-flex align-items-center gap-2 mb-2">
@ -428,7 +430,7 @@
</div>
</div>
<div class="col-lg-4">
<div class="col-xl-3 col-md-6">
<div class="card h-100 border-success">
<div class="card-body d-flex flex-column">
<div class="d-flex align-items-center gap-2 mb-2">
@ -449,7 +451,7 @@
</div>
</div>
<div class="col-lg-4">
<div class="col-xl-3 col-md-6">
<div class="card h-100 border-info">
<div class="card-body d-flex flex-column">
<div class="d-flex align-items-center gap-2 mb-2">
@ -465,6 +467,31 @@
</div>
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="card h-100 border-warning">
<div class="card-body d-flex flex-column">
<div class="d-flex align-items-center gap-2 mb-2">
<i class="bi bi-link-45deg fs-3 text-warning"></i>
<h6 class="mb-0">Link Records to ABHA (HIP)</h6>
</div>
<p class="text-muted small mb-2">Link hospital visits & diagnostic records to patient's ABHA address using ABDM M2 HIP workflows.</p>
<ul class="list-unstyled small text-muted mb-3">
<li><i class="bi bi-check-circle-fill text-success me-1"></i>Demographic Auth (Method 4)</li>
<li><i class="bi bi-check-circle-fill text-success me-1"></i>Link OPD & Diagnostics</li>
<li><i class="bi bi-check-circle-fill text-success me-1"></i>Deep Link SMS to ABHA App</li>
</ul>
<div class="d-grid gap-2 mt-auto">
<button type="button" class="btn btn-warning text-dark fw-semibold" onclick="openAbdmHipLinkModal()">
<i class="bi bi-link-45deg me-1"></i>Link Records to ABHA (HIP)
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="openAbdmHipSmsModal()">
<i class="bi bi-chat-dots me-1"></i>Send Deep Link SMS
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Legacy inline flows kept hidden; their element IDs are still used by the wizard scripts. -->

View File

@ -46,6 +46,14 @@ final class CareContextDiscoveryTest extends CIUnitTestCase
p_datetime TEXT
)");
$db->query("CREATE TABLE IF NOT EXISTS " . $db->prefixTable('opd_master') . " (
opd_id INTEGER PRIMARY KEY,
p_id INTEGER,
apointment_date TEXT,
opd_book_date TEXT,
doc_name TEXT
)");
$db->query("CREATE TABLE IF NOT EXISTS " . $db->prefixTable('health_records') . " (
id INTEGER PRIMARY KEY,
patient_id INTEGER,
@ -92,6 +100,7 @@ final class CareContextDiscoveryTest extends CIUnitTestCase
$db->table('charge_master')->emptyTable();
$db->table('lab_request')->emptyTable();
$db->table('opd_prescription')->emptyTable();
$db->table('opd_master')->emptyTable();
$db->table('health_records')->emptyTable();
$db->table('patient_master')->emptyTable();
$db->table('ipd_master')->emptyTable();
@ -323,5 +332,26 @@ final class CareContextDiscoveryTest extends CIUnitTestCase
$this->assertSame(1, $body['ok'] ?? 0);
$this->assertSame('RAD-31-20260929', $body['care_context_reference'] ?? '');
}
public function testDiscoversOpdMasterVisitWhenPrescriptionNotCreated(): void
{
$db = \Config\Database::connect();
$db->table('opd_master')->insert([
'opd_id' => 77,
'p_id' => 12,
'apointment_date' => '2026-09-29 14:30:00',
'opd_book_date' => '2026-09-29 14:00:00',
'doc_name' => 'NIDHI PANDEY',
]);
$refGateway = new ReflectionClass($this->gateway);
$method = $refGateway->getMethod('findCareContextsForPatient');
$method->setAccessible(true);
[$v3, $full] = $method->invoke($this->gateway, 12, 'P26071000012', 'KESHAV SINGH');
$refs = array_column($v3, 'referenceNumber');
$this->assertContains('OPD-12-S77-20260929', $refs);
}
}