feat(pharmacy): display full drug details with strength, formulation, and manufacturer in abdm search suggestions

This commit is contained in:
DevSoftTech Server 2026-10-27 01:35:50 +05:30
parent cf25a00ef5
commit 728eaea113
2 changed files with 111 additions and 66 deletions

View File

@ -6252,7 +6252,7 @@ class Medical extends BaseController
$limit = 10;
}
$cacheKey = 'abdm_drug_ac_' . md5($type . '_' . strtolower($q) . '_' . $limit);
$cacheKey = 'abdm_drug_ac_v2_' . md5($type . '_' . strtolower($q) . '_' . $limit);
$cached = cache($cacheKey);
if (is_array($cached) && ! empty($cached) && ($cached['ok'] ?? 0) === 1) {
return $this->response->setJSON($cached);
@ -6282,7 +6282,7 @@ class Medical extends BaseController
]);
$brandName = $this->extractDrugText($row, ['brand_name', 'trade_name']);
$label = $this->extractDrugText($row, [
'label', 'name', 'display', 'term', 'title', 'drug_name', 'product_name',
'label', 'display_name', 'name', 'display', 'term', 'title', 'drug_name', 'product_name',
'medicine_name', 'brand_name', 'trade_name',
]);
$identifier = $this->extractDrugText($row, ['identifier', 'id', 'code', 'concept_id', 'value']);
@ -6292,25 +6292,23 @@ class Medical extends BaseController
$itemType = $type;
}
if ($itemType === 'brand' && $brandName !== '') {
$label = $brandName;
}
if ($this->isDrugIdentifierLike($label) && $displayName !== '' && ! $this->isDrugIdentifierLike($displayName)) {
if ($displayName !== '') {
$label = $displayName;
} elseif ($brandName !== '') {
$label = $brandName;
} elseif ($label === '' || $this->isDrugIdentifierLike($label)) {
$label = $identifier;
}
if ($label === '' && $identifier === '') {
continue;
}
if ($label === '' && $displayName !== '') {
$label = $displayName;
}
if ($label === '') {
$label = $identifier;
}
$dosageForm = $this->extractDrugText($row, ['dosage_form', 'formulation', 'short_formulation', 'drug_form']);
$route = $this->extractDrugText($row, ['route', 'administration_route']);
$manufacturer = $this->extractDrugText($row, ['manufacturer_name', 'manufacturer', 'company_name', 'company']);
$strength = $this->extractDrugText($row, ['strength_text', 'strength']);
$packSize = $this->extractDrugText($row, ['pack_size_text', 'pack_size', 'package', 'packing']);
$suggestions[] = [
'label' => $label,
@ -6319,6 +6317,11 @@ class Medical extends BaseController
'generic_name' => $generic,
'identifier' => $identifier,
'type' => $itemType,
'dosage_form' => $dosageForm,
'route' => $route,
'manufacturer_name' => $manufacturer,
'strength_text' => $strength,
'pack_size_text' => $packSize,
];
}
@ -6351,7 +6354,7 @@ class Medical extends BaseController
]);
}
$cacheKey = 'abdm_drug_dt_' . md5($type . '_' . $identifier);
$cacheKey = 'abdm_drug_dt_v2_' . md5($type . '_' . $identifier);
$cached = cache($cacheKey);
if (is_array($cached) && ! empty($cached) && ($cached['ok'] ?? 0) === 1) {
return $this->response->setJSON($cached);
@ -6375,7 +6378,7 @@ class Medical extends BaseController
]);
$brandName = $this->extractDrugText($record, ['brand_name', 'trade_name']);
$label = $this->extractDrugText($record, [
'label', 'name', 'display', 'term', 'title', 'drug_name', 'product_name',
'label', 'display_name', 'name', 'display', 'term', 'title', 'drug_name', 'product_name',
'medicine_name', 'brand_name', 'trade_name',
]);
$generic = $this->extractDrugText($record, ['generic_name', 'genericname', 'generic', 'salt', 'molecule']);
@ -6392,17 +6395,11 @@ class Medical extends BaseController
$canonicalId = $identifier;
}
if ($itemType === 'brand' && $brandName !== '') {
if ($displayName !== '') {
$label = $displayName;
} elseif ($brandName !== '') {
$label = $brandName;
}
if ($this->isDrugIdentifierLike($label) && $displayName !== '' && ! $this->isDrugIdentifierLike($displayName)) {
$label = $displayName;
}
if ($label === '' && $displayName !== '') {
$label = $displayName;
}
if ($label === '') {
} elseif ($label === '' || $this->isDrugIdentifierLike($label)) {
$label = $canonicalId;
}

View File

@ -553,16 +553,26 @@ window.closeDrugMasterSubView = window.closeDrugMasterSubView || function () {
after = normalizeSpace(m[3]);
}
if (before) {
result.productName = before;
}
var formRegex = /\b(tablet|capsule|syrup|suspension|injection|cream|ointment|gel|drops?|solution|powder|lotion|spray|respules?|inhaler|patch|suppository|lozenge|granules?)\b/i;
var formRegex = /\b(tablet|capsule|syrup|suspension|injection|cream|ointment|gel|drops?|solution\s+for\s+(?:infusion|injection)|solution|powder|lotion|spray|respules?|inhaler|patch|suppository|lozenge|granules?)\b/i;
var formMatch = formRegex.exec(after || label);
if (formMatch) {
result.formulation = normalizeSpace(formMatch[1]);
}
if (before) {
var cleanAfter = after ? normalizeSpace(after.replace(/\b(oral|route|for\s+oral\s+use)\b/gi, '')) : '';
if (result.formulation && cleanAfter) {
var reForm = new RegExp('\\b' + result.formulation.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + '\\b', 'i');
var capForm = result.formulation.charAt(0).toUpperCase() + result.formulation.slice(1);
cleanAfter = cleanAfter.replace(reForm, capForm);
}
if (cleanAfter) {
result.productName = normalizeSpace(before + ' ' + cleanAfter);
} else {
result.productName = before;
}
}
if (inside) {
var genericTail = after;
if (formMatch && after) {
@ -708,25 +718,25 @@ window.closeDrugMasterSubView = window.closeDrugMasterSubView || function () {
}
function deriveDrugName(detail, parsed) {
var productName = normalizeSpace(parsed && parsed.productName ? parsed.productName : '');
var displayName = normalizeSpace(detail.display_name || '');
var label = normalizeSpace(detail.label || '');
var brandName = normalizeSpace(detail.brand_name || '');
var manufacturerName = normalizeSpace(detail.manufacturer_name || '');
var label = normalizeSpace(detail.label || '');
var displayName = normalizeSpace(detail.display_name || '');
var productName = normalizeSpace(parsed && parsed.productName ? parsed.productName : '');
if (brandName) {
return brandName;
if (productName && !isIdentifierLike(productName)) {
return productName;
}
if (manufacturerName && !isIdentifierLike(manufacturerName)) {
return manufacturerName;
if (displayName && !isIdentifierLike(displayName)) {
return displayName;
}
if (label && !isIdentifierLike(label)) {
return label;
}
if (displayName && !isIdentifierLike(displayName)) {
return parsed && parsed.productName ? productName : displayName;
if (brandName && !isIdentifierLike(brandName)) {
return brandName;
}
return productName || displayName || label;
return productName || displayName || label || '';
}
function deriveGenericName(detail, parsed, flatMeta) {
@ -1100,28 +1110,43 @@ window.closeDrugMasterSubView = window.closeDrugMasterSubView || function () {
var genericName = item.generic_name || '';
var type = item.type || '';
var identifier = item.identifier || '';
var dosageForm = item.dosage_form || '';
var manufacturerName = item.manufacturer_name || '';
clearSuggestionBox();
// Apply parsed fields immediately so user sees direct form fill.
applyParsedLabelToForm(label);
// Use the rich displayName (contains brand, generic, strength, route, and formulation)
var richLabel = displayName || label;
var parsed = parseDrugLabel(richLabel);
if (type === 'brand' && brandName && !isIdentifierLike(brandName)) {
$('#input_item_name').val(brandName);
} else if (displayName && !isIdentifierLike(displayName)) {
$('#input_item_name').val(displayName);
// Derive clean product name (e.g. "Dolo 650 mg Tablet")
var derivedName = parsed.productName || brandName || richLabel;
if (derivedName && !isIdentifierLike(derivedName)) {
$('#input_item_name').val(derivedName);
}
if (genericName) {
if (parsed.genericName) {
$('#input_genericname').val(parsed.genericName);
} else if (genericName) {
$('#input_genericname').val(genericName);
}
if (parsed.formulation) {
setFormulationValue(parsed.formulation);
setFormulationByCode(parsed.formulation);
} else if (dosageForm) {
setFormulationValue(dosageForm);
setFormulationByCode(dosageForm);
}
if (manufacturerName) {
setCompanyByName(manufacturerName);
}
$('#abdm_drug_display').val((type === 'brand' && brandName) ? brandName : label);
$('#abdm_drug_display').val(richLabel);
$('#abdm_drug_type').val(type);
$('#abdm_drug_identifier').val(identifier);
$('#abdm_drug_last_synced_at').val(new Date().toISOString().slice(0, 19).replace('T', ' '));
showSelectedDrugSummary();
// Fetch canonical details for richer metadata autofill.
// Fetch canonical details for richer metadata autofill (company code, HSN, tax, schedules, etc.)
fetchDrugDetail(type, identifier);
}
@ -1144,24 +1169,47 @@ window.closeDrugMasterSubView = window.closeDrugMasterSubView || function () {
var genericName = item.generic_name || '';
var type = item.type || '';
var identifier = item.identifier || '';
if (!label && !identifier) {
var dosageForm = item.dosage_form || '';
var manufacturerName = item.manufacturer_name || '';
var strengthText = item.strength_text || '';
if (!label && !identifier && !displayName) {
return;
}
var $a = $('<a href="#" class="list-group-item list-group-item-action py-1 px-2"></a>');
var fullTitle = displayName || label || brandName || identifier;
var $a = $('<a href="#" class="list-group-item list-group-item-action py-2 px-3 border-bottom"></a>');
$a.attr('data-idx', String(idx));
var mainText = (type === 'brand' ? (brandName || label) : '') || displayName || label || identifier;
var detailParts = [];
if (genericName && genericName.toLowerCase() !== String(mainText).toLowerCase()) {
detailParts.push('Generic: ' + genericName);
if (genericName) {
detailParts.push('Generic: <strong>' + $('<div>').text(genericName).html() + '</strong>');
}
if (type) {
detailParts.push('Type: ' + type);
if (dosageForm) {
detailParts.push('Form: ' + $('<div>').text(dosageForm).html());
}
if (identifier && identifier !== mainText) {
detailParts.push('ID: ' + identifier);
if (strengthText) {
detailParts.push('Strength: ' + $('<div>').text(strengthText).html());
}
$a.text(mainText + (detailParts.length ? ' | ' + detailParts.join(' | ') : ''));
if (identifier) {
detailParts.push('CDCI ID: ' + $('<div>').text(identifier).html());
}
var html = '<div class="d-flex justify-content-between align-items-center mb-1">'
+ ' <div class="fw-bold text-primary" style="font-size: 0.95rem;">' + $('<div>').text(fullTitle).html() + '</div>';
if (manufacturerName) {
html += ' <span class="badge bg-secondary text-white ms-2 text-truncate" style="max-width: 200px;" title="' + $('<div>').text(manufacturerName).html() + '">'
+ $('<div>').text(manufacturerName).html()
+ ' </span>';
}
html += '</div>';
if (detailParts.length) {
html += '<div class="text-muted small">' + detailParts.join(' &nbsp;|&nbsp; ') + '</div>';
}
$a.html(html);
$a.on('click', function (e) {
e.preventDefault();
chooseSuggestion(idx);