diff --git a/financer-common/src/main/java/de/financer/dto/AccountExpense.java b/financer-common/src/main/java/de/financer/dto/AccountExpense.java new file mode 100644 index 0000000..d07f94a --- /dev/null +++ b/financer-common/src/main/java/de/financer/dto/AccountExpense.java @@ -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; + } +} diff --git a/financer-server/src/main/java/de/financer/controller/AccountController.java b/financer-server/src/main/java/de/financer/controller/AccountController.java index 8488c4f..5b9d473 100644 --- a/financer-server/src/main/java/de/financer/controller/AccountController.java +++ b/financer-server/src/main/java/de/financer/controller/AccountController.java @@ -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 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); + } } diff --git a/financer-server/src/main/java/de/financer/dba/AccountRepository.java b/financer-server/src/main/java/de/financer/dba/AccountRepository.java index 0a0a072..6fc0e52 100644 --- a/financer-server/src/main/java/de/financer/dba/AccountRepository.java +++ b/financer-server/src/main/java/de/financer/dba/AccountRepository.java @@ -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 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 getAccountExpenses(LocalDate startDate, LocalDate startEnd, AccountType... expenseTypes); } diff --git a/financer-server/src/main/java/de/financer/service/AccountService.java b/financer-server/src/main/java/de/financer/service/AccountService.java index 183ff25..3b5b499 100644 --- a/financer-server/src/main/java/de/financer/service/AccountService.java +++ b/financer-server/src/main/java/de/financer/service/AccountService.java @@ -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 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); + } } diff --git a/financer-web-client/src/main/java/de/financer/chart/ChartType.java b/financer-web-client/src/main/java/de/financer/chart/ChartType.java index fc98c91..96e813c 100644 --- a/financer-web-client/src/main/java/de/financer/chart/ChartType.java +++ b/financer-web-client/src/main/java/de/financer/chart/ChartType.java @@ -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 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 7c44c07..718a2f4 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 @@ -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

) new AccountGroupExpensesGenerator(); break; + case ACCOUNT_EXPENSES_CURRENT_PERIOD: + // Fall through + case ACCOUNT_EXPENSES_FOR_PERIOD: + // TODO WHY IS THIS CAST NECESSARY??? + generator = (AbstractChartGenerator

) new AccountExpensesGenerator(); + break; default: generator = null; } diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java b/financer-web-client/src/main/java/de/financer/chart/impl/expense/AbstractExpensesGenerator.java similarity index 51% rename from financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java rename to financer-web-client/src/main/java/de/financer/chart/impl/expense/AbstractExpensesGenerator.java index 9b2b14c..e3ae1c0 100644 --- a/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java +++ b/financer-web-client/src/main/java/de/financer/chart/impl/expense/AbstractExpensesGenerator.java @@ -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 { +public abstract class AbstractExpensesGenerator extends AbstractChartGenerator { @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 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 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); } diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/expense/AccountExpensesGenerator.java b/financer-web-client/src/main/java/de/financer/chart/impl/expense/AccountExpensesGenerator.java new file mode 100644 index 0000000..44a01b9 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/impl/expense/AccountExpensesGenerator.java @@ -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 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; + } +} diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/expense/AccountGroupExpensesGenerator.java b/financer-web-client/src/main/java/de/financer/chart/impl/expense/AccountGroupExpensesGenerator.java new file mode 100644 index 0000000..29d1527 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/impl/expense/AccountGroupExpensesGenerator.java @@ -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 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; + } +} diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java b/financer-web-client/src/main/java/de/financer/chart/impl/expense/ExpensesParameter.java similarity index 89% rename from financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java rename to financer-web-client/src/main/java/de/financer/chart/impl/expense/ExpensesParameter.java index ab053e0..1a7f170 100644 --- a/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java +++ b/financer-web-client/src/main/java/de/financer/chart/impl/expense/ExpensesParameter.java @@ -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; 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 4bbd902..81b7836 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 @@ -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 generator = + final ChartGenerator 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 generator = - this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD); + final ChartGenerator 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 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 generator = + this.financerChartFactory.getGenerator(ChartType.ACCOUNT_EXPENSES_FOR_PERIOD); final JFreeChart chart = generator.generateChart(parameter); 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 2824bbc..aa4786a 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 @@ -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"), 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 94607c7..ace67d9 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 @@ -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); diff --git a/financer-web-client/src/main/java/de/financer/form/ConfigAccountExpenseForPeriodForm.java b/financer-web-client/src/main/java/de/financer/form/ConfigAccountExpenseForPeriodForm.java new file mode 100644 index 0000000..84ea639 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/form/ConfigAccountExpenseForPeriodForm.java @@ -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; + } +} diff --git a/financer-web-client/src/main/java/de/financer/template/GetAccountExpensesTemplate.java b/financer-web-client/src/main/java/de/financer/template/GetAccountExpensesTemplate.java new file mode 100644 index 0000000..e74c4e0 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/template/GetAccountExpensesTemplate.java @@ -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> 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>() + .exchange(expensesBuilder.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 64707eb..fb1a529 100644 --- a/financer-web-client/src/main/resources/i18n/message.properties +++ b/financer-web-client/src/main/resources/i18n/message.properties @@ -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! 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 c1b4c44..f2a403a 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 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/financer-web-client/src/main/resources/static/changelog.txt b/financer-web-client/src/main/resources/static/changelog.txt index 9b85f61..2a56a6a 100644 --- a/financer-web-client/src/main/resources/static/changelog.txt +++ b/financer-web-client/src/main/resources/static/changelog.txt @@ -1,4 +1,5 @@ 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 \ No newline at end of file +- 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 \ No newline at end of file diff --git a/financer-web-client/src/main/resources/static/css/main.css b/financer-web-client/src/main/resources/static/css/main.css index c5211ff..38bf607 100644 --- a/financer-web-client/src/main/resources/static/css/main.css +++ b/financer-web-client/src/main/resources/static/css/main.css @@ -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; diff --git a/financer-web-client/src/main/resources/templates/report/configureAccountExpensesForPeriod.html b/financer-web-client/src/main/resources/templates/report/configureAccountExpensesForPeriod.html new file mode 100644 index 0000000..278aa5b --- /dev/null +++ b/financer-web-client/src/main/resources/templates/report/configureAccountExpensesForPeriod.html @@ -0,0 +1,23 @@ + + + + + <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> \ No newline at end of file