Example #1
0
    def test_free_membership(self):
        self.user_membership.begins_at = session.utcnow().replace(
            day=self.membership_fee_current.booking_end.days + 1)

        end_date = last_day_of_month(session.utcnow().date())

        self.assertEquals(0.00, estimate_balance(self.user, end_date))
Example #2
0
def estimate_balance(session: Session, user, end_date):
    """Estimate the balance a user account will have at :paramref:`end_date`.

    :param session:
    :param user: The member
    :param end_date: Date of the end of the membership
    :return: Estimated balance at the end_date
    """

    now = utcnow().date()

    # Use tomorrow in case that it is the last of the month, the fee for the
    # current month will be added later
    tomorrow = now + timedelta(1)

    last_fee = session.scalars(
        select(MembershipFee).order_by(MembershipFee.ends_on.desc()).limit(1)
    ).first()

    if last_fee is None:
        raise ValueError("no fee information available")

    # Bring end_date to previous month if the end_date is in grace period
    end_date_justified = end_date - timedelta(last_fee.booking_begin.days - 1)

    months_to_pay = diff_month(end_date_justified, tomorrow)

    # If the user has to pay a fee for the current month
    has_to_pay_this_month = user.has_property(
        'membership_fee',
        tomorrow.replace(day=last_fee.booking_end.days)
    )
    if has_to_pay_this_month:
        months_to_pay += 1

    # If there was no fee booked yet for the last month and the user has to pay
    # a fee for the last month, increment months_to_pay
    last_month_last = tomorrow.replace(day=1) - timedelta(1)
    last_month_fee_outstanding = (
        fee_from_valid_date(session, last_month_last, user.account) is None
    )

    if last_month_fee_outstanding:
        had_to_pay_last_month = user.has_property(
            'membership_fee',
            last_month_last.replace(day=last_fee.booking_end.days)
        )
        if had_to_pay_last_month:
            months_to_pay += 1

    # If there is already a fee booked for this month, decrement months_to_pay
    this_month_fee_outstanding = (
        fee_from_valid_date(session, last_day_of_month(tomorrow), user.account) is None
    )
    if not this_month_fee_outstanding:
        months_to_pay -= 1

    return (-user.account.balance) - (months_to_pay * last_fee.regular_fee)
Example #3
0
 def test_last_date_of_month(self):
     for (d, expected) in [
         (date(2019, 9, 1), 30),
         (date(2019, 8, 1), 31),
         (date(2019, 2, 1), 28),
         (date(2016, 2, 1), 29),
     ]:
         with self.subTest(date=d, expected=expected):
             self.assertEqual(last_day_of_month(d),
                              d.replace(day=expected))
Example #4
0
class MembershipFeeFactory(BaseFactory):
    class Meta:
        model = MembershipFee

    name = Faker('word')
    regular_fee = 5.00
    booking_begin = timedelta(3)
    booking_end = timedelta(14)
    payment_deadline = timedelta(14)
    payment_deadline_final = timedelta(62)
    begins_on = LazyAttribute(lambda o: session.utcnow().date().replace(day=1))
    ends_on = LazyAttribute(lambda o: last_day_of_month(session.utcnow()))
Example #5
0
 def test_free_membership(self):
     new_start = session.utcnow().replace(
         day=self.membership_fee_current.booking_end.days + 1)
     self.user_membership.active_during = closedopen(new_start, None)
     end_date = last_day_of_month(session.utcnow().date())
     assert estimate_balance(self.session, self.user, end_date) == 0.00
Example #6
0
def test_last_date_of_month(d, expected):
    assert last_day_of_month(d) == d.replace(day=expected)