Files
fuj-management/legacy/tests/test_match_payments.py
T
kacerrandClaude Opus 5.5 022facc957
Deploy to K8s / deploy (push) Successful in 20s
refactor: move Python implementation to legacy/, make Go primary
Go (go/) becomes the primary implementation. The original Python
version moves to legacy/ and is kept runnable; new features are still
built in both (see the Dual implementation rule in CLAUDE.md).

- git mv app.py, scripts/, templates/, tests/, pyproject.toml, uv.lock
  and build/ into legacy/
- Makefile: Python targets point at legacy/, venv in legacy/.venv,
  CREDENTIALS_PATH exported for the root .secret/ file
- CI and make image build the Python image with legacy/ as context;
  the Makefile is no longer copied into the image
- legacy/.dockerignore moved to the context root so it takes effect
- CLAUDE.md, docs/README.md, Go comments, fixture README, capture
  script and VS Code launch config updated to the new layout

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:33:57 +02:00

70 lines
2.6 KiB
Python

import unittest
from scripts.match_payments import canonical_member_key, reconcile
class TestCanonicalMemberKey(unittest.TestCase):
def test_diacritics_and_case_collapse(self):
self.assertEqual(canonical_member_key("Mária Maco"), "maria maco")
self.assertEqual(canonical_member_key("MARIA MACO"), "maria maco")
self.assertEqual(canonical_member_key("maria maco"), "maria maco")
def test_whitespace_runs_collapse(self):
self.assertEqual(canonical_member_key("Mária Maco"), "maria maco")
self.assertEqual(canonical_member_key(" Mária Maco "), "maria maco")
def test_unknown_name_passes_through_normalized(self):
# Two genuinely different names must not collide.
self.assertNotEqual(
canonical_member_key("Mária Maco"),
canonical_member_key("Marek Maco"),
)
class TestReconcileTolerantPersonMatching(unittest.TestCase):
def _members(self):
return [("Mária Maco", "A", {"2026-04": (750, 4)})]
def _tx(self, person):
return {
"date": "2026-04-15",
"amount": 750,
"person": person,
"purpose": "2026-04",
"inferred_amount": 750,
"sender": "Maco Family",
"message": "fee",
}
def test_person_without_diacritics_matches(self):
result = reconcile(self._members(), ["2026-04"], [self._tx("Maria Maco")], {})
member = result["members"]["Mária Maco"]
self.assertEqual(member["months"]["2026-04"]["paid"], 750)
self.assertEqual(len(member["months"]["2026-04"]["transactions"]), 1)
self.assertEqual(result["unmatched"], [])
def test_person_with_extra_whitespace_matches(self):
result = reconcile(self._members(), ["2026-04"], [self._tx("Mária Maco")], {})
self.assertEqual(result["members"]["Mária Maco"]["months"]["2026-04"]["paid"], 750)
self.assertEqual(result["unmatched"], [])
def test_person_lowercase_matches(self):
result = reconcile(self._members(), ["2026-04"], [self._tx("mária maco")], {})
self.assertEqual(result["members"]["Mária Maco"]["months"]["2026-04"]["paid"], 750)
self.assertEqual(result["unmatched"], [])
def test_truly_unknown_person_still_unmatched(self):
result = reconcile(
self._members(), ["2026-04"], [self._tx("Někdo Neznámý")], {}
)
self.assertEqual(result["members"]["Mária Maco"]["months"]["2026-04"]["paid"], 0)
self.assertEqual(len(result["unmatched"]), 1)
if __name__ == "__main__":
unittest.main()