Add chart report for expenses grouped by account
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package de.financer.dto;
|
||||
|
||||
import de.financer.model.Account;
|
||||
|
||||
public class AccountExpense {
|
||||
private Account account;
|
||||
private Long expense;
|
||||
|
||||
public AccountExpense() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public AccountExpense(Account account, Long expense) {
|
||||
this.account = account;
|
||||
this.expense = expense;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Long getExpense() {
|
||||
return expense;
|
||||
}
|
||||
|
||||
public void setExpense(Long expense) {
|
||||
this.expense = expense;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.financer.controller;
|
||||
|
||||
import de.financer.ResponseReason;
|
||||
import de.financer.dto.AccountExpense;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.service.AccountService;
|
||||
import org.slf4j.Logger;
|
||||
@@ -101,4 +102,13 @@ public class AccountController {
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@RequestMapping("getAccountExpenses")
|
||||
public Iterable<AccountExpense> getAccountExpenses(String periodStart, String periodEnd) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("/accounts/getAccountExpenses got parameters: %s|%s", periodStart, periodEnd));
|
||||
}
|
||||
|
||||
return this.accountService.getAccountExpenses(periodStart, periodEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.financer.dba;
|
||||
|
||||
import de.financer.dto.AccountExpense;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.model.AccountType;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
@@ -7,10 +8,15 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public interface AccountRepository extends CrudRepository<Account, Long> {
|
||||
Account findByKey(String key);
|
||||
|
||||
@Query("SELECT SUM(a.currentBalance) FROM Account a WHERE a.type IN :accountTypes")
|
||||
Long getCurrentAssets(AccountType... accountTypes);
|
||||
|
||||
@Query("SELECT new de.financer.dto.AccountExpense(a, SUM(t.amount)) FROM Transaction t JOIN t.toAccount a WHERE a.type in :expenseTypes AND t.date BETWEEN :startDate AND :startEnd GROUP BY a")
|
||||
Iterable<AccountExpense> getAccountExpenses(LocalDate startDate, LocalDate startEnd, AccountType... expenseTypes);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package de.financer.service;
|
||||
|
||||
import de.financer.ResponseReason;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.dba.AccountRepository;
|
||||
import de.financer.dto.AccountExpense;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.model.AccountGroup;
|
||||
import de.financer.model.AccountStatus;
|
||||
@@ -15,8 +17,10 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Collections;
|
||||
|
||||
@Service
|
||||
public class AccountService {
|
||||
@@ -24,9 +28,13 @@ public class AccountService {
|
||||
|
||||
@Autowired
|
||||
private AccountRepository accountRepository;
|
||||
|
||||
@Autowired
|
||||
private AccountGroupService accountGroupService;
|
||||
|
||||
@Autowired
|
||||
private FinancerConfig financerConfig;
|
||||
|
||||
/**
|
||||
* This method returns the account identified by the given key.
|
||||
*
|
||||
@@ -152,4 +160,22 @@ public class AccountService {
|
||||
public Long getCurrentAssets() {
|
||||
return this.accountRepository.getCurrentAssets(AccountType.BANK, AccountType.CASH);
|
||||
}
|
||||
|
||||
public Iterable<AccountExpense> getAccountExpenses(String periodStart, String periodEnd) {
|
||||
LocalDate startDate;
|
||||
LocalDate endDate;
|
||||
|
||||
try {
|
||||
startDate = LocalDate.parse(periodStart, DateTimeFormatter.ofPattern(this.financerConfig.getDateFormat()));
|
||||
endDate = LocalDate.parse(periodEnd, DateTimeFormatter.ofPattern(this.financerConfig.getDateFormat()));
|
||||
} catch (DateTimeParseException dtpe) {
|
||||
LOGGER.error(String
|
||||
.format("Could not parse periodStart (%s) or periodEnd (%s): %s", periodStart, periodEnd, dtpe
|
||||
.getMessage()));
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return this.accountRepository.getAccountExpenses(startDate, endDate, AccountType.LIABILITY, AccountType.EXPENSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ import java.util.stream.Collectors;
|
||||
|
||||
public enum ChartType {
|
||||
ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD,
|
||||
ACCOUNT_GROUP_EXPENSES_FOR_PERIOD;
|
||||
ACCOUNT_GROUP_EXPENSES_FOR_PERIOD,
|
||||
ACCOUNT_EXPENSES_CURRENT_PERIOD,
|
||||
ACCOUNT_EXPENSES_FOR_PERIOD;
|
||||
|
||||
public static List<String> valueList() {
|
||||
return Arrays.stream(ChartType.values()).map(ChartType::name).collect(Collectors.toList());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.financer.chart;
|
||||
|
||||
import de.financer.chart.impl.AccountGroupExpensesGenerator;
|
||||
import de.financer.chart.impl.expense.AccountExpensesGenerator;
|
||||
import de.financer.chart.impl.expense.AccountGroupExpensesGenerator;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
@@ -19,9 +20,17 @@ public class FinancerChartFactory {
|
||||
|
||||
switch (chartType) {
|
||||
case ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD:
|
||||
// Fall through
|
||||
case ACCOUNT_GROUP_EXPENSES_FOR_PERIOD:
|
||||
// TODO WHY IS THIS CAST NECESSARY???
|
||||
generator = (AbstractChartGenerator<P>) new AccountGroupExpensesGenerator();
|
||||
break;
|
||||
case ACCOUNT_EXPENSES_CURRENT_PERIOD:
|
||||
// Fall through
|
||||
case ACCOUNT_EXPENSES_FOR_PERIOD:
|
||||
// TODO WHY IS THIS CAST NECESSARY???
|
||||
generator = (AbstractChartGenerator<P>) new AccountExpensesGenerator();
|
||||
break;
|
||||
default:
|
||||
generator = null;
|
||||
}
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
package de.financer.chart.impl;
|
||||
package de.financer.chart.impl.expense;
|
||||
|
||||
import de.financer.chart.AbstractChartGenerator;
|
||||
import de.financer.dto.AccountGroupExpense;
|
||||
import de.financer.template.GetAccountGroupExpensesTemplate;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.jfree.chart.ChartFactory;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
|
||||
import org.jfree.chart.plot.PiePlot;
|
||||
import org.jfree.data.general.DefaultPieDataset;
|
||||
import org.jfree.data.general.PieDataset;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class AccountGroupExpensesGenerator extends AbstractChartGenerator<AccountGroupExpensesParameter> {
|
||||
public abstract class AbstractExpensesGenerator extends AbstractChartGenerator<ExpensesParameter> {
|
||||
@Override
|
||||
public JFreeChart generateChart(AccountGroupExpensesParameter parameter) {
|
||||
public JFreeChart generateChart(ExpensesParameter 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);
|
||||
final PieDataset dataSet = getDataset(start, end, this.getFinancerConfig());
|
||||
|
||||
final JFreeChart chart = ChartFactory
|
||||
.createPieChart(this.getMessage(parameter.getTitle(), parameter.getArgsForTitle()), dataSet);
|
||||
@@ -40,12 +34,19 @@ public class AccountGroupExpensesGenerator extends AbstractChartGenerator<Accoun
|
||||
return chart;
|
||||
}
|
||||
|
||||
private PieDataset createDataSet(Iterable<AccountGroupExpense> data) {
|
||||
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
||||
|
||||
IterableUtils.toList(data).stream()
|
||||
.forEach((ex) -> dataSet.setValue(ex.getAccountGroup().getName(), (ex.getExpense() / 100D)));
|
||||
|
||||
return dataSet;
|
||||
}
|
||||
/**
|
||||
* This method obtains the chart data via a REST call from the backend server application and transforms them into
|
||||
* a compatible dataset.
|
||||
*
|
||||
* TODO Getting the data here seems kinda wrong as the data access is usually done in the controllers. However,
|
||||
* TODO this would require to pass the data from the calling controller via the ExpensesParameter. To do this
|
||||
* TODO the parameter class either needs to be extended into two subclasses that each declare the corresponding data
|
||||
* TODO field or the data has to be generified.
|
||||
*
|
||||
* @param start - the start of the period
|
||||
* @param end - the end of the period
|
||||
* @param financerConfig - the financer config that holds the REST endpoint config
|
||||
* @return the created dataset
|
||||
*/
|
||||
protected abstract PieDataset getDataset(String start, String end, FinancerConfig financerConfig);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.financer.chart.impl.expense;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.dto.AccountExpense;
|
||||
import de.financer.dto.AccountGroupExpense;
|
||||
import de.financer.template.GetAccountExpensesTemplate;
|
||||
import de.financer.template.GetAccountGroupExpensesTemplate;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.jfree.data.general.DefaultPieDataset;
|
||||
import org.jfree.data.general.PieDataset;
|
||||
|
||||
public class AccountExpensesGenerator extends AbstractExpensesGenerator {
|
||||
@Override
|
||||
protected PieDataset getDataset(String start, String end, FinancerConfig financerConfig) {
|
||||
final Iterable<AccountExpense> expenses = new GetAccountExpensesTemplate()
|
||||
.exchange(financerConfig, start, end).getBody();
|
||||
|
||||
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
||||
|
||||
IterableUtils.toList(expenses).stream()
|
||||
.forEach((ex) -> dataSet.setValue(ex.getAccount().getKey(), (ex.getExpense() / 100D)));
|
||||
|
||||
return dataSet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.financer.chart.impl.expense;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.dto.AccountGroupExpense;
|
||||
import de.financer.template.GetAccountGroupExpensesTemplate;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.jfree.data.general.DefaultPieDataset;
|
||||
import org.jfree.data.general.PieDataset;
|
||||
|
||||
public class AccountGroupExpensesGenerator extends AbstractExpensesGenerator {
|
||||
@Override
|
||||
protected PieDataset getDataset(String start, String end, FinancerConfig financerConfig) {
|
||||
final Iterable<AccountGroupExpense> expenses = new GetAccountGroupExpensesTemplate()
|
||||
.exchange(financerConfig, start, end).getBody();
|
||||
|
||||
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
||||
|
||||
IterableUtils.toList(expenses).stream()
|
||||
.forEach((ex) -> dataSet.setValue(ex.getAccountGroup().getName(), (ex.getExpense() / 100D)));
|
||||
|
||||
return dataSet;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package de.financer.chart.impl;
|
||||
package de.financer.chart.impl.expense;
|
||||
|
||||
import de.financer.chart.ChartParameter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class AccountGroupExpensesParameter implements ChartParameter {
|
||||
public class ExpensesParameter implements ChartParameter {
|
||||
private LocalDate periodStart;
|
||||
private LocalDate periodEnd;
|
||||
private String title;
|
||||
@@ -1,10 +1,11 @@
|
||||
package de.financer.controller;
|
||||
|
||||
import de.financer.chart.impl.AccountGroupExpensesParameter;
|
||||
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.config.FinancerConfig;
|
||||
import de.financer.form.ConfigAccountExpenseForPeriodForm;
|
||||
import de.financer.form.ConfigAccountGroupExpenseForPeriodForm;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import de.financer.util.ExpensePeriod;
|
||||
@@ -31,13 +32,13 @@ public class ChartController {
|
||||
public void getAccountGroupExpensesCurrentPeriod(HttpServletResponse response) {
|
||||
final ExpensePeriod period = ExpensePeriod
|
||||
.getCurrentExpensePeriod(this.financerConfig.getMonthPeriodStartDay());
|
||||
final AccountGroupExpensesParameter parameter = new AccountGroupExpensesParameter();
|
||||
final ExpensesParameter parameter = new ExpensesParameter();
|
||||
|
||||
parameter.setPeriodStart(period.getStart());
|
||||
parameter.setPeriodEnd(period.getEnd());
|
||||
parameter.setTitle("financer.chart.account-group-expenses-current-period.title");
|
||||
|
||||
final ChartGenerator<AccountGroupExpensesParameter> generator =
|
||||
final ChartGenerator<ExpensesParameter> generator =
|
||||
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD);
|
||||
|
||||
final JFreeChart chart = generator.generateChart(parameter);
|
||||
@@ -47,7 +48,7 @@ public class ChartController {
|
||||
|
||||
@PostMapping("/getAccountGroupExpensesForPeriod")
|
||||
public void getAccountGroupExpensesForPeriod(HttpServletResponse response, ConfigAccountGroupExpenseForPeriodForm form) {
|
||||
final AccountGroupExpensesParameter parameter = new AccountGroupExpensesParameter();
|
||||
final ExpensesParameter parameter = new ExpensesParameter();
|
||||
|
||||
parameter.setPeriodStart(ControllerUtils.parseDate(this.financerConfig, form.getFromDate()));
|
||||
parameter.setPeriodEnd(ControllerUtils.parseDate(this.financerConfig, form.getToDate()));
|
||||
@@ -57,8 +58,46 @@ public class ChartController {
|
||||
.getLocale()), ControllerUtils.formatDate(this.financerConfig, form.getToDate(), LocaleContextHolder
|
||||
.getLocale())});
|
||||
|
||||
final ChartGenerator<AccountGroupExpensesParameter> generator =
|
||||
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD);
|
||||
final ChartGenerator<ExpensesParameter> generator =
|
||||
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD);
|
||||
|
||||
final JFreeChart chart = generator.generateChart(parameter);
|
||||
|
||||
writeChart(response, chart);
|
||||
}
|
||||
|
||||
@GetMapping("/getAccountExpensesCurrentPeriod")
|
||||
public void getAccountExpensesCurrentPeriod(HttpServletResponse response) {
|
||||
final ExpensePeriod period = ExpensePeriod
|
||||
.getCurrentExpensePeriod(this.financerConfig.getMonthPeriodStartDay());
|
||||
final ExpensesParameter parameter = new ExpensesParameter();
|
||||
|
||||
parameter.setPeriodStart(period.getStart());
|
||||
parameter.setPeriodEnd(period.getEnd());
|
||||
parameter.setTitle("financer.chart.account-expenses-current-period.title");
|
||||
|
||||
final ChartGenerator<ExpensesParameter> generator =
|
||||
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_EXPENSES_CURRENT_PERIOD);
|
||||
|
||||
final JFreeChart chart = generator.generateChart(parameter);
|
||||
|
||||
writeChart(response, chart);
|
||||
}
|
||||
|
||||
@PostMapping("/getAccountExpensesForPeriod")
|
||||
public void getAccountExpensesForPeriod(HttpServletResponse response, ConfigAccountExpenseForPeriodForm form) {
|
||||
final ExpensesParameter parameter = new ExpensesParameter();
|
||||
|
||||
parameter.setPeriodStart(ControllerUtils.parseDate(this.financerConfig, form.getFromDate()));
|
||||
parameter.setPeriodEnd(ControllerUtils.parseDate(this.financerConfig, form.getToDate()));
|
||||
parameter.setTitle("financer.chart.account-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<ExpensesParameter> generator =
|
||||
this.financerChartFactory.getGenerator(ChartType.ACCOUNT_EXPENSES_FOR_PERIOD);
|
||||
|
||||
final JFreeChart chart = generator.generateChart(parameter);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ public enum Function {
|
||||
ACC_CLOSE_ACCOUNT("accounts/closeAccount"),
|
||||
ACC_OPEN_ACCOUNT("accounts/openAccount"),
|
||||
ACC_CURRENT_ASSETS("accounts/getCurrentAssets"),
|
||||
ACC_GET_ACC_EXPENSES("accounts/getAccountExpenses"),
|
||||
|
||||
ACC_GP_CREATE_ACCOUNT_GROUP("accountGroups/createAccountGroup"),
|
||||
ACC_GP_GET_ALL("accountGroups/getAll"),
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.financer.controller;
|
||||
|
||||
import de.financer.chart.ChartType;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.form.ConfigAccountExpenseForPeriodForm;
|
||||
import de.financer.form.ConfigAccountGroupExpenseForPeriodForm;
|
||||
import de.financer.form.SelectChartForm;
|
||||
import de.financer.util.ControllerUtils;
|
||||
@@ -56,6 +57,16 @@ public class ReportController {
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
|
||||
return "report/configureAccountGroupExpensesForPeriod";
|
||||
case ACCOUNT_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:/getAccountExpensesCurrentPeriod";
|
||||
case ACCOUNT_EXPENSES_FOR_PERIOD:
|
||||
model.addAttribute("form", new ConfigAccountExpenseForPeriodForm());
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
|
||||
return "report/configureAccountExpensesForPeriod";
|
||||
default:
|
||||
// Cannot happen
|
||||
throw new IllegalStateException("Unexpected value: " + selectedChartType);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package de.financer.form;
|
||||
|
||||
public class ConfigAccountExpenseForPeriodForm {
|
||||
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,23 @@
|
||||
package de.financer.template;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.controller.Function;
|
||||
import de.financer.dto.AccountExpense;
|
||||
import de.financer.dto.AccountGroupExpense;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
public class GetAccountExpensesTemplate {
|
||||
public ResponseEntity<Iterable<AccountExpense>> exchange(FinancerConfig financerConfig, String start, String end) {
|
||||
final UriComponentsBuilder expensesBuilder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.ACC_GET_ACC_EXPENSES))
|
||||
.queryParam("periodStart", start)
|
||||
.queryParam("periodEnd", end);
|
||||
|
||||
return new FinancerRestTemplate<Iterable<AccountExpense>>()
|
||||
.exchange(expensesBuilder.toUriString(), new ParameterizedTypeReference<Iterable<AccountExpense>>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -115,6 +115,11 @@ financer.chart-config-account-group-expenses-for-period.label.from-date=From dat
|
||||
financer.chart-config-account-group-expenses-for-period.label.to-date=To date\:
|
||||
financer.chart-config-account-group-expenses-for-period.submit=Generate
|
||||
|
||||
financer.chart-config-account-expenses-for-period.title=Configure account expenses for period chart
|
||||
financer.chart-config-account-expenses-for-period.label.from-date=From date\:
|
||||
financer.chart-config-account-expenses-for-period.label.to-date=To date\:
|
||||
financer.chart-config-account-expenses-for-period.submit=Generate
|
||||
|
||||
financer.interval-type.DAILY=Daily
|
||||
financer.interval-type.WEEKLY=Weekly
|
||||
financer.interval-type.MONTHLY=Monthly
|
||||
@@ -147,14 +152,19 @@ financer.heading.recurring-transaction-list.all=financer\: all recurring transac
|
||||
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.heading.chart-config-account-expenses-for-period=financer\: configure account expenses for period chart
|
||||
|
||||
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-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.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.chart.name.ACCOUNT_EXPENSES_CURRENT_PERIOD=Expenses of the current period grouped by account
|
||||
financer.chart.name.ACCOUNT_EXPENSES_FOR_PERIOD=Expenses for a configurable period grouped by account
|
||||
|
||||
financer.error-message.UNKNOWN_ERROR=An unknown error occurred!
|
||||
financer.error-message.INVALID_ACCOUNT_TYPE=The selected account type is not valid!
|
||||
|
||||
@@ -115,6 +115,11 @@ financer.chart-config-account-group-expenses-for-period.label.from-date=Von Datu
|
||||
financer.chart-config-account-group-expenses-for-period.label.to-date=Bis Datum\:
|
||||
financer.chart-config-account-group-expenses-for-period.submit=Erzeugen
|
||||
|
||||
financer.chart-config-account-expenses-for-period.title=Konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Konto Diagramm
|
||||
financer.chart-config-account-expenses-for-period.label.from-date=Von Datum\:
|
||||
financer.chart-config-account-expenses-for-period.label.to-date=Bis Datum\:
|
||||
financer.chart-config-account-expenses-for-period.submit=Erzeugen
|
||||
|
||||
financer.interval-type.DAILY=T\u00E4glich
|
||||
financer.interval-type.WEEKLY=W\u00F6chentlich
|
||||
financer.interval-type.MONTHLY=Monatlich
|
||||
@@ -152,6 +157,10 @@ 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-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.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
|
||||
financer.chart.name.ACCOUNT_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto
|
||||
financer.chart.name.ACCOUNT_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto
|
||||
@@ -2,3 +2,4 @@ v16 -> v17:
|
||||
- Add this changelog to the footer
|
||||
- Locale of the recurring transaction reminder email is now configurable
|
||||
- Recurring transaction indicator in transaction overview (account details) is now properly translated
|
||||
- Add chart report to visualize the expenses of the current/a configurable period grouped by account
|
||||
@@ -68,7 +68,8 @@ tr:hover {
|
||||
#new-recurring-transaction-form *,
|
||||
#recurring-to-transaction-with-amount-form *,
|
||||
#new-account-group-form *,
|
||||
#chart-config-account-group-expenses-for-period-form * {
|
||||
#chart-config-account-group-expenses-for-period-form *,
|
||||
#chart-config-account-expenses-for-period-form * {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
width: 20em;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="#{financer.chart-config-account-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-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-expenses-for-period-form" action="#"
|
||||
th:action="@{/getAccountExpensesForPeriod}" th:object="${form}" method="post">
|
||||
<label for="fromDate" th:text="#{financer.chart-config-account-expenses-for-period.label.from-date}"/>
|
||||
<input type="date" id="fromDate" th:field="*{fromDate}"/>
|
||||
<label for="toDate" th:text="#{financer.chart-config-account-expenses-for-period.label.to-date}"/>
|
||||
<input type="date" id="toDate" th:field="*{toDate}"/>
|
||||
<input type="submit" th:value="#{financer.chart-config-account-expenses-for-period.submit}"/>
|
||||
</form>
|
||||
<div th:replace="includes/footer :: footer" />
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user