EvaluationStateInfoService.java
package com.tdmconsult.ete.evaluation;
import static com.tdmconsult.ete.accounting.BalanceRecords.ZERO_AMOUNT;
import static com.tdmconsult.ete.accounting.SKR03Account.A2715;
import static com.tdmconsult.ete.accounting.SKR03Account.A4875;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class EvaluationStateInfoService {
public static final NumberFormat AMT_FORMAT = NumberFormat.getCurrencyInstance(Locale.GERMANY);
public static final NumberFormat AMT_FORMAT_RATE = NumberFormat.getCurrencyInstance(Locale.GERMANY);
static {
AMT_FORMAT_RATE.setMaximumFractionDigits(6);
}
public String getBuySellPhrase(final EvaluationState state) {
final var answer = new StringBuffer();
answer.append("Im Fiskaljahr " + state.getFiscalYear() + " wurden ");
if (state.getTotalBuyCost().signum() > 0) {
answer.append("Papiere im Wert von %s angeschafft".formatted(AMT_FORMAT.format(state.getTotalBuyCost())));
} else if (state.getTotalBuyCost().signum() == 0) {
answer.append("keine neuen Papiere dem Bestand hinzugefügt");
}
answer.append(" und ");
if (state.getTotalSellCost().signum() > 0) {
answer.append("Papiere im Wert von %s veräußert.".formatted(AMT_FORMAT.format(state.getTotalSellCost())));
} else if (state.getTotalSellCost().signum() == 0) {
answer.append("keine Papiere aus dem Bestand veräußert.");
}
final var diff = state.getTotalSellCost().subtract(state.getTotalBuyCost());
if (diff.signum() != 0) {
answer.append(" Damit wurde in diesem Jahr die Position insgesamt um %s %s.".formatted(
AMT_FORMAT.format(diff.abs()),
diff.signum() > 0 ? "reduziert" : "ausgeweitet"));
}
return answer.toString();
}
@SuppressWarnings("checkstyle:LineLength")
public String getProfitLossPhrase(final EvaluationState state) {
if (state.getTotalProfit().signum() > 0) {
return ("Mit den Verkäufen wurde ein realisierter Gewinn von %s erzielt, "
+ "der auf Konto 1348 im Haben ausgebucht wurde und das Konto 2725 im Soll verstärkt.")
.formatted(AMT_FORMAT.format(state.getTotalProfit().abs()));
}
if (state.getTotalLoss().signum() > 0) {
return ("Über die Verkäufe musste dabei ein realisierter Verlust von %s realisiert werden, "
+ "der aus Konto 1348 im Soll ausgebucht und gegen Konto 2325 im Haben eingebucht wurde.")
.formatted(AMT_FORMAT.format(state.getTotalLoss().abs()));
}
return "Es gab keine Gewinn-/Verlustrealisierung, demzufolge wurde weder Konto 2725 noch Konto 2325 im Jahresverlauf bebucht.";
}
@SuppressWarnings("checkstyle:LineLength")
public String getEoyEvaluationPhrase(final EvaluationState state) {
final var fiscalYear = state.getFiscalYear();
final var fiscalYearBefore = state.getFiscalYear() - 1;
final var statement1 = state.getTotalQuantity() == 0L
? "Zum Jahresabschluss %d gibt es keinen aktiven Bestand, demzufolge entfällt eine Folgebewertung des Umlaufvermögens nach Handelsrecht."
.formatted(fiscalYear)
: ("Zum Jahresabschluss %d erfolgt eine Jahresendbewertung. Der %s Stück umfassende Portfolio-Bestand wird "
+ "mit einem Schlußkurs von %s gemäß Jahresdepotauszug bewertet. "
+ "Per %s folgt daraus ein Marktwert der Wertpapiere zu %s.").formatted(
fiscalYear,
state.getTotalQuantity(),
AMT_FORMAT_RATE.format(state.getEvaluationRate(fiscalYear).map(EvaluationPosition.Rate::value).orElse(ZERO_AMOUNT)),
"31.12." + state.getFiscalYear(),
AMT_FORMAT.format(state.getEvaluationRate(fiscalYear).map(EvaluationPosition.Rate::value).orElse(ZERO_AMOUNT).multiply(new BigDecimal(state.getTotalQuantity()))));
// e.g. -64.979,05 € in 2024 - RWE AG
final var evaluationTotalDeltaT0 = state.getEvaluationTotalDelta(fiscalYear);
// e.g. -4.785,99 € € in 2023 - RWE AG
final var evaluationTotalDeltaT1 = state.getEvaluationTotalDelta(fiscalYear - 1);
final var statement2a = state.getEvaluationRate(fiscalYearBefore).map(rate -> (
"Im Vorjahr %d wurde der Portfolio-Bestand mit einem Schlußkurs von %s bewertet, woraus sich damals ein %s von %s ergab.").formatted(
fiscalYearBefore,
AMT_FORMAT_RATE.format(rate.value()),
evaluationTotalDeltaT1.signum() > 0 ? "Bewertungsgewinn" : "Bewertungsverlust",
AMT_FORMAT.format(evaluationTotalDeltaT1.abs())))
.orElse("Aus dem Vorjahr %d sind keine Zu- oder Abschreibungen zu berücksichtigen.".formatted(fiscalYearBefore));
final var statement2b = evaluationTotalDeltaT0.signum() == 0
? "In diesem Jahr entfällt die Bewertung in Ermangelung an einem Bestand."
: "In diesem Jahr ergibt sich für den Bestand ein %s von %s.".formatted(
evaluationTotalDeltaT0.signum() > 0 ? "Bewertungsgewinn" : "Bewertungsverlust",
AMT_FORMAT.format(evaluationTotalDeltaT0.abs()));
final var statement2 = statement2a + " " + statement2b;
var statement3 = "Die Wertpapiere sind im Umlaufvermögen zu führen, daher gilt das strenges Niederstwertprinzip "
+ "mit Abschreibungspflicht auf den Stichtagskurs (§ 253 Abs. 4 HGB) und Zuschreibungspflicht bis zu den Anschaffunsgkosten "
+ "bei Wertaufholung. ";
final var hrResult = new EvaluationHrCalculator(state).calculate();
final var statement4 = switch (hrResult.action()) {
case VALUE_NOOP -> "Es gibt keine Ab- und Zuschreibungen in diesem Zeitraum.";
case VALUE_DECREASE_WITH_WRITE_DOWN ->
"Unter Berücksichtigung der vorgenannten Rahmenbedingungen ist in diesem Jahr eine Abschreibung i.H.v "
+ AMT_FORMAT.format(hrResult.amount()) + " nach Handelsrecht durchzuführen. "
+ "Die Buchung erfolgt im Rahmen des Jahresabsachlusses zum 31.12. gegen das Konto 4875 " + A4875.getDisplayName() + ".";
case VALUE_DECREASE_NO_WRITE_DOWN ->
"Unter Berücksichtigung der vorgenannten Rahmenbedingungen ist in diesem Jahr keine Abschreibung zulässig, "
+ "weil der Kurswert zwar gegenüber dem Vorjahr abgenommen hat, aber noch über den Anschaffungskosten liegt.";
case VALUE_INCREASE_WITH_WRITE_UP ->
"Unter Berücksichtigung der vorgenannten Rahmenbedingungen ist in diesem Jahr eine Zuschreibung i.H.v "
+ AMT_FORMAT.format(hrResult.amount()) + " nach Handelsrecht durchzuführen. "
+ "Die Buchung erfolgt im Rahmen des Jahresabsachlusses zum 31.12. gegen das Konto 2715 " + A2715.getDisplayName() + ".";
case VALUE_INCREASE_NO_WRITE_UP ->
"Unter Berücksichtigung der vorgenannten Rahmenbedingungen ist in diesem Jahr keine Zuschreibung zulässig. "
+ "Zwar steigt der Marktwert des Bestandes in diesem Fiskaljahr, allerdings ist eine Zuschreibung im Handelsrecht über die Anschaffungskosten hinaus nicht zulässig.";
};
return statement1 + " " + statement2 + " " + statement3 + " " + statement4;
}
}