57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
import unittest
|
|
from scripts.match_payments import reconcile
|
|
|
|
class TestReconcileWithExceptions(unittest.TestCase):
|
|
def test_reconcile_applies_exceptions(self):
|
|
# 1. Setup mock data
|
|
# Member: Alice, Tier A, expected 750 (attendance-based)
|
|
members = [
|
|
('Alice', 'A', {'2026-01': (750, 4)})
|
|
]
|
|
sorted_months = ['2026-01']
|
|
|
|
# Exception: Alice should only pay 400 in 2026-01 (normalized keys, no accents)
|
|
exceptions = {
|
|
('alice', '2026-01'): {'amount': 400, 'note': 'Test exception'}
|
|
}
|
|
|
|
# Transaction: Alice paid 400
|
|
transactions = [{
|
|
'date': '2026-01-05',
|
|
'amount': 400,
|
|
'person': 'Alice',
|
|
'purpose': '2026-01',
|
|
'inferred_amount': 400,
|
|
'sender': 'Alice Sender',
|
|
'message': 'fee'
|
|
}]
|
|
|
|
# 2. Reconcile
|
|
result = reconcile(members, sorted_months, transactions, exceptions)
|
|
|
|
# 3. Assertions
|
|
alice_data = result['members']['Alice']
|
|
jan_data = alice_data['months']['2026-01']
|
|
|
|
self.assertEqual(jan_data['expected'], 400, "Expected amount should be overridden by exception")
|
|
self.assertEqual(jan_data['paid'], 400, "Paid amount should be 400")
|
|
self.assertEqual(alice_data['total_balance'], 0, "Balance should be 0 because 400/400")
|
|
|
|
def test_reconcile_fallback_to_attendance(self):
|
|
# Alice has attendance-based fee 750, NO exception
|
|
members = [
|
|
('Alice', 'A', {'2026-01': (750, 4)})
|
|
]
|
|
sorted_months = ['2026-01']
|
|
exceptions = {} # No exceptions
|
|
|
|
transactions = []
|
|
|
|
result = reconcile(members, sorted_months, transactions, exceptions)
|
|
|
|
alice_data = result['members']['Alice']
|
|
self.assertEqual(alice_data['months']['2026-01']['expected'], 750, "Should fallback to attendance fee")
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|