#29 Projected cash flow
This commit is contained in:
@@ -2,17 +2,32 @@ 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.decorator.AccountDecorator;
|
||||
import de.financer.dto.RecurringTransactionDueInRangeResponseDto;
|
||||
import de.financer.form.*;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.model.AccountType;
|
||||
import de.financer.model.RecurringTransaction;
|
||||
import de.financer.report.ReportType;
|
||||
import de.financer.template.FinancerRestTemplate;
|
||||
import de.financer.template.GetAllAccountsTemplate;
|
||||
import de.financer.template.exception.FinancerRestException;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
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 org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static de.financer.model.AccountType.*;
|
||||
import static de.financer.model.AccountType.LIABILITY;
|
||||
|
||||
@Controller
|
||||
public class ReportController {
|
||||
@@ -36,8 +51,7 @@ public class ReportController {
|
||||
|
||||
try {
|
||||
selectedChartType = ChartType.getByValue(form.getChartType());
|
||||
}
|
||||
catch (NoSuchElementException nsee) {
|
||||
} catch (NoSuchElementException nsee) {
|
||||
model.addAttribute("form", new SelectChartForm());
|
||||
model.addAttribute("errorMessage", "UNKNOWN_CHART_TYPE");
|
||||
model.addAttribute("availableCharts", ChartType.valueList(true));
|
||||
@@ -80,4 +94,126 @@ public class ReportController {
|
||||
throw new IllegalStateException("Unexpected value: " + selectedChartType);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/selectReport")
|
||||
public String selectReport(Model model) {
|
||||
model.addAttribute("form", new SelectReportForm());
|
||||
model.addAttribute("availableReports", ReportType.valueList());
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||
|
||||
return "report/selectReport";
|
||||
}
|
||||
|
||||
@PostMapping("/configureReport")
|
||||
public String configureReport(SelectReportForm form, Model model) {
|
||||
final ReportType selectedReportType;
|
||||
|
||||
try {
|
||||
selectedReportType = ReportType.getByValue(form.getReportType());
|
||||
} catch (NoSuchElementException nsee) {
|
||||
model.addAttribute("form", new SelectReportForm());
|
||||
model.addAttribute("errorMessage", "UNKNOWN_REPORT_TYPE");
|
||||
model.addAttribute("availableReports", ReportType.valueList());
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||
|
||||
return "report/selectReport";
|
||||
}
|
||||
|
||||
switch (selectedReportType) {
|
||||
case PROJECTED_CASH_FLOW:
|
||||
model.addAttribute("form", new ConfigProjectedCashFlowForPeriodForm());
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||
|
||||
return "report/configureProjectedCashFlowForPeriod";
|
||||
default:
|
||||
// Cannot happen
|
||||
throw new IllegalStateException("Unexpected value: " + selectedReportType);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/configureProjectedCashFlowForPeriodTransactions")
|
||||
public String configureProjectedCashFlowForPeriodTransactions(Model model, ConfigProjectedCashFlowForPeriodForm form) {
|
||||
try {
|
||||
final UriComponentsBuilder transactionBuilder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(this.financerConfig, Function.RT_GET_ALL_DUE_IN_RANGE));
|
||||
|
||||
transactionBuilder.queryParam("start", ControllerUtils.formatDate(this.financerConfig, form.getFromDate()));
|
||||
transactionBuilder.queryParam("end", ControllerUtils.formatDate(this.financerConfig, form.getToDate()));
|
||||
|
||||
final Iterable<RecurringTransactionDueInRangeResponseDto> trxs = FinancerRestTemplate.exchangeGet(transactionBuilder,
|
||||
new ParameterizedTypeReference<Iterable<RecurringTransactionDueInRangeResponseDto>>() {
|
||||
});
|
||||
|
||||
final List<RecurringTransaction> incomeTransactions = new ArrayList<>();
|
||||
final List<RecurringTransaction> expenseTransactions = new ArrayList<>();
|
||||
final EnumMap<AccountType, List<AccountType>> bookingRules = new EnumMap<>(AccountType.class);
|
||||
|
||||
bookingRules.put(BANK, Arrays.asList(BANK, EXPENSE, LIABILITY));
|
||||
bookingRules.put(CASH, Arrays.asList(EXPENSE, LIABILITY));
|
||||
|
||||
IterableUtils.toList(trxs).stream()
|
||||
.flatMap(dto -> IterableUtils.toList(dto.getRecurringTransactions()).stream()).forEach(rt -> {
|
||||
if (AccountType.INCOME == rt.getFromAccount().getType()) {
|
||||
incomeTransactions.add(rt);
|
||||
} else if (bookingRules.getOrDefault(rt.getFromAccount().getType(), Collections.EMPTY_LIST)
|
||||
.contains(rt.getToAccount().getType())) {
|
||||
expenseTransactions.add(rt);
|
||||
}
|
||||
});
|
||||
|
||||
ConfigProjectedCashFlowForPeriodTransactionsForm formTransactions =
|
||||
new ConfigProjectedCashFlowForPeriodTransactionsForm(incomeTransactions, expenseTransactions,
|
||||
form.isByAccount(), ControllerUtils.parseDate(this.financerConfig, form.getFromDate()),
|
||||
ControllerUtils.parseDate(this.financerConfig, form.getToDate()));
|
||||
|
||||
if(form.isByAccount()) {
|
||||
final ResponseEntity<Iterable<Account>> response = new GetAllAccountsTemplate().exchange(this.financerConfig);
|
||||
|
||||
decorateAccounts(ControllerUtils.filterAndSortAccounts(response.getBody(), false, LIABILITY, EXPENSE))
|
||||
.forEach(formTransactions::addAccountContainer);
|
||||
}
|
||||
else {
|
||||
// TODO by account group
|
||||
}
|
||||
|
||||
formTransactions.refresh();
|
||||
|
||||
model.addAttribute("form", formTransactions);
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||
|
||||
return "report/configureProjectedCashFlowForPeriodTransactions";
|
||||
} catch (FinancerRestException e) {
|
||||
model.addAttribute("errorMessage", e.getResponseReason().name());
|
||||
model.addAttribute("form", form);
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||
|
||||
return "report/configureProjectedCashFlowForPeriod";
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/configureProjectedCashFlowForPeriodTransactionsRefresh")
|
||||
public String configureProjectedCashFlowForPeriodTransactionsRefresh(Model model, ConfigProjectedCashFlowForPeriodTransactionsForm form) {
|
||||
form.refresh();
|
||||
|
||||
model.addAttribute("form", form);
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||
|
||||
return "report/configureProjectedCashFlowForPeriodTransactions";
|
||||
}
|
||||
|
||||
private List<AccountDecorator> decorateAccounts(List<Account> accounts) {
|
||||
return accounts.stream().map(AccountDecorator::new).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,4 +62,8 @@ public class AccountDecorator {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.financer.form;
|
||||
|
||||
public class ConfigProjectedCashFlowForPeriodForm {
|
||||
private String fromDate;
|
||||
private String toDate;
|
||||
private boolean byAccount;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean isByAccount() {
|
||||
return byAccount;
|
||||
}
|
||||
|
||||
public void setByAccount(boolean byAccount) {
|
||||
this.byAccount = byAccount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package de.financer.form;
|
||||
|
||||
import de.financer.decorator.AccountDecorator;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.model.RecurringTransaction;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigProjectedCashFlowForPeriodTransactionsForm {
|
||||
public static class AccountContainer {
|
||||
private Account account;
|
||||
private long spending;
|
||||
private long averageSpending;
|
||||
|
||||
public AccountContainer() {
|
||||
|
||||
}
|
||||
|
||||
public AccountContainer(Account account, long spending, long averageSpending) {
|
||||
this.account = account;
|
||||
this.spending = spending;
|
||||
this.averageSpending = averageSpending;
|
||||
|
||||
if(this.spending == 0 && this.averageSpending != 0) {
|
||||
this.spending = this.averageSpending;
|
||||
}
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public long getSpending() {
|
||||
return spending;
|
||||
}
|
||||
|
||||
public void setSpending(long spending) {
|
||||
this.spending = spending;
|
||||
}
|
||||
|
||||
public long getAverageSpending() {
|
||||
return averageSpending;
|
||||
}
|
||||
|
||||
public void setAverageSpending(long averageSpending) {
|
||||
this.averageSpending = averageSpending;
|
||||
}
|
||||
}
|
||||
|
||||
private List<RecurringTransaction> incomeTransactions;
|
||||
private List<RecurringTransaction> expenseTransactions;
|
||||
private List<AccountContainer> accountContainers;
|
||||
private long incomeSum;
|
||||
private long expenseSum;
|
||||
private long cashFlow;
|
||||
private boolean byAccount;
|
||||
private long accountSum;
|
||||
private LocalDate fromDate;
|
||||
private LocalDate toDate;
|
||||
|
||||
public ConfigProjectedCashFlowForPeriodTransactionsForm() {
|
||||
this.incomeTransactions = new ArrayList<>();
|
||||
this.expenseTransactions = new ArrayList<>();
|
||||
this.accountContainers = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ConfigProjectedCashFlowForPeriodTransactionsForm(List<RecurringTransaction> incomeTransactions,
|
||||
List<RecurringTransaction> expenseTransactions,
|
||||
boolean byAccount, LocalDate fromDate, LocalDate toDate
|
||||
) {
|
||||
this.incomeTransactions = incomeTransactions;
|
||||
this.expenseTransactions = expenseTransactions;
|
||||
this.accountContainers = new ArrayList<>();
|
||||
this.byAccount = byAccount;
|
||||
this.fromDate = fromDate;
|
||||
this.toDate = toDate;
|
||||
|
||||
Collections.sort(this.incomeTransactions, Comparator.comparing(RecurringTransaction::getAmount));
|
||||
Collections.sort(this.expenseTransactions, Comparator.comparing(RecurringTransaction::getAmount));
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
this.incomeSum = incomeTransactions.stream().mapToLong(RecurringTransaction::getAmount).sum();
|
||||
this.expenseSum = expenseTransactions.stream().mapToLong(RecurringTransaction::getAmount).sum();
|
||||
this.cashFlow = this.incomeSum - this.expenseSum;
|
||||
|
||||
if(this.byAccount) {
|
||||
this.accountSum = this.accountContainers.stream().filter(ac -> ac.spending != 0).mapToLong(AccountContainer::getSpending).sum();
|
||||
|
||||
this.cashFlow = this.cashFlow - this.accountSum;
|
||||
}
|
||||
else {
|
||||
// TODO account group calc
|
||||
}
|
||||
}
|
||||
|
||||
public List<RecurringTransaction> getIncomeTransactions() {
|
||||
return incomeTransactions;
|
||||
}
|
||||
|
||||
public void setIncomeTransactions(List<RecurringTransaction> incomeTransactions) {
|
||||
this.incomeTransactions = incomeTransactions;
|
||||
}
|
||||
|
||||
public List<RecurringTransaction> getExpenseTransactions() {
|
||||
return expenseTransactions;
|
||||
}
|
||||
|
||||
public void setExpenseTransactions(List<RecurringTransaction> expenseTransactions) {
|
||||
this.expenseTransactions = expenseTransactions;
|
||||
}
|
||||
|
||||
public List<AccountContainer> getAccountContainers() {
|
||||
return accountContainers;
|
||||
}
|
||||
|
||||
public void setAccountContainers(List<AccountContainer> accountContainers) {
|
||||
this.accountContainers = accountContainers;
|
||||
}
|
||||
|
||||
public void addAccountContainer(AccountDecorator account) {
|
||||
this.accountContainers.add(new AccountContainer(account.getAccount(), account.getSpendingCurrentExpensePeriod(), account.getAverageSpendingExpensePeriod()));
|
||||
}
|
||||
|
||||
public long getIncomeSum() {
|
||||
return incomeSum;
|
||||
}
|
||||
|
||||
public void setIncomeSum(long incomeSum) {
|
||||
this.incomeSum = incomeSum;
|
||||
}
|
||||
|
||||
public long getExpenseSum() {
|
||||
return expenseSum;
|
||||
}
|
||||
|
||||
public void setExpenseSum(long expenseSum) {
|
||||
this.expenseSum = expenseSum;
|
||||
}
|
||||
|
||||
public long getCashFlow() {
|
||||
return cashFlow;
|
||||
}
|
||||
|
||||
public boolean isByAccount() {
|
||||
return byAccount;
|
||||
}
|
||||
|
||||
public void setByAccount(boolean byAccount) {
|
||||
this.byAccount = byAccount;
|
||||
}
|
||||
|
||||
public long getAccountSum() {
|
||||
return accountSum;
|
||||
}
|
||||
|
||||
public void setAccountSum(long accountSum) {
|
||||
this.accountSum = accountSum;
|
||||
}
|
||||
|
||||
public LocalDate getFromDate() {
|
||||
return fromDate;
|
||||
}
|
||||
|
||||
public void setFromDate(LocalDate fromDate) {
|
||||
this.fromDate = fromDate;
|
||||
}
|
||||
|
||||
public LocalDate getToDate() {
|
||||
return toDate;
|
||||
}
|
||||
|
||||
public void setToDate(LocalDate toDate) {
|
||||
this.toDate = toDate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.financer.form;
|
||||
|
||||
public class SelectReportForm {
|
||||
private String reportType;
|
||||
|
||||
public String getReportType() {
|
||||
return reportType;
|
||||
}
|
||||
|
||||
public void setReportType(String reportType) {
|
||||
this.reportType = reportType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.financer.report;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum ReportType {
|
||||
PROJECTED_CASH_FLOW;
|
||||
|
||||
public static List<String> valueList() {
|
||||
return Arrays.stream(ReportType.values()).map(ReportType::name).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static ReportType getByValue(String value) {
|
||||
return Arrays.stream(values()).filter((ct) -> ct.name().equals(value)).findFirst().get();
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,7 @@ package de.financer.util;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.controller.Function;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.model.AccountGroup;
|
||||
import de.financer.model.AccountStatus;
|
||||
import de.financer.model.RecurringTransaction;
|
||||
import de.financer.model.*;
|
||||
import de.financer.util.comparator.AccountByTypeByGroupNameByIdComparator;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -14,6 +11,7 @@ import org.springframework.ui.Model;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -40,6 +38,15 @@ public class ControllerUtils {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<Account> filterAndSortAccounts(Iterable<Account> accounts, boolean showClosed, AccountType... filterAccountTypes) {
|
||||
return IterableUtils.toList(accounts).stream()
|
||||
.filter((acc) -> AccountStatus.OPEN
|
||||
.equals(acc.getStatus()) || showClosed)
|
||||
.filter(acc -> Arrays.asList(filterAccountTypes).contains(acc.getType()))
|
||||
.sorted(new AccountByTypeByGroupNameByIdComparator())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<AccountGroup> sortAccountGroups(Iterable<AccountGroup> accountGroups) {
|
||||
return IterableUtils.toList(accountGroups).stream()
|
||||
.sorted(Comparator.comparing(AccountGroup::getName))
|
||||
|
||||
@@ -10,6 +10,7 @@ financer.account-overview.available-actions.create-recurring-transaction=Create
|
||||
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.select-chart=Generate a chart
|
||||
financer.account-overview.available-actions.select-report=Generate a report
|
||||
financer.account-overview.available-actions.close-current-period=Close the current expense period
|
||||
financer.account-overview.available-actions.recurring-transaction-calendar=Recurring transaction calendar
|
||||
financer.account-overview.available-actions.period-overview=Period overview
|
||||
@@ -215,6 +216,17 @@ 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.report-config-projected-cashflow-for-period.title=Configure projected cash flow report
|
||||
financer.report-config-projected-cashflow-for-period.label.from-date=From date\:
|
||||
financer.report-config-projected-cashflow-for-period.label.to-date=To date\:
|
||||
financer.report-config-projected-cashflow-for-period.label.account-or-account-group-summary=By account or account group
|
||||
financer.report-config-projected-cashflow-for-period.label.by-account=Account
|
||||
financer.report-config-projected-cashflow-for-period.label.by-account-group=Account group
|
||||
financer.report-config-projected-cashflow-for-period.submit=Next step
|
||||
|
||||
financer.report-select.title=Select a report to generate
|
||||
financer.report-select.submit=Select
|
||||
|
||||
financer.period-overview.title=Period overview
|
||||
financer.period-overview.table-header.id=ID
|
||||
financer.period-overview.table-header.type=Period type
|
||||
@@ -276,6 +288,8 @@ financer.heading.period-overview=financer\: period overview
|
||||
financer.heading.upload-transactions=financer\: upload transactions
|
||||
financer.heading.create-upload-transactions=financer\: create uploaded transactions
|
||||
financer.heading.account-edit=financer\: edit account
|
||||
financer.heading.report-select=financer\: select a report to generate
|
||||
financer.heading.report-config-projected-cashflow-for-period=financer\: configure projected cash flow report
|
||||
|
||||
financer.cancel-back-to-overview=Cancel and back to overview
|
||||
financer.back-to-overview=Back to overview
|
||||
@@ -298,6 +312,8 @@ financer.chart.name.ACCOUNT_EXPENSES_FOR_PERIOD=Expenses for a configurable peri
|
||||
financer.chart.name.EXPENSE_PERIOD_TOTALS_CURRENT_YEAR=Overview about the income and expenses in the current year (bar chart)
|
||||
financer.chart.name.EXPENSE_PERIOD_TOTALS_FOR_YEAR=Overview about the income and expenses for a configurable year (bar chart)
|
||||
|
||||
financer.report.name.PROJECTED_CASH_FLOW=Projected cash flow
|
||||
|
||||
financer.recurring-transaction-calendar.title=financer\: recurring transaction calendar
|
||||
financer.calendar.calendarweek=CW
|
||||
financer.calendar.weekdays.MONDAY=Monday
|
||||
@@ -347,3 +363,13 @@ financer.error-message.UNKNOWN_CHART_TYPE=The selected chart type is not known!
|
||||
financer.error-message.INVALID_HAS_FILE_VALUE=The value for parameter hasFile cannot be parsed!
|
||||
financer.error-message.INVALID_FILE_CONTENT=File content is missing!
|
||||
financer.error-message.INVALID_FILE_NAME=File name is missing!
|
||||
|
||||
financer.report-config-projected-cashflow-for-period-transactions.title=Configure projected cash flow report
|
||||
financer.heading.report-config-projected-cashflow-for-period-transactions=financer\: configure projected cash flow report
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.income.sum=Income sum
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.expense.sum=Expense sum
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.accounts.sum=Accounts sum
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.cash-flow.sum=Cash flow sum
|
||||
financer.report-config-projected-cashflow-for-period-transactions.label.button.refresh=Refresh
|
||||
financer.report-config-projected-cashflow-for-period-transactions.label.button.create=Create report
|
||||
financer.heading.report-config-projected-cashflow-for-period-transactions-print=financer\: projected cash flow report
|
||||
@@ -8,8 +8,9 @@ financer.account-overview.available-actions.search-transactions=Buchungen suchen
|
||||
financer.account-overview.available-actions.upload-transactions=Buchungen hochladen
|
||||
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.create-account-group=Neue Konto-Gruppe erstellen
|
||||
financer.account-overview.available-actions.create-account-group=Neue Kontogruppe erstellen
|
||||
financer.account-overview.available-actions.select-chart=Ein Diagramm erzeugen
|
||||
financer.account-overview.available-actions.select-report=Einen Bericht erzeugen
|
||||
financer.account-overview.available-actions.close-current-period=Aktuelle Periode schlie\u00DFen
|
||||
financer.account-overview.available-actions.recurring-transaction-calendar=Kalender wiederkehrende Buchung
|
||||
financer.account-overview.available-actions.period-overview=Perioden\u00FCbersicht
|
||||
@@ -26,7 +27,7 @@ financer.account-overview.table-header.spending-current-period=Ausgaben aktuelle
|
||||
financer.account-overview.table-header.average-spending-period=Durchschnittliche Ausgaben
|
||||
financer.account-overview.table-header.type=Typ
|
||||
financer.account-overview.table-header.status=Status
|
||||
financer.account-overview.tooltip.status.current-expenses=Periode ab {0}. Durch Klicken des Betrags kann eine grafische \u00DCbersicht über die Ausgaben gruppiert nach Konto-Gruppe angezeigt werden
|
||||
financer.account-overview.tooltip.status.current-expenses=Periode ab {0}. Durch Klicken des Betrags kann eine grafische \u00DCbersicht über die Ausgaben gruppiert nach Kontogruppe angezeigt werden
|
||||
financer.account-overview.tooltip.status.current-assets=Kurzfristig verf\u00FCgbares Verm\u00F6gen
|
||||
financer.account-overview.expense-history.description=Ausgabenhistorie
|
||||
|
||||
@@ -37,9 +38,9 @@ financer.account-new.label.group=Gruppe\:
|
||||
financer.account-new.label.upload-match-regexps=Zuordnungsregexps\:
|
||||
financer.account-new.submit=Konto erstellen
|
||||
|
||||
financer.account-group-new.title=financer\: Neue Konto-Gruppe erstellen
|
||||
financer.account-group-new.title=financer\: Neue Kontogruppe erstellen
|
||||
financer.account-group-new.label.name=Name\:
|
||||
financer.account-group-new.submit=Konto-Gruppe erstellen
|
||||
financer.account-group-new.submit=Kontogruppe erstellen
|
||||
|
||||
financer.account-edit.title=financer\: Bearbeite Konto
|
||||
financer.account-edit.label.key=Schl\u00FCssel\:
|
||||
@@ -205,7 +206,7 @@ financer.create-upload-transactions.submit=Erstelle hochgeladene Buchungen
|
||||
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.title=Konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Kontogruppe 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
|
||||
@@ -215,6 +216,17 @@ 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.report-config-projected-cashflow-for-period.title=Konfigurieren von prognostizierter Cashflow Bericht
|
||||
financer.report-config-projected-cashflow-for-period.label.from-date=Von Datum\:
|
||||
financer.report-config-projected-cashflow-for-period.label.to-date=Bis Datum\:
|
||||
financer.report-config-projected-cashflow-for-period.label.account-or-account-group-summary=Konto oder Kontogruppe
|
||||
financer.report-config-projected-cashflow-for-period.label.by-account=Konto
|
||||
financer.report-config-projected-cashflow-for-period.label.by-account-group=Kontogruppe
|
||||
financer.report-config-projected-cashflow-for-period.submit=N\u00E4chster Schritt
|
||||
|
||||
financer.report-select.title=Einen Bericht zum Erzeugen ausw\u00E4hlen
|
||||
financer.report-select.submit=Ausw\u00E4hlen
|
||||
|
||||
financer.period-overview.title=Perioden\u00FCbersicht
|
||||
financer.period-overview.table-header.id=ID
|
||||
financer.period-overview.table-header.type=Periodentyp
|
||||
@@ -260,7 +272,7 @@ financer.period-type.GRAND_TOTAL=Gesamtausgaben
|
||||
financer.heading.transaction-new=financer\: Neue Buchung erstellen
|
||||
financer.heading.recurring-transaction-new=financer\: Neue wiederkehrende Buchung erstellen
|
||||
financer.heading.account-new=financer\: Neues Konto erstellen
|
||||
financer.heading.account-group-new=financer\: Neue Konto-Gruppe erstellen
|
||||
financer.heading.account-group-new=financer\: Neue Kontogruppe erstellen
|
||||
financer.heading.account-overview=financer\: \u00DCbersicht
|
||||
financer.heading.account-details=financer\: Kontodetails f\u00FCr {0}
|
||||
financer.heading.recurring-transaction-list.dueToday=financer\: Wiederkehrende Buchungen heute f\u00E4llig
|
||||
@@ -268,21 +280,23 @@ financer.heading.recurring-transaction-list.active=financer\: Aktive wiederkehre
|
||||
financer.heading.recurring-transaction-list.all=financer\: Alle wiederkehrende Buchungen
|
||||
financer.heading.recurring-to-transaction-with-override=financer\: Buchung mit \u00DCberschreibungen 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.heading.chart-config-account-group-expenses-for-period=financer\: Konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Kontogruppe Diagramm
|
||||
financer.heading.search-transactions=financer\: Buchungen suchen
|
||||
financer.heading.recurring-transaction-calendar=financer\: Kalender wiederkehrende Buchung
|
||||
financer.heading.period-overview=financer\: Perioden\u00FCbersicht
|
||||
financer.heading.upload-transactions=financer\: Buchungen hochladen
|
||||
financer.heading.create-upload-transactions=financer\: Erstelle hochgeladene Buchungen
|
||||
financer.heading.account-edit=financer\: Bearbeite Konto
|
||||
financer.heading.report-select=financer\: Einen Bericht zum Erzeugen ausw\u00E4hlen
|
||||
financer.heading.report-config-projected-cashflow-for-period=financer\: Konfigurieren von prognostizierter Cashflow Bericht
|
||||
|
||||
financer.cancel-back-to-overview=Abbrechen und zur\u00FCck zur \u00DCbersicht
|
||||
financer.back-to-overview=Zur\u00FCck zur \u00DCbersicht
|
||||
financer.show-actions=Anzeigen...
|
||||
financer.show-options=Zeige Optionen...
|
||||
|
||||
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-group-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Kontogruppe
|
||||
financer.chart.account-group-expenses-for-period.title=Ausgaben in der Periode vom {0} bis {1} gruppiert nach Kontogruppe
|
||||
financer.chart.account-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Konto
|
||||
financer.chart.account-expenses-for-period.title=Ausgaben in der Periode vom {0} bis {1} gruppiert nach Konto
|
||||
financer.chart.expense-period-totals-current-year.title=Gesamtbetr\u00E4ge gruppiert nach Periode für das aktuelle Jahr
|
||||
@@ -290,13 +304,15 @@ financer.chart.expense-period-totals-current-year.x=Betrag
|
||||
financer.chart.expense-period-totals-current-year.y=Periode
|
||||
financer.chart.expense-period-totals-current-year.open-period=OFFEN
|
||||
|
||||
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe (Kuchendiagramm)
|
||||
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto-Gruppe (Kuchendiagramm)
|
||||
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Kontogruppe (Kuchendiagramm)
|
||||
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Kontogruppe (Kuchendiagramm)
|
||||
financer.chart.name.ACCOUNT_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto (Kuchendiagramm)
|
||||
financer.chart.name.ACCOUNT_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto (Kuchendiagramm)
|
||||
financer.chart.name.EXPENSE_PERIOD_TOTALS_CURRENT_YEAR=\u00DCbersicht über das Einkommen und die Ausgaben im laufenden Jahr (Balkendiagramm)
|
||||
financer.chart.name.EXPENSE_PERIOD_TOTALS_FOR_YEAR=\u00DCbersicht über das Einkommen und die Ausgaben für ein konfigurierbares Jahr (Balkendiagramm)
|
||||
|
||||
financer.report.name.PROJECTED_CASH_FLOW=Prognostizierter Cashflow
|
||||
|
||||
financer.recurring-transaction-calendar.title=financer\: Kalender wiederkehrende Buchung
|
||||
financer.calendar.calendarweek=KW
|
||||
financer.calendar.weekdays.MONDAY=Montag
|
||||
@@ -340,9 +356,19 @@ financer.error-message.INVALID_TRANSACTION_ID=Die ausgew\u00E4hlte Buchung ist u
|
||||
financer.error-message.TRANSACTION_NOT_FOUND=Die ausgew\u00E4hlte Buchung wurde nicht gefunden!
|
||||
financer.error-message.ACCOUNT_NOT_FOUND=Das ausgew\u00E4hlte Konto wurde nicht gefunden!
|
||||
financer.error-message.DUPLICATE_ACCOUNT_KEY=Ein Konto mit diesem Schl\u00FCssel existiert bereits!
|
||||
financer.error-message.DUPLICATE_ACCOUNT_GROUP_NAME=Eine Konto-Gruppe mit diesem Namen existiert bereits!
|
||||
financer.error-message.ACCOUNT_GROUP_NOT_FOUND=Die ausgew\u00E4hlte Konto-Gruppe wurde nicht gefunden!
|
||||
financer.error-message.DUPLICATE_ACCOUNT_GROUP_NAME=Eine Kontogruppe mit diesem Namen existiert bereits!
|
||||
financer.error-message.ACCOUNT_GROUP_NOT_FOUND=Die ausgew\u00E4hlte Kontogruppe wurde nicht gefunden!
|
||||
financer.error-message.UNKNOWN_CHART_TYPE=Das ausgew\u00E4hlte Diagramm wurde nicht gefunden!
|
||||
financer.error-message.INVALID_HAS_FILE_VALUE=Der Wert des Parameters hasFile kann nicht verarbeitet werden!
|
||||
financer.error-message.INVALID_FILE_CONTENT=Der Inhalt der Datei fehlt!
|
||||
financer.error-message.INVALID_FILE_NAME=Der Dateiname fehlt!
|
||||
|
||||
financer.report-config-projected-cashflow-for-period-transactions.title=Konfigurieren von prognostizierter Cashflow Bericht
|
||||
financer.heading.report-config-projected-cashflow-for-period-transactions=financer\: Konfigurieren von prognostizierter Cashflow Bericht
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.income.sum=Einkommen
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.expense.sum=Wiederkehrende Buchungen
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.accounts.sum=Konten
|
||||
financer.report-config-projected-cashflow-for-period-transactions.table.cash-flow.sum=Cashflow
|
||||
financer.report-config-projected-cashflow-for-period-transactions.label.button.refresh=Aktualisieren
|
||||
financer.report-config-projected-cashflow-for-period-transactions.label.button.create=Bericht erstellen
|
||||
financer.heading.report-config-projected-cashflow-for-period-transactions-print=financer\: Prognostizierter Cashflow Bericht
|
||||
@@ -1,5 +1,5 @@
|
||||
v49 -> v50:
|
||||
-
|
||||
- #29 Added projected cash flow report
|
||||
|
||||
v48 -> v49:
|
||||
- #27 The recurring transaction selection during transaction import now contains all recurring transaction instead of
|
||||
|
||||
@@ -72,7 +72,8 @@ a {
|
||||
#transaction-table,
|
||||
#recurring-transaction-list-table,
|
||||
#period-overview-table,
|
||||
#create-upload-transactions-table {
|
||||
#create-upload-transactions-table,
|
||||
#report-config-projected-cashflow-for-period-transactions-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
@@ -89,7 +90,8 @@ a {
|
||||
#period-overview-table th,
|
||||
#period-overview-table td,
|
||||
#create-upload-transactions-table th,
|
||||
#create-upload-transactions-table td {
|
||||
#create-upload-transactions-table td,
|
||||
#report-config-projected-cashflow-for-period-transactions-table td {
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 0.3em;
|
||||
vertical-align: top;
|
||||
@@ -174,6 +176,7 @@ tr:hover {
|
||||
#new-account-group-form *,
|
||||
#chart-config-account-group-expenses-for-period-form *,
|
||||
#chart-config-account-expenses-for-period-form *,
|
||||
#report-config-projected-cashflow-for-period-form *,
|
||||
#search-transactions-form *,
|
||||
#upload-transactions-form *,
|
||||
#edit-account-form * {
|
||||
@@ -201,6 +204,12 @@ tr:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#report-select-form div {
|
||||
width: 20em;
|
||||
margin-top: 1em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
input[type=submit] {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
@@ -398,3 +407,63 @@ input[type=submit] {
|
||||
.transaction-upload-fieldset * {
|
||||
width: 17.75em !important;
|
||||
}
|
||||
|
||||
.report-config-projected-cashflow-fieldset {
|
||||
margin-left: 1em;
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
.report-config-projected-cashflow-fieldset * {
|
||||
width: 17.75em !important;
|
||||
}
|
||||
|
||||
.display-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: 'Source Code Pro', monospace;
|
||||
}
|
||||
|
||||
.projected-cashflow-transaction {
|
||||
padding-left: 1em !important;
|
||||
}
|
||||
|
||||
.projected-cashflow-sum > * {
|
||||
font-weight: bolder;
|
||||
padding-top: 1em !important;
|
||||
}
|
||||
|
||||
#report-config-projected-cashflow-for-period-transactions-table {
|
||||
width: 55% !important;
|
||||
}
|
||||
|
||||
.report-config-projected-cashflow-for-period-transactions-table-amount {
|
||||
width: 5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.print {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media print{
|
||||
.noprint{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.print {
|
||||
display: table-cell !important;
|
||||
}
|
||||
|
||||
.print-padding {
|
||||
padding-top: 1em;
|
||||
padding-left: 1em;
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.report-config-projected-cashflow-for-period-transactions-table-average-spending {
|
||||
width: 13em;
|
||||
text-align: right;
|
||||
}
|
||||
@@ -73,6 +73,8 @@
|
||||
<div id="action-container-sub-reports">
|
||||
<a th:href="@{/selectChart}"
|
||||
th:text="#{financer.account-overview.available-actions.select-chart}"/>
|
||||
<a th:href="@{/selectReport}"
|
||||
th:text="#{financer.account-overview.available-actions.select-report}"/>
|
||||
</div>
|
||||
</div>
|
||||
<table id="account-overview-table">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div id="footer-container" th:fragment="footer">
|
||||
<div id="footer-container" th:fragment="footer" class="noprint">
|
||||
<hr>
|
||||
<div>
|
||||
<span th:text="'financer v' + ${financerVersion}"/>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="#{financer.report-config-projected-cashflow-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 th:if="${darkMode}" rel="stylesheet" th:href="@{/css/darkModeColors.css}"/>
|
||||
<link th:if="${!darkMode}" rel="stylesheet" th:href="@{/css/lightModeColors.css}"/>
|
||||
<link rel="stylesheet" th:href="@{/css/main.css}">
|
||||
<link rel="shortcut icon" th:href="@{/favicon.ico}"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:text="#{financer.heading.report-config-projected-cashflow-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="report-config-projected-cashflow-for-period-form" action="#"
|
||||
th:action="@{/configureProjectedCashFlowForPeriodTransactions}" th:object="${form}" method="post">
|
||||
<label for="fromDate" th:text="#{financer.report-config-projected-cashflow-for-period.label.from-date}"/>
|
||||
<input type="date" id="fromDate" th:field="*{fromDate}"/>
|
||||
<label for="toDate" th:text="#{financer.report-config-projected-cashflow-for-period.label.to-date}"/>
|
||||
<input type="date" id="toDate" th:field="*{toDate}"/>
|
||||
<details>
|
||||
<summary th:text="#{financer.show-options}"/>
|
||||
<fieldset class="report-config-projected-cashflow-fieldset">
|
||||
<legend th:text="#{financer.report-config-projected-cashflow-for-period.label.account-or-account-group-summary}"/>
|
||||
<label for="by-account" th:text="#{financer.report-config-projected-cashflow-for-period.label.by-account}"/>
|
||||
<input type="radio" th:value="${true}" th:field="*{byAccount}" id="by-account" checked />
|
||||
<label for="by-account-group" th:text="#{financer.report-config-projected-cashflow-for-period.label.by-account-group}"/>
|
||||
<input type="radio" th:value="${false}" th:field="*{byAccount}" id="by-account-group"/>
|
||||
</fieldset>
|
||||
</details>
|
||||
<input type="submit" th:value="#{financer.report-config-projected-cashflow-for-period.submit}"/>
|
||||
</form>
|
||||
<div th:replace="includes/footer :: footer"/>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="#{financer.report-config-projected-cashflow-for-period-transactions.title}"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link th:if="${darkMode}" rel="stylesheet" th:href="@{/css/darkModeColors.css}"/>
|
||||
<link th:if="${!darkMode}" rel="stylesheet" th:href="@{/css/lightModeColors.css}"/>
|
||||
<link rel="stylesheet" th:href="@{/css/main.css}">
|
||||
<link rel="shortcut icon" th:href="@{/favicon.ico}"/>
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:text="#{financer.heading.report-config-projected-cashflow-for-period-transactions}" class="noprint"/>
|
||||
<h1 th:text="#{financer.heading.report-config-projected-cashflow-for-period-transactions-print}" class="print"/>
|
||||
<span th:text="${#temporals.format(form.fromDate) + ' - ' + #temporals.format(form.toDate)}" class="print print-padding" />
|
||||
<span class="errorMessage noprint" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}" />
|
||||
<a th:href="@{/accountOverview}" th:text="#{financer.cancel-back-to-overview}" class="noprint"/>
|
||||
<form id="report-config-projected-cashflow-for-period-transactions-form" action="#" th:object="${form}" method="post">
|
||||
<table id="report-config-projected-cashflow-for-period-transactions-table">
|
||||
<tr class="projected-cashflow-sum">
|
||||
<td th:text="#{financer.report-config-projected-cashflow-for-period-transactions.table.income.sum}"/>
|
||||
<td th:utext="${#numbers.formatDecimal(form.incomeSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||
class="projected-cashflow-sum report-config-projected-cashflow-for-period-transactions-table-amount"/>
|
||||
</tr>
|
||||
<tr th:each="entry, i : ${form.incomeTransactions}">
|
||||
<td class="projected-cashflow-transaction">
|
||||
<span th:text="*{incomeTransactions[__${i.index}__].description}" />
|
||||
<input type="hidden" th:field="*{incomeTransactions[__${i.index}__].description}" class="display-none" />
|
||||
</td>
|
||||
<td class="report-config-projected-cashflow-for-period-transactions-table-amount noprint">
|
||||
<input type="text" th:field="*{incomeTransactions[__${i.index}__].amount}" />
|
||||
</td>
|
||||
<td class="report-config-projected-cashflow-for-period-transactions-table-amount print">
|
||||
<span th:utext="${#numbers.formatDecimal(form.incomeTransactions[__${i.index}__].amount/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="projected-cashflow-sum">
|
||||
<td th:text="#{financer.report-config-projected-cashflow-for-period-transactions.table.expense.sum}"/>
|
||||
<td th:utext="${#numbers.formatDecimal((form.expenseSum/100D)*-1, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||
class="report-config-projected-cashflow-for-period-transactions-table-amount"/>
|
||||
</tr>
|
||||
<tr th:each="entry, i : ${form.expenseTransactions}">
|
||||
<td class="projected-cashflow-transaction">
|
||||
<span th:text="*{expenseTransactions[__${i.index}__].description}" />
|
||||
<input type="hidden" th:field="*{expenseTransactions[__${i.index}__].description}" class="display-none" />
|
||||
</td>
|
||||
<td class="report-config-projected-cashflow-for-period-transactions-table-amount noprint">
|
||||
<input type="text" th:field="*{expenseTransactions[__${i.index}__].amount}" />
|
||||
</td>
|
||||
<td class="report-config-projected-cashflow-for-period-transactions-table-amount print">
|
||||
<span th:utext="${#numbers.formatDecimal(form.expenseTransactions[__${i.index}__].amount/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="projected-cashflow-sum">
|
||||
<td th:text="#{financer.report-config-projected-cashflow-for-period-transactions.table.accounts.sum}"/>
|
||||
<td th:utext="${#numbers.formatDecimal((form.accountSum/100D)*-1, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||
class="report-config-projected-cashflow-for-period-transactions-table-amount"/>
|
||||
<td th:text="#{financer.account-overview.table-header.average-spending-period}"
|
||||
class="report-config-projected-cashflow-for-period-transactions-table-average-spending noprint"/>
|
||||
</tr>
|
||||
<tr th:each="entry, i : ${form.accountContainers}">
|
||||
<td class="projected-cashflow-transaction">
|
||||
<span th:text="*{accountContainers[__${i.index}__].account.key}" />
|
||||
<input type="hidden" th:field="*{accountContainers[__${i.index}__].account.key}" class="display-none" />
|
||||
</td>
|
||||
<td class="report-config-projected-cashflow-for-period-transactions-table-amount noprint">
|
||||
<input type="text" th:field="*{accountContainers[__${i.index}__].spending}" />
|
||||
</td>
|
||||
<td class="report-config-projected-cashflow-for-period-transactions-table-amount print">
|
||||
<span th:utext="${#numbers.formatDecimal(form.accountContainers[__${i.index}__].spending/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
</td>
|
||||
<td class="noprint report-config-projected-cashflow-for-period-transactions-table-average-spending">
|
||||
<span th:utext="${#numbers.formatDecimal(form.accountContainers[__${i.index}__].averageSpending/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
<input type="hidden" th:field="*{accountContainers[__${i.index}__].averageSpending}" class="display-none" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="projected-cashflow-sum">
|
||||
<td th:text="#{financer.report-config-projected-cashflow-for-period-transactions.table.cash-flow.sum}"/>
|
||||
<td th:utext="${#numbers.formatDecimal(form.cashFlow/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||
th:classappend="${form.cashFlow == 0 ? 'color-neutral' : form.cashFlow < 0 ? 'color-bad' : 'color-good'}"
|
||||
class="report-config-projected-cashflow-for-period-transactions-table-amount"/>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="hidden" th:field="*{fromDate}" class="display-none"/>
|
||||
<input type="hidden" th:field="*{toDate}" class="display-none"/>
|
||||
<input type="hidden" th:field="*{byAccount}" class="display-none"/>
|
||||
<input type="submit" th:formaction="@{/configureProjectedCashFlowForPeriodTransactionsRefresh}"
|
||||
th:value="#{financer.report-config-projected-cashflow-for-period-transactions.label.button.refresh}" class="noprint"/>
|
||||
<input type="submit" onClick="window.print()"
|
||||
th:value="#{financer.report-config-projected-cashflow-for-period-transactions.label.button.create}" class="noprint"/>
|
||||
</form>
|
||||
<div th:replace="includes/footer :: footer" />
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="#{financer.report-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 th:if="${darkMode}" rel="stylesheet" th:href="@{/css/darkModeColors.css}" />
|
||||
<link th:if="${!darkMode}" rel="stylesheet" th:href="@{/css/lightModeColors.css}" />
|
||||
<link rel="stylesheet" th:href="@{/css/main.css}">
|
||||
<link rel="shortcut icon" th:href="@{/favicon.ico}" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:text="#{financer.heading.report-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="report-select-form" action="#" th:action="@{/configureReport}" th:object="${form}" method="post">
|
||||
<th:block th:each="report, iterStat : ${availableReports}">
|
||||
<div>
|
||||
<input type="radio" th:value="${report}" th:field="*{reportType}" th:id="'report' + ${iterStat.count}"/>
|
||||
<label th:for="'report' + ${iterStat.count}" th:text="#{${'financer.report.name.' + report}}"/>
|
||||
</div>
|
||||
</th:block>
|
||||
<input type="submit" th:value="#{financer.report-select.submit}"/>
|
||||
</form>
|
||||
<div th:replace="includes/footer :: footer"/>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user