from datetime import date
from dateutil.relativedelta import relativedelta
import calendar
[docs]
def calculate_next_anniversary_date(source_date: date):
return source_date + relativedelta(years=1)
[docs]
def calculate_free_look_end_date(effective_date, free_look_days):
free_look_end_date = effective_date + relativedelta(days=free_look_days)
return free_look_end_date
[docs]
def calculate_maturity_date(date_of_birth, maturity_age):
maturity_date = date_of_birth + relativedelta(years=maturity_age)
return maturity_date
[docs]
def calculate_next_paid_to_date(paid_to_date, payment_mode):
next_paid_to_date = paid_to_date + relativedelta(months=payment_mode)
return next_paid_to_date
[docs]
def calculate_last_paid_to_date(paid_to_date, payment_mode):
last_paid_to_date = paid_to_date - relativedelta(months=payment_mode)
return last_paid_to_date
[docs]
def calculate_next_payment_request_date(next_paid_to_date, lead_days):
next_payment_request_date = next_paid_to_date - relativedelta(days=lead_days)
return next_payment_request_date
[docs]
def calculate_lapse_date(effective_date, grace_period):
lapse_date = effective_date + relativedelta(days=grace_period)
return lapse_date
[docs]
def calculate_not_taken_date(effective_date, not_taken_days):
not_taken_date = effective_date + relativedelta(days=not_taken_days)
return not_taken_date
[docs]
def calculate_next_billed_to_date(billed_to_date, payment_mode):
next_billed_to_date = billed_to_date + relativedelta(months=payment_mode)
return next_billed_to_date
[docs]
def calculate_next_modal_date(current_date: date, reference_date: date, payment_mode_id: int, allow_same_day: bool):
"""
Calculates next modal date of a reference date starting from the current_date according to the mode
reference_date is only on day 1 to 28
special case where reference_date.day is 29 to 31,
if the date does not exist, we take the last day of the month
"""
from ace.centralize.codes import Payment
reference_day = reference_date.day
reference_month = reference_date.month
current_day = current_date.day
current_month = current_date.month
current_year = current_date.year
next_modal_date_year = reference_date.year
next_modal_date_month = reference_month
if payment_mode_id == Payment.Mode.MONTHLY.ID:
next_modal_date_year = current_year + 1 if current_day >= reference_day and current_month == 12 and not allow_same_day else current_year
next_modal_date_month = (current_date + relativedelta(months=1)).month if current_day >= reference_day and not allow_same_day else current_month
if payment_mode_id == Payment.Mode.ANNUAL.ID:
next_modal_date_year = current_year + 1 if current_day >= reference_day and current_month >= reference_month and not allow_same_day else current_year
try:
next_modal_date = date(
year=next_modal_date_year,
month=next_modal_date_month,
day=reference_day
)
except ValueError: # In the case, the day is not valid for this month/year
next_modal_date = date(
year=next_modal_date_year,
month=next_modal_date_month,
day=calendar.monthrange(next_modal_date_year, next_modal_date_month)[1] # Last day of this month
)
if payment_mode_id == Payment.Mode.UNKNOWN.ID: # A.K.A. Daily (for testing purposes)
next_modal_date = current_date + relativedelta(days=1)
return next_modal_date