Include transactions without categories

This commit is contained in:
William Brawner 2021-02-05 18:53:31 -07:00
parent c30e445024
commit 847a122e74
4 changed files with 45 additions and 12 deletions

View file

@ -9,6 +9,8 @@ import com.wbrawner.budgetserver.user.UserRepository;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Authorization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@ -16,13 +18,13 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.transaction.Transactional;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.wbrawner.budgetserver.Utils.getCurrentUser;
import static com.wbrawner.budgetserver.Utils.getFirstOfMonth;
import static com.wbrawner.budgetserver.Utils.*;
@RestController
@RequestMapping(value = "/budgets")
@ -33,6 +35,7 @@ public class BudgetController {
private final TransactionRepository transactionRepository;
private final UserRepository userRepository;
private final UserPermissionRepository userPermissionsRepository;
private final Logger logger = LoggerFactory.getLogger(BudgetController.class);
public BudgetController(
BudgetRepository budgetRepository,
@ -85,9 +88,29 @@ public class BudgetController {
@GetMapping(value = "/{id}/balance", produces = {MediaType.APPLICATION_JSON_VALUE})
@ApiOperation(value = "getBudgetBalance", nickname = "getBudgetBalance", tags = {"Budgets"})
public ResponseEntity<BudgetBalanceResponse> getBudgetBalance(@PathVariable String id) {
public ResponseEntity<BudgetBalanceResponse> getBudgetBalance(
@PathVariable String id,
@RequestParam(value = "from", required = false) String from,
@RequestParam(value = "from", required = false) String to
) {
return getBudgetWithPermission(id, Permission.READ, (budget) -> {
var balance = transactionRepository.sumBalanceByBudgetId(budget.getId(), getFirstOfMonth());
Instant fromInstant;
try {
fromInstant = Instant.parse(from);
} catch (Exception e) {
if (!(e instanceof NullPointerException))
logger.error("Failed to parse '" + from + "' to Instant for 'from' parameter", e);
fromInstant = Instant.ofEpochSecond(0);
}
Instant toInstant;
try {
toInstant = Instant.parse(to);
} catch (Exception e) {
if (!(e instanceof NullPointerException))
logger.error("Failed to parse '" + to + "' to Instant for 'to' parameter", e);
toInstant = Instant.now();
}
var balance = transactionRepository.sumBalanceByBudgetId(budget.getId(), fromInstant, toInstant);
return ResponseEntity.ok(new BudgetBalanceResponse(budget.getId(), balance));
});
}

View file

@ -70,11 +70,9 @@ public class TransactionController {
.map(UserPermission::getBudget)
.collect(Collectors.toList());
List<Category> categories;
List<Category> categories = null;
if (categoryIds != null && !categoryIds.isEmpty()) {
categories = categoryRepository.findAllByBudgetInAndIdIn(budgets, categoryIds, null);
} else {
categories = categoryRepository.findAllByBudgetIn(budgets, null, null, null);
}
var pageRequest = PageRequest.of(
Math.min(0, page != null ? page - 1 : 0),
@ -98,13 +96,19 @@ public class TransactionController {
logger.error("Failed to parse '" + to + "' to Instant for 'to' parameter", e);
toInstant = getEndOfMonth().toInstant();
}
var transactions = transactionRepository.findAllByBudgetInAndCategoryInAndDateGreaterThanAndDateLessThan(
var query = categories == null ? transactionRepository.findAllByBudgetInAndDateGreaterThanAndDateLessThan(
budgets,
fromInstant,
toInstant,
pageRequest
) : transactionRepository.findAllByBudgetInAndCategoryInAndDateGreaterThanAndDateLessThan(
budgets,
categories,
fromInstant,
toInstant,
pageRequest
)
);
var transactions = query
.stream()
.map(TransactionResponse::new)
.collect(Collectors.toList());

View file

@ -22,13 +22,20 @@ public interface TransactionRepository extends PagingAndSortingRepository<Transa
Pageable pageable
);
List<Transaction> findAllByBudgetInAndDateGreaterThanAndDateLessThan(
List<Budget> budgets,
Instant start,
Instant end,
Pageable pageable
);
List<Transaction> findAllByBudgetAndCategory(Budget budget, Category category);
@Query(
nativeQuery = true,
value = "SELECT (COALESCE((SELECT SUM(amount) from transaction WHERE Budget_id = :BudgetId AND expense = 0 AND date > :start), 0)) - (COALESCE((SELECT SUM(amount) from transaction WHERE Budget_id = :BudgetId AND expense = 1 AND date > :date), 0));"
value = "SELECT (COALESCE((SELECT SUM(amount) from transaction WHERE Budget_id = :BudgetId AND expense = 0 AND date >= :from AND date <= :to), 0)) - (COALESCE((SELECT SUM(amount) from transaction WHERE Budget_id = :BudgetId AND expense = 1 AND date >= :from AND date <= :to), 0));"
)
Long sumBalanceByBudgetId(String BudgetId, Date start);
Long sumBalanceByBudgetId(String BudgetId, Instant from, Instant to);
@Query(
nativeQuery = true,

View file

@ -2,7 +2,6 @@ spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://localhost:3306/budget
spring.datasource.username=budget
spring.datasource.password=budget
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.profiles.active=prod
spring.session.jdbc.initialize-schema=always
spring.datasource.testWhileIdle=true