diff --git a/crates/immo-core/src/fixtures/loan_offer_fixture.rs b/crates/immo-core/src/fixtures/loan_offer_fixture.rs index 33f4bca..9b8db7b 100644 --- a/crates/immo-core/src/fixtures/loan_offer_fixture.rs +++ b/crates/immo-core/src/fixtures/loan_offer_fixture.rs @@ -40,6 +40,20 @@ pub struct LoanOfferFixture { pub annual_nominal_rate: InterestRate, pub total_duration_in_months: u64, pub deferral_in_months: u64, + /// Capital sur lequel court l'amortissement, après capitalisation des + /// intérêts du différé. Égal à `borrowed_capital` hors différé total. + /// + /// C'est **ce** capital, et non `borrowed_capital`, qui alimente la formule + /// de mensualité. Sur l'offre B, le différé total porte les 439 000 EUR + /// empruntés à 444 405,27 EUR amortissables. + pub amortised_capital: Euros, + /// Nombre d'échéances amortissantes, différé exclu. C'est le `n` de la + /// formule de mensualité, à ne pas confondre avec `total_duration_in_months`. + /// + /// Alimenter la formule avec `borrowed_capital` et `total_duration_in_months` + /// sur l'offre B donne 1 958,39 EUR au lieu des 2 011,86 EUR du tableau : + /// l'écart est un cumul des deux confusions, pas une dérive d'arrondi. + pub amortisation_in_months: u64, pub monthly_repayment: Euros, pub total_credit_cost: Euros, pub total_paid: Euros, @@ -5826,6 +5840,8 @@ pub fn offre_a() -> LoanOfferFixture { annual_nominal_rate: InterestRate::from_fraction(Decimal::new(341, 4)), total_duration_in_months: 240, deferral_in_months: 0, + amortised_capital: Euros::from_cents_as_i64(150_000_00), + amortisation_in_months: 240, monthly_repayment: Euros::from_cents_as_i64(863_02), total_credit_cost: Euros::from_cents_as_i64(57_124_30), total_paid: Euros::from_cents_as_i64(207_124_30), @@ -5841,6 +5857,8 @@ pub fn offre_b_differe_total() -> LoanOfferFixture { annual_nominal_rate: InterestRate::from_fraction(Decimal::new(245, 4)), total_duration_in_months: 300, deferral_in_months: 6, + amortised_capital: Euros::from_cents_as_i64(444_405_27), + amortisation_in_months: 294, monthly_repayment: Euros::from_cents_as_i64(2_011_86), total_credit_cost: Euros::from_cents_as_i64(152_486_18), total_paid: Euros::from_cents_as_i64(591_486_18), @@ -5856,6 +5874,8 @@ pub fn offre_b_differe_partiel() -> LoanOfferFixture { annual_nominal_rate: InterestRate::from_fraction(Decimal::new(245, 4)), total_duration_in_months: 300, deferral_in_months: 6, + amortised_capital: Euros::from_cents_as_i64(439_000_00), + amortisation_in_months: 294, monthly_repayment: Euros::from_cents_as_i64(1_987_39), total_credit_cost: Euros::from_cents_as_i64(150_669_69), total_paid: Euros::from_cents_as_i64(589_669_69), @@ -5871,6 +5891,8 @@ pub fn offre_c_ptz() -> LoanOfferFixture { annual_nominal_rate: InterestRate::from_fraction(Decimal::new(0, 0)), total_duration_in_months: 120, deferral_in_months: 0, + amortised_capital: Euros::from_cents_as_i64(95_000_00), + amortisation_in_months: 120, monthly_repayment: Euros::from_cents_as_i64(791_67), total_credit_cost: Euros::from_cents_as_i64(0_00), total_paid: Euros::from_cents_as_i64(95_000_00), diff --git a/scripts/loan_schedule.py b/scripts/loan_schedule.py index b3754cf..389ebc3 100644 --- a/scripts/loan_schedule.py +++ b/scripts/loan_schedule.py @@ -575,6 +575,20 @@ pub struct LoanOfferFixture {{ pub annual_nominal_rate: InterestRate, pub total_duration_in_months: u64, pub deferral_in_months: u64, + /// Capital sur lequel court l'amortissement, après capitalisation des + /// intérêts du différé. Égal à `borrowed_capital` hors différé total. + /// + /// C'est **ce** capital, et non `borrowed_capital`, qui alimente la formule + /// de mensualité. Sur l'offre B, le différé total porte les 439 000 EUR + /// empruntés à 444 405,27 EUR amortissables. + pub amortised_capital: Euros, + /// Nombre d'échéances amortissantes, différé exclu. C'est le `n` de la + /// formule de mensualité, à ne pas confondre avec `total_duration_in_months`. + /// + /// Alimenter la formule avec `borrowed_capital` et `total_duration_in_months` + /// sur l'offre B donne 1 958,39 EUR au lieu des 2 011,86 EUR du tableau : + /// l'écart est un cumul des deux confusions, pas une dérive d'arrondi. + pub amortisation_in_months: u64, pub monthly_repayment: Euros, pub total_credit_cost: Euros, pub total_paid: Euros, @@ -657,6 +671,8 @@ def render_rust(offers: list[LoanOffer], path: str) -> str: f" annual_nominal_rate: {rust_interest_rate(offer.annual_nominal_rate)},\n" f" total_duration_in_months: {offer.total_duration_in_months},\n" f" deferral_in_months: {offer.deferral_in_months},\n" + f" amortised_capital: {rust_euros(offer.amortised_capital)},\n" + f" amortisation_in_months: {offer.amortisation_in_months},\n" f" monthly_repayment: {rust_euros(offer.monthly_repayment)},\n" f" total_credit_cost: {rust_euros(offer.total_credit_cost(rows))},\n" f" total_paid: {rust_euros(offer.total_paid(rows))},\n"