feat(pharmacy): display full drug details with strength, formulation, and manufacturer in abdm search suggestions
This commit is contained in:
parent
cf25a00ef5
commit
728eaea113
|
|
@ -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,33 +6292,36 @@ 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,
|
||||
'display_name' => $displayName,
|
||||
'brand_name' => $brandName,
|
||||
'generic_name' => $generic,
|
||||
'identifier' => $identifier,
|
||||
'type' => $itemType,
|
||||
'label' => $label,
|
||||
'display_name' => $displayName,
|
||||
'brand_name' => $brandName,
|
||||
'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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(' | ') + '</div>';
|
||||
}
|
||||
|
||||
$a.html(html);
|
||||
$a.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
chooseSuggestion(idx);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user