Add expense period total chart

This commit is contained in:
2019-08-19 20:59:27 +02:00
parent 7a73f45921
commit 6be58d6462
18 changed files with 340 additions and 12 deletions

View File

@@ -1,6 +1,7 @@
package de.financer.controller;
import de.financer.ResponseReason;
import de.financer.dto.ExpensePeriodTotal;
import de.financer.model.Transaction;
import de.financer.service.TransactionService;
import org.slf4j.Logger;
@@ -10,9 +11,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
@RestController
@RequestMapping("transactions")
public class TransactionController {
@@ -94,4 +92,20 @@ public class TransactionController {
return response;
}
@RequestMapping("getExpensePeriodTotals")
public Iterable<ExpensePeriodTotal> getExpensePeriodTotals(Integer monthPeriodStartDay, Integer year) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/transactions/getExpensePeriodTotals got parameters: %s, %s", monthPeriodStartDay, year));
}
final Iterable<ExpensePeriodTotal> expensePeriodTotals = this.transactionService
.getExpensePeriodTotals(monthPeriodStartDay, year);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("/transactions/getExpensePeriodTotals returns with %s", expensePeriodTotals));
}
return expensePeriodTotals;
}
}

View File

@@ -1,5 +1,6 @@
package de.financer.dba;
import de.financer.dto.ExpensePeriodTotal;
import de.financer.model.Account;
import de.financer.model.AccountType;
import de.financer.model.Transaction;
@@ -9,6 +10,7 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
@Transactional(propagation = Propagation.REQUIRED)
public interface TransactionRepository extends CrudRepository<Transaction, Long> {
@@ -16,4 +18,11 @@ public interface TransactionRepository extends CrudRepository<Transaction, Long>
@Query("SELECT SUM(t.amount) FROM Transaction t JOIN t.toAccount a WHERE t.date BETWEEN :periodStart AND :periodEnd AND a.type IN :expenseTypes")
Long getExpensesCurrentPeriod(LocalDate periodStart, LocalDate periodEnd, AccountType... expenseTypes);
// The HQL contains a hack because Hibernate can't resolve the alias of the CASE column in the GROUP BY clause
// That's why the generated alias is used directly in the HQL. It will break if the columns in the SELECT clause get reordered
// col_0_0_ instead of periodShortCode
// col_2_0_ instead of AccType
@Query("SELECT new de.financer.dto.ExpensePeriodTotal(CASE WHEN EXTRACT(DAY FROM t.date) >= :startDay THEN CONCAT(CAST(EXTRACT(YEAR FROM t.date) AS string), '/', CAST(EXTRACT(MONTH FROM t.date) AS string)) ELSE CASE WHEN EXTRACT(MONTH FROM t.date) = 1 THEN CONCAT(CAST(EXTRACT(YEAR FROM t.date) - 1 AS string), '/12') ELSE CONCAT(CAST(EXTRACT(YEAR FROM t.date) AS string), '/', CAST(EXTRACT(MONTH FROM t.date) - 1 AS string)) END END AS periodShortCode, SUM(t.amount), CASE WHEN fa.type = :incomeType THEN fa.type ELSE ta.type END AS AccType) FROM Transaction t JOIN t.toAccount ta JOIN t.fromAccount fa WHERE ((ta.type IN :expenseTypes AND fa.type <> :startType) OR (fa.type = :incomeType)) AND t.date BETWEEN :lowerBound AND :upperBound GROUP BY col_0_0_, col_2_0_ ORDER BY periodShortCode, AccType ASC")
List<ExpensePeriodTotal> getAccountExpenseTotals(int startDay, LocalDate lowerBound, LocalDate upperBound, AccountType incomeType, AccountType startType, AccountType... expenseTypes);
}

View File

@@ -1,8 +1,10 @@
package de.financer.service;
import com.google.common.collect.Iterables;
import de.financer.ResponseReason;
import de.financer.config.FinancerConfig;
import de.financer.dba.TransactionRepository;
import de.financer.dto.ExpensePeriodTotal;
import de.financer.model.Account;
import de.financer.model.AccountType;
import de.financer.model.RecurringTransaction;
@@ -21,6 +23,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Service
@@ -239,4 +242,17 @@ public class TransactionService {
return Optional.ofNullable(expensesCurrentPeriod).orElse(Long.valueOf(0l));
}
public Iterable<ExpensePeriodTotal> getExpensePeriodTotals(Integer monthPeriodStartDay, Integer year) {
final List<ExpensePeriod> expensePeriods = ExpensePeriod.generateExpensePeriodsForYear(monthPeriodStartDay, year);
final ExpensePeriod lowerBound = Iterables.get(expensePeriods, 0);
final ExpensePeriod upperBound = Iterables.getLast(expensePeriods);
final List<ExpensePeriodTotal> expensePeriodTotals = this.transactionRepository
.getAccountExpenseTotals(monthPeriodStartDay, lowerBound.getStart(), upperBound
.getEnd(), AccountType.INCOME, AccountType.START, AccountType.EXPENSE, AccountType.LIABILITY);
return expensePeriodTotals;
}
}