Add another chart + UI for charts
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
package de.financer.chart;
|
||||||
|
|
||||||
|
import de.financer.config.FinancerConfig;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
|
||||||
|
public abstract class AbstractChartGenerator<P extends ChartParameter> implements ChartGenerator<P> {
|
||||||
|
private FinancerConfig financerConfig;
|
||||||
|
private MessageSource messageSource;
|
||||||
|
|
||||||
|
public String getMessage(String key) {
|
||||||
|
return this.getMessage(key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage(String key, Object[] args) {
|
||||||
|
return this.messageSource.getMessage(key, args, LocaleContextHolder.getLocale());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FinancerConfig getFinancerConfig() {
|
||||||
|
return financerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFinancerConfig(FinancerConfig financerConfig) {
|
||||||
|
this.financerConfig = financerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessageSource(MessageSource messageSource) {
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package de.financer.chart;
|
|
||||||
|
|
||||||
import de.financer.config.FinancerConfig;
|
|
||||||
import de.financer.dto.AccountGroupExpense;
|
|
||||||
import de.financer.template.GetAccountGroupExpensesTemplate;
|
|
||||||
import de.financer.util.ControllerUtils;
|
|
||||||
import org.apache.commons.collections4.IterableUtils;
|
|
||||||
import org.jfree.chart.ChartFactory;
|
|
||||||
import org.jfree.chart.JFreeChart;
|
|
||||||
import org.jfree.data.general.DefaultPieDataset;
|
|
||||||
import org.jfree.data.general.PieDataset;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
|
|
||||||
public class AccountGroupExpensesChartGenerator {
|
|
||||||
public JFreeChart generateChart(FinancerConfig financerConfig, LocalDate periodStart, LocalDate periodEnd, MessageSource messageSource) {
|
|
||||||
final String start = ControllerUtils.formatDate(financerConfig, periodStart);
|
|
||||||
final String end = ControllerUtils.formatDate(financerConfig, periodEnd);
|
|
||||||
|
|
||||||
final Iterable<AccountGroupExpense> expenses = new GetAccountGroupExpensesTemplate()
|
|
||||||
.exchange(financerConfig, start, end).getBody();
|
|
||||||
|
|
||||||
final PieDataset dataSet = createDataSet(expenses);
|
|
||||||
|
|
||||||
return ChartFactory.createPieChart(messageSource
|
|
||||||
.getMessage("financer.chart.account-group-expenses-current-period.title", null, LocaleContextHolder
|
|
||||||
.getLocale()), dataSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PieDataset createDataSet(Iterable<AccountGroupExpense> data) {
|
|
||||||
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
|
||||||
|
|
||||||
IterableUtils.toList(data).stream()
|
|
||||||
.forEach((ex) -> dataSet.setValue(ex.getAccountGroup().getName(), ex.getExpense()));
|
|
||||||
|
|
||||||
return dataSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package de.financer.chart;
|
||||||
|
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
|
||||||
|
public interface ChartGenerator<P extends ChartParameter> {
|
||||||
|
JFreeChart generateChart(P parameter);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package de.financer.chart;
|
||||||
|
|
||||||
|
public interface ChartParameter {
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package de.financer.chart;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public enum ChartType {
|
||||||
|
ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD,
|
||||||
|
ACCOUNT_GROUP_EXPENSES_FOR_PERIOD;
|
||||||
|
|
||||||
|
public static List<String> valueList() {
|
||||||
|
return Arrays.stream(ChartType.values()).map(ChartType::name).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChartType getByValue(String value) {
|
||||||
|
return Arrays.asList(values()).stream().filter((ct) -> ct.name().equals(value)).findFirst().get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package de.financer.chart;
|
||||||
|
|
||||||
|
import de.financer.chart.impl.AccountGroupExpensesGenerator;
|
||||||
|
import de.financer.config.FinancerConfig;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class FinancerChartFactory {
|
||||||
|
@Autowired
|
||||||
|
private FinancerConfig financerConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageSource messageSource;
|
||||||
|
|
||||||
|
public <P extends ChartParameter> ChartGenerator<P> getGenerator(ChartType chartType) {
|
||||||
|
AbstractChartGenerator<P> generator;
|
||||||
|
|
||||||
|
switch (chartType) {
|
||||||
|
case ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD:
|
||||||
|
// TODO WHY IS THIS CAST NECESSARY???
|
||||||
|
generator = (AbstractChartGenerator<P>) new AccountGroupExpensesGenerator();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
generator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
configureGenerator(generator);
|
||||||
|
|
||||||
|
return generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureGenerator(AbstractChartGenerator<?> generator) {
|
||||||
|
generator.setFinancerConfig(this.financerConfig);
|
||||||
|
generator.setMessageSource(this.messageSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package de.financer.chart.impl;
|
||||||
|
|
||||||
|
import de.financer.chart.AbstractChartGenerator;
|
||||||
|
import de.financer.dto.AccountGroupExpense;
|
||||||
|
import de.financer.template.GetAccountGroupExpensesTemplate;
|
||||||
|
import de.financer.util.ControllerUtils;
|
||||||
|
import org.apache.commons.collections4.IterableUtils;
|
||||||
|
import org.jfree.chart.ChartFactory;
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
import org.jfree.data.general.DefaultPieDataset;
|
||||||
|
import org.jfree.data.general.PieDataset;
|
||||||
|
|
||||||
|
public class AccountGroupExpensesGenerator extends AbstractChartGenerator<AccountGroupExpensesParameter> {
|
||||||
|
@Override
|
||||||
|
public JFreeChart generateChart(AccountGroupExpensesParameter parameter) {
|
||||||
|
final String start = ControllerUtils.formatDate(this.getFinancerConfig(), parameter.getPeriodStart());
|
||||||
|
final String end = ControllerUtils.formatDate(this.getFinancerConfig(), parameter.getPeriodEnd());
|
||||||
|
|
||||||
|
final Iterable<AccountGroupExpense> expenses = new GetAccountGroupExpensesTemplate()
|
||||||
|
.exchange(this.getFinancerConfig(), start, end).getBody();
|
||||||
|
|
||||||
|
final PieDataset dataSet = createDataSet(expenses);
|
||||||
|
|
||||||
|
return ChartFactory
|
||||||
|
.createPieChart(this.getMessage(parameter.getTitle(), parameter.getArgsForTitle()), dataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PieDataset createDataSet(Iterable<AccountGroupExpense> data) {
|
||||||
|
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
||||||
|
|
||||||
|
IterableUtils.toList(data).stream()
|
||||||
|
.forEach((ex) -> dataSet.setValue(ex.getAccountGroup().getName(), ex.getExpense()));
|
||||||
|
|
||||||
|
return dataSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package de.financer.chart.impl;
|
||||||
|
|
||||||
|
import de.financer.chart.ChartParameter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public class AccountGroupExpensesParameter implements ChartParameter {
|
||||||
|
private LocalDate periodStart;
|
||||||
|
private LocalDate periodEnd;
|
||||||
|
private String title;
|
||||||
|
private Object[] argsForTitle;
|
||||||
|
|
||||||
|
public LocalDate getPeriodStart() {
|
||||||
|
return periodStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeriodStart(LocalDate periodStart) {
|
||||||
|
this.periodStart = periodStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getPeriodEnd() {
|
||||||
|
return periodEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeriodEnd(LocalDate periodEnd) {
|
||||||
|
this.periodEnd = periodEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
package de.financer.controller;
|
package de.financer.controller;
|
||||||
|
|
||||||
import de.financer.chart.AccountGroupExpensesChartGenerator;
|
import de.financer.chart.impl.AccountGroupExpensesParameter;
|
||||||
|
import de.financer.chart.ChartGenerator;
|
||||||
|
import de.financer.chart.ChartType;
|
||||||
|
import de.financer.chart.FinancerChartFactory;
|
||||||
import de.financer.config.FinancerConfig;
|
import de.financer.config.FinancerConfig;
|
||||||
|
import de.financer.form.ConfigAccountGroupExpenseForPeriodForm;
|
||||||
|
import de.financer.util.ControllerUtils;
|
||||||
import de.financer.util.ExpensePeriod;
|
import de.financer.util.ExpensePeriod;
|
||||||
import org.jfree.chart.ChartUtils;
|
import org.jfree.chart.ChartUtils;
|
||||||
import org.jfree.chart.JFreeChart;
|
import org.jfree.chart.JFreeChart;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -19,16 +25,47 @@ public class ChartController {
|
|||||||
private FinancerConfig financerConfig;
|
private FinancerConfig financerConfig;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MessageSource messageSource;
|
private FinancerChartFactory financerChartFactory;
|
||||||
|
|
||||||
@GetMapping("/getAccountGroupExpensesCurrentPeriod")
|
@GetMapping("/getAccountGroupExpensesCurrentPeriod")
|
||||||
public void getAccountGroupExpensesCurrentPeriod(HttpServletResponse response) {
|
public void getAccountGroupExpensesCurrentPeriod(HttpServletResponse response) {
|
||||||
final ExpensePeriod period = ExpensePeriod
|
final ExpensePeriod period = ExpensePeriod
|
||||||
.getCurrentExpensePeriod(this.financerConfig.getMonthPeriodStartDay());
|
.getCurrentExpensePeriod(this.financerConfig.getMonthPeriodStartDay());
|
||||||
|
final AccountGroupExpensesParameter parameter = new AccountGroupExpensesParameter();
|
||||||
|
|
||||||
JFreeChart chart = new AccountGroupExpensesChartGenerator()
|
parameter.setPeriodStart(period.getStart());
|
||||||
.generateChart(this.financerConfig, period.getStart(), period.getEnd(), this.messageSource);
|
parameter.setPeriodEnd(period.getEnd());
|
||||||
|
parameter.setTitle("financer.chart.account-group-expenses-current-period.title");
|
||||||
|
|
||||||
|
final ChartGenerator<AccountGroupExpensesParameter> generator =
|
||||||
|
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD);
|
||||||
|
|
||||||
|
final JFreeChart chart = generator.generateChart(parameter);
|
||||||
|
|
||||||
|
writeChart(response, chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/getAccountGroupExpensesForPeriod")
|
||||||
|
public void getAccountGroupExpensesForPeriod(HttpServletResponse response, ConfigAccountGroupExpenseForPeriodForm form) {
|
||||||
|
final AccountGroupExpensesParameter parameter = new AccountGroupExpensesParameter();
|
||||||
|
|
||||||
|
parameter.setPeriodStart(ControllerUtils.parseDate(this.financerConfig, form.getFromDate()));
|
||||||
|
parameter.setPeriodEnd(ControllerUtils.parseDate(this.financerConfig, form.getToDate()));
|
||||||
|
parameter.setTitle("financer.chart.account-group-expenses-for-period.title");
|
||||||
|
parameter.setArgsForTitle(new Object[]{ControllerUtils.formatDate(this.financerConfig, form
|
||||||
|
.getFromDate(), LocaleContextHolder
|
||||||
|
.getLocale()), ControllerUtils.formatDate(this.financerConfig, form.getToDate(), LocaleContextHolder
|
||||||
|
.getLocale())});
|
||||||
|
|
||||||
|
final ChartGenerator<AccountGroupExpensesParameter> generator =
|
||||||
|
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD);
|
||||||
|
|
||||||
|
final JFreeChart chart = generator.generateChart(parameter);
|
||||||
|
|
||||||
|
writeChart(response, chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeChart(HttpServletResponse response, JFreeChart chart) {
|
||||||
response.setContentType("image/png");
|
response.setContentType("image/png");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package de.financer.controller;
|
||||||
|
|
||||||
|
import de.financer.chart.ChartType;
|
||||||
|
import de.financer.config.FinancerConfig;
|
||||||
|
import de.financer.form.ConfigAccountGroupExpenseForPeriodForm;
|
||||||
|
import de.financer.form.SelectChartForm;
|
||||||
|
import de.financer.util.ControllerUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ReportController {
|
||||||
|
@Autowired
|
||||||
|
private FinancerConfig financerConfig;
|
||||||
|
|
||||||
|
@GetMapping("/selectChart")
|
||||||
|
public String selectChart(Model model) {
|
||||||
|
model.addAttribute("form", new SelectChartForm());
|
||||||
|
model.addAttribute("availableCharts", ChartType.valueList());
|
||||||
|
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||||
|
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||||
|
|
||||||
|
return "report/selectChart";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/configureChart")
|
||||||
|
public String configureChart(SelectChartForm form, Model model) {
|
||||||
|
final ChartType selectedChartType;
|
||||||
|
|
||||||
|
try {
|
||||||
|
selectedChartType = ChartType.getByValue(form.getChartType());
|
||||||
|
}
|
||||||
|
catch (NoSuchElementException nsee) {
|
||||||
|
model.addAttribute("form", new SelectChartForm());
|
||||||
|
model.addAttribute("errorMessage", "UNKNOWN_CHART_TYPE");
|
||||||
|
model.addAttribute("availableCharts", ChartType.valueList());
|
||||||
|
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||||
|
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||||
|
|
||||||
|
return "report/selectChart";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(selectedChartType) {
|
||||||
|
case ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD:
|
||||||
|
// Special case: this chart does not require parameters, so we can
|
||||||
|
// directly redirect to the actual chart instead of the config page
|
||||||
|
return "redirect:/getAccountGroupExpensesCurrentPeriod";
|
||||||
|
case ACCOUNT_GROUP_EXPENSES_FOR_PERIOD:
|
||||||
|
model.addAttribute("form", new ConfigAccountGroupExpenseForPeriodForm());
|
||||||
|
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||||
|
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||||
|
|
||||||
|
return "report/configureAccountGroupExpensesForPeriod";
|
||||||
|
default:
|
||||||
|
// Cannot happen
|
||||||
|
throw new IllegalStateException("Unexpected value: " + selectedChartType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package de.financer.form;
|
||||||
|
|
||||||
|
public class ConfigAccountGroupExpenseForPeriodForm {
|
||||||
|
private String fromDate;
|
||||||
|
private String toDate;
|
||||||
|
|
||||||
|
public String getFromDate() {
|
||||||
|
return fromDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFromDate(String fromDate) {
|
||||||
|
this.fromDate = fromDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToDate() {
|
||||||
|
return toDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToDate(String toDate) {
|
||||||
|
this.toDate = toDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package de.financer.form;
|
||||||
|
|
||||||
|
public class SelectChartForm {
|
||||||
|
private String chartType;
|
||||||
|
|
||||||
|
public String getChartType() {
|
||||||
|
return chartType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChartType(String chartType) {
|
||||||
|
this.chartType = chartType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,13 @@ import org.apache.commons.collections4.IterableUtils;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.FormatStyle;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ControllerUtils {
|
public class ControllerUtils {
|
||||||
@@ -55,6 +58,26 @@ public class ControllerUtils {
|
|||||||
return formatted.format(DateTimeFormatter.ofPattern(financerConfig.getDateFormat()));
|
return formatted.format(DateTimeFormatter.ofPattern(financerConfig.getDateFormat()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatDate(FinancerConfig financerConfig, String dateFromForm, Locale locale) {
|
||||||
|
if (StringUtils.isEmpty(dateFromForm)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The format is always "yyyy-MM-dd", see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date
|
||||||
|
final LocalDate formatted = LocalDate.parse(dateFromForm, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
|
||||||
|
return formatted.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDate parseDate(FinancerConfig financerConfig, String dateFromForm) {
|
||||||
|
if (StringUtils.isEmpty(dateFromForm)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The format is always "yyyy-MM-dd", see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date
|
||||||
|
return LocalDate.parse(dateFromForm, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
}
|
||||||
|
|
||||||
public static List<RecurringTransaction> filterEmptyEntries(Iterable<RecurringTransaction> recurringTransactions) {
|
public static List<RecurringTransaction> filterEmptyEntries(Iterable<RecurringTransaction> recurringTransactions) {
|
||||||
return IterableUtils.toList(recurringTransactions).stream()
|
return IterableUtils.toList(recurringTransactions).stream()
|
||||||
.filter((rt) -> rt.getFromAccount() != null && rt.getToAccount() != null)
|
.filter((rt) -> rt.getFromAccount() != null && rt.getToAccount() != null)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ financer.account-overview.available-actions.create-transaction=Create new transa
|
|||||||
financer.account-overview.available-actions.create-recurring-transaction=Create new recurring transaction
|
financer.account-overview.available-actions.create-recurring-transaction=Create new recurring transaction
|
||||||
financer.account-overview.available-actions.recurring-transaction-all=Show all recurring transactions
|
financer.account-overview.available-actions.recurring-transaction-all=Show all recurring transactions
|
||||||
financer.account-overview.available-actions.create-account-group=Create new account group
|
financer.account-overview.available-actions.create-account-group=Create new account group
|
||||||
|
financer.account-overview.available-actions.select-chart=Generate a chart
|
||||||
financer.account-overview.status=Status\:
|
financer.account-overview.status=Status\:
|
||||||
financer.account-overview.status.recurring-transaction-due-today=Recurring transactions due today\:
|
financer.account-overview.status.recurring-transaction-due-today=Recurring transactions due today\:
|
||||||
financer.account-overview.status.recurring-transaction-active=Active recurring transactions\:
|
financer.account-overview.status.recurring-transaction-active=Active recurring transactions\:
|
||||||
@@ -18,7 +19,7 @@ financer.account-overview.table-header.group=Group
|
|||||||
financer.account-overview.table-header.balance=Current Balance
|
financer.account-overview.table-header.balance=Current Balance
|
||||||
financer.account-overview.table-header.type=Type
|
financer.account-overview.table-header.type=Type
|
||||||
financer.account-overview.table-header.status=Status
|
financer.account-overview.table-header.status=Status
|
||||||
financer.account-overview.tooltip.status.current-expenses=Period from {0} to {1}
|
financer.account-overview.tooltip.status.current-expenses=Period from {0} to {1}. Clicking the amount will open a graphical overview about the expenses grouped by account group
|
||||||
financer.account-overview.tooltip.status.current-assets=Assets available at short-notice
|
financer.account-overview.tooltip.status.current-assets=Assets available at short-notice
|
||||||
|
|
||||||
financer.account-new.title=financer\: create new account
|
financer.account-new.title=financer\: create new account
|
||||||
@@ -103,6 +104,14 @@ financer.recurring-to-transaction-with-amount.title=financer\: create transactio
|
|||||||
financer.recurring-to-transaction-with-amount.label.amount=Amount\:
|
financer.recurring-to-transaction-with-amount.label.amount=Amount\:
|
||||||
financer.recurring-to-transaction-with-amount.submit=Create
|
financer.recurring-to-transaction-with-amount.submit=Create
|
||||||
|
|
||||||
|
financer.chart-select.title=Select a chart to generate
|
||||||
|
financer.chart-select.submit=Select
|
||||||
|
|
||||||
|
financer.chart-config-account-group-expenses-for-period.title=Configure account group expenses for period chart
|
||||||
|
financer.chart-config-account-group-expenses-for-period.label.from-date=From date\:
|
||||||
|
financer.chart-config-account-group-expenses-for-period.label.to-date=To date\:
|
||||||
|
financer.chart-config-account-group-expenses-for-period.submit=Generate
|
||||||
|
|
||||||
financer.interval-type.DAILY=Daily
|
financer.interval-type.DAILY=Daily
|
||||||
financer.interval-type.WEEKLY=Weekly
|
financer.interval-type.WEEKLY=Weekly
|
||||||
financer.interval-type.MONTHLY=Monthly
|
financer.interval-type.MONTHLY=Monthly
|
||||||
@@ -133,10 +142,16 @@ financer.heading.recurring-transaction-list.dueToday=financer\: recurring transa
|
|||||||
financer.heading.recurring-transaction-list.active=financer\: active recurring transactions
|
financer.heading.recurring-transaction-list.active=financer\: active recurring transactions
|
||||||
financer.heading.recurring-transaction-list.all=financer\: all recurring transaction
|
financer.heading.recurring-transaction-list.all=financer\: all recurring transaction
|
||||||
financer.heading.recurring-to-transaction-with-amount=financer\: create transaction from recurring with amount
|
financer.heading.recurring-to-transaction-with-amount=financer\: create transaction from recurring with amount
|
||||||
|
financer.heading.chart-select=financer\: select a chart to generate
|
||||||
|
financer.heading.chart-config-account-group-expenses-for-period=financer\: configure account group expenses for period chart
|
||||||
|
|
||||||
financer.cancel-back-to-overview=Cancel and back to overview
|
financer.cancel-back-to-overview=Cancel and back to overview
|
||||||
|
|
||||||
financer.chart.account-group-expenses-current-period.title=Expenses of the current period grouped by account group
|
financer.chart.account-group-expenses-current-period.title=Expenses of the current period grouped by account group
|
||||||
|
financer.chart.account-group-expenses-for-period.title=Expenses for period from {0} to {1} grouped by account group
|
||||||
|
|
||||||
|
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Expenses of the current period grouped by account group
|
||||||
|
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Expenses for a configurable period grouped by account group
|
||||||
|
|
||||||
financer.error-message.UNKNOWN_ERROR=An unknown error occurred!
|
financer.error-message.UNKNOWN_ERROR=An unknown error occurred!
|
||||||
financer.error-message.INVALID_ACCOUNT_TYPE=The selected account type is not valid!
|
financer.error-message.INVALID_ACCOUNT_TYPE=The selected account type is not valid!
|
||||||
@@ -165,3 +180,4 @@ financer.error-message.ACCOUNT_NOT_FOUND=The account could not be found!
|
|||||||
financer.error-message.DUPLICATE_ACCOUNT_KEY=An account with the given key already exists!
|
financer.error-message.DUPLICATE_ACCOUNT_KEY=An account with the given key already exists!
|
||||||
financer.error-message.DUPLICATE_ACCOUNT_GROUP_NAME=An account group with the given key already exists!
|
financer.error-message.DUPLICATE_ACCOUNT_GROUP_NAME=An account group with the given key already exists!
|
||||||
financer.error-message.ACCOUNT_GROUP_NOT_FOUND=The account group could not be found!
|
financer.error-message.ACCOUNT_GROUP_NOT_FOUND=The account group could not be found!
|
||||||
|
financer.error-message.UNKNOWN_CHART_TYPE=The selected chart type is not known!
|
||||||
@@ -7,6 +7,7 @@ financer.account-overview.available-actions.create-transaction=Neue Buchung erst
|
|||||||
financer.account-overview.available-actions.create-recurring-transaction=Neue wiederkehrende Buchung erstellen
|
financer.account-overview.available-actions.create-recurring-transaction=Neue wiederkehrende Buchung erstellen
|
||||||
financer.account-overview.available-actions.recurring-transaction-all=Zeige alle wiederkehrende Buchungen
|
financer.account-overview.available-actions.recurring-transaction-all=Zeige alle wiederkehrende Buchungen
|
||||||
financer.account-overview.available-actions.create-account-group=Neue Konto-Gruppe erstellen
|
financer.account-overview.available-actions.create-account-group=Neue Konto-Gruppe erstellen
|
||||||
|
financer.account-overview.available-actions.select-chart=Ein Diagramm erzeugen
|
||||||
financer.account-overview.status=Status\:
|
financer.account-overview.status=Status\:
|
||||||
financer.account-overview.status.recurring-transaction-due-today=Wiederkehrende Buchungen heute f\u00E4llig\:
|
financer.account-overview.status.recurring-transaction-due-today=Wiederkehrende Buchungen heute f\u00E4llig\:
|
||||||
financer.account-overview.status.recurring-transaction-active=Aktive wiederkehrende Buchungen\:
|
financer.account-overview.status.recurring-transaction-active=Aktive wiederkehrende Buchungen\:
|
||||||
@@ -18,7 +19,7 @@ financer.account-overview.table-header.group=Gruppe
|
|||||||
financer.account-overview.table-header.balance=Kontostand
|
financer.account-overview.table-header.balance=Kontostand
|
||||||
financer.account-overview.table-header.type=Typ
|
financer.account-overview.table-header.type=Typ
|
||||||
financer.account-overview.table-header.status=Status
|
financer.account-overview.table-header.status=Status
|
||||||
financer.account-overview.tooltip.status.current-expenses=Periode ab {0} bis {1}
|
financer.account-overview.tooltip.status.current-expenses=Periode ab {0} bis {1}. Durch Klicken des Betrags kann eine grafische \u00DCbersicht über die Ausgaben gruppiert nach Konto-Gruppe angezeigt werden
|
||||||
financer.account-overview.tooltip.status.current-assets=Kurzfristig verf\u00FCgbares Verm\u00F6gen
|
financer.account-overview.tooltip.status.current-assets=Kurzfristig verf\u00FCgbares Verm\u00F6gen
|
||||||
|
|
||||||
financer.account-new.title=financer\: Neues Konto erstellen
|
financer.account-new.title=financer\: Neues Konto erstellen
|
||||||
@@ -103,6 +104,14 @@ financer.recurring-to-transaction-with-amount.title=financer\: Buchung mit Betra
|
|||||||
financer.recurring-to-transaction-with-amount.label.amount=Betrag\:
|
financer.recurring-to-transaction-with-amount.label.amount=Betrag\:
|
||||||
financer.recurring-to-transaction-with-amount.submit=Erstellen
|
financer.recurring-to-transaction-with-amount.submit=Erstellen
|
||||||
|
|
||||||
|
financer.chart-select.title=Ein Diagramm zum Erzeugen ausw\u00E4hlen
|
||||||
|
financer.chart-select.submit=Ausw\u00E4hlen
|
||||||
|
|
||||||
|
financer.chart-config-account-group-expenses-for-period.title=Konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Konto-Gruppe Diagramm
|
||||||
|
financer.chart-config-account-group-expenses-for-period.label.from-date=Von Datum\:
|
||||||
|
financer.chart-config-account-group-expenses-for-period.label.to-date=Bis Datum\:
|
||||||
|
financer.chart-config-account-group-expenses-for-period.submit=Erzeugen
|
||||||
|
|
||||||
financer.interval-type.DAILY=T\u00E4glich
|
financer.interval-type.DAILY=T\u00E4glich
|
||||||
financer.interval-type.WEEKLY=W\u00F6chentlich
|
financer.interval-type.WEEKLY=W\u00F6chentlich
|
||||||
financer.interval-type.MONTHLY=Monatlich
|
financer.interval-type.MONTHLY=Monatlich
|
||||||
@@ -133,7 +142,13 @@ financer.heading.recurring-transaction-list.dueToday=financer\: wiederkehrende B
|
|||||||
financer.heading.recurring-transaction-list.active=financer\: aktive wiederkehrende Buchungen
|
financer.heading.recurring-transaction-list.active=financer\: aktive wiederkehrende Buchungen
|
||||||
financer.heading.recurring-transaction-list.all=financer\: alle wiederkehrende Buchungen
|
financer.heading.recurring-transaction-list.all=financer\: alle wiederkehrende Buchungen
|
||||||
financer.heading.recurring-to-transaction-with-amount=financer\: Buchung mit Betrag aus wiederkehrender Buchung erstellen
|
financer.heading.recurring-to-transaction-with-amount=financer\: Buchung mit Betrag aus wiederkehrender Buchung erstellen
|
||||||
|
financer.heading.chart-select=financer\: ein Diagramm zum Erzeugen ausw\u00E4hlen
|
||||||
|
financer.heading.chart-config-account-group-expenses-for-period=financer\: konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Konto-Gruppe Diagramm
|
||||||
|
|
||||||
financer.cancel-back-to-overview=Abbrechen und zur \u00DCbersicht
|
financer.cancel-back-to-overview=Abbrechen und zur \u00DCbersicht
|
||||||
|
|
||||||
financer.chart.account-group-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe
|
financer.chart.account-group-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe
|
||||||
|
financer.chart.account-group-expenses-for-period.title=Ausgaben in der Periode vom {0} bis {1} gruppiert nach Konto-Gruppe
|
||||||
|
|
||||||
|
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe
|
||||||
|
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto-Gruppe
|
||||||
@@ -67,15 +67,24 @@ tr:hover {
|
|||||||
#new-transaction-form *,
|
#new-transaction-form *,
|
||||||
#new-recurring-transaction-form *,
|
#new-recurring-transaction-form *,
|
||||||
#recurring-to-transaction-with-amount-form *,
|
#recurring-to-transaction-with-amount-form *,
|
||||||
#new-account-group-form * {
|
#new-account-group-form *,
|
||||||
|
#chart-config-account-group-expenses-for-period-form * {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
width: 20em;
|
width: 20em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#chart-select-form div {
|
||||||
|
width: 20em;
|
||||||
|
margin-top: 1em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
input[type=submit] {
|
input[type=submit] {
|
||||||
|
margin-top: 1em;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
width: 20em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer-container {
|
#footer-container {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
<span th:text="#{financer.account-overview.status.recurring-transaction-active}"/>
|
<span th:text="#{financer.account-overview.status.recurring-transaction-active}"/>
|
||||||
<a th:href="@{/recurringTransactionActive}" th:text="${rtAllActiveCount}"/>
|
<a th:href="@{/recurringTransactionActive}" th:text="${rtAllActiveCount}"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<span th:text="#{financer.account-overview.available-actions}"/>
|
<span th:text="#{financer.account-overview.available-actions}"/>
|
||||||
<div id="action-container">
|
<div id="action-container">
|
||||||
@@ -48,6 +49,10 @@
|
|||||||
<a th:href="@{/recurringTransactionAll}"
|
<a th:href="@{/recurringTransactionAll}"
|
||||||
th:text="#{financer.account-overview.available-actions.recurring-transaction-all}"/>
|
th:text="#{financer.account-overview.available-actions.recurring-transaction-all}"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="action-container-sub-reports">
|
||||||
|
<a th:href="@{/selectChart}"
|
||||||
|
th:text="#{financer.account-overview.available-actions.select-chart}"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table id="account-overview-table">
|
<table id="account-overview-table">
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title th:text="#{financer.chart-config-account-group-expenses-for-period.title}"/>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" th:href="@{/css/main.css}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 th:text="#{financer.heading.chart-config-account-group-expenses-for-period}"/>
|
||||||
|
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
|
||||||
|
<a th:href="@{/accountOverview}" th:text="#{financer.cancel-back-to-overview}"/>
|
||||||
|
<form id="chart-config-account-group-expenses-for-period-form" action="#"
|
||||||
|
th:action="@{/getAccountGroupExpensesForPeriod}" th:object="${form}" method="post">
|
||||||
|
<label for="fromDate" th:text="#{financer.chart-config-account-group-expenses-for-period.label.from-date}"/>
|
||||||
|
<input type="date" id="fromDate" th:field="*{fromDate}"/>
|
||||||
|
<label for="toDate" th:text="#{financer.chart-config-account-group-expenses-for-period.label.to-date}"/>
|
||||||
|
<input type="date" id="toDate" th:field="*{toDate}"/>
|
||||||
|
<input type="submit" th:value="#{financer.chart-config-account-group-expenses-for-period.submit}"/>
|
||||||
|
</form>
|
||||||
|
<div th:replace="includes/footer :: footer"/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title th:text="#{financer.chart-select.title}"/>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" th:href="@{/css/main.css}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 th:text="#{financer.heading.chart-select}"/>
|
||||||
|
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
|
||||||
|
<a th:href="@{/accountOverview}" th:text="#{financer.cancel-back-to-overview}"/>
|
||||||
|
<form id="chart-select-form" action="#" th:action="@{/configureChart}" th:object="${form}" method="post">
|
||||||
|
<th:block th:each="chart, iterStat : ${availableCharts}">
|
||||||
|
<div>
|
||||||
|
<input type="radio" th:value="${chart}" th:field="*{chartType}" th:id="'chart' + ${iterStat.count}"/>
|
||||||
|
<label th:for="'chart' + ${iterStat.count}" th:text="#{${'financer.chart.name.' + chart}}"/>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
<input type="submit" th:value="#{financer.chart-select.submit}"/>
|
||||||
|
</form>
|
||||||
|
<div th:replace="includes/footer :: footer"/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user