67 lines
1.7 KiB
Python
67 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
from typing import Literal
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class InstallmentType(str, Enum):
|
|
equal = "equal"
|
|
decreasing = "decreasing"
|
|
|
|
|
|
class OverpaymentEffect(str, Enum):
|
|
shorten = "shorten"
|
|
lower_payment = "lower_payment"
|
|
|
|
|
|
class RateChange(BaseModel):
|
|
month: int = Field(ge=1, description="Miesiac od startu kredytu")
|
|
annual_rate: float = Field(ge=0, le=30, description="Roczne oprocentowanie procentowo")
|
|
|
|
|
|
class Overpayment(BaseModel):
|
|
month: int = Field(ge=1)
|
|
amount: float = Field(gt=0)
|
|
repeat: Literal["once", "monthly", "yearly"] = "once"
|
|
until_month: int | None = Field(default=None, ge=1)
|
|
|
|
|
|
class SimulationRequest(BaseModel):
|
|
principal: float = Field(gt=0)
|
|
years: int = Field(ge=1, le=50)
|
|
margin: float = Field(ge=0, le=20, default=2.0)
|
|
base_rate: float = Field(ge=0, le=30, default=5.75)
|
|
installment_type: InstallmentType = InstallmentType.equal
|
|
overpayment_effect: OverpaymentEffect = OverpaymentEffect.shorten
|
|
rate_changes: list[RateChange] = Field(default_factory=list)
|
|
overpayments: list[Overpayment] = Field(default_factory=list)
|
|
|
|
|
|
class ScheduleRow(BaseModel):
|
|
month: int
|
|
rate: float
|
|
payment: float
|
|
principal_part: float
|
|
interest_part: float
|
|
overpayment: float
|
|
remaining: float
|
|
|
|
|
|
class Summary(BaseModel):
|
|
months: int
|
|
total_paid: float
|
|
total_interest: float
|
|
total_overpayment: float
|
|
interest_saved: float
|
|
months_saved: int
|
|
baseline_interest: float
|
|
baseline_months: int
|
|
average_payment: float
|
|
max_payment: float
|
|
|
|
|
|
class SimulationResponse(BaseModel):
|
|
schedule: list[ScheduleRow]
|
|
summary: Summary
|