From e68c8c310b988880290736882737c854db0c279f Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Sun, 5 Apr 2020 10:58:28 -0300 Subject: [PATCH] Support no first payment when checking for debts. Fixes #174. --- website/members/logic.py | 30 +++++++++++++++-------- website/members/tests.py | 53 ++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/website/members/logic.py b/website/members/logic.py index e8ff508..e72e4cf 100644 --- a/website/members/logic.py +++ b/website/members/logic.py @@ -133,22 +133,32 @@ def create_recurring_payments(recurring_records): def get_debt_state(member, limit_year, limit_month): """Return if the member is in debt, and the missing quotas. - The quotas verified are from first payment up to the given year/month limit (including). + If the member has a first payment, the quotas verified are from that first payment up + to the given year/month limit (including). + + If the member never paid, the registration date is used, and that month is also included. """ + if member.first_payment_year is None: + # never paid! using registration date to start with + yearmonths_paid = set() + year_to_check = member.registration_date.year + month_to_check = member.registration_date.month + else: + # build a set for the year/month of paid quotas + quotas = Quota.objects.filter(member=member).all() + yearmonths_paid = {(q.year, q.month) for q in quotas} + + year_to_check = member.first_payment_year + month_to_check = member.first_payment_month + # verify the limit is after member started paying - if member.first_payment_year == limit_year: - if member.first_payment_month > limit_month: + if year_to_check == limit_year: + if month_to_check > limit_month: return [] - elif member.first_payment_year > limit_year: + elif year_to_check > limit_year: return [] - # build a set for the year/month of paid quotas - quotas = Quota.objects.filter(member=member).all() - yearmonths_paid = {(q.year, q.month) for q in quotas} - # build a set of all the year/month the member should have paid up to (including) the limit - year_to_check = member.first_payment_year - month_to_check = member.first_payment_month should_have_paid = set() while True: should_have_paid.add((year_to_check, month_to_check)) diff --git a/website/members/tests.py b/website/members/tests.py index 96c3c41..e3316b6 100644 --- a/website/members/tests.py +++ b/website/members/tests.py @@ -12,8 +12,15 @@ from members import logic, views from members.models import ( - Member, Patron, Category, PaymentStrategy, Quota, Person, - Organization, Payment) + Category, + Member, + Organization, + Patron, + Payment, + PaymentStrategy, + Person, + Quota, +) from .factories import ( PatronFactory, QuotaFactory, @@ -34,14 +41,15 @@ def create_category(): return category -def create_member(first_payment_year=None, first_payment_month=None, patron=None): +def create_member( + first_payment_year=None, first_payment_month=None, patron=None, registration_date=None): """Create a testing Member.""" - first_payment_year = first_payment_year or 2017 - first_payment_month = first_payment_month or 5 + first_payment_year = first_payment_year + first_payment_month = first_payment_month category = create_category() return Member.objects.create( first_payment_year=first_payment_year, first_payment_month=first_payment_month, - category=category, patron=patron) + category=category, patron=patron, registration_date=registration_date) def create_patron(email=None): @@ -215,7 +223,7 @@ class CreatePaymentTestCase(TestCase): def test_first_payment(self): # needed objects - member = create_member() + member = create_member(first_payment_year=2017, first_payment_month=5) ps = create_payment_strategy() # create the payment @@ -295,7 +303,7 @@ def test_crossing_years(self): def test_not_exact_amount_small(self): # needed objects - member = create_member() + member = create_member(first_payment_year=2017, first_payment_month=5) ps = create_payment_strategy() # create the payment @@ -346,7 +354,7 @@ def test_simple_empty(self): # needed objects payer_id = 'test@example.com' ps = create_payment_strategy(platform=PaymentStrategy.MERCADO_PAGO, payer_id=payer_id) - member = create_member(patron=ps.patron) + member = create_member(patron=ps.patron, first_payment_year=2017, first_payment_month=5) # create the payment tstamp = make_aware(datetime.datetime(year=2017, month=2, day=5)) @@ -366,7 +374,7 @@ def test_simple_previous_payments(self): # needed objects payer_id = 'test@example.com' ps = create_payment_strategy(platform=PaymentStrategy.MERCADO_PAGO, payer_id=payer_id) - member = create_member(patron=ps.patron) + member = create_member(patron=ps.patron, first_payment_year=2017, first_payment_month=5) # create three payments in different timestamps tstamp1 = make_aware(datetime.datetime(year=2017, month=2, day=5)) @@ -399,7 +407,7 @@ def test_simple_everything_previous(self): # needed objects payer_id = 'test@example.com' ps = create_payment_strategy(platform=PaymentStrategy.MERCADO_PAGO, payer_id=payer_id) - create_member(patron=ps.patron) + create_member(patron=ps.patron, first_payment_year=2017, first_payment_month=5) # create two payments in different timestamps tstamp1 = make_aware(datetime.datetime(year=2017, month=2, day=5)) @@ -427,9 +435,9 @@ def test_multiple_payers(self): payer_id1 = 'test@example.com' payer_id2 = 'other@example.com' ps = create_payment_strategy(platform=PaymentStrategy.MERCADO_PAGO, payer_id=payer_id1) - member1 = create_member(patron=ps.patron) + member1 = create_member(patron=ps.patron, first_payment_year=2017, first_payment_month=5) ps = create_payment_strategy(platform=PaymentStrategy.MERCADO_PAGO, payer_id=payer_id2) - member2 = create_member(patron=ps.patron) + member2 = create_member(patron=ps.patron, first_payment_year=2017, first_payment_month=5) # create the payment tstampA = make_aware(datetime.datetime(year=2017, month=2, day=5)) @@ -497,7 +505,7 @@ def test_no_payment_match(self): # needed objects payer_id = 'test@example.com' ps = create_payment_strategy(platform=PaymentStrategy.MERCADO_PAGO, payer_id=payer_id) - create_member(patron=ps.patron) + create_member(patron=ps.patron, first_payment_year=2017, first_payment_month=5) # create two payments in different timestamps tstamp1 = make_aware(datetime.datetime(year=2017, month=2, day=1)) @@ -588,6 +596,21 @@ def test_multiyear(self): (2019, 7), (2019, 8), (2019, 9), (2019, 10), (2019, 11), (2019, 12), (2020, 1), (2020, 2)]) + def test_no_payment_yet_previous_month(self): + member = create_member(registration_date=datetime.date(2017, 5, 13)) + debt = logic.get_debt_state(member, 2017, 1) + self.assertEqual(debt, []) + + def test_no_payment_yet_registration_month(self): + member = create_member(registration_date=datetime.date(2017, 5, 13)) + debt = logic.get_debt_state(member, 2017, 5) + self.assertEqual(debt, [(2017, 5)]) + + def test_no_payment_yet_several_months(self): + member = create_member(registration_date=datetime.date(2017, 5, 13)) + debt = logic.get_debt_state(member, 2017, 8) + self.assertEqual(debt, [(2017, 5), (2017, 6), (2017, 7), (2017, 8)]) + class BuildDebtStringTestCase(TestCase): """Tests for the string debt building utility.""" @@ -645,7 +668,7 @@ def test_get_members_list_page(self): self.assertTemplateUsed(response, 'members/members_list.html') def test_get_member_detail_page(self): - member = create_member() + member = create_member(first_payment_year=2017, first_payment_month=5) response = self.client.get(reverse('member_detail', kwargs={"pk": member.pk})) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'members/member_detail.html')