fix: Payment inference returns only exact-name matches when present
match_members() now short-circuits on whole-word full-name hits and uses word-boundary regex everywhere else, so a nickname that is a substring of another member's surname (e.g. "tov" inside "ottova") no longer produces false positives. Adds tests/test_match_members.py. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
53
tests/test_match_members.py
Normal file
53
tests/test_match_members.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import unittest
|
||||
from scripts.match_payments import match_members
|
||||
|
||||
|
||||
MEMBERS = [
|
||||
"Henrietta Ottová",
|
||||
"Tomáš Němeček (Tov)",
|
||||
"František Vrbík (Štrúdl)",
|
||||
"Jana Nováková",
|
||||
]
|
||||
|
||||
|
||||
class TestMatchMembersExact(unittest.TestCase):
|
||||
def test_full_name_in_message_returns_only_that_member(self):
|
||||
# "tov" is a substring of "ottova" — the old code returned both members
|
||||
result = match_members("Henrietta Ottová (Heny): 04/2026", MEMBERS)
|
||||
names = [r[0] for r in result]
|
||||
self.assertEqual(names, ["Henrietta Ottová"])
|
||||
self.assertTrue(all(conf == "auto" for _, conf in result))
|
||||
|
||||
def test_nickname_tov_not_matched_inside_ottova(self):
|
||||
# Bare nickname message should NOT match Tomáš via "tov" inside "ottova"
|
||||
result = match_members("platba ottova 04/2026", MEMBERS)
|
||||
names = [r[0] for r in result]
|
||||
self.assertNotIn("Tomáš Němeček (Tov)", names)
|
||||
|
||||
def test_combined_payment_two_full_names(self):
|
||||
result = match_members("Henrietta Ottová a Tomáš Němeček 04/2026", MEMBERS)
|
||||
names = [r[0] for r in result]
|
||||
self.assertIn("Henrietta Ottová", names)
|
||||
self.assertIn("Tomáš Němeček (Tov)", names)
|
||||
self.assertTrue(all(conf == "auto" for _, conf in result))
|
||||
|
||||
def test_nickname_alone_still_matches_correctly(self):
|
||||
# "Tov" alone should still match Tomáš (as long as "ottova" is not in the text)
|
||||
result = match_members("Tov platba 04/2026", MEMBERS)
|
||||
names = [r[0] for r in result]
|
||||
self.assertIn("Tomáš Němeček (Tov)", names)
|
||||
|
||||
def test_full_name_no_diacritics_still_matches(self):
|
||||
result = match_members("Henrietta Ottova 04/2026", MEMBERS)
|
||||
names = [r[0] for r in result]
|
||||
self.assertIn("Henrietta Ottová", names)
|
||||
self.assertNotIn("Tomáš Němeček (Tov)", names)
|
||||
|
||||
def test_first_last_name_present_any_order(self):
|
||||
result = match_members("Platba od Nemeček Tomas 04/2026", MEMBERS)
|
||||
names = [r[0] for r in result]
|
||||
self.assertIn("Tomáš Němeček (Tov)", names)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user