Pharmacy product edit: smarter medicine autofill from ABDM label/detail
This commit is contained in:
parent
0558ac5a2e
commit
e221581578
|
|
@ -208,6 +208,228 @@ $flag = static function ($v): string {
|
|||
$('#abdm-drug-suggest').hide().empty();
|
||||
}
|
||||
|
||||
function normalizeSpace(text) {
|
||||
return String(text || '').replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
|
||||
function parseDrugLabel(rawLabel) {
|
||||
var label = normalizeSpace(rawLabel);
|
||||
var result = {
|
||||
productName: label,
|
||||
genericName: '',
|
||||
formulation: ''
|
||||
};
|
||||
|
||||
if (!label) {
|
||||
return result;
|
||||
}
|
||||
|
||||
var before = '';
|
||||
var inside = '';
|
||||
var after = '';
|
||||
var m = label.match(/^([^()]+?)\s*\(([^)]+)\)\s*(.*)$/);
|
||||
if (m) {
|
||||
before = normalizeSpace(m[1]);
|
||||
inside = normalizeSpace(m[2]);
|
||||
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 formMatch = formRegex.exec(after || label);
|
||||
if (formMatch) {
|
||||
result.formulation = normalizeSpace(formMatch[1]);
|
||||
}
|
||||
|
||||
if (inside) {
|
||||
var genericTail = after;
|
||||
if (formMatch && after) {
|
||||
genericTail = normalizeSpace(after.substring(0, formMatch.index));
|
||||
}
|
||||
// Remove common dosage-route filler just before formulation.
|
||||
genericTail = normalizeSpace(genericTail.replace(/\b(oral|route|for\s+oral\s+use)\b/gi, ''));
|
||||
result.genericName = normalizeSpace((inside + ' ' + genericTail).trim());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseJsonObject(text) {
|
||||
if (!text) {
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
var obj = JSON.parse(String(text));
|
||||
return (obj && typeof obj === 'object') ? obj : {};
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function flattenMeta(input, out) {
|
||||
if (!input || typeof input !== 'object') {
|
||||
return out;
|
||||
}
|
||||
|
||||
Object.keys(input).forEach(function (key) {
|
||||
var value = input[key];
|
||||
var k = String(key || '').toLowerCase();
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (value.length && (typeof value[0] === 'string' || typeof value[0] === 'number' || typeof value[0] === 'boolean')) {
|
||||
out[k] = value.map(String).join(', ');
|
||||
}
|
||||
value.forEach(function (child) {
|
||||
if (child && typeof child === 'object') {
|
||||
flattenMeta(child, out);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
flattenMeta(value, out);
|
||||
return;
|
||||
}
|
||||
|
||||
out[k] = String(value).trim();
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function getMetaText(meta, keys) {
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = String(keys[i] || '').toLowerCase();
|
||||
var value = normalizeSpace(meta[key] || '');
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getMetaNumber(meta, keys) {
|
||||
var raw = getMetaText(meta, keys);
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
var num = parseFloat(String(raw).replace(/[^0-9.\-]/g, ''));
|
||||
return isNaN(num) ? null : num;
|
||||
}
|
||||
|
||||
function hasMetaKey(meta, keys) {
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (Object.prototype.hasOwnProperty.call(meta, String(keys[i] || '').toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getMetaBool(meta, keys) {
|
||||
var raw = getMetaText(meta, keys).toLowerCase();
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
if (['1', 'true', 'yes', 'y', 'on'].indexOf(raw) >= 0) {
|
||||
return true;
|
||||
}
|
||||
if (['0', 'false', 'no', 'n', 'off'].indexOf(raw) >= 0) {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function setFormulationValue(formulation) {
|
||||
var value = normalizeSpace(formulation).toLowerCase();
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
var $f = $('#input_formulation');
|
||||
var matchedVal = '';
|
||||
$f.find('option').each(function () {
|
||||
var v = normalizeSpace($(this).val()).toLowerCase();
|
||||
var t = normalizeSpace($(this).text()).toLowerCase();
|
||||
if (v === value || t === value || v.indexOf(value) >= 0 || t.indexOf(value) >= 0 || value.indexOf(v) >= 0 || value.indexOf(t) >= 0) {
|
||||
matchedVal = $(this).val();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (matchedVal !== '') {
|
||||
$f.val(matchedVal);
|
||||
}
|
||||
}
|
||||
|
||||
function setCompanyByName(companyName) {
|
||||
var needle = normalizeSpace(companyName).toLowerCase();
|
||||
if (!needle) {
|
||||
return;
|
||||
}
|
||||
var $c = $('#input_company_name');
|
||||
var matchedVal = '';
|
||||
$c.find('option').each(function () {
|
||||
var text = normalizeSpace($(this).text()).toLowerCase();
|
||||
if (!text || text === 'select') {
|
||||
return;
|
||||
}
|
||||
if (text === needle || text.indexOf(needle) >= 0 || needle.indexOf(text) >= 0) {
|
||||
matchedVal = $(this).val();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (matchedVal !== '') {
|
||||
$c.val(matchedVal);
|
||||
}
|
||||
}
|
||||
|
||||
function setCategoryByName(categoryText) {
|
||||
var raw = normalizeSpace(categoryText);
|
||||
if (!raw) {
|
||||
return;
|
||||
}
|
||||
var tokens = raw.split(/[|,;/]+/).map(function (x) { return normalizeSpace(x).toLowerCase(); }).filter(Boolean);
|
||||
if (!tokens.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var selected = [];
|
||||
$('#med_cat_id option').each(function () {
|
||||
var text = normalizeSpace($(this).text()).toLowerCase();
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
var matched = tokens.some(function (t) {
|
||||
return text === t || text.indexOf(t) >= 0 || t.indexOf(text) >= 0;
|
||||
});
|
||||
if (matched) {
|
||||
selected.push($(this).val());
|
||||
}
|
||||
});
|
||||
|
||||
if (selected.length) {
|
||||
$('#med_cat_id').val(selected).trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
function setCheckboxFromMeta(selector, meta, keys) {
|
||||
if (!hasMetaKey(meta, keys)) {
|
||||
return;
|
||||
}
|
||||
var boolVal = getMetaBool(meta, keys);
|
||||
if (boolVal === null) {
|
||||
return;
|
||||
}
|
||||
$(selector).prop('checked', !!boolVal);
|
||||
}
|
||||
|
||||
function applyDrugDetail(detail) {
|
||||
if (!detail || typeof detail !== 'object') {
|
||||
return;
|
||||
|
|
@ -219,34 +441,98 @@ $flag = static function ($v): string {
|
|||
var formulation = detail.formulation || '';
|
||||
var packing = detail.packing || '';
|
||||
|
||||
if (label) {
|
||||
$('#input_item_name').val(label);
|
||||
$('#abdm_drug_display').val(label);
|
||||
var parsed = parseDrugLabel(label);
|
||||
var payloadObj = parseJsonObject(detail.payload_json || '{}');
|
||||
var flatMeta = flattenMeta(payloadObj, {});
|
||||
|
||||
var metaGeneric = getMetaText(flatMeta, ['generic_name', 'genericname', 'generic', 'salt', 'molecule', 'composition']);
|
||||
var metaCompany = getMetaText(flatMeta, ['company', 'manufacturer', 'brand_owner', 'marketer']);
|
||||
var metaCategory = getMetaText(flatMeta, ['medicine_category', 'category', 'drug_category', 'schedule_category']);
|
||||
var metaFormulation = getMetaText(flatMeta, ['formulation', 'dosage_form', 'drug_form']);
|
||||
var metaPacking = getMetaText(flatMeta, ['packing', 'pack_size', 'package']);
|
||||
var metaHsn = getMetaText(flatMeta, ['hsn_code', 'hsn', 'hscode']);
|
||||
|
||||
var cgstVal = getMetaNumber(flatMeta, ['cgst', 'cgst_per', 'cgst_percent']);
|
||||
var sgstVal = getMetaNumber(flatMeta, ['sgst', 'sgst_per', 'sgst_percent']);
|
||||
var gstTotal = getMetaNumber(flatMeta, ['gst', 'gst_per', 'gst_percent', 'igst', 'tax_percent']);
|
||||
|
||||
var finalProductName = normalizeSpace(parsed.productName || label);
|
||||
var finalGeneric = normalizeSpace(generic || metaGeneric || parsed.genericName);
|
||||
var finalFormulation = normalizeSpace(formulation || metaFormulation || parsed.formulation);
|
||||
var finalPacking = normalizeSpace(packing || metaPacking);
|
||||
var finalHsn = normalizeSpace(hsnCode || metaHsn);
|
||||
|
||||
if (finalProductName) {
|
||||
$('#input_item_name').val(finalProductName);
|
||||
}
|
||||
if (generic && !$('#input_genericname').val()) {
|
||||
$('#input_genericname').val(generic);
|
||||
if (finalGeneric) {
|
||||
$('#input_genericname').val(finalGeneric);
|
||||
}
|
||||
if (hsnCode && !$('#input_HSNCODE').val()) {
|
||||
$('#input_HSNCODE').val(hsnCode);
|
||||
if (finalHsn) {
|
||||
$('#input_HSNCODE').val(finalHsn);
|
||||
}
|
||||
if (finalFormulation) {
|
||||
setFormulationValue(finalFormulation);
|
||||
}
|
||||
if (finalPacking && !$('#input_packing_type').val()) {
|
||||
$('#input_packing_type').val(finalPacking);
|
||||
}
|
||||
|
||||
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 (metaCompany) {
|
||||
setCompanyByName(metaCompany);
|
||||
}
|
||||
if (metaCategory) {
|
||||
setCategoryByName(metaCategory);
|
||||
}
|
||||
|
||||
if (cgstVal !== null) {
|
||||
$('#input_CGST').val(cgstVal.toFixed(2).replace(/\.00$/, ''));
|
||||
}
|
||||
if (sgstVal !== null) {
|
||||
$('#input_SGST').val(sgstVal.toFixed(2).replace(/\.00$/, ''));
|
||||
}
|
||||
if (gstTotal !== null && (cgstVal === null || sgstVal === null)) {
|
||||
var half = (gstTotal / 2);
|
||||
if (cgstVal === null) {
|
||||
$('#input_CGST').val(half.toFixed(2).replace(/\.00$/, ''));
|
||||
}
|
||||
if (sgstVal === null) {
|
||||
$('#input_SGST').val(half.toFixed(2).replace(/\.00$/, ''));
|
||||
}
|
||||
}
|
||||
|
||||
if (packing && !$('#input_packing_type').val()) {
|
||||
$('#input_packing_type').val(packing);
|
||||
setCheckboxFromMeta('#chk_batch_applicable', flatMeta, ['batch_applicable', 'batch_required']);
|
||||
setCheckboxFromMeta('#chk_exp_date_applicable', flatMeta, ['exp_date_applicable', 'expiry_applicable']);
|
||||
setCheckboxFromMeta('#chk_is_continue', flatMeta, ['is_continue', 'is_continued']);
|
||||
setCheckboxFromMeta('#chk_narcotic', flatMeta, ['narcotic']);
|
||||
setCheckboxFromMeta('#chk_schedule_h', flatMeta, ['schedule_h']);
|
||||
setCheckboxFromMeta('#chk_schedule_h1', flatMeta, ['schedule_h1']);
|
||||
setCheckboxFromMeta('#chk_schedule_x', flatMeta, ['schedule_x']);
|
||||
setCheckboxFromMeta('#chk_schedule_g', flatMeta, ['schedule_g']);
|
||||
setCheckboxFromMeta('#chk_high_risk', flatMeta, ['high_risk']);
|
||||
|
||||
var scheduleRaw = getMetaText(flatMeta, ['schedule', 'schedule_type']);
|
||||
if (scheduleRaw) {
|
||||
var s = scheduleRaw.toUpperCase();
|
||||
if (s.indexOf('H1') >= 0) {
|
||||
$('#chk_schedule_h1').prop('checked', true);
|
||||
}
|
||||
if (s.indexOf('H') >= 0) {
|
||||
$('#chk_schedule_h').prop('checked', true);
|
||||
}
|
||||
if (s.indexOf('X') >= 0) {
|
||||
$('#chk_schedule_x').prop('checked', true);
|
||||
}
|
||||
if (s.indexOf('G') >= 0) {
|
||||
$('#chk_schedule_g').prop('checked', true);
|
||||
}
|
||||
}
|
||||
|
||||
$('#abdm_drug_display').val(label || finalProductName);
|
||||
|
||||
$('#abdm_drug_type').val(detail.type || '');
|
||||
$('#abdm_drug_identifier').val(detail.identifier || '');
|
||||
$('#abdm_drug_generic').val(generic);
|
||||
$('#abdm_drug_generic').val(finalGeneric);
|
||||
$('#abdm_drug_payload_json').val(detail.payload_json || '{}');
|
||||
$('#abdm_drug_last_synced_at').val(detail.synced_at || '');
|
||||
showSelectedDrugSummary();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user