#18 Period overview: improvements
This commit is contained in:
@@ -23,7 +23,7 @@ orderByExpression
|
|||||||
regularExpression
|
regularExpression
|
||||||
: (stringExpression | intExpression | booleanExpression | dateExpression) ;
|
: (stringExpression | intExpression | booleanExpression | dateExpression) ;
|
||||||
stringExpression
|
stringExpression
|
||||||
: field=IDENTIFIER operator=STRING_OPERATOR value=STRING_VALUE ;
|
: field=IDENTIFIER operator=STRING_OPERATOR value=(STRING_VALUE | ACCOUNT_TYPE_VALUE) ;
|
||||||
intExpression
|
intExpression
|
||||||
: field=IDENTIFIER operator=(INT_OPERATOR | STRING_OPERATOR) value=INT_VALUE ;
|
: field=IDENTIFIER operator=(INT_OPERATOR | STRING_OPERATOR) value=INT_VALUE ;
|
||||||
|
|
||||||
@@ -96,34 +96,34 @@ fragment K : ('K' | 'k') ;
|
|||||||
fragment SPACE : ' ' ;
|
fragment SPACE : ' ' ;
|
||||||
|
|
||||||
// Keywords
|
// Keywords
|
||||||
BETWEEN : B E T W E E N ;
|
BETWEEN : B E T W E E N ;
|
||||||
AND : A N D ;
|
AND : A N D ;
|
||||||
OR : O R ;
|
OR : O R ;
|
||||||
ORDER_BY : O R D E R SPACE B Y ;
|
ORDER_BY : O R D E R SPACE B Y ;
|
||||||
DESC : D E S C ;
|
DESC : D E S C ;
|
||||||
ASC : A S C ;
|
ASC : A S C ;
|
||||||
TRUE : T R U E ;
|
TRUE : T R U E ;
|
||||||
FALSE : F A L S E ;
|
FALSE : F A L S E ;
|
||||||
LIKE : L I K E ;
|
LIKE : L I K E ;
|
||||||
IN : I N ;
|
IN : I N ;
|
||||||
COMMA : ',' ;
|
COMMA : ',' ;
|
||||||
|
|
||||||
// Constant values
|
// Constant values
|
||||||
CURRENT : C U R R E N T ;
|
CURRENT : C U R R E N T ;
|
||||||
LAST : L A S T ;
|
LAST : L A S T ;
|
||||||
YEAR : Y E A R ;
|
YEAR : Y E A R ;
|
||||||
GRAND_TOTAL : G R A N D '_' T O T A L ;
|
GRAND_TOTAL : G R A N D '_' T O T A L ;
|
||||||
CURRENT_YEAR : CURRENT '_' YEAR ;
|
CURRENT_YEAR : CURRENT '_' YEAR ;
|
||||||
LAST_YEAR : LAST '_' YEAR ;
|
LAST_YEAR : LAST '_' YEAR ;
|
||||||
|
|
||||||
STRING_OPERATOR : '=' ;
|
STRING_OPERATOR : '=' ;
|
||||||
INT_OPERATOR : '>' | '<' | '>=' | '<=' | '!=' ;
|
INT_OPERATOR : '>' | '<' | '>=' | '<=' | '!=' ;
|
||||||
L_PAREN : '(' ;
|
L_PAREN : '(' ;
|
||||||
R_PAREN : ')' ;
|
R_PAREN : ')' ;
|
||||||
IDENTIFIER : [a-zA-Z]+ ;
|
IDENTIFIER : [a-zA-Z]+ ;
|
||||||
INT_VALUE : [0-9]+ ;
|
INT_VALUE : [0-9]+ ;
|
||||||
STRING_VALUE : '\'' [a-zA-Z0-9\-/.&%@$ ]+ '\'' ;
|
STRING_VALUE : '\'' [a-zA-Z0-9\-/.&%@$ ]+ '\'' ;
|
||||||
DATE_VALUE : [0-9][0-9][0-9][0-9][-][0-9][0-9][-][0-9][0-9] ; // ANTLR does not support regex quantifiers
|
DATE_VALUE : [0-9][0-9][0-9][0-9][-][0-9][0-9][-][0-9][0-9] ; // ANTLR does not support regex quantifiers
|
||||||
|
|
||||||
NEWLINE : ('\r'? '\n' | '\r')+ ;
|
NEWLINE : ('\r'? '\n' | '\r')+ ;
|
||||||
WHITESPACE : ' ' -> skip;
|
WHITESPACE : ' ' -> skip;
|
||||||
@@ -7,24 +7,38 @@ import de.financer.model.*;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public enum FieldMapping {
|
public enum FieldMapping {
|
||||||
AMOUNT("amount", Transaction_.AMOUNT, Transaction.class, NoopJoinHandler.class, JoinKey
|
AMOUNT("amount", Transaction_.AMOUNT, Transaction.class, NoopJoinHandler.class,
|
||||||
.of(Transaction.class), null, IntHandler.class),
|
JoinKey.of(Transaction.class), null, IntHandler.class),
|
||||||
|
|
||||||
PERIOD("period", Period_.ID, Period.class, PeriodJoinHandler.class, JoinKey.of(Period.class), null, PeriodConstHandler.class),
|
PERIOD("period", Period_.ID, Period.class, PeriodJoinHandler.class,
|
||||||
|
JoinKey.of(Period.class), null, PeriodConstHandler.class),
|
||||||
|
|
||||||
FROM_ACCOUNT("fromAccount", Account_.KEY, Account.class, FromAccountJoinHandler.class, JoinKey
|
/**
|
||||||
.of(Account.class, "FROM"), null, StringHandler.class),
|
* ONLY FOR INTERNAL USAGE - NOT EXPOSED TO USER
|
||||||
|
*/
|
||||||
|
PERIOD_ID("periodId", Period_.ID, Period.class, PeriodJoinHandler.class,
|
||||||
|
JoinKey.of(Period.class), null, PeriodIdHandler.class),
|
||||||
|
|
||||||
TO_ACCOUNT("toAccount", Account_.KEY, Account.class, ToAccountJoinHandler.class, JoinKey
|
FROM_ACCOUNT("fromAccount", Account_.KEY, Account.class, FromAccountJoinHandler.class,
|
||||||
.of(Account.class, "TO"), null, StringHandler.class),
|
JoinKey.of(Account.class, "FROM"), null, StringHandler.class),
|
||||||
|
|
||||||
FROM_ACCOUNT_GROUP("fromAccountGroup", AccountGroup_.NAME, AccountGroup.class,
|
TO_ACCOUNT("toAccount", Account_.KEY, Account.class, ToAccountJoinHandler.class,
|
||||||
AccountGroupJoinHandler.class, JoinKey.of(AccountGroup.class, "FROM"), FROM_ACCOUNT, StringHandler.class),
|
JoinKey.of(Account.class, "TO"), null, StringHandler.class),
|
||||||
|
|
||||||
TO_ACCOUNT_GROUP("toAccountGroup", AccountGroup_.NAME, AccountGroup.class,
|
FROM_ACCOUNT_GROUP("fromAccountGroup", AccountGroup_.NAME, AccountGroup.class, AccountGroupJoinHandler.class,
|
||||||
AccountGroupJoinHandler.class, JoinKey.of(AccountGroup.class, "TO"), TO_ACCOUNT, StringHandler.class),
|
JoinKey.of(AccountGroup.class, "FROM"), FROM_ACCOUNT, StringHandler.class),
|
||||||
|
|
||||||
DATE("date", Transaction_.DATE, Transaction.class, NoopJoinHandler.class, JoinKey.of(Transaction.class), null, DateHandler.class),
|
TO_ACCOUNT_GROUP("toAccountGroup", AccountGroup_.NAME, AccountGroup.class, AccountGroupJoinHandler.class,
|
||||||
|
JoinKey.of(AccountGroup.class, "TO"), TO_ACCOUNT, StringHandler.class),
|
||||||
|
|
||||||
|
FROM_ACCOUNT_TYPE("fromAccountType", Account_.TYPE, Account.class, FromAccountJoinHandler.class,
|
||||||
|
JoinKey.of(Account.class, "FROM"), null, AccountTypeHandler.class),
|
||||||
|
|
||||||
|
TO_ACCOUNT_TYPE("toAccountType", Account_.TYPE, Account.class, ToAccountJoinHandler.class,
|
||||||
|
JoinKey.of(Account.class, "TO"), null, AccountTypeHandler.class),
|
||||||
|
|
||||||
|
DATE("date", Transaction_.DATE, Transaction.class, NoopJoinHandler.class,
|
||||||
|
JoinKey.of(Transaction.class), null, DateHandler.class),
|
||||||
|
|
||||||
RECURRING("recurring", Transaction_.RECURRING_TRANSACTION, Transaction.class, NoopJoinHandler.class,
|
RECURRING("recurring", Transaction_.RECURRING_TRANSACTION, Transaction.class, NoopJoinHandler.class,
|
||||||
JoinKey.of(Transaction.class), null, NotNullSyntheticHandler.class),
|
JoinKey.of(Transaction.class), null, NotNullSyntheticHandler.class),
|
||||||
@@ -32,10 +46,11 @@ public enum FieldMapping {
|
|||||||
TAX_RELEVANT("taxRelevant", Transaction_.TAX_RELEVANT, Transaction.class, NoopJoinHandler.class,
|
TAX_RELEVANT("taxRelevant", Transaction_.TAX_RELEVANT, Transaction.class, NoopJoinHandler.class,
|
||||||
JoinKey.of(Transaction.class), null, BooleanHandler.class),
|
JoinKey.of(Transaction.class), null, BooleanHandler.class),
|
||||||
|
|
||||||
HAS_FILE("hasFile", File_.ID, File.class, FileJoinHandler.class, JoinKey.of(File.class), null, NotNullSyntheticHandler.class),
|
HAS_FILE("hasFile", File_.ID, File.class, FileJoinHandler.class,
|
||||||
|
JoinKey.of(File.class), null, NotNullSyntheticHandler.class),
|
||||||
|
|
||||||
DESCRIPTION("description", Transaction_.DESCRIPTION, Transaction.class, NoopJoinHandler.class, JoinKey.of(Transaction.class),
|
DESCRIPTION("description", Transaction_.DESCRIPTION, Transaction.class, NoopJoinHandler.class,
|
||||||
null, StringHandler.class);
|
JoinKey.of(Transaction.class), null, StringHandler.class);
|
||||||
|
|
||||||
private final String fieldName;
|
private final String fieldName;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package de.financer.fql.field_handler;
|
||||||
|
|
||||||
|
import de.financer.fql.FQLException;
|
||||||
|
import de.financer.fql.FieldMapping;
|
||||||
|
import de.financer.fql.join_handler.JoinKey;
|
||||||
|
import de.financer.model.AccountType;
|
||||||
|
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.From;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AccountTypeHandler implements FieldHandler<String> {
|
||||||
|
@Override
|
||||||
|
public Predicate apply(FieldMapping fieldMapping, Map<JoinKey, From<?, ?>> froms, CriteriaBuilder criteriaBuilder, String value) {
|
||||||
|
return criteriaBuilder
|
||||||
|
.equal(froms.get(fieldMapping.getJoinKey()).get(fieldMapping.getAttributeName()), toAccountType(FieldHandlerUtils.removeQuotes(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AccountType toAccountType(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new FQLException("NULL cannot be solved to AccountType!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return AccountType.valueOf(value.toUpperCase());
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
throw new FQLException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package de.financer.fql.field_handler;
|
||||||
|
|
||||||
|
import de.financer.fql.FQLException;
|
||||||
|
import de.financer.fql.FieldMapping;
|
||||||
|
import de.financer.fql.join_handler.JoinKey;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.From;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PeriodIdHandler implements FieldHandler<String> {
|
||||||
|
@Override
|
||||||
|
public Predicate apply(FieldMapping fieldMapping, Map<JoinKey, From<?, ?>> froms, CriteriaBuilder criteriaBuilder, String value) {
|
||||||
|
final String unquotedValue = FieldHandlerUtils.removeQuotes(value);
|
||||||
|
|
||||||
|
if (!NumberUtils.isCreatable(unquotedValue)) {
|
||||||
|
throw new FQLException(String.format("Invalid value %s for field periodId - only numbers allowed!", unquotedValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
return criteriaBuilder.equal(froms.get(fieldMapping.getJoinKey()).get(fieldMapping.getAttributeName()), NumberUtils.toLong(unquotedValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,31 +58,72 @@ public class PeriodController {
|
|||||||
return "period/periodOverview";
|
return "period/periodOverview";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/showTransactions")
|
private String showInternal(Model model, Long periodId, String fql, boolean showSum) {
|
||||||
public String showTransactions(Model model, Long periodId) {
|
final SearchTransactionsForm form = new SearchTransactionsForm();
|
||||||
|
|
||||||
|
form.setFql(fql);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Iterable<SearchTransactionsResponseDto> response =
|
final UriComponentsBuilder transactionBuilder = UriComponentsBuilder
|
||||||
new SearchTransactionsTemplate()
|
.fromHttpUrl(ControllerUtils.buildUrl(this.financerConfig, Function.TR_SEARCH_BY_FQL));
|
||||||
.exchangeGet(financerConfig, null, null, periodId, null,
|
|
||||||
Order.TRANSACTIONS_BY_DATE_DESC, null, false);
|
|
||||||
|
|
||||||
final List<SearchTransactionsResponseDto> transactions = IterableUtils.toList(response);
|
transactionBuilder.queryParam("fql", form.getFql());
|
||||||
|
|
||||||
|
final Iterable<SearchTransactionsResponseDto> trxs = FinancerRestTemplate.exchangeGet(transactionBuilder,
|
||||||
|
new ParameterizedTypeReference<Iterable<SearchTransactionsResponseDto>>() {
|
||||||
|
});
|
||||||
|
|
||||||
model.addAttribute("transactions", transactions);
|
model.addAttribute("transactions", trxs);
|
||||||
model.addAttribute("transactionCount", IterableUtils.size(transactions));
|
model.addAttribute("transactionCount", IterableUtils.size(trxs));
|
||||||
}
|
|
||||||
catch(FinancerRestException e) {
|
if (showSum) {
|
||||||
|
Long trxSum = IterableUtils.toList(trxs).stream().mapToLong(t -> t.getAmount()).sum();
|
||||||
|
|
||||||
|
model.addAttribute("transactionSum", trxSum);
|
||||||
|
}
|
||||||
|
} catch (FinancerRestException e) {
|
||||||
model.addAttribute("errorMessage", e.getResponseReason().name());
|
model.addAttribute("errorMessage", e.getResponseReason().name());
|
||||||
model.addAttribute("transactionCount", 0);
|
model.addAttribute("transactionCount", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
model.addAttribute("form", new SearchTransactionsForm());
|
model.addAttribute("form", form);
|
||||||
model.addAttribute("showSum", false);
|
model.addAttribute("showSum", showSum);
|
||||||
|
model.addAttribute("returnTo", "/periodOverview");
|
||||||
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
ControllerUtils.addVersionAttribute(model, this.financerConfig);
|
||||||
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
ControllerUtils.addCurrencySymbol(model, this.financerConfig);
|
||||||
ControllerUtils.addDarkMode(model, this.financerConfig);
|
ControllerUtils.addDarkMode(model, this.financerConfig);
|
||||||
|
|
||||||
return "transaction/searchTransactions";
|
return "transaction/searchTransactions";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/showAllTransactions")
|
||||||
|
public String showAllTransactions(Model model, Long periodId) {
|
||||||
|
final String fql = String.format("periodId = '%s' ORDER BY date DESC", periodId);
|
||||||
|
|
||||||
|
return showInternal(model, periodId, fql, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/showIncomeTransactions")
|
||||||
|
public String showIncomeTransactions(Model model, Long periodId) {
|
||||||
|
final String fql = String
|
||||||
|
.format("periodId = '%s' AND (fromAccountType = 'INCOME' OR (fromAccountType = 'LIABILITY' AND (toAccountType = 'BANK' OR toAccountType = 'CASH')) OR (fromAccountType = 'START' AND (toAccountType = 'BANK' OR toAccountType = 'CASH'))) ORDER BY date DESC", periodId);
|
||||||
|
|
||||||
|
return showInternal(model, periodId, fql, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/showExpenseTransactions")
|
||||||
|
public String showExpenseTransactions(Model model, Long periodId) {
|
||||||
|
final String fql = String
|
||||||
|
.format("periodId = '%s' AND (fromAccountType = 'BANK' OR fromAccountType = 'CASH') AND toAccountType = 'EXPENSE' ORDER BY date DESC", periodId);
|
||||||
|
|
||||||
|
return showInternal(model, periodId, fql, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/showLiabilityTransactions")
|
||||||
|
public String showLiabilityTransactions(Model model, Long periodId) {
|
||||||
|
final String fql = String
|
||||||
|
.format("periodId = '%s' AND (fromAccountType = 'BANK' OR fromAccountType = 'CASH') AND toAccountType = 'LIABILITY' ORDER BY date DESC", periodId);
|
||||||
|
|
||||||
|
return showInternal(model, periodId, fql, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ financer.search-transactions.show-query-options.fromAccount=fromAccount\: the ke
|
|||||||
financer.search-transactions.show-query-options.toAccount=toAccount\: the key of the to account
|
financer.search-transactions.show-query-options.toAccount=toAccount\: the key of the to account
|
||||||
financer.search-transactions.show-query-options.fromAccountGroup=fromAccountGroup\: the name of the account group of the from account
|
financer.search-transactions.show-query-options.fromAccountGroup=fromAccountGroup\: the name of the account group of the from account
|
||||||
financer.search-transactions.show-query-options.toAccountGroup=toAccountGroup\: the name of the account group of the to account
|
financer.search-transactions.show-query-options.toAccountGroup=toAccountGroup\: the name of the account group of the to account
|
||||||
|
financer.search-transactions.show-query-options.fromAccountType=fromAccountType\: the type of the from account
|
||||||
|
financer.search-transactions.show-query-options.toAccountType=toAccountType\: the type of the to account
|
||||||
financer.search-transactions.show-query-options.date=date\: the date of the transaction in the format yyyy-mm-dd
|
financer.search-transactions.show-query-options.date=date\: the date of the transaction in the format yyyy-mm-dd
|
||||||
financer.search-transactions.show-query-options.recurring=recurring\: whether the transaction has been created from a recurring transaction
|
financer.search-transactions.show-query-options.recurring=recurring\: whether the transaction has been created from a recurring transaction
|
||||||
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: whether the transaction is relevant for tax declaration
|
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: whether the transaction is relevant for tax declaration
|
||||||
@@ -185,7 +187,11 @@ financer.period-overview.table-header.total=Total
|
|||||||
financer.period-overview.table-header.assets=Assets
|
financer.period-overview.table-header.assets=Assets
|
||||||
financer.period-overview.table-header.transactions=Transaction count
|
financer.period-overview.table-header.transactions=Transaction count
|
||||||
financer.period-overview.table-header.actions=Actions
|
financer.period-overview.table-header.actions=Actions
|
||||||
financer.period-overview.table.actions.showTransactions=Show transactions
|
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.DAILY=Daily
|
||||||
financer.interval-type.WEEKLY=Weekly
|
financer.interval-type.WEEKLY=Weekly
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ financer.search-transactions.show-query-options.fromAccount=fromAccount\: der Sc
|
|||||||
financer.search-transactions.show-query-options.toAccount=toAccount\: der Schl\u00FCssel des An Kontos
|
financer.search-transactions.show-query-options.toAccount=toAccount\: der Schl\u00FCssel des An Kontos
|
||||||
financer.search-transactions.show-query-options.fromAccountGroup=fromAccountGroup\: der Name der Kontogruppe des Von Kontos
|
financer.search-transactions.show-query-options.fromAccountGroup=fromAccountGroup\: der Name der Kontogruppe des Von Kontos
|
||||||
financer.search-transactions.show-query-options.toAccountGroup=toAccountGroup\: der Name der Kontogruppe des An Kontos
|
financer.search-transactions.show-query-options.toAccountGroup=toAccountGroup\: der Name der Kontogruppe des An Kontos
|
||||||
|
financer.search-transactions.show-query-options.fromAccountType=fromAccountType\: der Typ des Von Kontos
|
||||||
|
financer.search-transactions.show-query-options.toAccountType=toAccountType\: der Typ des An Kontos
|
||||||
financer.search-transactions.show-query-options.date=date\: das Datum der Buchung im Format jjjj-mm-tt
|
financer.search-transactions.show-query-options.date=date\: das Datum der Buchung im Format jjjj-mm-tt
|
||||||
financer.search-transactions.show-query-options.recurring=recurring\: ob die Buchung durch eine wiederkehrende Buchung erzeugt wurde
|
financer.search-transactions.show-query-options.recurring=recurring\: ob die Buchung durch eine wiederkehrende Buchung erzeugt wurde
|
||||||
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: ob die Buchung als steuerrelevant markiert wurde
|
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: ob die Buchung als steuerrelevant markiert wurde
|
||||||
@@ -185,7 +187,11 @@ financer.period-overview.table-header.total=Insgesamt
|
|||||||
financer.period-overview.table-header.assets=Umlaufverm\u00F6gen
|
financer.period-overview.table-header.assets=Umlaufverm\u00F6gen
|
||||||
financer.period-overview.table-header.transactions=Anzahl Buchungen
|
financer.period-overview.table-header.transactions=Anzahl Buchungen
|
||||||
financer.period-overview.table-header.actions=Aktionen
|
financer.period-overview.table-header.actions=Aktionen
|
||||||
financer.period-overview.table.actions.showTransactions=Zeige Buchungen
|
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.DAILY=T\u00E4glich
|
||||||
financer.interval-type.WEEKLY=W\u00F6chentlich
|
financer.interval-type.WEEKLY=W\u00F6chentlich
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
v45 -> v46:
|
v45 -> v46:
|
||||||
- #17 Add actions to the period overview
|
- #17 Add actions to the period overview
|
||||||
|
- #18 Improve actions in the period overview
|
||||||
|
- Introduce new FQL fields toAccountType and fromAccountType
|
||||||
|
|
||||||
v44 -> v45:
|
v44 -> v45:
|
||||||
- #5 Having no periods breaks the "expenses per period" graph on the account overview page
|
- #5 Having no periods breaks the "expenses per period" graph on the account overview page
|
||||||
|
|||||||
@@ -46,6 +46,14 @@
|
|||||||
color: var(--neutral-color);
|
color: var(--neutral-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expense-period-period-overview {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-year-period-period-overview {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
#period-overview-asset-container {
|
#period-overview-asset-container {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1 th:text="#{financer.heading.period-overview}"/>
|
<h1 th:text="#{financer.heading.period-overview}"/>
|
||||||
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
|
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
|
||||||
<a th:href="@{/accountOverview}" th:text="#{financer.cancel-back-to-overview}"/>
|
<a th:href="@{/accountOverview}" th:text="#{financer.back-to-overview}"/>
|
||||||
<table id="period-overview-table">
|
<table id="period-overview-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th th:text="#{financer.period-overview.table-header.id}"/>
|
<th th:text="#{financer.period-overview.table-header.id}"/>
|
||||||
@@ -28,30 +28,62 @@
|
|||||||
<th th:text="#{financer.period-overview.table-header.actions}"/>
|
<th th:text="#{financer.period-overview.table-header.actions}"/>
|
||||||
</tr>
|
</tr>
|
||||||
<tr th:each="periodOverview : ${periodOverviews}">
|
<tr th:each="periodOverview : ${periodOverviews}">
|
||||||
<td th:text="${periodOverview.periodId}"/>
|
<td th:text="${periodOverview.periodId}"
|
||||||
<td th:text="#{'financer.period-type.' + ${periodOverview.periodType}}"/>
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
<td th:text="${#temporals.format(periodOverview.periodStart)}"/>
|
<td>
|
||||||
<td th:text="${#temporals.format(periodOverview.periodEnd)}"/>
|
<div>
|
||||||
<td th:utext="${#numbers.formatDecimal(periodOverview.incomeSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
<span th:text="#{'financer.period-type.' + ${periodOverview.periodType}}"
|
||||||
<td th:utext="${#numbers.formatDecimal(periodOverview.expenseSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
th:classappend="${(periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE ? 'expense-period-period-overview' : '') +
|
||||||
<td th:utext="${#numbers.formatDecimal(periodOverview.liabilitySum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
(periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR ? 'expense-year-period-period-overview' : '')}"/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td th:text="${#temporals.format(periodOverview.periodStart)}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
|
<td th:text="${#temporals.format(periodOverview.periodEnd)}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
|
<td th:utext="${#numbers.formatDecimal(periodOverview.incomeSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
|
<td th:utext="${#numbers.formatDecimal(periodOverview.expenseSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
|
<td th:utext="${#numbers.formatDecimal(periodOverview.liabilitySum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
<td th:utext="${#numbers.formatDecimal(periodOverview.total/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
<td th:utext="${#numbers.formatDecimal(periodOverview.total/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||||
th:classappend="${periodOverview.total > periodOverview.incomeSum} ? overspend"/>
|
th:classappend="${(periodOverview.total > periodOverview.incomeSum ? 'overspend' : '') +
|
||||||
|
(periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR ? ' expense-year-period-period-overview' : '')}"/>
|
||||||
<td th:if="${periodOverview.assetsSum != null}">
|
<td th:if="${periodOverview.assetsSum != null}">
|
||||||
<div id="period-overview-asset-container">
|
<div id="period-overview-asset-container">
|
||||||
<span th:utext="${#numbers.formatDecimal(periodOverview.assetsSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"/>
|
<span th:utext="${#numbers.formatDecimal(periodOverview.assetsSum/100D, 1, 'DEFAULT', 2, 'DEFAULT') + currencySymbol}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
<span th:if="${periodOverview.assetTrend == T(de.financer.dto.AssetTrend).UP}" class="icon color-good"></span>
|
<span th:if="${periodOverview.assetTrend == T(de.financer.dto.AssetTrend).UP}" class="icon color-good"></span>
|
||||||
<span th:if="${periodOverview.assetTrend == T(de.financer.dto.AssetTrend).DOWN}" class="icon color-bad"></span>
|
<span th:if="${periodOverview.assetTrend == T(de.financer.dto.AssetTrend).DOWN}" class="icon color-bad"></span>
|
||||||
<span th:if="${periodOverview.assetTrend == T(de.financer.dto.AssetTrend).EQUAL}" class="icon color-neutral"></span>
|
<span th:if="${periodOverview.assetTrend == T(de.financer.dto.AssetTrend).EQUAL}" class="icon color-neutral"></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td th:if="${periodOverview.assetsSum == null}" />
|
<td th:if="${periodOverview.assetsSum == null}" />
|
||||||
<td th:text="${periodOverview.transactionCount}"/>
|
<td th:text="${periodOverview.transactionCount}"
|
||||||
|
th:classappend="${periodOverview.periodType == T(de.financer.model.PeriodType).EXPENSE_YEAR} ? expense-year-period-period-overview"/>
|
||||||
<td nowrap>
|
<td nowrap>
|
||||||
<div id="period-overview-actions-container">
|
<details>
|
||||||
<a th:href="@{/showTransactions(periodId=${periodOverview.periodId})}"
|
<summary th:text="#{financer.period-overview.show-actions}"/>
|
||||||
th:text="#{financer.period-overview.table.actions.showTransactions}" />
|
<div id="period-overview-show-actions-detail-container">
|
||||||
</div>
|
<div id="period-overview-show-actions-detail-container-show-all">
|
||||||
|
<a th:href="@{/showAllTransactions(periodId=${periodOverview.periodId})}"
|
||||||
|
th:text="#{financer.period-overview.table.actions.showAllTransactions}" />
|
||||||
|
</div>
|
||||||
|
<div id="period-overview-show-actions-detail-container-show-income">
|
||||||
|
<a th:href="@{/showIncomeTransactions(periodId=${periodOverview.periodId})}"
|
||||||
|
th:text="#{financer.period-overview.table.actions.showIncomeTransactions}" />
|
||||||
|
</div>
|
||||||
|
<div id="period-overview-show-actions-detail-container-show-expense">
|
||||||
|
<a th:href="@{/showExpenseTransactions(periodId=${periodOverview.periodId})}"
|
||||||
|
th:text="#{financer.period-overview.table.actions.showExpenseTransactions}" />
|
||||||
|
</div>
|
||||||
|
<div id="period-overview-show-actions-detail-container-show-liability">
|
||||||
|
<a th:href="@{/showLiabilityTransactions(periodId=${periodOverview.periodId})}"
|
||||||
|
th:text="#{financer.period-overview.table.actions.showLiabilityTransactions}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1 th:text="#{financer.heading.search-transactions}" />
|
<h1 th:text="#{financer.heading.search-transactions}" />
|
||||||
<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/>
|
<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}"/>
|
<a th:if="${returnTo == null}" th:href="@{/accountOverview}" th:text="#{financer.search-transactions.back-to-overview}"/>
|
||||||
|
<a th:if="${returnTo != null}" th:href="@{${returnTo}}" th:text="#{financer.search-transactions.back-to-overview}"/>
|
||||||
<form id="search-transactions-form" action="#" th:action="@{/searchTransactions}" th:object="${form}"
|
<form id="search-transactions-form" action="#" th:action="@{/searchTransactions}" th:object="${form}"
|
||||||
method="post">
|
method="post">
|
||||||
<label for="inputFql" th:text="#{financer.search-transactions.label.fql}"/>
|
<label for="inputFql" th:text="#{financer.search-transactions.label.fql}"/>
|
||||||
@@ -30,6 +31,8 @@
|
|||||||
<li th:text="#{financer.search-transactions.show-query-options.toAccount}" />
|
<li th:text="#{financer.search-transactions.show-query-options.toAccount}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.fromAccountGroup}" />
|
<li th:text="#{financer.search-transactions.show-query-options.fromAccountGroup}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.toAccountGroup}" />
|
<li th:text="#{financer.search-transactions.show-query-options.toAccountGroup}" />
|
||||||
|
<li th:text="#{financer.search-transactions.show-query-options.fromAccountType}" />
|
||||||
|
<li th:text="#{financer.search-transactions.show-query-options.toAccountType}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.date}" />
|
<li th:text="#{financer.search-transactions.show-query-options.date}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.recurring}" />
|
<li th:text="#{financer.search-transactions.show-query-options.recurring}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.taxRelevant}" />
|
<li th:text="#{financer.search-transactions.show-query-options.taxRelevant}" />
|
||||||
|
|||||||
Reference in New Issue
Block a user