Add current assets to status on overview page

This commit is contained in:
2019-06-24 21:11:36 +02:00
parent 30ebc2a154
commit 6ec073d08e
10 changed files with 71 additions and 17 deletions

View File

@@ -86,4 +86,19 @@ public class AccountController {
return responseReason.toResponseEntity(); return responseReason.toResponseEntity();
} }
@RequestMapping("getCurrentAssets")
public Long getCurrentAssets() {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("/accounts/getCurrentAssets called");
}
final Long response = this.accountService.getCurrentAssets();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/accounts/getCurrentAssets returns with %s", response));
}
return response;
}
} }

View File

@@ -1,6 +1,8 @@
package de.financer.dba; package de.financer.dba;
import de.financer.model.Account; import de.financer.model.Account;
import de.financer.model.AccountType;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -8,4 +10,7 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional(propagation = Propagation.REQUIRED) @Transactional(propagation = Propagation.REQUIRED)
public interface AccountRepository extends CrudRepository<Account, Long> { public interface AccountRepository extends CrudRepository<Account, Long> {
Account findByKey(String key); Account findByKey(String key);
@Query("SELECT SUM(a.currentBalance) FROM Account a WHERE a.type IN :accountTypes")
Long getCurrentAssets(AccountType... accountTypes);
} }

View File

@@ -31,6 +31,7 @@ public class AccountService {
* This method returns the account identified by the given key. * This method returns the account identified by the given key.
* *
* @param key the key to get the account for * @param key the key to get the account for
*
* @return the account or <code>null</code> if no account with the given key can be found * @return the account or <code>null</code> if no account with the given key can be found
*/ */
public Account getAccountByKey(String key) { public Account getAccountByKey(String key) {
@@ -38,15 +39,16 @@ public class AccountService {
} }
/** /**
* @return all existing accounts, regardless of their type or status. This explicitly covers accounts in {@link AccountStatus#CLOSED CLOSED} as well. * @return all existing accounts, regardless of their type or status. This explicitly covers accounts in {@link
* AccountStatus#CLOSED CLOSED} as well.
*/ */
public Iterable<Account> getAll() { public Iterable<Account> getAll() {
return this.accountRepository.findAll(); return this.accountRepository.findAll();
} }
/** /**
* This method saves the given account. It either updates the account if it already exists or inserts * This method saves the given account. It either updates the account if it already exists or inserts it if it's
* it if it's new. * new.
* *
* @param account the account to save * @param account the account to save
*/ */
@@ -56,17 +58,17 @@ public class AccountService {
} }
/** /**
* This method creates new account with the given key and type. The account has status {@link AccountStatus#OPEN OPEN} * This method creates new account with the given key and type. The account has status {@link AccountStatus#OPEN
* and a current balance of <code>0</code>. * OPEN} and a current balance of <code>0</code>.
* *
* @param key the key of the new account * @param key the key of the new account
* @param type the type of the new account. Must be one of {@link AccountType}. * @param type the type of the new account. Must be one of {@link AccountType}.
* @param accountGroupName the name of the account group to use, can be <code>null</code> * @param accountGroupName the name of the account group to use, can be <code>null</code>
* @return {@link ResponseReason#INVALID_ACCOUNT_TYPE} if the given type is not a valid {@link AccountType}, *
* {@link ResponseReason#UNKNOWN_ERROR} if an unexpected error occurs, * @return {@link ResponseReason#INVALID_ACCOUNT_TYPE} if the given type is not a valid {@link AccountType}, {@link
* {@link ResponseReason#OK} if the operation completed successfully, * ResponseReason#UNKNOWN_ERROR} if an unexpected error occurs, {@link ResponseReason#OK} if the operation completed
* {@link ResponseReason#DUPLICATE_ACCOUNT_KEY} if an account with the given key * successfully, {@link ResponseReason#DUPLICATE_ACCOUNT_KEY} if an account with the given key already exists and
* already exists and {@link ResponseReason#ACCOUNT_GROUP_NOT_FOUND} if the optional parameter * {@link ResponseReason#ACCOUNT_GROUP_NOT_FOUND} if the optional parameter
* <code>accountGroupName</code> does not identify a valid account group. Never returns <code>null</code>. * <code>accountGroupName</code> does not identify a valid account group. Never returns <code>null</code>.
*/ */
@Transactional(propagation = Propagation.SUPPORTS) @Transactional(propagation = Propagation.SUPPORTS)
@@ -96,13 +98,11 @@ public class AccountService {
try { try {
this.accountRepository.save(account); this.accountRepository.save(account);
} } catch (DataIntegrityViolationException dive) {
catch (DataIntegrityViolationException dive) {
LOGGER.error(String.format("Duplicate key! %s|%s|%s", key, type, accountGroupName), dive); LOGGER.error(String.format("Duplicate key! %s|%s|%s", key, type, accountGroupName), dive);
return ResponseReason.DUPLICATE_ACCOUNT_KEY; return ResponseReason.DUPLICATE_ACCOUNT_KEY;
} } catch (Exception e) {
catch (Exception e) {
LOGGER.error(String.format("Could not save account %s|%s|%s", key, type, accountGroupName), e); LOGGER.error(String.format("Could not save account %s|%s|%s", key, type, accountGroupName), e);
return ResponseReason.UNKNOWN_ERROR; return ResponseReason.UNKNOWN_ERROR;
@@ -133,8 +133,7 @@ public class AccountService {
try { try {
this.accountRepository.save(account); this.accountRepository.save(account);
} } catch (Exception e) {
catch (Exception e) {
LOGGER.error(String.format("Could not update account status %s|%s", key, accountStatus.name()), e); LOGGER.error(String.format("Could not update account status %s|%s", key, accountStatus.name()), e);
return ResponseReason.UNKNOWN_ERROR; return ResponseReason.UNKNOWN_ERROR;
@@ -142,4 +141,15 @@ public class AccountService {
return ResponseReason.OK; return ResponseReason.OK;
} }
/**
* Get the current assets for the specified account types, basically the sum of all the current balances of all
* accounts with the given types. We are specifying BANK and CASH here as these are virtually always available on a
* very short notice. So this is the amount of money we have at disposal right now.
*
* @return the current assets
*/
public Long getCurrentAssets() {
return this.accountRepository.getCurrentAssets(AccountType.BANK, AccountType.CASH);
}
} }

View File

@@ -32,11 +32,13 @@ public class AccountController {
.exchange(this.financerConfig); .exchange(this.financerConfig);
final ResponseEntity<Iterable<RecurringTransaction>> rtAllActRes = new GetAllActiveRecurringTransactionsTemplate() final ResponseEntity<Iterable<RecurringTransaction>> rtAllActRes = new GetAllActiveRecurringTransactionsTemplate()
.exchange(this.financerConfig); .exchange(this.financerConfig);
final ResponseEntity<Long> currentAssets = new GetCurrentAssetsTemplate().exchange(this.financerConfig);
final boolean showClosedBoolean = BooleanUtils.toBoolean(showClosed); final boolean showClosedBoolean = BooleanUtils.toBoolean(showClosed);
model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(response.getBody(), showClosedBoolean)); model.addAttribute("accounts", ControllerUtils.filterAndSortAccounts(response.getBody(), showClosedBoolean));
model.addAttribute("rtDueTodayCount", IterableUtils.size(rtDtRes.getBody())); model.addAttribute("rtDueTodayCount", IterableUtils.size(rtDtRes.getBody()));
model.addAttribute("rtAllActiveCount", IterableUtils.size(rtAllActRes.getBody())); model.addAttribute("rtAllActiveCount", IterableUtils.size(rtAllActRes.getBody()));
model.addAttribute("currentAssets", currentAssets.getBody());
model.addAttribute("showClosed", showClosedBoolean); model.addAttribute("showClosed", showClosedBoolean);
ControllerUtils.addVersionAttribute(model, this.financerConfig); ControllerUtils.addVersionAttribute(model, this.financerConfig);

View File

@@ -6,6 +6,7 @@ public enum Function {
ACC_CREATE_ACCOUNT("accounts/createAccount"), ACC_CREATE_ACCOUNT("accounts/createAccount"),
ACC_CLOSE_ACCOUNT("accounts/closeAccount"), ACC_CLOSE_ACCOUNT("accounts/closeAccount"),
ACC_OPEN_ACCOUNT("accounts/openAccount"), ACC_OPEN_ACCOUNT("accounts/openAccount"),
ACC_CURRENT_ASSETS("accounts/getCurrentAssets"),
ACC_GP_CREATE_ACCOUNT_GROUP("accountGroups/createAccountGroup"), ACC_GP_CREATE_ACCOUNT_GROUP("accountGroups/createAccountGroup"),
ACC_GP_GET_ALL("accountGroups/getAll"), ACC_GP_GET_ALL("accountGroups/getAll"),

View File

@@ -0,0 +1,15 @@
package de.financer.controller.template;
import de.financer.config.FinancerConfig;
import de.financer.controller.Function;
import de.financer.util.ControllerUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.ResponseEntity;
public class GetCurrentAssetsTemplate {
public ResponseEntity<Long> exchange(FinancerConfig financerConfig) {
return new FinancerRestTemplate<Long>().exchange(ControllerUtils
.buildUrl(financerConfig, Function.ACC_CURRENT_ASSETS), new ParameterizedTypeReference<Long>() {
});
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@@ -10,6 +10,7 @@ financer.account-overview.available-actions.create-account-group=Create new acco
financer.account-overview.status=Status\: financer.account-overview.status=Status\:
financer.account-overview.status.recurring-transaction-due-today=Recurring transactions due today\: financer.account-overview.status.recurring-transaction-due-today=Recurring transactions due today\:
financer.account-overview.status.recurring-transaction-active=Active recurring transactions\: financer.account-overview.status.recurring-transaction-active=Active recurring transactions\:
financer.account-overview.status.current-assets=Current assets\:
financer.account-overview.table-header.id=ID financer.account-overview.table-header.id=ID
financer.account-overview.table-header.key=Account financer.account-overview.table-header.key=Account
financer.account-overview.table-header.group=Group financer.account-overview.table-header.group=Group

View File

@@ -10,6 +10,7 @@ financer.account-overview.available-actions.create-account-group=Neue Konto-Grup
financer.account-overview.status=Status\: financer.account-overview.status=Status\:
financer.account-overview.status.recurring-transaction-due-today=Wiederkehrende Buchungen heute f\u00E4llig\: financer.account-overview.status.recurring-transaction-due-today=Wiederkehrende Buchungen heute f\u00E4llig\:
financer.account-overview.status.recurring-transaction-active=Aktive wiederkehrende Buchungen\: financer.account-overview.status.recurring-transaction-active=Aktive wiederkehrende Buchungen\:
financer.account-overview.status.current-assets=Umlaufverm\u00F6gen\:
financer.account-overview.table-header.id=ID financer.account-overview.table-header.id=ID
financer.account-overview.table-header.key=Konto financer.account-overview.table-header.key=Konto
financer.account-overview.table-header.group=Gruppe financer.account-overview.table-header.group=Gruppe

View File

@@ -10,6 +10,10 @@
<h1 th:text="#{financer.heading.account-overview}" /> <h1 th:text="#{financer.heading.account-overview}" />
<div id="status-container"> <div id="status-container">
<span th:text="#{financer.account-overview.status}"/> <span th:text="#{financer.account-overview.status}"/>
<div>
<span th:text="#{financer.account-overview.status.current-assets}"/>
<span th:text="${#numbers.formatDecimal(currentAssets/100D, 1, 'DEFAULT', 2, 'DEFAULT')}"/>
</div>
<div> <div>
<span th:text="#{financer.account-overview.status.recurring-transaction-due-today}"/> <span th:text="#{financer.account-overview.status.recurring-transaction-due-today}"/>
<a th:href="@{/recurringTransactionDueToday}" th:text="${rtDueTodayCount}"/> <a th:href="@{/recurringTransactionDueToday}" th:text="${rtDueTodayCount}"/>