Make OPD medicine duplicate detection strength-aware
This commit is contained in:
parent
779dbcbaa1
commit
3cef35c832
|
|
@ -69,6 +69,61 @@ class OpdMedicineModel
|
||||||
return trim($name);
|
return trim($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract strength tokens so near-identical brands with different strengths
|
||||||
|
* (e.g. 20 MG vs 40 MG) are not treated as duplicates.
|
||||||
|
*/
|
||||||
|
private function extractStrengthSignature(string $name, string $formulation = ''): string
|
||||||
|
{
|
||||||
|
$source = trim($name . ' ' . $formulation);
|
||||||
|
if ($source === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$source = mb_strtolower($source);
|
||||||
|
$source = preg_replace('/[\(\)\[\],\/\-]+/', ' ', $source) ?? $source;
|
||||||
|
$source = preg_replace('/\s+/', ' ', $source) ?? $source;
|
||||||
|
|
||||||
|
preg_match_all('/\b(\d+(?:\.\d+)?)\s*(mcg|mg|g|kg|ml|l|iu|units|meq|mmol)?\b/i', $source, $matches, PREG_SET_ORDER);
|
||||||
|
if (empty($matches)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens = [];
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
$number = trim((string) ($match[1] ?? ''));
|
||||||
|
if ($number === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$unit = strtolower(trim((string) ($match[2] ?? '')));
|
||||||
|
$tokens[] = $number . ($unit !== '' ? $unit : 'n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($tokens)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens = array_values(array_unique($tokens));
|
||||||
|
sort($tokens, SORT_NATURAL);
|
||||||
|
|
||||||
|
return implode('|', $tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildDuplicateKey(string $name, string $formulation = ''): string
|
||||||
|
{
|
||||||
|
$base = $this->normalizeMedicineNameFuzzy($name);
|
||||||
|
if ($base === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$strength = $this->extractStrengthSignature($name, $formulation);
|
||||||
|
if ($strength === '') {
|
||||||
|
return $base;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $base . '::' . $strength;
|
||||||
|
}
|
||||||
|
|
||||||
public function findDuplicateByName(string $itemName, int $excludeId = 0): ?array
|
public function findDuplicateByName(string $itemName, int $excludeId = 0): ?array
|
||||||
{
|
{
|
||||||
if (! $this->tableExists()) {
|
if (! $this->tableExists()) {
|
||||||
|
|
@ -81,7 +136,7 @@ class OpdMedicineModel
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
|
||||||
$needle = $this->normalizeMedicineNameFuzzy($itemName);
|
$needle = $this->buildDuplicateKey($itemName, '');
|
||||||
if ($needle === '') {
|
if ($needle === '') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +147,7 @@ class OpdMedicineModel
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$current = $this->normalizeMedicineNameFuzzy((string) ($row['item_name'] ?? ''));
|
$current = $this->buildDuplicateKey((string) ($row['item_name'] ?? ''), (string) ($row['formulation'] ?? ''));
|
||||||
if ($current !== '' && $current === $needle) {
|
if ($current !== '' && $current === $needle) {
|
||||||
return $row;
|
return $row;
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +170,7 @@ class OpdMedicineModel
|
||||||
|
|
||||||
$groups = [];
|
$groups = [];
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
$norm = $this->normalizeMedicineNameFuzzy((string) ($row['item_name'] ?? ''));
|
$norm = $this->buildDuplicateKey((string) ($row['item_name'] ?? ''), (string) ($row['formulation'] ?? ''));
|
||||||
if ($norm === '') {
|
if ($norm === '') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user