Add FQL and rework /transaction endpoint

This commit is contained in:
2020-03-14 23:44:43 +01:00
parent 1cc7fdf052
commit d4fef75903
85 changed files with 2257 additions and 472 deletions

View File

@@ -4,6 +4,7 @@ financer.account-overview.available-actions.show-closed=Show closed accounts
financer.account-overview.available-actions.hide-closed=Hide closed accounts
financer.account-overview.available-actions.create-account=Create new account
financer.account-overview.available-actions.create-transaction=Create new transaction
financer.account-overview.available-actions.search-transactions=Search transactions
financer.account-overview.available-actions.create-recurring-transaction=Create new recurring transaction
financer.account-overview.available-actions.recurring-transaction-all=Show all recurring transactions
financer.account-overview.available-actions.create-account-group=Create new account group
@@ -98,28 +99,34 @@ 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
financer.account-details.table-header.date=Date
financer.account-details.table-header.amount=Amount
financer.account-details.table-header.description=Description
financer.account-details.table-header.byRecurring=Recurring
financer.account-details.table-header.taxRelevant=Tax relevant
financer.transaction-list.table-header.id=ID
financer.transaction-list.table-header.fromAccount=From account
financer.transaction-list.table-header.toAccount=To account
financer.transaction-list.table-header.date=Date
financer.transaction-list.table-header.amount=Amount
financer.transaction-list.table-header.description=Description
financer.transaction-list.table-header.byRecurring=Recurring
financer.transaction-list.table-header.taxRelevant=Tax relevant
financer.account-details.details.type=Type\:
financer.account-details.details.balance=Current balance\:
financer.account-details.details.group=Group\:
financer.account-details.table-header.actions=Actions
financer.account-details.table.actions.deleteTransaction=Delete
financer.account-details.table.recurring.yes=Yes
financer.account-details.table.recurring.no=No
financer.account-details.table.taxRelevant.true=Yes
financer.account-details.table.taxRelevant.false=No
financer.transaction-list.table-header.actions=Actions
financer.transaction-list.table.actions.deleteTransaction=Delete
financer.transaction-list.table.recurring.yes=Yes
financer.transaction-list.table.recurring.no=No
financer.transaction-list.table.taxRelevant.true=Yes
financer.transaction-list.table.taxRelevant.false=No
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.search-transactions.title=financer\: search transactions
financer.search-transactions.back-to-overview=Back to overview
financer.search-transactions.label.fql=FQL expression\:
financer.search-transactions.submit=Search
financer.search-transactions.show-query-options=Show query options
financer.chart-select.title=Select a chart to generate
financer.chart-select.submit=Select
@@ -166,6 +173,7 @@ financer.heading.recurring-to-transaction-with-amount=financer\: create transact
financer.heading.chart-select=financer\: select a chart to generate
financer.heading.chart-config-account-group-expenses-for-period=financer\: configure account group expenses for period chart
financer.heading.chart-config-account-expenses-for-period=financer\: configure account expenses for period chart
financer.heading.search-transactions=financer\: search transactions
financer.cancel-back-to-overview=Cancel and back to overview

View File

@@ -4,6 +4,7 @@ financer.account-overview.available-actions.show-closed=Zeige auch geschlossene
financer.account-overview.available-actions.hide-closed=Verstecke geschlossene Konten
financer.account-overview.available-actions.create-account=Neues Konto erstellen
financer.account-overview.available-actions.create-transaction=Neue Buchung erstellen
financer.account-overview.available-actions.search-transactions=Buchungen suchen
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
@@ -18,6 +19,8 @@ financer.account-overview.table-header.id=ID
financer.account-overview.table-header.key=Konto
financer.account-overview.table-header.group=Gruppe
financer.account-overview.table-header.balance=Kontostand
financer.account-overview.table-header.spending-current-period=Ausgaben aktuelle Periode
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
@@ -96,28 +99,34 @@ 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
financer.account-details.table-header.date=Datum
financer.account-details.table-header.amount=Betrag
financer.account-details.table-header.description=Beschreibung
financer.account-details.table-header.byRecurring=Wiederkehrend
financer.account-details.table-header.taxRelevant=Relevant f\u00FCr Steuererkl\u00E4rung
financer.transaction-list.table-header.id=ID
financer.transaction-list.table-header.fromAccount=Von Konto
financer.transaction-list.table-header.toAccount=An Konto
financer.transaction-list.table-header.date=Datum
financer.transaction-list.table-header.amount=Betrag
financer.transaction-list.table-header.description=Beschreibung
financer.transaction-list.table-header.byRecurring=Wiederkehrend
financer.transaction-list.table-header.taxRelevant=Relevant f\u00FCr Steuererkl\u00E4rung
financer.account-details.details.type=Typ\:
financer.account-details.details.balance=Kontostand\:
financer.account-details.details.group=Gruppe\:
financer.account-details.table-header.actions=Aktionen
financer.account-details.table.actions.deleteTransaction=L\u00F6schen
financer.account-details.table.recurring.yes=Ja
financer.account-details.table.recurring.no=Nein
financer.account-details.table.taxRelevant.true=Ja
financer.account-details.table.taxRelevant.false=Nein
financer.transaction-list.table-header.actions=Aktionen
financer.transaction-list.table.actions.deleteTransaction=L\u00F6schen
financer.transaction-list.table.recurring.yes=Ja
financer.transaction-list.table.recurring.no=Nein
financer.transaction-list.table.taxRelevant.true=Ja
financer.transaction-list.table.taxRelevant.false=Nein
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.search-transactions.title=financer\: Buchungen suchen
financer.search-transactions.back-to-overview=Zur\u00FCck zur \u00DCbersicht
financer.search-transactions.label.fql=FQL Ausdruck\:
financer.search-transactions.submit=Suchen
financer.search-transactions.show-query-options=Suchoptionen anzeigen
financer.chart-select.title=Ein Diagramm zum Erzeugen ausw\u00E4hlen
financer.chart-select.submit=Ausw\u00E4hlen
@@ -157,12 +166,13 @@ financer.heading.account-new=financer\: Neues Konto erstellen
financer.heading.account-group-new=financer\: Neue Konto-Gruppe 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
financer.heading.recurring-transaction-list.active=financer\: aktive wiederkehrende Buchungen
financer.heading.recurring-transaction-list.all=financer\: alle wiederkehrende Buchungen
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.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-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
financer.cancel-back-to-overview=Abbrechen und zur \u00DCbersicht

View File

@@ -2,7 +2,10 @@ v26 -> v27:
- Changed sort order of accounts in overview page. The accounts are now sorted by the account type first (BCILES), then
by the account group name and then by the account ID, leading to an overall more organic order of accounts
- Add tax relevance flag to transaction and recurring transaction creation. This flag denotes whether a transaction or
the instances of a recurring transaction are relevant for a tax declaration. This is preparation for extended reports.
the instances of a recurring transaction are relevant for a tax declaration. This is preparation for extended reports
- Add searching of transactions via FQL (Financer Query Language)
- Rework /transaction end point to better adhere to REST API requirements (proper HTTP return codes and HTTP method
usage)
v25 -> v26:
- Close of the current expense period now creates null statistic entries for accounts that have not been used in

View File

@@ -12,7 +12,7 @@
/* --------------------- */
#account-overview-table,
#account-transaction-table,
#transaction-table,
#recurring-transaction-list-table {
width: 100%;
border-collapse: collapse;
@@ -23,8 +23,8 @@
#account-overview-table th,
#account-overview-table td,
#account-transaction-table th,
#account-transaction-table td,
#transaction-table th,
#transaction-table td,
#recurring-transaction-list-table th,
#recurring-transaction-list-table td {
border-bottom: 1px solid #ddd;
@@ -33,7 +33,7 @@
}
#account-overview-table th,
#account-transaction-table th,
#transaction-table th,
#recurring-transaction-list-table th {
position: sticky;
top: 0px;
@@ -107,13 +107,18 @@ tr:hover {
#recurring-to-transaction-with-amount-form *,
#new-account-group-form *,
#chart-config-account-group-expenses-for-period-form *,
#chart-config-account-expenses-for-period-form * {
#chart-config-account-expenses-for-period-form *,
#search-transactions-form * {
display: block;
margin-top: 1em;
width: 20em;
box-sizing: border-box;
}
#search-transactions-form > input[type=text] {
width: 100% !important;
}
#chart-select-form div {
width: 20em;
margin-top: 1em;
@@ -187,4 +192,15 @@ input[type=submit] {
#type-row {
width: var(--type-row-width);
padding: 0px !important
}
#search-transactions-fql-detail {
border: 1px solid grey;
border-radius: 0.5em;
padding-inline: 0.3em;
background-color: lightgrey;
}
#search-transactions-fql-detail > * {
font-size: 0.7em;
}

View File

@@ -14,8 +14,9 @@
7. Transactions
8. Recurring transactions
9. Reporting
10. Setup
11. Planned features
10. FQL
11. Setup
12. Planned features
1. About
========
@@ -170,12 +171,15 @@
9. Reporting
============
10. Setup
10. FQL
=======
11. Setup
=========
This chapter explains how to setup a financer instance. It requires PostgreSQL as a database backend and a Java
Servlet Container (e.g. Apache Tomcat) as a runtime environment.
10.1 Database setup
11.1 Database setup
-------------------
First install PostgreSQL. Then create a user for financer:
sudo -iu postgres
@@ -191,7 +195,7 @@
\q
exit
11. Planned features
12. Planned features
====================
This chapter lists planned features. The list is in no particular order:
- Transaction import from online banking (file based)

View File

@@ -35,36 +35,7 @@
<a th:href="@{/accountOverview}"
th:text="#{financer.account-details.available-actions.back-to-overview}"/>
</div>
<table id="account-transaction-table">
<tr>
<th class="hideable-column" th:text="#{financer.account-details.table-header.id}"/>
<th th:text="#{financer.account-details.table-header.fromAccount}"/>
<th th:text="#{financer.account-details.table-header.toAccount}"/>
<th th:text="#{financer.account-details.table-header.date}"/>
<th th:text="#{financer.account-details.table-header.amount}"/>
<th th:text="#{financer.account-details.table-header.description}"/>
<th th:text="#{financer.account-details.table-header.byRecurring}"/>
<th th:text="#{financer.account-details.table-header.taxRelevant}"/>
<th th:text="#{financer.account-details.table-header.actions}"/>
</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:text="${#numbers.formatDecimal(transaction.amount/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
<td th:text="${transaction.description}" />
<td th:if="${transaction.recurringTransaction != null}" th:text="#{financer.account-details.table.recurring.yes}" />
<td th:if="${transaction.recurringTransaction == null}" th:text="#{financer.account-details.table.recurring.no}" />
<td th:text="#{'financer.account-details.table.taxRelevant.' + ${transaction.taxRelevant}}" />
<td>
<div id="account-transaction-table-actions-container">
<a th:href="@{/deleteTransaction(transactionId=${transaction.id}, accountKey=${account.key})}"
th:text="#{financer.account-details.table.actions.deleteTransaction}"/>
</div>
</td>
</tr>
</table>
<div th:replace="transaction/transactionList :: transaction-list"/>
<div th:replace="includes/footer :: footer"/>
</body>
</html>

View File

@@ -49,6 +49,7 @@
</div>
<div id="action-container-sub-transactions">
<a th:href="@{/newTransaction}" th:text="#{financer.account-overview.available-actions.create-transaction}"/>
<a th:href="@{/searchTransactions}" th:text="#{financer.account-overview.available-actions.search-transactions}"/>
</div>
<div id="action-container-sub-recurring-transactions">
<a th:href="@{/newRecurringTransaction}"

View File

@@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{financer.search-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 rel="stylesheet" th:href="@{/css/main.css}">
<link rel="shortcut icon" th:href="@{/favicon.ico}" />
</head>
<body>
<h1 th:text="#{financer.heading.search-transactions}" />
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
<a th:href="@{/accountOverview}" th:text="#{financer.search-transactions.back-to-overview}"/>
<form id="search-transactions-form" action="#" th:action="@{/searchTransactions}" th:object="${form}"
method="post">
<label for="inputFql" th:text="#{financer.search-transactions.label.fql}"/>
<input type="text" id="inputFql" th:field="*{fql}"/>
<input type="submit" th:value="#{financer.search-transactions.submit}"/>
</form>
<details>
<summary th:text="#{financer.search-transactions.show-query-options}"/>
<div id="search-transactions-fql-detail">
<p>
<div>Available fields:</div>
<ul>
<li>amount: the amount of a transaction</li>
<li>fromAccount: the key of the from account</li>
<li>toAccount: the key of the to account</li>
<li>fromAccountGroup: the name of the account group of the from account</li>
<li>toAccountGroup: the name of the account group of the to account</li>
<li>date: the date of the transaction in the format yyyy-mm-dd</li>
<li>recurring: whether the transaction has been created from a recurring transaction</li>
<li>taxRelevant: whether the transaction is relevant for tax declaration</li>
<li>period: the period the transaction is assigned to
<ul>
<li>CURRENT: denotes the current expense period</li>
<li>LAST: denotes the last expense period</li>
<li>CURRENT_YEAR: denotes the current year period</li>
<li>LAST_YEAR: denotes the last year period</li>
<li>GRAND_TOTAL: denotes the grand total period</li>
</ul>
</li>
</ul>
</p>
<p>
<div>General</div>
<ul>
<li>Conjunctions with OR, AND</li>
<li>Grouping of expressions with parenthesis</li>
<li>Strings enclosed in single quotes</li>
<li>Case-insensitive</li>
<li>Possible operators =, >, >=, <, <=, !=</li>
<li>Ordering for a single field ASC, DESC via ORDER BY</li>
</ul>
</p>
</div>
</details>
<div th:replace="transaction/transactionList :: transaction-list"/>
<div th:replace="includes/footer :: footer"/>
</body>
</html>

View File

@@ -0,0 +1,32 @@
<div id="transaction-list-container" th:fragment="transaction-list">
<table id="transaction-table">
<tr>
<th class="hideable-column" th:text="#{financer.transaction-list.table-header.id}"/>
<th th:text="#{financer.transaction-list.table-header.fromAccount}"/>
<th th:text="#{financer.transaction-list.table-header.toAccount}"/>
<th th:text="#{financer.transaction-list.table-header.date}"/>
<th th:text="#{financer.transaction-list.table-header.amount}"/>
<th th:text="#{financer.transaction-list.table-header.description}"/>
<th th:text="#{financer.transaction-list.table-header.byRecurring}"/>
<th th:text="#{financer.transaction-list.table-header.taxRelevant}"/>
<th th:if="${showActions}" th:text="#{financer.transaction-list.table-header.actions}"/>
</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:text="${#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:if="${showActions}">
<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}"/>
</div>
</td>
</tr>
</table>
</div>