feat: add document verification API views and core settings configurations
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 35s
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 35s
This commit is contained in:
parent
ddb5dd3aa1
commit
4e60430b73
1 changed files with 10 additions and 35 deletions
|
|
@ -41,45 +41,20 @@ def compare_names(name1: str, name2: str) -> dict:
|
|||
if norm1 == norm2:
|
||||
return {"matched": True, "score": 100.0, "reason": "Exact name match"}
|
||||
|
||||
# Strict 100% match requirement: names must match 100%
|
||||
# If spaces/delimiters differ, e.g. "VIGNESHKRISHNASAMY" vs "VIGNESH KRISHNASAMY"
|
||||
if "".join(norm1.split()) == "".join(norm2.split()):
|
||||
return {"matched": True, "score": 100.0, "reason": "Exact name match (case & whitespace insensitive)"}
|
||||
|
||||
# Any non-100% similarity is rejected as name mismatch
|
||||
words1, words2 = norm1.split(), norm2.split()
|
||||
# Reject complete first name mismatch (e.g. PRIYA SHARMA vs ROHIT SHARMA)
|
||||
if len(words1) >= 2 and len(words2) >= 2:
|
||||
if words1[0] != words2[0] and words1[-1] != words2[0] and words1[0] != words2[-1]:
|
||||
if len(words1[0]) >= 3 and len(words2[0]) >= 3:
|
||||
fn_sim = SequenceMatcher(None, words1[0], words2[0]).ratio()
|
||||
if fn_sim < 0.65:
|
||||
return {
|
||||
"matched": False,
|
||||
"score": round(fn_sim * 100, 1),
|
||||
"reason": f"First name mismatch ('{words1[0]}' vs '{words2[0]}')",
|
||||
}
|
||||
|
||||
set1, set2 = set(words1), set(words2)
|
||||
if set1 == set2:
|
||||
return {"matched": True, "score": 98.0, "reason": "Permuted words match"}
|
||||
|
||||
common = set1.intersection(set2)
|
||||
if len(common) == min(len(set1), len(set2)):
|
||||
return {"matched": True, "score": 95.0, "reason": "Subset token match"}
|
||||
|
||||
# Initial check (e.g. 'RAHUL K' vs 'RAHUL KUMAR' or 'V SANKAR' vs 'VIGNESH SANKAR')
|
||||
if len(words1) == len(words2):
|
||||
initial_match = True
|
||||
for w1, w2 in zip(words1, words2):
|
||||
if w1 != w2 and not (len(w1) == 1 and w2.startswith(w1)) and not (len(w2) == 1 and w1.startswith(w2)):
|
||||
initial_match = False
|
||||
break
|
||||
if initial_match:
|
||||
return {"matched": True, "score": 92.0, "reason": "Initials abbreviation match"}
|
||||
|
||||
sort_ratio = SequenceMatcher(None, " ".join(sorted(words1)), " ".join(sorted(words2))).ratio() * 100
|
||||
seq_ratio = SequenceMatcher(None, norm1, norm2).ratio() * 100
|
||||
best_score = max(sort_ratio, seq_ratio)
|
||||
matched = best_score >= 80.0
|
||||
sim_score = round(max(sort_ratio, seq_ratio), 1)
|
||||
return {
|
||||
"matched": matched,
|
||||
"score": round(best_score, 1),
|
||||
"reason": "Fuzzy token match" if matched else "Name similarity score below 80% threshold",
|
||||
"matched": False,
|
||||
"score": sim_score,
|
||||
"reason": f"Name match score is {sim_score}%. Strict 100% match is required.",
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue