from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta def calculate_monthly_rate(interest_rate: float, rate_type: str) -> float: if rate_type == "annual": return interest_rate / 100 / 12 return interest_rate / 100 def generate_equal_installment_plan( amount: int, interest_rate: float, rate_type: str, period_count: int, start_date: datetime ) -> list[dict]: mr = calculate_monthly_rate(interest_rate, rate_type) if mr == 0: principal_each = amount // period_count plans = [] for i in range(period_count): due = start_date + relativedelta(months=i + 1) p = principal_each if i < period_count - 1 else amount - principal_each * (period_count - 1) plans.append({"due_date": due, "principal_due": p, "interest_due": 0, "total_due": p}) return plans mp = amount * mr * (1 + mr) ** period_count / ((1 + mr) ** period_count - 1) plans = [] remaining = amount for i in range(period_count): due = start_date + relativedelta(months=i + 1) interest = int(remaining * mr) principal = int(mp) - interest if i == period_count - 1: principal = remaining interest = int(remaining * mr) remaining -= principal total = principal + interest plans.append({"due_date": due, "principal_due": principal, "interest_due": interest, "total_due": total}) return plans def generate_interest_first_plan( amount: int, interest_rate: float, rate_type: str, period_count: int, start_date: datetime ) -> list[dict]: mr = calculate_monthly_rate(interest_rate, rate_type) plans = [] for i in range(period_count): due = start_date + relativedelta(months=i + 1) interest = int(amount * mr) principal = amount if i == period_count - 1 else 0 total = principal + interest plans.append({"due_date": due, "principal_due": principal, "interest_due": interest, "total_due": total}) return plans def generate_lump_sum_plan( amount: int, interest_rate: float, rate_type: str, period_count: int, period_unit: str, start_date: datetime ) -> list[dict]: if period_unit == "year": total_interest = int(amount * interest_rate / 100 * period_count) else: total_interest = int(amount * interest_rate / 100 / 12 * period_count) due = start_date + relativedelta(months=period_count) if period_unit == "month" else start_date + relativedelta(years=period_count) return [{"due_date": due, "principal_due": amount, "interest_due": total_interest, "total_due": amount + total_interest}] def generate_repayment_plan( amount: int, interest_rate: float, rate_type: str, repayment_method: str, period_count: int, period_unit: str, start_date: datetime ) -> list[dict]: if repayment_method == "equal_installment": return generate_equal_installment_plan(amount, interest_rate, rate_type, period_count, start_date) elif repayment_method == "interest_first": return generate_interest_first_plan(amount, interest_rate, rate_type, period_count, start_date) elif repayment_method == "lump_sum": return generate_lump_sum_plan(amount, interest_rate, rate_type, period_count, period_unit, start_date) return []