Introduce periods (and other smaller stuff)
This commit is contained in:
@@ -3,6 +3,7 @@ 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.GetAccountExpensesCurrentExpensePeriodTemplate;
|
||||
import de.financer.template.GetAccountExpensesTemplate;
|
||||
import de.financer.template.GetAccountGroupExpensesTemplate;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
@@ -12,8 +13,14 @@ 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();
|
||||
Iterable<AccountExpense> expenses;
|
||||
|
||||
if (start == null && end == null) {
|
||||
expenses = new GetAccountExpensesCurrentExpensePeriodTemplate().exchange(financerConfig).getBody();
|
||||
}
|
||||
else {
|
||||
expenses = new GetAccountExpensesTemplate().exchange(financerConfig, start, end).getBody();
|
||||
}
|
||||
|
||||
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.financer.chart.impl.expense;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.dto.AccountGroupExpense;
|
||||
import de.financer.template.GetAccountGroupExpensesCurrentExpensePeriodTemplate;
|
||||
import de.financer.template.GetAccountGroupExpensesTemplate;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.jfree.data.general.DefaultPieDataset;
|
||||
@@ -10,8 +11,14 @@ 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();
|
||||
Iterable<AccountGroupExpense> expenses;
|
||||
|
||||
if (start == null && end == null) {
|
||||
expenses = new GetAccountGroupExpensesCurrentExpensePeriodTemplate().exchange(financerConfig).getBody();
|
||||
}
|
||||
else {
|
||||
expenses = new GetAccountGroupExpensesTemplate().exchange(financerConfig, start, end).getBody();
|
||||
}
|
||||
|
||||
final DefaultPieDataset dataSet = new DefaultPieDataset();
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@ package de.financer.chart.impl.total;
|
||||
|
||||
import de.financer.chart.AbstractChartGenerator;
|
||||
import de.financer.dto.ExpensePeriodTotal;
|
||||
import de.financer.model.Period;
|
||||
import de.financer.template.GetExpensePeriodTotalsTemplate;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import de.financer.util.ExpensePeriod;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
import org.jfree.chart.ChartFactory;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
@@ -17,7 +16,7 @@ import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import java.text.NumberFormat;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class PeriodTotalGenerator extends AbstractChartGenerator<PeriodTotalParameter> {
|
||||
@Override
|
||||
@@ -45,30 +44,36 @@ public class PeriodTotalGenerator extends AbstractChartGenerator<PeriodTotalPara
|
||||
|
||||
private CategoryDataset getDataset(PeriodTotalParameter parameter) {
|
||||
final DefaultCategoryDataset result = new DefaultCategoryDataset();
|
||||
final List<ExpensePeriod> expensePeriods = ExpensePeriod
|
||||
.generateExpensePeriodsForYear(this.getFinancerConfig().getMonthPeriodStartDay(), parameter.getYear());
|
||||
|
||||
final Iterable<ExpensePeriodTotal> totalData = new GetExpensePeriodTotalsTemplate()
|
||||
.exchange(this.getFinancerConfig(), parameter.getYear()).getBody();
|
||||
|
||||
IterableUtils.toList(totalData).stream()
|
||||
.sorted(Comparator.comparing((ExpensePeriodTotal ept) -> ept.getPeriod().getStart())
|
||||
.thenComparing((ExpensePeriodTotal ept) -> ept.getType()))
|
||||
.forEach((ept) -> result.addValue((ept.getTotal() / 100D),
|
||||
this.getMessage("financer.account-type." + ept.getType()),
|
||||
expensePeriods.stream()
|
||||
.filter((ep) -> ep.generatePeriodShortCode()
|
||||
.equals(ept.getPeriodShortCode()))
|
||||
.map((ep) -> formatDateY(ep))
|
||||
.findFirst().get()));
|
||||
formatDateY(ept.getPeriod())));
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String formatDateY(ExpensePeriod ep) {
|
||||
return String.format("%s - %s",
|
||||
ep.getStart().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(LocaleContextHolder.getLocale())),
|
||||
ep.getEnd().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(LocaleContextHolder.getLocale())));
|
||||
private String formatDateY(Period ep) {
|
||||
final String start = ep.getStart().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(LocaleContextHolder.getLocale()));
|
||||
|
||||
String end;
|
||||
|
||||
if (ep.getEnd() == null) {
|
||||
end = this.getMessage("financer.chart.expense-period-totals-current-year.open-period");
|
||||
}
|
||||
else {
|
||||
end = ep.getEnd().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
.withLocale(LocaleContextHolder.getLocale()));
|
||||
}
|
||||
|
||||
return String.format("%s - %s", start, end);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package de.financer.controller;
|
||||
|
||||
import de.financer.ResponseReason;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.decorator.AccountDecorator;
|
||||
import de.financer.template.*;
|
||||
import de.financer.form.NewAccountForm;
|
||||
import de.financer.model.*;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import de.financer.util.ExpensePeriod;
|
||||
import de.financer.util.TransactionUtils;
|
||||
import de.financer.util.comparator.TransactionByDateByIdDescComparator;
|
||||
import org.apache.commons.collections4.IterableUtils;
|
||||
@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
public class AccountController {
|
||||
@@ -34,18 +35,20 @@ public class AccountController {
|
||||
final ResponseEntity<Iterable<RecurringTransaction>> rtAllActRes = new GetAllActiveRecurringTransactionsTemplate()
|
||||
.exchange(this.financerConfig);
|
||||
final ResponseEntity<Long> currentAssets = new GetCurrentAssetsTemplate().exchange(this.financerConfig);
|
||||
final ResponseEntity<Long> currentExpenses = new GetExpensesCurrentPeriodTemplate().exchange(this.financerConfig);
|
||||
final ResponseEntity<Long> currentExpenses = new GetExpensesCurrentPeriodTemplate()
|
||||
.exchange(this.financerConfig);
|
||||
final boolean showClosedBoolean = BooleanUtils.toBoolean(showClosed);
|
||||
final ExpensePeriod expensePeriod = ExpensePeriod
|
||||
.getCurrentExpensePeriod(this.financerConfig.getMonthPeriodStartDay());
|
||||
final ResponseEntity<Period> expensePeriodRes = new GetCurrentExpensePeriodTemplate()
|
||||
.exchange(this.financerConfig);
|
||||
final Period expensePeriod = expensePeriodRes.getBody();
|
||||
|
||||
model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(response.getBody(), showClosedBoolean));
|
||||
model.addAttribute("accounts", decorateAccounts(ControllerUtils
|
||||
.filterAndSortAccounts(response.getBody(), showClosedBoolean)));
|
||||
model.addAttribute("rtDueTodayCount", IterableUtils.size(rtDtRes.getBody()));
|
||||
model.addAttribute("rtAllActiveCount", IterableUtils.size(rtAllActRes.getBody()));
|
||||
model.addAttribute("currentAssets", currentAssets.getBody());
|
||||
model.addAttribute("currentExpenses", currentExpenses.getBody());
|
||||
model.addAttribute("periodStart", expensePeriod.getStart());
|
||||
model.addAttribute("periodEnd", expensePeriod.getEnd());
|
||||
model.addAttribute("showClosed", showClosedBoolean);
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
@@ -53,6 +56,10 @@ public class AccountController {
|
||||
return "account/accountOverview";
|
||||
}
|
||||
|
||||
private Iterable<AccountDecorator> decorateAccounts(List<Account> accounts) {
|
||||
return accounts.stream().map((a) -> new AccountDecorator(a)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@GetMapping("/newAccount")
|
||||
public String newAccount(Model model) {
|
||||
final ResponseEntity<Iterable<AccountGroup>> accountGroupResponse = new GetAllAccountGroupsTemplate()
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package de.financer.controller;
|
||||
|
||||
import de.financer.chart.impl.expense.ExpensesParameter;
|
||||
import de.financer.chart.ChartGenerator;
|
||||
import de.financer.chart.ChartType;
|
||||
import de.financer.chart.FinancerChartFactory;
|
||||
import de.financer.chart.impl.expense.ExpensesParameter;
|
||||
import de.financer.chart.impl.total.PeriodTotalParameter;
|
||||
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;
|
||||
import org.jfree.chart.ChartUtils;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -32,12 +31,8 @@ public class ChartController {
|
||||
|
||||
@GetMapping("/getAccountGroupExpensesCurrentPeriod")
|
||||
public void getAccountGroupExpensesCurrentPeriod(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-group-expenses-current-period.title");
|
||||
|
||||
final ChartGenerator<ExpensesParameter> generator =
|
||||
@@ -70,12 +65,8 @@ public class ChartController {
|
||||
|
||||
@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 =
|
||||
|
||||
@@ -8,10 +8,12 @@ public enum Function {
|
||||
ACC_OPEN_ACCOUNT("accounts/openAccount"),
|
||||
ACC_CURRENT_ASSETS("accounts/getCurrentAssets"),
|
||||
ACC_GET_ACC_EXPENSES("accounts/getAccountExpenses"),
|
||||
ACC_GET_ACC_EXPENSES_CURRENT_EXPENSE_PERIOD("accounts/getAccountExpensesCurrentExpensePeriod"),
|
||||
|
||||
ACC_GP_CREATE_ACCOUNT_GROUP("accountGroups/createAccountGroup"),
|
||||
ACC_GP_GET_ALL("accountGroups/getAll"),
|
||||
ACC_GP_GET_ACC_GP_EXPENSES("accountGroups/getAccountGroupExpenses"),
|
||||
ACC_GP_GET_ACC_GP_EXPENSES_CURRENT_EXPENSE_PERIOD("accountGroups/getAccountGroupExpensesCurrentExpensePeriod"),
|
||||
|
||||
TR_GET_ALL("transactions/getAll"),
|
||||
TR_GET_ALL_FOR_ACCOUNT("transactions/getAllForAccount"),
|
||||
@@ -26,7 +28,10 @@ public enum Function {
|
||||
RT_GET_ALL_DUE_TODAY("recurringTransactions/getAllDueToday"),
|
||||
RT_CREATE_RECURRING_TRANSACTION("recurringTransactions/createRecurringTransaction"),
|
||||
RT_DELETE_RECURRING_TRANSACTION("recurringTransactions/deleteRecurringTransaction"),
|
||||
RT_CREATE_TRANSACTION("recurringTransactions/createTransaction");
|
||||
RT_CREATE_TRANSACTION("recurringTransactions/createTransaction"),
|
||||
|
||||
P_GET_CURRENT_EXPENSE_PERIOD("periods/getCurrentExpensePeriod"),
|
||||
P_CLOSE_CURRENT_EXPENSE_PERIOD("periods/closeCurrentExpensePeriod");
|
||||
|
||||
private String path;
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.financer.controller;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.template.StringTemplate;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
@Controller
|
||||
public class PeriodController {
|
||||
@Autowired
|
||||
private FinancerConfig financerConfig;
|
||||
|
||||
@GetMapping("/closePeriod")
|
||||
public String closePeriod() {
|
||||
final UriComponentsBuilder builder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(this.financerConfig, Function.P_CLOSE_CURRENT_EXPENSE_PERIOD));
|
||||
|
||||
new StringTemplate().exchange(builder);
|
||||
|
||||
return "redirect:/accountOverview";
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,10 @@ package de.financer.controller;
|
||||
|
||||
import de.financer.ResponseReason;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.model.*;
|
||||
import de.financer.template.*;
|
||||
import de.financer.form.NewRecurringTransactionForm;
|
||||
import de.financer.form.RecurringToTransactionWithAmountForm;
|
||||
import de.financer.model.Account;
|
||||
import de.financer.model.HolidayWeekendType;
|
||||
import de.financer.model.IntervalType;
|
||||
import de.financer.model.RecurringTransaction;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -19,6 +16,8 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
public class RecurringTransactionController {
|
||||
@@ -30,10 +29,18 @@ public class RecurringTransactionController {
|
||||
public String newRecurringTransaction(Model model) {
|
||||
final ResponseEntity<Iterable<Account>> response = new GetAllAccountsTemplate().exchange(this.financerConfig);
|
||||
final NewRecurringTransactionForm form = new NewRecurringTransactionForm();
|
||||
final List<Account> fromAccounts = ControllerUtils.filterAndSortAccounts(response.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.EXPENSE)
|
||||
.collect(Collectors.toList());
|
||||
final List<Account> toAccounts = ControllerUtils.filterAndSortAccounts(response.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.INCOME && a
|
||||
.getType() != AccountType.START)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
form.setRemind(Boolean.TRUE);
|
||||
|
||||
model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(response.getBody()));
|
||||
model.addAttribute("fromAccounts", fromAccounts);
|
||||
model.addAttribute("toAccounts", toAccounts);
|
||||
model.addAttribute("intervalTypes", IntervalType.valueList());
|
||||
model.addAttribute("holidayWeekendTypes", HolidayWeekendType.valueList());
|
||||
model.addAttribute("form", form);
|
||||
@@ -64,8 +71,16 @@ public class RecurringTransactionController {
|
||||
if (!ResponseReason.OK.equals(responseReason)) {
|
||||
final ResponseEntity<Iterable<Account>> getAllResponse = new GetAllAccountsTemplate()
|
||||
.exchange(this.financerConfig);
|
||||
final List<Account> fromAccounts = ControllerUtils.filterAndSortAccounts(getAllResponse.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.EXPENSE)
|
||||
.collect(Collectors.toList());
|
||||
final List<Account> toAccounts = ControllerUtils.filterAndSortAccounts(getAllResponse.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.INCOME && a
|
||||
.getType() != AccountType.START)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(getAllResponse.getBody()));
|
||||
model.addAttribute("fromAccounts", fromAccounts);
|
||||
model.addAttribute("toAccounts", toAccounts);
|
||||
model.addAttribute("intervalTypes", IntervalType.valueList());
|
||||
model.addAttribute("holidayWeekendTypes", HolidayWeekendType.valueList());
|
||||
model.addAttribute("form", form);
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.financer.controller;
|
||||
|
||||
import de.financer.ResponseReason;
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.model.AccountType;
|
||||
import de.financer.template.GetAccountByKeyTemplate;
|
||||
import de.financer.template.GetAllAccountsTemplate;
|
||||
import de.financer.template.GetAllTransactionsForAccountTemplate;
|
||||
@@ -23,6 +24,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
public class TransactionController {
|
||||
@@ -33,8 +35,16 @@ public class TransactionController {
|
||||
@GetMapping("/newTransaction")
|
||||
public String newTransaction(Model model) {
|
||||
final ResponseEntity<Iterable<Account>> response = new GetAllAccountsTemplate().exchange(this.financerConfig);
|
||||
final List<Account> fromAccounts = ControllerUtils.filterAndSortAccounts(response.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.EXPENSE)
|
||||
.collect(Collectors.toList());
|
||||
final List<Account> toAccounts = ControllerUtils.filterAndSortAccounts(response.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.INCOME && a
|
||||
.getType() != AccountType.START)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(response.getBody()));
|
||||
model.addAttribute("fromAccounts", fromAccounts);
|
||||
model.addAttribute("toAccounts", toAccounts);
|
||||
model.addAttribute("form", new NewTransactionForm());
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||
@@ -57,8 +67,16 @@ public class TransactionController {
|
||||
|
||||
if (!ResponseReason.OK.equals(responseReason)) {
|
||||
final ResponseEntity<Iterable<Account>> accRes = new GetAllAccountsTemplate().exchange(this.financerConfig);
|
||||
final List<Account> fromAccounts = ControllerUtils.filterAndSortAccounts(accRes.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.EXPENSE)
|
||||
.collect(Collectors.toList());
|
||||
final List<Account> toAccounts = ControllerUtils.filterAndSortAccounts(accRes.getBody()).stream()
|
||||
.filter((a) -> a.getType() != AccountType.INCOME && a
|
||||
.getType() != AccountType.START)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(accRes.getBody()));
|
||||
model.addAttribute("fromAccounts", fromAccounts);
|
||||
model.addAttribute("toAccounts", toAccounts);
|
||||
model.addAttribute("form", form);
|
||||
model.addAttribute("errorMessage", responseReason.name());
|
||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||
@@ -79,7 +97,8 @@ public class TransactionController {
|
||||
final ResponseEntity<String> response = new StringTemplate().exchange(builder);
|
||||
final ResponseReason responseReason = ResponseReason.fromResponseEntity(response);
|
||||
|
||||
final ResponseEntity<Account> accountResponse = new GetAccountByKeyTemplate().exchange(this.financerConfig, accountKey);
|
||||
final ResponseEntity<Account> accountResponse = new GetAccountByKeyTemplate()
|
||||
.exchange(this.financerConfig, accountKey);
|
||||
final Account account = accountResponse.getBody();
|
||||
final ResponseEntity<Iterable<Transaction>> transactionResponse = new GetAllTransactionsForAccountTemplate()
|
||||
.exchange(this.financerConfig, account.getKey());
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package de.financer.decorator;
|
||||
|
||||
import de.financer.model.*;
|
||||
|
||||
public class AccountDecorator {
|
||||
private final Account account;
|
||||
|
||||
public Long getId() {
|
||||
return account.getId();
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return account.getKey();
|
||||
}
|
||||
|
||||
public AccountType getType() {
|
||||
return account.getType();
|
||||
}
|
||||
|
||||
public AccountStatus getStatus() {
|
||||
return account.getStatus();
|
||||
}
|
||||
|
||||
public Long getCurrentBalance() {
|
||||
return account.getCurrentBalance();
|
||||
}
|
||||
|
||||
public AccountGroup getAccountGroup() {
|
||||
return account.getAccountGroup();
|
||||
}
|
||||
|
||||
public AccountDecorator(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Long getSpendingCurrentExpensePeriod() {
|
||||
if (this.account.getType() == AccountType.EXPENSE || this.account.getType() == AccountType.LIABILITY) {
|
||||
return this.account.getAccountStatistics().stream()
|
||||
.filter((as) -> as.getPeriod().getType().equals(PeriodType.EXPENSE) && as.getPeriod()
|
||||
.getEnd() == null)
|
||||
.findFirst()
|
||||
.orElseGet(() -> {
|
||||
AccountStatistic as = new AccountStatistic();
|
||||
as.setTransactionCountTo(0l);
|
||||
return as;
|
||||
})
|
||||
.getSpendingTotalTo();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Long getAverageSpendingExpensePeriod() {
|
||||
if (this.account.getType() == AccountType.EXPENSE || this.account.getType() == AccountType.LIABILITY) {
|
||||
return Math.round(this.account.getAccountStatistics().stream()
|
||||
.filter((as) -> as.getPeriod().getType().equals(PeriodType.EXPENSE) && as.getPeriod()
|
||||
.getEnd() != null)
|
||||
.mapToLong((as) -> as.getSpendingTotalTo())
|
||||
.average()
|
||||
.orElseGet(() -> Double.valueOf(0d)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.financer.template;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.controller.Function;
|
||||
import de.financer.dto.AccountExpense;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
public class GetAccountExpensesCurrentExpensePeriodTemplate {
|
||||
public ResponseEntity<Iterable<AccountExpense>> exchange(FinancerConfig financerConfig) {
|
||||
final UriComponentsBuilder expensesBuilder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.ACC_GET_ACC_EXPENSES_CURRENT_EXPENSE_PERIOD));
|
||||
|
||||
return new FinancerRestTemplate<Iterable<AccountExpense>>()
|
||||
.exchange(expensesBuilder.toUriString(), new ParameterizedTypeReference<Iterable<AccountExpense>>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.financer.template;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.controller.Function;
|
||||
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 GetAccountGroupExpensesCurrentExpensePeriodTemplate {
|
||||
public ResponseEntity<Iterable<AccountGroupExpense>> exchange(FinancerConfig financerConfig) {
|
||||
final UriComponentsBuilder expensesBuilder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.ACC_GP_GET_ACC_GP_EXPENSES_CURRENT_EXPENSE_PERIOD));
|
||||
|
||||
return new FinancerRestTemplate<Iterable<AccountGroupExpense>>()
|
||||
.exchange(expensesBuilder.toUriString(), new ParameterizedTypeReference<Iterable<AccountGroupExpense>>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.financer.template;
|
||||
|
||||
import de.financer.config.FinancerConfig;
|
||||
import de.financer.controller.Function;
|
||||
import de.financer.model.Period;
|
||||
import de.financer.util.ControllerUtils;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
public class GetCurrentExpensePeriodTemplate {
|
||||
public ResponseEntity<Period> exchange(FinancerConfig financerConfig) {
|
||||
final UriComponentsBuilder expensesBuilder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.P_GET_CURRENT_EXPENSE_PERIOD));
|
||||
|
||||
return new FinancerRestTemplate<Period>()
|
||||
.exchange(expensesBuilder.toUriString(), new ParameterizedTypeReference<Period>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ public class GetExpensePeriodTotalsTemplate {
|
||||
public ResponseEntity<Iterable<ExpensePeriodTotal>> exchange(FinancerConfig financerConfig, int year) {
|
||||
final UriComponentsBuilder builder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.TR_EXPENSE_PERIOD_TOTALS))
|
||||
.queryParam("monthPeriodStartDay", financerConfig.getMonthPeriodStartDay())
|
||||
.queryParam("year", year);
|
||||
|
||||
return new FinancerRestTemplate<Iterable<ExpensePeriodTotal>>()
|
||||
|
||||
@@ -10,8 +10,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
public class GetExpensesCurrentPeriodTemplate {
|
||||
public ResponseEntity<Long> exchange(FinancerConfig financerConfig) {
|
||||
final UriComponentsBuilder transactionBuilder = UriComponentsBuilder
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.TR_EXPENSES_CURRENT_PERIOD))
|
||||
.queryParam("monthPeriodStartDay", financerConfig.getMonthPeriodStartDay());
|
||||
.fromHttpUrl(ControllerUtils.buildUrl(financerConfig, Function.TR_EXPENSES_CURRENT_PERIOD));
|
||||
|
||||
return new FinancerRestTemplate<Long>()
|
||||
.exchange(transactionBuilder.toUriString(), new ParameterizedTypeReference<Long>() {
|
||||
|
||||
@@ -44,6 +44,10 @@ public class ControllerUtils {
|
||||
}
|
||||
|
||||
public static String formatDate(FinancerConfig financerConfig, LocalDate date) {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return date.format(DateTimeFormatter.ofPattern(financerConfig.getDateFormat()));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,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.close-current-period=Close the current expense period
|
||||
financer.account-overview.status=Status\:
|
||||
financer.account-overview.status.recurring-transaction-due-today=Recurring transactions due today\:
|
||||
financer.account-overview.status.recurring-transaction-active=Active recurring transactions\:
|
||||
@@ -16,10 +17,12 @@ financer.account-overview.status.current-expenses=Expenses in the current period
|
||||
financer.account-overview.table-header.id=ID
|
||||
financer.account-overview.table-header.key=Account
|
||||
financer.account-overview.table-header.group=Group
|
||||
financer.account-overview.table-header.balance=Current Balance
|
||||
financer.account-overview.table-header.balance=Balance
|
||||
financer.account-overview.table-header.spending-current-period=Spending current period
|
||||
financer.account-overview.table-header.average-spending-period=Average spending
|
||||
financer.account-overview.table-header.type=Type
|
||||
financer.account-overview.table-header.status=Status
|
||||
financer.account-overview.tooltip.status.current-expenses=Period from {0} to {1}. Clicking the amount will open a graphical overview about the expenses grouped by account group
|
||||
financer.account-overview.tooltip.status.current-expenses=Period starting at {0}. Clicking the amount will open a graphical overview about the expenses grouped by account group
|
||||
financer.account-overview.tooltip.status.current-assets=Assets available at short-notice
|
||||
|
||||
financer.account-new.title=financer\: create new account
|
||||
@@ -88,6 +91,7 @@ financer.account-details.available-actions=Available actions\:
|
||||
financer.account-details.available-actions.close-account=Close account
|
||||
financer.account-details.available-actions.open-account=Open account
|
||||
financer.account-details.available-actions.back-to-overview=Back to overview
|
||||
financer.account-details.available-actions.create-transaction=Create new transaction
|
||||
financer.account-details.table-header.id=ID
|
||||
financer.account-details.table-header.fromAccount=From account
|
||||
financer.account-details.table-header.toAccount=To account
|
||||
@@ -163,6 +167,7 @@ financer.chart.account-expenses-for-period.title=Expenses for period from {0} to
|
||||
financer.chart.expense-period-totals-current-year.title=Expense period totals for the current year
|
||||
financer.chart.expense-period-totals-current-year.x=Amount
|
||||
financer.chart.expense-period-totals-current-year.y=Period
|
||||
financer.chart.expense-period-totals-current-year.open-period=OPEN
|
||||
|
||||
financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Expenses of the current period grouped by account group (pie chart)
|
||||
financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Expenses for a configurable period grouped by account group (pie chart)
|
||||
|
||||
@@ -8,6 +8,7 @@ financer.account-overview.available-actions.create-recurring-transaction=Neue wi
|
||||
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.select-chart=Ein Diagramm erzeugen
|
||||
financer.account-overview.available-actions.close-current-period=Aktuelle Periode schlie\u00DFen
|
||||
financer.account-overview.status=Status\:
|
||||
financer.account-overview.status.recurring-transaction-due-today=Wiederkehrende Buchungen heute f\u00E4llig\:
|
||||
financer.account-overview.status.recurring-transaction-active=Aktive wiederkehrende Buchungen\:
|
||||
@@ -19,7 +20,7 @@ financer.account-overview.table-header.group=Gruppe
|
||||
financer.account-overview.table-header.balance=Kontostand
|
||||
financer.account-overview.table-header.type=Typ
|
||||
financer.account-overview.table-header.status=Status
|
||||
financer.account-overview.tooltip.status.current-expenses=Periode ab {0} bis {1}. Durch Klicken des Betrags kann eine grafische \u00DCbersicht über die Ausgaben gruppiert nach Konto-Gruppe angezeigt werden
|
||||
financer.account-overview.tooltip.status.current-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-assets=Kurzfristig verf\u00FCgbares Verm\u00F6gen
|
||||
|
||||
financer.account-new.title=financer\: Neues Konto erstellen
|
||||
@@ -88,6 +89,7 @@ financer.account-details.available-actions=Verf\u00FCgbare Aktionen\:
|
||||
financer.account-details.available-actions.close-account=Konto schlie\u00DFen
|
||||
financer.account-details.available-actions.open-account=Konto \u00F6ffnen
|
||||
financer.account-details.available-actions.back-to-overview=Zur\u00FCck zur \u00DCbersicht
|
||||
financer.account-details.available-actions.create-transaction=Neue Buchung erstellen
|
||||
financer.account-details.table-header.id=ID
|
||||
financer.account-details.table-header.fromAccount=Von Konto
|
||||
financer.account-details.table-header.toAccount=An Konto
|
||||
@@ -162,6 +164,7 @@ financer.chart.account-expenses-for-period.title=Ausgaben in der Periode vom {0}
|
||||
financer.chart.expense-period-totals-current-year.title=Gesamtbetr\u00E4ge gruppiert nach Periode für das aktuelle Jahr
|
||||
financer.chart.expense-period-totals-current-year.x=Betrag
|
||||
financer.chart.expense-period-totals-current-year.y=Periode
|
||||
financer.chart.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)
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
v18 -> v19:
|
||||
- Fix a bug in recurring transaction handling that caused a recurring transaction with Holiday/Weekend type
|
||||
'previous workday' and a planned occurrence on a Sunday to be due on Friday and Saturday
|
||||
- Filter from and to account lists when creating a transaction or a recurring transaction by account types that
|
||||
are allowed in from and to
|
||||
- Add the create new transaction action to the account detail view
|
||||
- Rework periods (e.g. expense) so that the underlying technical structures are better defined. This is preparation for
|
||||
more reports and budgeting functions
|
||||
- Add action to close the current expense period manually. This also opens a new one
|
||||
- Add spending in current expense period per account to the account overview
|
||||
- Add average spending in expense period per account to the account overview
|
||||
|
||||
v17 -> v18:
|
||||
- Add readme to the footer
|
||||
- Translate error messages to German
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
<span th:text="#{financer.account-details.details.balance}"/>
|
||||
<span th:text="${#numbers.formatDecimal(account.currentBalance/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
</div>
|
||||
<div id="group-container">
|
||||
<div id="group-container" th:if="${account.accountGroup != null}">
|
||||
<span th:text="#{financer.account-details.details.group}"/>
|
||||
<span th:text="${account.accountGroup?.name}"/>
|
||||
<span th:text="${account.accountGroup.name}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="account-details-action-container">
|
||||
@@ -29,6 +29,8 @@
|
||||
th:text="#{financer.account-details.available-actions.close-account}"/>
|
||||
<a th:if="${isClosed}" th:href="@{/openAccount(key=${account.key})}"
|
||||
th:text="#{financer.account-details.available-actions.open-account}"/>
|
||||
<a th:href="@{/newTransaction}"
|
||||
th:text="#{financer.account-details.available-actions.create-transaction}"/>
|
||||
<a th:href="@{/accountOverview}"
|
||||
th:text="#{financer.account-details.available-actions.back-to-overview}"/>
|
||||
</div>
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:text="#{financer.heading.account-overview}" />
|
||||
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
|
||||
<div id="status-container">
|
||||
<span th:text="#{financer.account-overview.status}"/>
|
||||
<div th:title="#{financer.account-overview.tooltip.status.current-assets}">
|
||||
<span th:text="#{financer.account-overview.status.current-assets}"/>
|
||||
<span th:text="${#numbers.formatDecimal(currentAssets/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
</div>
|
||||
<div th:title="#{'financer.account-overview.tooltip.status.current-expenses'(${#temporals.format(periodStart)}, ${#temporals.format(periodEnd)})}">
|
||||
<div th:title="#{'financer.account-overview.tooltip.status.current-expenses'(${#temporals.format(periodStart)})}">
|
||||
<span th:text="#{financer.account-overview.status.current-expenses}"/>
|
||||
<a th:href="@{/getAccountGroupExpensesCurrentPeriod}">
|
||||
<span th:text="${#numbers.formatDecimal(currentExpenses/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}" />
|
||||
@@ -28,7 +29,6 @@
|
||||
<span th:text="#{financer.account-overview.status.recurring-transaction-active}"/>
|
||||
<a th:href="@{/recurringTransactionActive}" th:text="${rtAllActiveCount}"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<span th:text="#{financer.account-overview.available-actions}"/>
|
||||
<div id="action-container">
|
||||
@@ -49,6 +49,10 @@
|
||||
<a th:href="@{/recurringTransactionAll}"
|
||||
th:text="#{financer.account-overview.available-actions.recurring-transaction-all}"/>
|
||||
</div>
|
||||
<div id="action-container-sub-period">
|
||||
<a th:href="@{/closePeriod}"
|
||||
th:text="#{financer.account-overview.available-actions.close-current-period}"/>
|
||||
</div>
|
||||
<div id="action-container-sub-reports">
|
||||
<a th:href="@{/selectChart}"
|
||||
th:text="#{financer.account-overview.available-actions.select-chart}"/>
|
||||
@@ -59,6 +63,8 @@
|
||||
<th class="hideable-column" th:text="#{financer.account-overview.table-header.id}"/>
|
||||
<th th:text="#{financer.account-overview.table-header.key}"/>
|
||||
<th th:text="#{financer.account-overview.table-header.balance}"/>
|
||||
<th class="hideable-column" th:text="#{financer.account-overview.table-header.spending-current-period}"/>
|
||||
<th class="hideable-column" th:text="#{financer.account-overview.table-header.average-spending-period}"/>
|
||||
<th class="hideable-column" th:text="#{financer.account-overview.table-header.group}"/>
|
||||
<th class="hideable-column" th:text="#{financer.account-overview.table-header.type}"/>
|
||||
<th class="hideable-column" th:text="#{financer.account-overview.table-header.status}"/>
|
||||
@@ -69,6 +75,12 @@
|
||||
<a th:href="@{/accountDetails(key=${acc.key})}" th:text="${acc.key}"/>
|
||||
</td>
|
||||
<td th:text="${#numbers.formatDecimal(acc.currentBalance/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
<td th:if="${acc.spendingCurrentExpensePeriod != null}"
|
||||
th:text="${#numbers.formatDecimal(acc.spendingCurrentExpensePeriod/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
<td th:if="${acc.averageSpendingExpensePeriod != null}"
|
||||
th:text="${#numbers.formatDecimal(acc.averageSpendingExpensePeriod/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
||||
<td th:if="${acc.spendingCurrentExpensePeriod == null}">-</td>
|
||||
<td th:if="${acc.averageSpendingExpensePeriod == null}">-</td>
|
||||
<td class="hideable-column" th:text="${acc.accountGroup?.name}"/>
|
||||
<td class="hideable-column" th:text="#{'financer.account-type.' + ${acc.type}}"/>
|
||||
<td class="hideable-column" th:text="#{'financer.account-status.' + ${acc.status}}"/>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
method="post">
|
||||
<label for="selectFromAccount" th:text="#{financer.recurring-transaction-new.label.from-account}"/>
|
||||
<select id="selectFromAccount" th:field="*{fromAccountKey}">
|
||||
<option th:each="acc : ${accounts}" th:value="${acc.key}"
|
||||
<option th:each="acc : ${fromAccounts}" th:value="${acc.key}"
|
||||
th:text="#{'financer.recurring-transaction-new.account-type.' + ${acc.type}(${acc.key},${#numbers.formatDecimal(acc.currentBalance/100D, 1, 'DEFAULT', 2, 'DEFAULT')},${currencySymbol})}"/>
|
||||
</select>
|
||||
<label for="selectToAccount" th:text="#{financer.recurring-transaction-new.label.to-account}"/>
|
||||
<select id="selectToAccount" th:field="*{toAccountKey}">
|
||||
<option th:each="acc : ${accounts}" th:value="${acc.key}"
|
||||
<option th:each="acc : ${toAccounts}" th:value="${acc.key}"
|
||||
th:text="#{'financer.recurring-transaction-new.account-type.' + ${acc.type}(${acc.key},${#numbers.formatDecimal(acc.currentBalance/100D, 1, 'DEFAULT', 2, 'DEFAULT')},${currencySymbol})}"/>
|
||||
</select>
|
||||
<label for="inputAmount" th:text="#{financer.recurring-transaction-new.label.amount}"/>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
method="post">
|
||||
<label for="selectFromAccount" th:text="#{financer.transaction-new.label.from-account}"/>
|
||||
<select id="selectFromAccount" th:field="*{fromAccountKey}">
|
||||
<option th:each="acc : ${accounts}" th:value="${acc.key}"
|
||||
<option th:each="acc : ${fromAccounts}" th:value="${acc.key}"
|
||||
th:text="#{'financer.transaction-new.account-type.' + ${acc.type}(${acc.key},${#numbers.formatDecimal(acc.currentBalance/100D, 1, 'DEFAULT', 2, 'DEFAULT')},${currencySymbol})}"/>
|
||||
</select>
|
||||
<label for="selectToAccount" th:text="#{financer.transaction-new.label.to-account}"/>
|
||||
<select id="selectToAccount" th:field="*{toAccountKey}">
|
||||
<option th:each="acc : ${accounts}" th:value="${acc.key}"
|
||||
<option th:each="acc : ${toAccounts}" th:value="${acc.key}"
|
||||
th:text="#{'financer.transaction-new.account-type.' + ${acc.type}(${acc.key},${#numbers.formatDecimal(acc.currentBalance/100D, 1, 'DEFAULT', 2, 'DEFAULT')},${currencySymbol})}"/>
|
||||
</select>
|
||||
<label for="inputAmount" th:text="#{financer.transaction-new.label.amount}"/>
|
||||
|
||||
Reference in New Issue
Block a user