Pharmacy: add ABDM drug terminology autocomplete + canonical mapping
This commit is contained in:
parent
12cacc3a9c
commit
0558ac5a2e
|
|
@ -85,10 +85,14 @@ $routes->get('Product_master/medicine_category_Sub', 'Medical::medicine_category
|
|||
$routes->post('Product_master/medicine_category_Update', 'Medical::medicine_category_update');
|
||||
$routes->get('product_master/drug_master_list', 'Medical::drug_master_list');
|
||||
$routes->post('product_master/Product_search', 'Medical::product_search');
|
||||
$routes->get('product_master/drug_terminology_autocomplete', 'Medical::drug_terminology_autocomplete');
|
||||
$routes->get('product_master/drug_terminology_detail', 'Medical::drug_terminology_detail');
|
||||
$routes->get('product_master/Product_edit/(:num)', 'Medical::product_edit/$1');
|
||||
$routes->post('product_master/product_master_update/(:num)', 'Medical::product_master_update/$1');
|
||||
$routes->get('Product_master/drug_master_list', 'Medical::drug_master_list');
|
||||
$routes->post('Product_master/Product_search', 'Medical::product_search');
|
||||
$routes->get('Product_master/drug_terminology_autocomplete', 'Medical::drug_terminology_autocomplete');
|
||||
$routes->get('Product_master/drug_terminology_detail', 'Medical::drug_terminology_detail');
|
||||
$routes->get('Product_master/Product_edit/(:num)', 'Medical::product_edit/$1');
|
||||
$routes->post('Product_master/product_master_update/(:num)', 'Medical::product_master_update/$1');
|
||||
$routes->get('Medical/Purchase', 'Medical::purchase');
|
||||
|
|
|
|||
|
|
@ -5071,6 +5071,226 @@ class Medical extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function drug_terminology_autocomplete()
|
||||
{
|
||||
if ($deny = $this->ensurePharmacyAccess()) {
|
||||
return $deny;
|
||||
}
|
||||
|
||||
$q = trim((string) ($this->request->getGet('q') ?? $this->request->getPost('q') ?? ''));
|
||||
$q = preg_replace('/[^A-Za-z0-9_ \-]/', '', $q);
|
||||
if (mb_strlen($q) < 2) {
|
||||
return $this->response->setJSON([
|
||||
'ok' => 1,
|
||||
'suggestions' => [],
|
||||
'error_text' => '',
|
||||
]);
|
||||
}
|
||||
|
||||
$type = strtolower(trim((string) ($this->request->getGet('type') ?? $this->request->getPost('type') ?? 'generic')));
|
||||
$allowedTypes = ['generic', 'brand', 'product', 'substance'];
|
||||
if (! in_array($type, $allowedTypes, true)) {
|
||||
$type = 'generic';
|
||||
}
|
||||
|
||||
$limit = (int) ($this->request->getGet('limit') ?? $this->request->getPost('limit') ?? 10);
|
||||
if ($limit <= 0 || $limit > 50) {
|
||||
$limit = 10;
|
||||
}
|
||||
|
||||
try {
|
||||
$connector = new \App\Libraries\Abdm\EAtriaBridgeConnector();
|
||||
$result = $connector->drugsAutocomplete($q, $type, $limit);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->response->setJSON([
|
||||
'ok' => 0,
|
||||
'suggestions' => [],
|
||||
'error_text' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
$items = $this->extractDrugResultList($result);
|
||||
$suggestions = [];
|
||||
foreach ($items as $row) {
|
||||
if (! is_array($row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$label = $this->extractDrugText($row, ['label', 'name', 'display', 'term', 'title', 'drug_name']);
|
||||
$identifier = $this->extractDrugText($row, ['identifier', 'id', 'code', 'concept_id', 'value']);
|
||||
$itemType = strtolower($this->extractDrugText($row, ['type', 'entity_type', 'category']));
|
||||
if ($itemType === '') {
|
||||
$itemType = $type;
|
||||
}
|
||||
|
||||
if ($label === '' && $identifier === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$suggestions[] = [
|
||||
'label' => $label !== '' ? $label : $identifier,
|
||||
'identifier' => $identifier,
|
||||
'type' => $itemType,
|
||||
];
|
||||
}
|
||||
|
||||
return $this->response->setJSON([
|
||||
'ok' => (int) ($result['ok'] ?? 0),
|
||||
'suggestions' => $suggestions,
|
||||
'error_text' => (string) ($result['error_text'] ?? $result['message'] ?? ''),
|
||||
]);
|
||||
}
|
||||
|
||||
public function drug_terminology_detail()
|
||||
{
|
||||
if ($deny = $this->ensurePharmacyAccess()) {
|
||||
return $deny;
|
||||
}
|
||||
|
||||
$type = strtolower(trim((string) ($this->request->getGet('type') ?? $this->request->getPost('type') ?? 'generic')));
|
||||
$identifier = trim((string) ($this->request->getGet('identifier') ?? $this->request->getPost('identifier') ?? ''));
|
||||
if ($identifier === '') {
|
||||
return $this->response->setJSON([
|
||||
'ok' => 0,
|
||||
'selected' => null,
|
||||
'error_text' => 'Identifier is required',
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$connector = new \App\Libraries\Abdm\EAtriaBridgeConnector();
|
||||
$result = $connector->drugsDetail($type, $identifier);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->response->setJSON([
|
||||
'ok' => 0,
|
||||
'selected' => null,
|
||||
'error_text' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
$record = $this->extractDrugResultObject($result);
|
||||
$label = $this->extractDrugText($record, ['label', 'name', 'display', 'term', 'title', 'drug_name']);
|
||||
$generic = $this->extractDrugText($record, ['generic_name', 'genericname', 'generic', 'salt', 'molecule']);
|
||||
$hsnCode = $this->extractDrugText($record, ['hsn_code', 'hsn', 'hscode']);
|
||||
$formulation = $this->extractDrugText($record, ['formulation', 'dosage_form', 'drug_form']);
|
||||
$packing = $this->extractDrugText($record, ['packing', 'pack_size', 'package']);
|
||||
$itemType = strtolower($this->extractDrugText($record, ['type', 'entity_type', 'category']));
|
||||
if ($itemType === '') {
|
||||
$itemType = $type;
|
||||
}
|
||||
$canonicalId = $this->extractDrugText($record, ['identifier', 'id', 'code', 'concept_id', 'value']);
|
||||
if ($canonicalId === '') {
|
||||
$canonicalId = $identifier;
|
||||
}
|
||||
|
||||
$payloadJson = json_encode($record, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (! is_string($payloadJson)) {
|
||||
$payloadJson = '{}';
|
||||
}
|
||||
|
||||
return $this->response->setJSON([
|
||||
'ok' => (int) ($result['ok'] ?? 0),
|
||||
'selected' => [
|
||||
'label' => $label,
|
||||
'generic_name' => $generic,
|
||||
'hsn_code' => $hsnCode,
|
||||
'formulation' => $formulation,
|
||||
'packing' => $packing,
|
||||
'type' => $itemType,
|
||||
'identifier' => $canonicalId,
|
||||
'payload_json' => $payloadJson,
|
||||
'synced_at' => date('Y-m-d H:i:s'),
|
||||
],
|
||||
'error_text' => (string) ($result['error_text'] ?? $result['message'] ?? ''),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $result
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function extractDrugResultList(array $result): array
|
||||
{
|
||||
$candidate = $result['data'] ?? $result['result'] ?? $result;
|
||||
if (! is_array($candidate)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (array_is_list($candidate)) {
|
||||
return array_values(array_filter($candidate, static fn ($v) => is_array($v)));
|
||||
}
|
||||
|
||||
foreach (['items', 'suggestions', 'results', 'data', 'records'] as $key) {
|
||||
if (isset($candidate[$key]) && is_array($candidate[$key]) && array_is_list($candidate[$key])) {
|
||||
return array_values(array_filter($candidate[$key], static fn ($v) => is_array($v)));
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->extractDrugText($candidate, ['identifier', 'id', 'code', 'concept_id', 'value']) !== '') {
|
||||
return [$candidate];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $result
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function extractDrugResultObject(array $result): array
|
||||
{
|
||||
$candidate = $result['data'] ?? $result['result'] ?? $result;
|
||||
if (! is_array($candidate)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (array_is_list($candidate)) {
|
||||
$first = $candidate[0] ?? [];
|
||||
return is_array($first) ? $first : [];
|
||||
}
|
||||
|
||||
foreach (['item', 'result', 'record', 'data'] as $key) {
|
||||
if (isset($candidate[$key]) && is_array($candidate[$key])) {
|
||||
return $candidate[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<int, string> $keys
|
||||
*/
|
||||
private function extractDrugText(array $data, array $keys): string
|
||||
{
|
||||
$flat = [];
|
||||
$walker = static function ($node) use (&$walker, &$flat): void {
|
||||
if (! is_array($node)) {
|
||||
return;
|
||||
}
|
||||
foreach ($node as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$walker($v);
|
||||
continue;
|
||||
}
|
||||
if (is_scalar($v) || $v === null) {
|
||||
$flat[strtolower((string) $k)] = trim((string) $v);
|
||||
}
|
||||
}
|
||||
};
|
||||
$walker($data);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$val = trim((string) ($flat[strtolower($key)] ?? ''));
|
||||
if ($val !== '') {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product_edit($productId = 0)
|
||||
{
|
||||
if ($deny = $this->ensurePharmacyAccess()) {
|
||||
|
|
@ -5149,6 +5369,15 @@ class Medical extends BaseController
|
|||
$coldStorage = trim((string) ($this->request->getPost('input_cold_storage') ?? ''));
|
||||
$companyId = (int) ($this->request->getPost('input_company_name') ?? 0);
|
||||
$relatedDrugId = (int) ($this->request->getPost('related_drug_id') ?? 0);
|
||||
$abdmDrugType = trim((string) ($this->request->getPost('abdm_drug_type') ?? ''));
|
||||
$abdmDrugIdentifier = trim((string) ($this->request->getPost('abdm_drug_identifier') ?? ''));
|
||||
$abdmDrugDisplay = trim((string) ($this->request->getPost('abdm_drug_display') ?? ''));
|
||||
$abdmDrugGeneric = trim((string) ($this->request->getPost('abdm_drug_generic') ?? ''));
|
||||
$abdmDrugPayloadJson = trim((string) ($this->request->getPost('abdm_drug_payload_json') ?? ''));
|
||||
$abdmDrugLastSyncedAt = trim((string) ($this->request->getPost('abdm_drug_last_synced_at') ?? ''));
|
||||
if (strlen($abdmDrugPayloadJson) > 65000) {
|
||||
$abdmDrugPayloadJson = substr($abdmDrugPayloadJson, 0, 65000);
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
if ($itemName === '' || mb_strlen($itemName) < 3) {
|
||||
|
|
@ -5193,6 +5422,12 @@ class Medical extends BaseController
|
|||
'shelf_no' => $shelfNo,
|
||||
'cold_storage' => $coldStorage,
|
||||
'company_id' => $companyId,
|
||||
'abdm_drug_type' => $abdmDrugType,
|
||||
'abdm_drug_identifier' => $abdmDrugIdentifier,
|
||||
'abdm_drug_display' => $abdmDrugDisplay,
|
||||
'abdm_drug_generic' => $abdmDrugGeneric,
|
||||
'abdm_drug_payload_json' => $abdmDrugPayloadJson,
|
||||
'abdm_drug_last_synced_at' => $abdmDrugLastSyncedAt,
|
||||
'ban_flag_id' => $flag('chk_ban_flag_id'),
|
||||
'batch_applicable' => $flag('chk_batch_applicable'),
|
||||
'is_continue' => $flag('chk_is_continue'),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddAbdmDrugTerminologyFieldsToMedProductMaster extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
if (! $this->db->tableExists('med_product_master')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fields = $this->db->getFieldNames('med_product_master') ?? [];
|
||||
$add = [];
|
||||
|
||||
if (! in_array('abdm_drug_type', $fields, true)) {
|
||||
$add['abdm_drug_type'] = ['type' => 'VARCHAR', 'constraint' => 30, 'null' => true, 'default' => null];
|
||||
}
|
||||
if (! in_array('abdm_drug_identifier', $fields, true)) {
|
||||
$add['abdm_drug_identifier'] = ['type' => 'VARCHAR', 'constraint' => 120, 'null' => true, 'default' => null];
|
||||
}
|
||||
if (! in_array('abdm_drug_display', $fields, true)) {
|
||||
$add['abdm_drug_display'] = ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true, 'default' => null];
|
||||
}
|
||||
if (! in_array('abdm_drug_generic', $fields, true)) {
|
||||
$add['abdm_drug_generic'] = ['type' => 'VARCHAR', 'constraint' => 255, 'null' => true, 'default' => null];
|
||||
}
|
||||
if (! in_array('abdm_drug_payload_json', $fields, true)) {
|
||||
$add['abdm_drug_payload_json'] = ['type' => 'MEDIUMTEXT', 'null' => true];
|
||||
}
|
||||
if (! in_array('abdm_drug_last_synced_at', $fields, true)) {
|
||||
$add['abdm_drug_last_synced_at'] = ['type' => 'DATETIME', 'null' => true, 'default' => null];
|
||||
}
|
||||
|
||||
if ($add !== []) {
|
||||
$this->forge->addColumn('med_product_master', $add);
|
||||
}
|
||||
|
||||
// Optional index for fast traceability lookup.
|
||||
$indexes = $this->db->query('SHOW INDEX FROM med_product_master')->getResultArray();
|
||||
$hasIdx = false;
|
||||
foreach ($indexes as $idx) {
|
||||
if (strcasecmp((string) ($idx['Key_name'] ?? ''), 'idx_abdm_drug_identifier') === 0) {
|
||||
$hasIdx = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $hasIdx && in_array('abdm_drug_identifier', $this->db->getFieldNames('med_product_master') ?? [], true)) {
|
||||
try {
|
||||
$this->db->query('ALTER TABLE med_product_master ADD INDEX idx_abdm_drug_identifier (abdm_drug_identifier)');
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore index creation failures to keep migration non-blocking.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
if (! $this->db->tableExists('med_product_master')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->db->query('ALTER TABLE med_product_master DROP INDEX idx_abdm_drug_identifier');
|
||||
} catch (\Throwable $e) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
$fields = $this->db->getFieldNames('med_product_master') ?? [];
|
||||
foreach ([
|
||||
'abdm_drug_type',
|
||||
'abdm_drug_identifier',
|
||||
'abdm_drug_display',
|
||||
'abdm_drug_generic',
|
||||
'abdm_drug_payload_json',
|
||||
'abdm_drug_last_synced_at',
|
||||
] as $column) {
|
||||
if (in_array($column, $fields, true)) {
|
||||
$this->forge->dropColumn('med_product_master', $column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -539,4 +539,47 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface
|
|||
{
|
||||
return $this->post('/v3/hip/link/sms-notify', $payload);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Drug Terminology (CDCI)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function drugsAutocomplete(string $q, string $type = 'generic', int $limit = 10): array
|
||||
{
|
||||
$query = [
|
||||
'q' => $q,
|
||||
'type' => $type,
|
||||
'limit' => max(1, min(50, $limit)),
|
||||
];
|
||||
|
||||
if ($this->hfrId !== '') {
|
||||
$query['hfr_id'] = $this->hfrId;
|
||||
}
|
||||
|
||||
return $this->get('/v3/drugs/autocomplete', $query);
|
||||
}
|
||||
|
||||
public function drugsDetail(string $type, string $identifier): array
|
||||
{
|
||||
$query = [
|
||||
'type' => $type,
|
||||
'identifier' => $identifier,
|
||||
];
|
||||
|
||||
if ($this->hfrId !== '') {
|
||||
$query['hfr_id'] = $this->hfrId;
|
||||
}
|
||||
|
||||
return $this->get('/v3/drugs/detail', $query);
|
||||
}
|
||||
|
||||
public function drugsVersion(): array
|
||||
{
|
||||
$query = [];
|
||||
if ($this->hfrId !== '') {
|
||||
$query['hfr_id'] = $this->hfrId;
|
||||
}
|
||||
|
||||
return $this->get('/v3/drugs/version', $query);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ $shelfNo = (string) ($product->shelf_no ?? '');
|
|||
$coldStorage = (string) ($product->cold_storage ?? '');
|
||||
$companyId = (int) ($product->company_id ?? 0);
|
||||
$relatedDrugId = (int) ($product->related_drug_id ?? 0);
|
||||
$abdmDrugType = (string) ($product->abdm_drug_type ?? '');
|
||||
$abdmDrugIdentifier = (string) ($product->abdm_drug_identifier ?? '');
|
||||
$abdmDrugDisplay = (string) ($product->abdm_drug_display ?? '');
|
||||
$abdmDrugGeneric = (string) ($product->abdm_drug_generic ?? '');
|
||||
$abdmDrugPayloadJson = (string) ($product->abdm_drug_payload_json ?? '');
|
||||
$abdmDrugLastSyncedAt = (string) ($product->abdm_drug_last_synced_at ?? '');
|
||||
|
||||
$flag = static function ($v): string {
|
||||
return ((int) $v === 1) ? 'checked' : '';
|
||||
|
|
@ -25,16 +31,47 @@ $flag = static function ($v): string {
|
|||
<div class="card">
|
||||
<div class="card-header">Product <?= $productId > 0 ? '<small class="text-muted">#' . $productId . '</small>' : '' ?></div>
|
||||
<div class="card-body pt-3">
|
||||
<style>
|
||||
#abdm-drug-suggest {
|
||||
max-height: 260px;
|
||||
overflow-y: auto;
|
||||
z-index: 1055;
|
||||
display: none;
|
||||
width: 100%;
|
||||
}
|
||||
#abdm-drug-selected {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
<div id="product-msg"></div>
|
||||
|
||||
<form id="product-form" class="row g-2" method="post" action="javascript:void(0)">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" id="product_id" name="product_id" value="<?= esc((string) $productId) ?>">
|
||||
<input type="hidden" id="related_drug_id" name="related_drug_id" value="<?= esc((string) $relatedDrugId) ?>">
|
||||
<input type="hidden" id="abdm_drug_type" name="abdm_drug_type" value="<?= esc($abdmDrugType) ?>">
|
||||
<input type="hidden" id="abdm_drug_identifier" name="abdm_drug_identifier" value="<?= esc($abdmDrugIdentifier) ?>">
|
||||
<input type="hidden" id="abdm_drug_display" name="abdm_drug_display" value="<?= esc($abdmDrugDisplay) ?>">
|
||||
<input type="hidden" id="abdm_drug_generic" name="abdm_drug_generic" value="<?= esc($abdmDrugGeneric) ?>">
|
||||
<input type="hidden" id="abdm_drug_payload_json" name="abdm_drug_payload_json" value="<?= esc($abdmDrugPayloadJson) ?>">
|
||||
<input type="hidden" id="abdm_drug_last_synced_at" name="abdm_drug_last_synced_at" value="<?= esc($abdmDrugLastSyncedAt) ?>">
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Product Name</label>
|
||||
<input class="form-control" name="input_item_name" id="input_item_name" type="text" value="<?= esc($itemName) ?>">
|
||||
<div class="position-relative">
|
||||
<input class="form-control" name="input_item_name" id="input_item_name" type="text" value="<?= esc($itemName) ?>" autocomplete="off">
|
||||
<div id="abdm-drug-suggest" class="list-group position-absolute shadow-sm"></div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 mt-1">
|
||||
<small class="text-muted">ABDM Drug Search</small>
|
||||
<select id="abdm_drug_search_type" class="form-select form-select-sm" style="width:auto;">
|
||||
<option value="generic" selected>Generic</option>
|
||||
<option value="brand">Brand</option>
|
||||
<option value="product">Product</option>
|
||||
<option value="substance">Substance</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="abdm-drug-selected" class="text-success mt-1"></div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Formulation</label>
|
||||
|
|
@ -131,6 +168,9 @@ $flag = static function ($v): string {
|
|||
|
||||
<script>
|
||||
(function () {
|
||||
var suggestTimer = null;
|
||||
var lastQuery = '';
|
||||
|
||||
if (window.jQuery && $.fn.select2) {
|
||||
$('#med_cat_id').select2({
|
||||
width: '100%',
|
||||
|
|
@ -142,6 +182,177 @@ $flag = static function ($v): string {
|
|||
$('#product-msg').html(html || '');
|
||||
}
|
||||
|
||||
function showSelectedDrugSummary() {
|
||||
var id = $('#abdm_drug_identifier').val() || '';
|
||||
var label = $('#abdm_drug_display').val() || '';
|
||||
var type = $('#abdm_drug_type').val() || '';
|
||||
var generic = $('#abdm_drug_generic').val() || '';
|
||||
var syncedAt = $('#abdm_drug_last_synced_at').val() || '';
|
||||
|
||||
if (!id && !label) {
|
||||
$('#abdm-drug-selected').html('');
|
||||
return;
|
||||
}
|
||||
|
||||
var parts = [];
|
||||
if (label) { parts.push(label); }
|
||||
if (generic) { parts.push('Generic: ' + generic); }
|
||||
if (type) { parts.push('Type: ' + type); }
|
||||
if (id) { parts.push('Identifier: ' + id); }
|
||||
if (syncedAt) { parts.push('Synced: ' + syncedAt); }
|
||||
|
||||
$('#abdm-drug-selected').text(parts.join(' | '));
|
||||
}
|
||||
|
||||
function clearSuggestionBox() {
|
||||
$('#abdm-drug-suggest').hide().empty();
|
||||
}
|
||||
|
||||
function applyDrugDetail(detail) {
|
||||
if (!detail || typeof detail !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
var label = detail.label || '';
|
||||
var generic = detail.generic_name || '';
|
||||
var hsnCode = detail.hsn_code || '';
|
||||
var formulation = detail.formulation || '';
|
||||
var packing = detail.packing || '';
|
||||
|
||||
if (label) {
|
||||
$('#input_item_name').val(label);
|
||||
$('#abdm_drug_display').val(label);
|
||||
}
|
||||
if (generic && !$('#input_genericname').val()) {
|
||||
$('#input_genericname').val(generic);
|
||||
}
|
||||
if (hsnCode && !$('#input_HSNCODE').val()) {
|
||||
$('#input_HSNCODE').val(hsnCode);
|
||||
}
|
||||
|
||||
if (formulation) {
|
||||
var $f = $('#input_formulation');
|
||||
var exists = $f.find('option').filter(function () {
|
||||
return String($(this).val()).toLowerCase() === String(formulation).toLowerCase();
|
||||
}).length > 0;
|
||||
if (exists) {
|
||||
$f.val(formulation);
|
||||
}
|
||||
}
|
||||
|
||||
if (packing && !$('#input_packing_type').val()) {
|
||||
$('#input_packing_type').val(packing);
|
||||
}
|
||||
|
||||
$('#abdm_drug_type').val(detail.type || '');
|
||||
$('#abdm_drug_identifier').val(detail.identifier || '');
|
||||
$('#abdm_drug_generic').val(generic);
|
||||
$('#abdm_drug_payload_json').val(detail.payload_json || '{}');
|
||||
$('#abdm_drug_last_synced_at').val(detail.synced_at || '');
|
||||
showSelectedDrugSummary();
|
||||
}
|
||||
|
||||
function fetchDrugDetail(type, identifier) {
|
||||
if (!identifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.getJSON('<?= base_url('product_master/drug_terminology_detail') ?>', {
|
||||
type: type || 'generic',
|
||||
identifier: identifier
|
||||
}, function (resp) {
|
||||
if (!resp || Number(resp.ok || 0) !== 1 || !resp.selected) {
|
||||
return;
|
||||
}
|
||||
applyDrugDetail(resp.selected);
|
||||
});
|
||||
}
|
||||
|
||||
function renderSuggestions(items) {
|
||||
var $box = $('#abdm-drug-suggest');
|
||||
$box.empty();
|
||||
|
||||
if (!Array.isArray(items) || items.length === 0) {
|
||||
clearSuggestionBox();
|
||||
return;
|
||||
}
|
||||
|
||||
items.forEach(function (item) {
|
||||
var label = item.label || '';
|
||||
var type = item.type || '';
|
||||
var identifier = item.identifier || '';
|
||||
if (!label && !identifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $a = $('<a href="#" class="list-group-item list-group-item-action py-1 px-2"></a>');
|
||||
$a.text(label + (type ? ' [' + type + ']' : '') + (identifier ? ' (' + identifier + ')' : ''));
|
||||
$a.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
clearSuggestionBox();
|
||||
if (label) {
|
||||
$('#input_item_name').val(label);
|
||||
}
|
||||
fetchDrugDetail(type, identifier);
|
||||
});
|
||||
$box.append($a);
|
||||
});
|
||||
|
||||
if ($box.children().length > 0) {
|
||||
$box.show();
|
||||
} else {
|
||||
clearSuggestionBox();
|
||||
}
|
||||
}
|
||||
|
||||
function fetchDrugSuggestions() {
|
||||
var q = ($('#input_item_name').val() || '').trim();
|
||||
var type = ($('#abdm_drug_search_type').val() || 'generic').trim();
|
||||
|
||||
if (q.length < 2) {
|
||||
clearSuggestionBox();
|
||||
return;
|
||||
}
|
||||
if (q === lastQuery) {
|
||||
return;
|
||||
}
|
||||
lastQuery = q;
|
||||
|
||||
$.getJSON('<?= base_url('product_master/drug_terminology_autocomplete') ?>', {
|
||||
q: q,
|
||||
type: type,
|
||||
limit: 10
|
||||
}, function (resp) {
|
||||
if (!resp || Number(resp.ok || 0) !== 1) {
|
||||
clearSuggestionBox();
|
||||
return;
|
||||
}
|
||||
renderSuggestions(resp.suggestions || []);
|
||||
}).fail(function () {
|
||||
clearSuggestionBox();
|
||||
});
|
||||
}
|
||||
|
||||
$('#input_item_name').off('input').on('input', function () {
|
||||
if (suggestTimer) {
|
||||
clearTimeout(suggestTimer);
|
||||
}
|
||||
suggestTimer = setTimeout(fetchDrugSuggestions, 250);
|
||||
});
|
||||
|
||||
$('#abdm_drug_search_type').off('change').on('change', function () {
|
||||
lastQuery = '';
|
||||
fetchDrugSuggestions();
|
||||
});
|
||||
|
||||
$(document).off('click.abdmDrug').on('click.abdmDrug', function (evt) {
|
||||
if (!$(evt.target).closest('#abdm-drug-suggest, #input_item_name').length) {
|
||||
clearSuggestionBox();
|
||||
}
|
||||
});
|
||||
|
||||
showSelectedDrugSummary();
|
||||
|
||||
$('#btn_update_stock').off('click').on('click', function () {
|
||||
$.post('<?= base_url('product_master/product_master_update') ?>/' + ($('#product_id').val() || '0'), $('#product-form').serialize(), function (data) {
|
||||
if (!data || typeof data !== 'object') {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user