valueList() {
return Arrays.stream(ChartType.values()).map(ChartType::name).collect(Collectors.toList());
diff --git a/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java b/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java
index 718a2f4..924b442 100644
--- a/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java
+++ b/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java
@@ -2,6 +2,7 @@ package de.financer.chart;
import de.financer.chart.impl.expense.AccountExpensesGenerator;
import de.financer.chart.impl.expense.AccountGroupExpensesGenerator;
+import de.financer.chart.impl.total.PeriodTotalGenerator;
import de.financer.config.FinancerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
@@ -31,6 +32,10 @@ public class FinancerChartFactory {
// TODO WHY IS THIS CAST NECESSARY???
generator = (AbstractChartGenerator) new AccountExpensesGenerator();
break;
+ case EXPENSE_PERIOD_TOTALS_CURRENT_YEAR:
+ // TODO WHY IS THIS CAST NECESSARY???
+ generator = (AbstractChartGenerator
) new PeriodTotalGenerator();
+ break;
default:
generator = null;
}
diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/total/PeriodTotalGenerator.java b/financer-web-client/src/main/java/de/financer/chart/impl/total/PeriodTotalGenerator.java
new file mode 100644
index 0000000..e65bb7c
--- /dev/null
+++ b/financer-web-client/src/main/java/de/financer/chart/impl/total/PeriodTotalGenerator.java
@@ -0,0 +1,74 @@
+package de.financer.chart.impl.total;
+
+import de.financer.chart.AbstractChartGenerator;
+import de.financer.dto.ExpensePeriodTotal;
+import de.financer.template.GetExpensePeriodTotalsTemplate;
+import de.financer.util.ControllerUtils;
+import de.financer.util.ExpensePeriod;
+import org.apache.commons.collections4.IterableUtils;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.category.DefaultCategoryDataset;
+import org.springframework.context.i18n.LocaleContextHolder;
+
+import java.text.NumberFormat;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.List;
+
+public class PeriodTotalGenerator extends AbstractChartGenerator {
+ @Override
+ public JFreeChart generateChart(PeriodTotalParameter parameter) {
+ final CategoryDataset dataSet = getDataset(parameter);
+
+ final JFreeChart chart = ChartFactory
+ .createBarChart(this.getMessage(parameter.getTitle(), parameter.getArgsForTitle()),
+ this.getMessage(parameter.getyAxis()),
+ this.getMessage(parameter.getxAxis()),
+ dataSet, PlotOrientation.VERTICAL, true, true, false);
+
+ final NumberAxis axis = (NumberAxis) chart.getCategoryPlot().getRangeAxis();
+
+ axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits(LocaleContextHolder
+ .getLocale()));
+
+ final NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(LocaleContextHolder.getLocale());
+ currencyInstance.setCurrency(this.getFinancerConfig().getCurrency());
+
+ axis.setNumberFormatOverride(currencyInstance);
+
+ return chart;
+ }
+
+ private CategoryDataset getDataset(PeriodTotalParameter parameter) {
+ final DefaultCategoryDataset result = new DefaultCategoryDataset();
+ final List expensePeriods = ExpensePeriod
+ .generateExpensePeriodsForYear(this.getFinancerConfig().getMonthPeriodStartDay(), parameter.getYear());
+
+ final Iterable totalData = new GetExpensePeriodTotalsTemplate()
+ .exchange(this.getFinancerConfig(), parameter.getYear()).getBody();
+
+ IterableUtils.toList(totalData).stream()
+ .forEach((ept) -> result.addValue((ept.getTotal() / 100D),
+ this.getMessage("financer.account-type." + ept.getType()),
+ expensePeriods.stream()
+ .filter((ep) -> ep.generatePeriodShortCode()
+ .equals(ept.getPeriodShortCode()))
+ .map((ep) -> formatDateY(ep))
+ .findFirst().get()));
+
+
+ return result;
+ }
+
+ private String formatDateY(ExpensePeriod ep) {
+ return String.format("%s - %s",
+ ep.getStart().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
+ .withLocale(LocaleContextHolder.getLocale())),
+ ep.getEnd().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
+ .withLocale(LocaleContextHolder.getLocale())));
+ }
+}
diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/total/PeriodTotalParameter.java b/financer-web-client/src/main/java/de/financer/chart/impl/total/PeriodTotalParameter.java
new file mode 100644
index 0000000..97f97cb
--- /dev/null
+++ b/financer-web-client/src/main/java/de/financer/chart/impl/total/PeriodTotalParameter.java
@@ -0,0 +1,51 @@
+package de.financer.chart.impl.total;
+
+import de.financer.chart.ChartParameter;
+
+public class PeriodTotalParameter implements ChartParameter {
+ private String title;
+ private Object[] argsForTitle;
+ private String yAxis;
+ private String xAxis;
+ private int year;
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Object[] getArgsForTitle() {
+ return argsForTitle;
+ }
+
+ public void setArgsForTitle(Object[] argsForTitle) {
+ this.argsForTitle = argsForTitle;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+ public String getyAxis() {
+ return yAxis;
+ }
+
+ public void setyAxis(String yAxis) {
+ this.yAxis = yAxis;
+ }
+
+ public String getxAxis() {
+ return xAxis;
+ }
+
+ public void setxAxis(String xAxis) {
+ this.xAxis = xAxis;
+ }
+}
diff --git a/financer-web-client/src/main/java/de/financer/controller/ChartController.java b/financer-web-client/src/main/java/de/financer/controller/ChartController.java
index 81b7836..4802bc4 100644
--- a/financer-web-client/src/main/java/de/financer/controller/ChartController.java
+++ b/financer-web-client/src/main/java/de/financer/controller/ChartController.java
@@ -4,6 +4,7 @@ import de.financer.chart.impl.expense.ExpensesParameter;
import de.financer.chart.ChartGenerator;
import de.financer.chart.ChartType;
import de.financer.chart.FinancerChartFactory;
+import de.financer.chart.impl.total.PeriodTotalParameter;
import de.financer.config.FinancerConfig;
import de.financer.form.ConfigAccountExpenseForPeriodForm;
import de.financer.form.ConfigAccountGroupExpenseForPeriodForm;
@@ -19,6 +20,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.time.LocalDate;
@Controller
public class ChartController {
@@ -104,6 +106,23 @@ public class ChartController {
writeChart(response, chart);
}
+ @GetMapping("/getExpensePeriodTotalCurrentYear")
+ public void getExpensePeriodTotalCurrentYear(HttpServletResponse response) {
+ PeriodTotalParameter parameter = new PeriodTotalParameter();
+
+ parameter.setYear(LocalDate.now().getYear());
+ parameter.setTitle("financer.chart.expense-period-totals-current-year.title");
+ parameter.setxAxis("financer.chart.expense-period-totals-current-year.x");
+ parameter.setyAxis("financer.chart.expense-period-totals-current-year.y");
+
+ final ChartGenerator generator =
+ this.financerChartFactory.getGenerator(ChartType.EXPENSE_PERIOD_TOTALS_CURRENT_YEAR);
+
+ final JFreeChart chart = generator.generateChart(parameter);
+
+ writeChart(response, chart);
+ }
+
private void writeChart(HttpServletResponse response, JFreeChart chart) {
response.setContentType("image/png");
diff --git a/financer-web-client/src/main/java/de/financer/controller/Function.java b/financer-web-client/src/main/java/de/financer/controller/Function.java
index aa4786a..899fbc9 100644
--- a/financer-web-client/src/main/java/de/financer/controller/Function.java
+++ b/financer-web-client/src/main/java/de/financer/controller/Function.java
@@ -18,6 +18,7 @@ public enum Function {
TR_CREATE_TRANSACTION("transactions/createTransaction"),
TR_DELETE_TRANSACTION("transactions/deleteTransaction"),
TR_EXPENSES_CURRENT_PERIOD("transactions/getExpensesCurrentPeriod"),
+ TR_EXPENSE_PERIOD_TOTALS("transactions/getExpensePeriodTotals"),
RT_GET_ALL("recurringTransactions/getAll"),
RT_GET_ALL_ACTIVE("recurringTransactions/getAllActive"),
diff --git a/financer-web-client/src/main/java/de/financer/controller/ReportController.java b/financer-web-client/src/main/java/de/financer/controller/ReportController.java
index ace67d9..8546bc3 100644
--- a/financer-web-client/src/main/java/de/financer/controller/ReportController.java
+++ b/financer-web-client/src/main/java/de/financer/controller/ReportController.java
@@ -67,6 +67,10 @@ public class ReportController {
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
return "report/configureAccountExpensesForPeriod";
+ case EXPENSE_PERIOD_TOTALS_CURRENT_YEAR:
+ // Special case: this chart does not require parameters, so we can
+ // directly redirect to the actual chart instead of the config page
+ return "redirect:/getExpensePeriodTotalCurrentYear";
default:
// Cannot happen
throw new IllegalStateException("Unexpected value: " + selectedChartType);
diff --git a/financer-web-client/src/main/java/de/financer/template/GetExpensePeriodTotalsTemplate.java b/financer-web-client/src/main/java/de/financer/template/GetExpensePeriodTotalsTemplate.java
new file mode 100644
index 0000000..3c4795f
--- /dev/null
+++ b/financer-web-client/src/main/java/de/financer/template/GetExpensePeriodTotalsTemplate.java
@@ -0,0 +1,22 @@
+package de.financer.template;
+
+import de.financer.config.FinancerConfig;
+import de.financer.controller.Function;
+import de.financer.dto.ExpensePeriodTotal;
+import de.financer.util.ControllerUtils;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.util.UriComponentsBuilder;
+
+public class GetExpensePeriodTotalsTemplate {
+ public ResponseEntity> exchange(FinancerConfig financerConfig, int year) {
+ final UriComponentsBuilder builder = UriComponentsBuilder
+ .fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.TR_EXPENSE_PERIOD_TOTALS))
+ .queryParam("monthPeriodStartDay", financerConfig.getMonthPeriodStartDay())
+ .queryParam("year", year);
+
+ return new FinancerRestTemplate>()
+ .exchange(builder.toUriString(), new ParameterizedTypeReference>() {
+ });
+ }
+}
diff --git a/financer-web-client/src/main/resources/i18n/message.properties b/financer-web-client/src/main/resources/i18n/message.properties
index 88f75f8..6a00e8b 100644
--- a/financer-web-client/src/main/resources/i18n/message.properties
+++ b/financer-web-client/src/main/resources/i18n/message.properties
@@ -160,11 +160,16 @@ financer.chart.account-group-expenses-current-period.title=Expenses of the curre
financer.chart.account-group-expenses-for-period.title=Expenses for period from {0} to {1} grouped by account group
financer.chart.account-expenses-current-period.title=Expenses of the current period grouped by account
financer.chart.account-expenses-for-period.title=Expenses for period from {0} to {1} grouped by account
+financer.chart.expense-period-totals-current-year.title=Expense period totals for the current year
+financer.chart.expense-period-totals-current-year.x=Amount
+financer.chart.expense-period-totals-current-year.y=Period
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Expenses of the current period grouped by account group (pie chart)
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Expenses for a configurable period grouped by account group (pie chart)
financer.chart.name.ACCOUNT_EXPENSES_CURRENT_PERIOD=Expenses of the current period grouped by account (pie chart)
financer.chart.name.ACCOUNT_EXPENSES_FOR_PERIOD=Expenses for a configurable period grouped by account (pie chart)
+financer.chart.name.EXPENSE_PERIOD_TOTALS_CURRENT_YEAR=Overview about the income and expenses in the current year (bar chart)
+financer.chart.name.EXPENSE_PERIOD_TOTALS_FOR_YEAR=Overview about the income and expenses for a configurable year (bar chart)
financer.error-message.UNKNOWN_ERROR=An unknown error occurred!
financer.error-message.INVALID_ACCOUNT_TYPE=The selected account type is not valid!
diff --git a/financer-web-client/src/main/resources/i18n/message_de_DE.properties b/financer-web-client/src/main/resources/i18n/message_de_DE.properties
index 26324bd..fee2ccd 100644
--- a/financer-web-client/src/main/resources/i18n/message_de_DE.properties
+++ b/financer-web-client/src/main/resources/i18n/message_de_DE.properties
@@ -159,11 +159,16 @@ financer.chart.account-group-expenses-current-period.title=Ausgaben in der aktue
financer.chart.account-group-expenses-for-period.title=Ausgaben in der Periode vom {0} bis {1} gruppiert nach Konto-Gruppe
financer.chart.account-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Konto
financer.chart.account-expenses-for-period.title=Ausgaben in der Periode vom {0} bis {1} gruppiert nach Konto
+financer.chart.expense-period-totals-current-year.title=Gesamtbetr\u00E4ge gruppiert nach Periode für das aktuelle Jahr
+financer.chart.expense-period-totals-current-year.x=Betrag
+financer.chart.expense-period-totals-current-year.y=Periode
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe (Kuchendiagramm)
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto-Gruppe (Kuchendiagramm)
financer.chart.name.ACCOUNT_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto (Kuchendiagramm)
financer.chart.name.ACCOUNT_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto (Kuchendiagramm)
+financer.chart.name.EXPENSE_PERIOD_TOTALS_CURRENT_YEAR=\u00DCbersicht über das Einkommen und die Ausgaben im laufenden Jahr (Balkendiagramm)
+financer.chart.name.EXPENSE_PERIOD_TOTALS_FOR_YEAR=\u00DCbersicht über das Einkommen und die Ausgaben für ein konfigurierbares Jahr (Balkendiagramm)
financer.error-message.UNKNOWN_ERROR=Ein unbekannter Fehler ist aufgetreten!
financer.error-message.INVALID_ACCOUNT_TYPE=Der ausgew\u00E4hlte Kontotyp ist ung\u00FCltig!
diff --git a/financer-web-client/src/main/resources/static/changelog.txt b/financer-web-client/src/main/resources/static/changelog.txt
index 91aa056..eeba98f 100644
--- a/financer-web-client/src/main/resources/static/changelog.txt
+++ b/financer-web-client/src/main/resources/static/changelog.txt
@@ -2,6 +2,7 @@ v17 -> v18:
- Add readme to the footer
- Translate error messages to German
- Add chart type to chart description in chart type selection page
+- Add expense period total chart
v16 -> v17:
- Add this changelog to the footer
diff --git a/pom.xml b/pom.xml
index 81e1c02..50ef3b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,11 @@
junit
4.12
+
+ com.google.guava
+ guava
+ 28.0-jre
+
de.77zzcx7.financer
financer-common