#11 Add possibility to specify booking date at recurring transaction booking

This commit is contained in:
2021-09-01 13:17:36 +02:00
parent ddec50eca8
commit 2cb7589b96
13 changed files with 116 additions and 74 deletions

View File

@@ -1,15 +1,13 @@
package de.financer.controller;
import com.google.common.collect.Lists;
import de.financer.ResponseReason;
import de.financer.calendar.Day;
import de.financer.calendar.Week;
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.form.RecurringToTransactionWithOverrideForm;
import de.financer.util.ControllerUtils;
import org.apache.commons.collections4.IterableUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
@@ -18,15 +16,9 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.util.UriComponentsBuilder;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalField;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@Controller
@@ -218,11 +210,28 @@ public class RecurringTransactionController {
return "redirect:/accountOverview";
}
@GetMapping("/recurringToTransactionWithAmount")
public String recurringToTransactionWithAmount(String recurringTransactionId, String sub, Model model) {
RecurringToTransactionWithAmountForm form = new RecurringToTransactionWithAmountForm();
@GetMapping("/recurringToTransactionWithOverrides")
public String recurringToTransactionWithOverrides(String recurringTransactionId, String sub, Model model) {
final ResponseEntity<Iterable<RecurringTransaction>> response = new GetAllRecurringTransactionsTemplate()
.exchange(this.financerConfig);
final RecurringToTransactionWithOverrideForm form =
IterableUtils.toList(response.getBody()).stream()
.filter(rt ->
rt.getId().equals(Long.valueOf(recurringTransactionId)))
.findFirst()
.map(rt -> {
RecurringToTransactionWithOverrideForm tmpForm =
new RecurringToTransactionWithOverrideForm();
tmpForm.setRecurringTransactionId(rt.getId().toString());
tmpForm.setAmount(rt.getAmount().toString());
tmpForm.setDate(
ControllerUtils.formatDateForForm(LocalDate.now()));
return tmpForm;
})
.get();
form.setRecurringTransactionId(recurringTransactionId);
form.setSubTitle(sub);
model.addAttribute("form", form);
@@ -231,15 +240,16 @@ public class RecurringTransactionController {
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
ControllerUtils.addDarkMode(model, this.financerConfig);
return "recurringTransaction/recurringToTransactionWithAmount";
return "recurringTransaction/recurringToTransactionWithOverrides";
}
@PostMapping("/createTransactionWithAmount")
public String createTransactionWithAmount(RecurringToTransactionWithAmountForm form, Model model) {
@PostMapping("/createTransactionWithOverrides")
public String createTransactionWithOverrides(RecurringToTransactionWithOverrideForm form, Model model) {
final UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl(ControllerUtils.buildUrl(this.financerConfig, Function.RT_CREATE_TRANSACTION))
.queryParam("recurringTransactionId", form.getRecurringTransactionId())
.queryParam("amount", form.getAmount());
.queryParam("amount", form.getAmount())
.queryParam("date", ControllerUtils.formatDate(this.financerConfig, form.getDate()));
final ResponseEntity<String> response = new StringTemplate().exchange(builder);
final ResponseReason responseReason = ResponseReason.fromResponseEntity(response);

View File

@@ -1,9 +1,10 @@
package de.financer.form;
public class RecurringToTransactionWithAmountForm {
public class RecurringToTransactionWithOverrideForm {
private String recurringTransactionId;
private String amount;
private String subTitle;
private String date;
public String getRecurringTransactionId() {
return recurringTransactionId;
@@ -28,4 +29,12 @@ public class RecurringToTransactionWithAmountForm {
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}

View File

@@ -65,6 +65,15 @@ public class ControllerUtils {
return formatted.format(DateTimeFormatter.ofPattern(financerConfig.getDateFormat()));
}
public static String formatDateForForm(LocalDate date) {
if (date == null) {
return null;
}
// The format is always "yyyy-MM-dd", see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date
return DateTimeFormatter.ofPattern("yyyy-MM-dd").format(date);
}
public static String formatDate(FinancerConfig financerConfig, String dateFromForm, Locale locale) {
if (StringUtils.isEmpty(dateFromForm)) {
return null;

View File

@@ -90,7 +90,7 @@ financer.recurring-transaction-list.table-header.holidayWeekendType=Holiday/week
financer.recurring-transaction-list.table-header.taxRelevant=Tax relevant
financer.recurring-transaction-list.table-header.actions=Actions
financer.recurring-transaction-list.table.actions.createTransaction=Create transaction
financer.recurring-transaction-list.table.actions.createTransactionWithAmount=Create transaction with amount
financer.recurring-transaction-list.table.actions.createTransactionWithOverrides=Create transaction with overrides
financer.recurring-transaction-list.table.actions.editRecurringTransaction=Edit
financer.recurring-transaction-list.table.actions.deleteRecurringTransaction=Delete
financer.recurring-transaction-list.table.taxRelevant.true=Yes
@@ -124,9 +124,10 @@ financer.transaction-list.table.taxRelevant.true=Yes
financer.transaction-list.table.taxRelevant.false=No
financer.transaction-list.transaction-count=Found {0} transactions
financer.recurring-to-transaction-with-amount.title=financer\: create transaction from recurring with amount
financer.recurring-to-transaction-with-amount.label.amount=Amount\:
financer.recurring-to-transaction-with-amount.submit=Create
financer.recurring-to-transaction-with-override.title=financer\: create transaction from recurring with overrides
financer.recurring-to-transaction-with-override.label.amount=Amount\:
financer.recurring-to-transaction-with-override.label.date=Date\:
financer.recurring-to-transaction-with-override.submit=Create
financer.search-transactions.title=financer\: search transactions
financer.search-transactions.back-to-overview=Back to overview
@@ -217,7 +218,6 @@ financer.period-overview.table.actions.showAllTransactions=All transactions
financer.period-overview.table.actions.showIncomeTransactions=Income transactions
financer.period-overview.table.actions.showExpenseTransactions=Expense transactions
financer.period-overview.table.actions.showLiabilityTransactions=Liability transactions
financer.period-overview.show-actions=Show...
financer.interval-type.DAILY=Daily
financer.interval-type.WEEKLY=Weekly
@@ -253,7 +253,7 @@ financer.heading.account-details=financer\: account details for {0}
financer.heading.recurring-transaction-list.dueToday=financer\: recurring transactions due today
financer.heading.recurring-transaction-list.active=financer\: active recurring transactions
financer.heading.recurring-transaction-list.all=financer\: all recurring transaction
financer.heading.recurring-to-transaction-with-amount=financer\: create transaction from recurring with amount
financer.heading.recurring-to-transaction-with-override=financer\: create transaction from recurring with overrides
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
@@ -266,6 +266,8 @@ financer.heading.create-upload-transactions=financer\: create uploaded transacti
financer.cancel-back-to-overview=Cancel and back to overview
financer.back-to-overview=Back to overview
financer.show-actions=Show...
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

View File

@@ -90,7 +90,7 @@ financer.recurring-transaction-list.table-header.holidayWeekendType=Feiertag-/Wo
financer.recurring-transaction-list.table-header.taxRelevant=Relevant f\u00FCr Steuererkl\u00E4rung
financer.recurring-transaction-list.table-header.actions=Aktionen
financer.recurring-transaction-list.table.actions.createTransaction=Erstelle Buchung
financer.recurring-transaction-list.table.actions.createTransactionWithAmount=Erstelle Buchung mit Betrag
financer.recurring-transaction-list.table.actions.createTransactionWithOverrides=Erstelle Buchung mit \u00DCberschreibungen
financer.recurring-transaction-list.table.actions.editRecurringTransaction=Bearbeiten
financer.recurring-transaction-list.table.actions.deleteRecurringTransaction=L\u00F6schen
financer.recurring-transaction-list.table.taxRelevant.true=Ja
@@ -124,9 +124,10 @@ financer.transaction-list.table.taxRelevant.true=Ja
financer.transaction-list.table.taxRelevant.false=Nein
financer.transaction-list.transaction-count={0} Buchungen gefunden
financer.recurring-to-transaction-with-amount.title=financer\: Buchung mit Betrag aus wiederkehrender Buchung erstellen
financer.recurring-to-transaction-with-amount.label.amount=Betrag\:
financer.recurring-to-transaction-with-amount.submit=Erstellen
financer.recurring-to-transaction-with-override.title=financer\: Buchung mit \u00DCberschreibungen aus wiederkehrender Buchung erstellen
financer.recurring-to-transaction-with-override.label.amount=Betrag\:
financer.recurring-to-transaction-with-override.label.date=Datum\:
financer.recurring-to-transaction-with-override.submit=Erstellen
financer.search-transactions.title=financer\: Buchungen suchen
financer.search-transactions.back-to-overview=Zur\u00FCck zur \u00DCbersicht
@@ -217,7 +218,6 @@ financer.period-overview.table.actions.showAllTransactions=Alle Buchungen
financer.period-overview.table.actions.showIncomeTransactions=Einkommenbuchungen
financer.period-overview.table.actions.showExpenseTransactions=Ausgabebuchungen
financer.period-overview.table.actions.showLiabilityTransactions=Verbindlichkeitenbuchungen
financer.period-overview.show-actions=Anzeigen...
financer.interval-type.DAILY=T\u00E4glich
financer.interval-type.WEEKLY=W\u00F6chentlich
@@ -253,7 +253,7 @@ financer.heading.account-details=financer\: Kontodetails f\u00FCr {0}
financer.heading.recurring-transaction-list.dueToday=financer\: Wiederkehrende Buchungen heute f\u00E4llig
financer.heading.recurring-transaction-list.active=financer\: Aktive wiederkehrende Buchungen
financer.heading.recurring-transaction-list.all=financer\: Alle wiederkehrende Buchungen
financer.heading.recurring-to-transaction-with-amount=financer\: Buchung mit Betrag aus wiederkehrender Buchung erstellen
financer.heading.recurring-to-transaction-with-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.search-transactions=financer\: Buchungen suchen
@@ -264,6 +264,7 @@ financer.heading.create-upload-transactions=financer\: Erstelle hochgeladene Buc
financer.cancel-back-to-overview=Abbrechen und zur\u00FCck zur \u00DCbersicht
financer.back-to-overview=Zur\u00FCck zur \u00DCbersicht
financer.show-actions=Anzeigen...
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

View File

@@ -1,6 +1,7 @@
v48 -> v49:
- #27 The recurring transaction selection during transaction import now contains all recurring transaction instead of
only the active ones
- #11 It is now possible to specify a date during creation of a transaction from a recurring transaction
v47 -> v48:
- Added new property 'transaction type' to a transaction, denoting the type of the transaction, e.g. asset swap,

View File

@@ -170,7 +170,7 @@ tr:hover {
#new-account-form *,
#new-transaction-form *,
#new-recurring-transaction-form *,
#recurring-to-transaction-with-amount-form *,
#recurring-to-transaction-with-override-form *,
#new-account-group-form *,
#chart-config-account-group-expenses-for-period-form *,
#chart-config-account-expenses-for-period-form *,

View File

@@ -64,7 +64,7 @@
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
<td nowrap>
<details>
<summary th:text="#{financer.period-overview.show-actions}"/>
<summary th:text="#{financer.show-actions}"/>
<div id="period-overview-show-actions-detail-container">
<div id="period-overview-show-actions-detail-container-show-all">
<a th:href="@{/showAllTransactions(periodId=${periodOverview.periodId})}"

View File

@@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{financer.recurring-to-transaction-with-amount.title}"/>
<title th:text="#{financer.recurring-to-transaction-with-override.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}" />
@@ -10,16 +10,18 @@
<link rel="shortcut icon" th:href="@{/favicon.ico}" />
</head>
<body>
<h1 th:text="#{financer.heading.recurring-to-transaction-with-amount}" />
<h1 th:text="#{financer.heading.recurring-to-transaction-with-override}" />
<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="recurring-to-transaction-with-amount-form" action="#" th:action="@{/createTransactionWithAmount}" th:object="${form}"
<form id="recurring-to-transaction-with-override-form" action="#" th:action="@{/createTransactionWithOverrides}" th:object="${form}"
method="post">
<label for="inputAmount" th:text="#{financer.recurring-to-transaction-with-amount.label.amount}"/>
<label for="inputAmount" th:text="#{financer.recurring-to-transaction-with-override.label.amount}"/>
<input type="text" id="inputAmount" th:field="*{amount}"/>
<label for="inputDate" th:text="#{financer.recurring-to-transaction-with-override.label.date}"/>
<input type="date" id="inputDate" th:field="*{date}"/>
<input type="hidden" id="inputId" th:field="*{recurringTransactionId}"/>
<input type="hidden" id="inputSub" th:field="*{subTitle}"/>
<input type="submit" th:value="#{financer.recurring-to-transaction-with-amount.submit}"/>
<input type="submit" th:value="#{financer.recurring-to-transaction-with-override.submit}"/>
</form>
<div th:replace="includes/footer :: footer"/>
</body>

View File

@@ -4,10 +4,10 @@
<title th:text="#{'financer.recurring-transaction-list.title.' + ${subTitle}}"/>
<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 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}" />
<link rel="shortcut icon" th:href="@{/favicon.ico}"/>
</head>
<body>
<h1 th:text="#{'financer.heading.recurring-transaction-list.' + ${subTitle}}"/>
@@ -41,16 +41,20 @@
<td th:text="${rt.description}"/>
<td th:text="#{'financer.interval-type.' + ${rt.intervalType}}"/>
<td th:text="#{'financer.holiday-weekend-type.' + ${rt.holidayWeekendType}}"/>
<td th:text="#{'financer.recurring-transaction-list.table.taxRelevant.' + ${rt.taxRelevant}}" />
<td>
<div id="recurring-transaction-list-table-actions-container">
<a th:href="@{/recurringToTransaction(recurringTransactionId=${rt.id}, sub=${subTitle})}"
th:text="#{financer.recurring-transaction-list.table.actions.createTransaction}"/>
<a th:href="@{/recurringToTransactionWithAmount(recurringTransactionId=${rt.id}, sub=${subTitle})}"
th:text="#{financer.recurring-transaction-list.table.actions.createTransactionWithAmount}"/>
<a th:if="${subTitle == 'all'}" th:href="@{/deleteRecurringTransaction(recurringTransactionId=${rt.id})}"
th:text="#{financer.recurring-transaction-list.table.actions.deleteRecurringTransaction}"/>
</div>
<td th:text="#{'financer.recurring-transaction-list.table.taxRelevant.' + ${rt.taxRelevant}}"/>
<td nowrap>
<details>
<summary th:text="#{financer.show-actions}"/>
<div id="recurring-transaction-list-table-actions-container">
<a th:href="@{/recurringToTransaction(recurringTransactionId=${rt.id}, sub=${subTitle})}"
th:text="#{financer.recurring-transaction-list.table.actions.createTransaction}"/>
<a th:href="@{/recurringToTransactionWithOverrides(recurringTransactionId=${rt.id}, sub=${subTitle})}"
th:text="#{financer.recurring-transaction-list.table.actions.createTransactionWithOverrides}"/>
<a th:if="${subTitle == 'all'}"
th:href="@{/deleteRecurringTransaction(recurringTransactionId=${rt.id})}"
th:text="#{financer.recurring-transaction-list.table.actions.deleteRecurringTransaction}"/>
</div>
</details>
</td>
</tr>
</table>

View File

@@ -1,6 +1,7 @@
<div id="transaction-list-container" th:fragment="transaction-list">
<div id="transaction-list-container-count-con" th:if="${transactionCount != null}">
<p id="transaction-list-container-count-con-text" th:text="#{'financer.transaction-list.transaction-count'(${transactionCount})}"/>
<p id="transaction-list-container-count-con-text"
th:text="#{'financer.transaction-list.transaction-count'(${transactionCount})}"/>
</div>
<table id="transaction-table">
<tr>
@@ -23,23 +24,26 @@
</tr>
<tr th:each="transaction : ${transactions}">
<td class="hideable-column" th:text="${transaction.id}"/>
<td th:text="${transaction.fromAccount.key}" />
<td th:text="${transaction.toAccount.key}" />
<td th:text="${#temporals.format(transaction.date)}" />
<td th:utext="${#numbers.formatDecimal(transaction.amount/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}" />
<td th:text="${transaction.description}" />
<td th:if="${transaction.recurring}" th:text="#{financer.transaction-list.table.recurring.yes}" />
<td th:if="${!transaction.recurring}" th:text="#{financer.transaction-list.table.recurring.no}" />
<td th:text="#{'financer.transaction-list.table.taxRelevant.' + ${transaction.taxRelevant}}" />
<td th:text="${transaction.fromAccount.key}"/>
<td th:text="${transaction.toAccount.key}"/>
<td th:text="${#temporals.format(transaction.date)}"/>
<td th:utext="${#numbers.formatDecimal(transaction.amount/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
<td th:text="${transaction.description}"/>
<td th:if="${transaction.recurring}" th:text="#{financer.transaction-list.table.recurring.yes}"/>
<td th:if="${!transaction.recurring}" th:text="#{financer.transaction-list.table.recurring.no}"/>
<td th:text="#{'financer.transaction-list.table.taxRelevant.' + ${transaction.taxRelevant}}"/>
<td nowrap>
<div id="account-transaction-table-actions-container">
<a th:href="@{/deleteTransaction(transactionId=${transaction.id}, accountKey=${account.key})}"
th:text="#{financer.transaction-list.table.actions.deleteTransaction}"
th:if="${showActionDelete}" />
<a th:href="@{/downloadFile(fileId=${transaction.fileId})}"
th:text="#{financer.transaction-list.table.actions.downloadFile}"
th:if="${transaction.fileId != null}" />
</div>
<details>
<summary th:text="#{financer.show-actions}"/>
<div id="account-transaction-table-actions-container">
<a th:href="@{/deleteTransaction(transactionId=${transaction.id}, accountKey=${account.key})}"
th:text="#{financer.transaction-list.table.actions.deleteTransaction}"
th:if="${showActionDelete}"/>
<a th:href="@{/downloadFile(fileId=${transaction.fileId})}"
th:text="#{financer.transaction-list.table.actions.downloadFile}"
th:if="${transaction.fileId != null}"/>
</div>
</details>
</td>
</tr>
</table>