diff --git a/Darlehenberechner.java b/Darlehenberechner.java index 914dca1..2717d0b 100644 --- a/Darlehenberechner.java +++ b/Darlehenberechner.java @@ -12,11 +12,12 @@ class Darlehenberechner { private static final class Konfiguration { private BigDecimal darlehenswert; - private BigDecimal zinssatzProzent; + private BigDecimal zinssatzReal; private BigDecimal monatlicheRate; private Integer laufzeitJahre; - private Integer tilgungsfreieZeit; + private Integer aktTilgungsfreieZeit; private YearMonth anfangsmonat; + private BigDecimal sondertilgungReal; public BigDecimal getDarlehenswert() { @@ -30,13 +31,13 @@ class Darlehenberechner { } - public BigDecimal getZinssatzProzent() { - return zinssatzProzent; + public BigDecimal getZinssatz() { + return zinssatzReal; } public Konfiguration setZinssatzProzent(BigDecimal zinssatzProzent) { - this.zinssatzProzent = zinssatzProzent; + this.zinssatzReal = zinssatzProzent.divide(EINHUNDERT, MathContext.DECIMAL128); return this; } @@ -63,13 +64,13 @@ class Darlehenberechner { } - public Integer getTilgungsfreieZeit() { - return tilgungsfreieZeit; + public Integer getaktTilgungsfreieZeit() { + return aktTilgungsfreieZeit; } - public Konfiguration setTilgungsfreieZeit(Integer tilgungsfreieZeit) { - this.tilgungsfreieZeit = tilgungsfreieZeit; + public Konfiguration setaktTilgungsfreieZeit(Integer aktTilgungsfreieZeit) { + this.aktTilgungsfreieZeit = aktTilgungsfreieZeit; return this; } @@ -83,128 +84,223 @@ class Darlehenberechner { this.anfangsmonat = anfangsmonat; return this; } + + + public BigDecimal getSondertilgung() { + return sondertilgungReal; + } + + + public Konfiguration setSondertilgungProzent(BigDecimal sondertilgungProzent) { + this.sondertilgungReal = sondertilgungProzent.divide(EINHUNDERT, MathContext.DECIMAL128); + return this; + } } private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(Locale.GERMAN)); private static final BigDecimal ZWOELF = BigDecimal.valueOf(12); + private static final BigDecimal EINHUNDERT = BigDecimal.valueOf(100); - public static void main(String[] args) throws ParseException { - /*berechneWerte(new Konfiguration() - .setDarlehenswert(BigDecimal.valueOf(168_000)) - .setZinssatzProzent(BigDecimal.valueOf(3.73)) - .setMonatlicheRate(BigDecimal.valueOf(1_500)) - .setTilgungsfreieZeit(0) - .setAnfangsmonat(YearMonth.of(2024, Month.SEPTEMBER))); - return;*/ + private final Integer laufzeitJahre; + private final BigDecimal zinssatz; + private BigDecimal sondertilgung; + private int summeMonate; + private BigDecimal aktRestschuld; + private BigDecimal aktMonatlicheRate; + private BigDecimal aktZinsbetrag; + private BigDecimal aktTilgungsbetrag; + private Integer aktTilgungsfreieZeit; + private YearMonth aktMonat; + private BigDecimal summeZinsen; + private BigDecimal summeTilgung; + private BigDecimal jahressummeRatenKalenderjahr; + private BigDecimal jahressummeRatenKreditjahr; + private BigDecimal summeRaten; - /*berechneWerte(new Konfiguration() - .setDarlehenswert(BigDecimal.valueOf(168_000)) - .setZinssatzProzent(BigDecimal.valueOf(3.73)) - .setMonatlicheRate(BigDecimal.valueOf(1_500)) - .setTilgungsfreieZeit(0) - .setLaufzeitJahre(11) - .setAnfangsmonat(YearMonth.of(2024, Month.SEPTEMBER))); - return;*/ - var konfig = new Konfiguration(); - int count = 0; - DECIMAL_FORMAT.setParseBigDecimal(true); - while (count < args.length) { - String arg = args[count]; - if (arg.equals("-hilfe")) { - System.out.println("-darlehenswert 1000,00 -zinssatz 3,73 -monatlicheRate 30,00 -anfangsmonat 2024-09" - + "[-laufzeitJahre 11] [-tilgungsfreieZeit 5]"); - } - if (arg.equals("-darlehenswert")) { - count++; - konfig.setDarlehenswert((BigDecimal) DECIMAL_FORMAT.parse(args[count])); - } - if (arg.equals("-zinssatz")) { - count++; - konfig.setZinssatzProzent((BigDecimal) DECIMAL_FORMAT.parse(args[count])); - } - if (arg.equals("-monatlicheRate")) { - count++; - konfig.setMonatlicheRate((BigDecimal) DECIMAL_FORMAT.parse(args[count])); - } - if (arg.equals("-tilgungsfreieZeit")) { - count++; - konfig.setTilgungsfreieZeit(Integer.parseInt(args[count])); - } - if (arg.equals("-laufzeitJahre")) { - count++; - konfig.setLaufzeitJahre(Integer.parseInt(args[count])); - } - if (arg.equals("-anfangsmonat")) { - count++; - konfig.setAnfangsmonat(YearMonth.parse(args[count])); - } - count++; + public static void main(String[] args) throws ParseException { + new Darlehenberechner(new Konfiguration() + .setDarlehenswert(BigDecimal.valueOf(168_000)) + .setZinssatzProzent(BigDecimal.valueOf(3.73)) + .setMonatlicheRate(BigDecimal.valueOf(1_500)) + .setaktTilgungsfreieZeit(0) + .setAnfangsmonat(YearMonth.of(2024, Month.SEPTEMBER)) + .setSondertilgungProzent(BigDecimal.valueOf(2.5)) + ).berechneWerte(); + return; + + /*new Darlehenberechner(new Konfiguration() + .setDarlehenswert(BigDecimal.valueOf(168_000)) + .setZinssatzProzent(BigDecimal.valueOf(3.73)) + .setMonatlicheRate(BigDecimal.valueOf(1_500)) + .setaktTilgungsfreieZeit(0) + .setLaufzeitJahre(11) + .setAnfangsmonat(YearMonth.of(2024, Month.SEPTEMBER)) + ).berechneWerte(); + return;*/ + + /*var konfig = new Konfiguration(); + int count = 0; + DECIMAL_FORMAT.setParseBigDecimal(true); + while (count < args.length) { + String arg = args[count]; + if (arg.equals("-hilfe")) { + System.out.println("-darlehenswert 1000,00 -zinssatz 3,73 -monatlicheRate 30,00 -anfangsmonat 2024-09" + + "[-laufzeitJahre 11] [-aktTilgungsfreieZeit 5]"); } - berechneWerte(konfig); + if (arg.equals("-darlehenswert")) { + count++; + konfig.setDarlehenswert((BigDecimal) DECIMAL_FORMAT.parse(args[count])); + } + if (arg.equals("-zinssatz")) { + count++; + konfig.setZinssatzProzent((BigDecimal) DECIMAL_FORMAT.parse(args[count])); + } + if (arg.equals("-sondertilgung")) { + count++; + konfig.setSondertilgungProzent((BigDecimal) DECIMAL_FORMAT.parse(args[count])); + } + if (arg.equals("-monatlicheRate")) { + count++; + konfig.setMonatlicheRate((BigDecimal) DECIMAL_FORMAT.parse(args[count])); + } + if (arg.equals("-aktTilgungsfreieZeit")) { + count++; + konfig.setaktTilgungsfreieZeit(Integer.parseInt(args[count])); + } + if (arg.equals("-laufzeitJahre")) { + count++; + konfig.setLaufzeitJahre(Integer.parseInt(args[count])); + } + if (arg.equals("-anfangsmonat")) { + count++; + konfig.setAnfangsmonat(YearMonth.parse(args[count])); + } + count++; + } + new Darlehenberechner(konfig).berechneWerte();*/ } - private static void berechneWerte(Konfiguration konfig) { - BigDecimal zinssatzReal = konfig.getZinssatzProzent().divide(BigDecimal.valueOf(100), MathContext.DECIMAL128); - BigDecimal monatlicheRate = konfig.getMonatlicheRate(); - Integer laufzeitJahre = konfig.getLaufzeitJahre(); - Integer tilgungsfreieZeit = konfig.getTilgungsfreieZeit(); - BigDecimal restschuld = konfig.getDarlehenswert(); - YearMonth aktuellerMonat = konfig.getAnfangsmonat(); - BigDecimal summeZinsen = BigDecimal.ZERO; - BigDecimal summeTilgung = BigDecimal.ZERO; - BigDecimal jahressummeRatenKalenderjahr = BigDecimal.ZERO; - BigDecimal jahressummeRatenKreditjahr = BigDecimal.ZERO; - BigDecimal summeRaten = BigDecimal.ZERO; - int laufzeitMonate = 0; - System.out.println("Monat: Rate = Zinsen + Tilgung| Restschuld"); - while ((laufzeitJahre == null || laufzeitMonate < (laufzeitJahre * 12)) && restschuld.signum() > 0) { - // berechne Beträge/ aktualisiere Restschuld - BigDecimal zinsbetrag = restschuld.multiply(zinssatzReal).divide(ZWOELF, MathContext.DECIMAL128); - if (monatlicheRate.compareTo(restschuld) > 0) { - monatlicheRate = restschuld.add(zinsbetrag); // die letzte Rate ist gleich der Restschuld + Zinsen - } - BigDecimal tilgungsbetrag = tilgungsfreieZeit != null && tilgungsfreieZeit > 0 ? BigDecimal.ZERO : monatlicheRate.subtract(zinsbetrag); - restschuld = restschuld.subtract(tilgungsbetrag); - System.out.println(aktuellerMonat + ": " + DECIMAL_FORMAT.format(monatlicheRate) + " = " + DECIMAL_FORMAT.format(zinsbetrag) - + " + " + DECIMAL_FORMAT.format(tilgungsbetrag) + " | " + DECIMAL_FORMAT.format(restschuld)); - // berechne Summen für Zusammenfassung - summeZinsen = summeZinsen.add(zinsbetrag); - summeTilgung = summeTilgung.add(tilgungsbetrag); - jahressummeRatenKalenderjahr = jahressummeRatenKalenderjahr.add(monatlicheRate); - jahressummeRatenKreditjahr = jahressummeRatenKreditjahr.add(monatlicheRate); - summeRaten = summeRaten.add(monatlicheRate); - boolean kreditjahrVergangen = laufzeitMonate > 0 && laufzeitMonate % 11 == 0; - if (kreditjahrVergangen || aktuellerMonat.getMonthValue() == 12) { - BigDecimal jahressummeRaten; - String desc; - if (kreditjahrVergangen) { - jahressummeRaten = jahressummeRatenKreditjahr; - jahressummeRatenKreditjahr = BigDecimal.ZERO; - desc = "Kreditjahr"; - } else { - jahressummeRaten = jahressummeRatenKalenderjahr; - jahressummeRatenKalenderjahr = BigDecimal.ZERO; - desc = "Kalenderjahr"; - } - System.out.println("Summe " + desc + ":\n" + DECIMAL_FORMAT.format(jahressummeRaten) + " = " - + DECIMAL_FORMAT.format(summeZinsen) + " + " + DECIMAL_FORMAT.format(summeTilgung)); - } - // aktualisiere Werte für den nächsten Lauf - aktuellerMonat = aktuellerMonat.plusMonths(1); - laufzeitMonate++; - if (tilgungsfreieZeit != null) { - tilgungsfreieZeit--; - } + private Darlehenberechner(Konfiguration konfig) { + laufzeitJahre = konfig.getLaufzeitJahre(); + zinssatz = konfig.getZinssatz(); + sondertilgung = konfig.getSondertilgung() != null ? konfig.getSondertilgung().multiply(konfig.getDarlehenswert()) : BigDecimal.ZERO; + summeMonate = 1; + aktRestschuld = konfig.getDarlehenswert(); + aktMonatlicheRate = konfig.getMonatlicheRate(); + aktTilgungsfreieZeit = konfig.getaktTilgungsfreieZeit(); + aktMonat = konfig.getAnfangsmonat(); + summeZinsen = BigDecimal.ZERO; + summeTilgung = BigDecimal.ZERO; + jahressummeRatenKalenderjahr = BigDecimal.ZERO; + jahressummeRatenKreditjahr = BigDecimal.ZERO; + summeRaten = BigDecimal.ZERO; + } + + + private void berechneWerte() { + druckeUeberschrift(); + while ((laufzeitJahre == null || summeMonate < (laufzeitJahre * 12)) && aktRestschuld.signum() > 0) { + zahleSondertilgung(); + berechneBeitragAufteilung(); + berechneRestschuld(); + druckeAktuelleMonatswerte(); + berechneSummen(); + druckeJahressumeBedingt(); + aktualisiereZeitwerte(); } - // letzte Zusammenfassung - System.out.println("Summe:\n" + DECIMAL_FORMAT.format(summeRaten) + " = " - + DECIMAL_FORMAT.format(summeZinsen) + " + " + DECIMAL_FORMAT.format(summeTilgung)); - // Ausgabe Laufzeit + Restschuld - laufzeitJahre = laufzeitJahre == null ? laufzeitMonate / 12 : laufzeitJahre; - int laufzeitMonateTeil = laufzeitMonate - (laufzeitJahre * 12); - System.out.println("Laufzeit: " + laufzeitJahre + " Jahre " + laufzeitMonateTeil + " Monate"); - System.out.println("Restschuld: " + DECIMAL_FORMAT.format(restschuld)); + druckeFinaleSummen(); + druckeLaufzeitUndRestschuld(); + } + + + private void druckeUeberschrift() { + System.out.println("Monat: Rate = Zinsen + Tilgung| Restschuld"); + } + + + private void zahleSondertilgung() { + if (sondertilgung.signum() == 0) { + return; + } + boolean sondertilgungFaellingErstesJahr = summeMonate < 12 && aktMonat.getMonth() == Month.DECEMBER; + if (sondertilgungFaellingErstesJahr || summeMonate > 1 && aktMonat.getMonth() == Month.JANUARY) { + aktRestschuld = aktRestschuld.subtract(sondertilgung); + System.out.println(aktMonat + ": " + DECIMAL_FORMAT.format(sondertilgung) + " = 0,00 + " + DECIMAL_FORMAT.format(sondertilgung) + " | " + DECIMAL_FORMAT.format(aktRestschuld)); + } + } + + + private void berechneBeitragAufteilung() { + aktZinsbetrag = aktRestschuld.multiply(zinssatz) + .divide(ZWOELF, MathContext.DECIMAL128); + if (aktMonatlicheRate.compareTo(aktRestschuld) > 0) { + aktMonatlicheRate = aktRestschuld.add(aktZinsbetrag); // die letzte Rate ist gleich der Restschuld + Zinsen + } + aktTilgungsbetrag = aktTilgungsfreieZeit != null && aktTilgungsfreieZeit > 0 ? BigDecimal.ZERO : aktMonatlicheRate.subtract(aktZinsbetrag); + } + + + private void berechneRestschuld() { + aktRestschuld = aktRestschuld.subtract(aktTilgungsbetrag); + } + + + private void druckeAktuelleMonatswerte() { + System.out.println(aktMonat + ": " + DECIMAL_FORMAT.format(aktMonatlicheRate) + " = " + DECIMAL_FORMAT.format(aktZinsbetrag) + + " + " + DECIMAL_FORMAT.format(aktTilgungsbetrag) + " | " + DECIMAL_FORMAT.format(aktRestschuld)); + } + + + private void berechneSummen() { + summeZinsen = summeZinsen.add(aktZinsbetrag); + summeTilgung = summeTilgung.add(aktTilgungsbetrag); + jahressummeRatenKalenderjahr = jahressummeRatenKalenderjahr.add(aktMonatlicheRate); + jahressummeRatenKreditjahr = jahressummeRatenKreditjahr.add(aktMonatlicheRate); + summeRaten = summeRaten.add(aktMonatlicheRate); + } + + + private void druckeJahressumeBedingt() { + boolean kreditjahrVergangen = summeMonate > 1 && summeMonate % 12 == 0; + if (kreditjahrVergangen || aktMonat.getMonth() == Month.DECEMBER) { + BigDecimal jahressummeRaten; + String desc; + if (kreditjahrVergangen) { + jahressummeRaten = jahressummeRatenKreditjahr; + jahressummeRatenKreditjahr = BigDecimal.ZERO; + desc = "Kreditjahr " + summeMonate / 12; + } else { + jahressummeRaten = jahressummeRatenKalenderjahr; + jahressummeRatenKalenderjahr = BigDecimal.ZERO; + desc = "Kalenderjahr " + aktMonat.getYear(); + } + System.out.println("Summe " + desc + ":\n" + DECIMAL_FORMAT.format(jahressummeRaten) + " = " + DECIMAL_FORMAT.format(summeZinsen) + " + " + + DECIMAL_FORMAT.format(summeTilgung)); + } + } + + + private void aktualisiereZeitwerte() { + aktMonat = aktMonat.plusMonths(1); + summeMonate++; + if (aktTilgungsfreieZeit != null) { + aktTilgungsfreieZeit--; + } + } + + + private void druckeFinaleSummen() { + System.out.println("Summe:\n" + DECIMAL_FORMAT.format(summeRaten) + " = " + DECIMAL_FORMAT.format(summeZinsen) + + " + " + DECIMAL_FORMAT.format(summeTilgung)); + } + + + private void druckeLaufzeitUndRestschuld() { + int laufzeitJahreFinal = laufzeitJahre == null ? summeMonate / 12 : laufzeitJahre; + int teillaufzeitMonateFinal = summeMonate - (laufzeitJahreFinal * 12); + System.out.println("Laufzeit: " + laufzeitJahreFinal + " Jahre " + teillaufzeitMonateFinal + " Monate"); + System.out.println("Restschuld: " + DECIMAL_FORMAT.format(aktRestschuld)); } }