diff --git a/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java b/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java index ea0bdf4..38a291d 100644 --- a/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java +++ b/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java @@ -1,5 +1,6 @@ package fun.trackmoney.transaction.controller; +import fun.trackmoney.transaction.dto.BillResponseDTO; import fun.trackmoney.transaction.dto.CreateTransactionDTO; import fun.trackmoney.transaction.dto.TransactionResponseDTO; import fun.trackmoney.transaction.dto.TransactionUpdateDTO; @@ -61,6 +62,12 @@ public ResponseEntity> getExpense(@PathVariable Integer new ApiResponse<>(true,"Get expense", transactionService.getExpense(id),null)); } + @GetMapping("/bill/{id}") + public ResponseEntity> getBill(@PathVariable Integer id) { + return ResponseEntity.ok().body( + new ApiResponse<>(true,"Get expense", transactionService.getBill(id),null)); + } + @PutMapping("/{id}") public ResponseEntity> updateTransaction(@PathVariable Integer id, @RequestBody TransactionUpdateDTO dto) { diff --git a/src/main/java/fun/trackmoney/transaction/dto/BillResponseDTO.java b/src/main/java/fun/trackmoney/transaction/dto/BillResponseDTO.java new file mode 100644 index 0000000..7f93ceb --- /dev/null +++ b/src/main/java/fun/trackmoney/transaction/dto/BillResponseDTO.java @@ -0,0 +1,8 @@ +package fun.trackmoney.transaction.dto; + +import java.math.BigDecimal; + +public record BillResponseDTO(BigDecimal bill, + BigDecimal totalUpcoming, + BigDecimal bueSoon) { +} diff --git a/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java b/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java index dca4c67..ff89f9f 100644 --- a/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java +++ b/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java @@ -9,5 +9,5 @@ public interface TransactionRepository extends JpaRepository { @Query("SELECT a FROM TransactionEntity a WHERE a.account.accountId = :accountId") - List findAllByUserEmail(@Param("accountId") Integer accountId); + List findAllByAccountId(@Param("accountId") Integer accountId); } diff --git a/src/main/java/fun/trackmoney/transaction/service/TransactionService.java b/src/main/java/fun/trackmoney/transaction/service/TransactionService.java index 4dede65..056695e 100644 --- a/src/main/java/fun/trackmoney/transaction/service/TransactionService.java +++ b/src/main/java/fun/trackmoney/transaction/service/TransactionService.java @@ -6,6 +6,7 @@ import fun.trackmoney.category.entity.CategoryEntity; import fun.trackmoney.category.service.CategoryService; import fun.trackmoney.enums.TransactionType; +import fun.trackmoney.transaction.dto.BillResponseDTO; import fun.trackmoney.transaction.dto.CreateTransactionDTO; import fun.trackmoney.transaction.dto.TransactionResponseDTO; import fun.trackmoney.transaction.dto.TransactionUpdateDTO; @@ -16,6 +17,7 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; +import java.time.LocalDate; import java.util.List; import java.util.Objects; @@ -82,7 +84,7 @@ public void delete(Integer id) { } public BigDecimal getIncome(Integer accountId) { - return transactionRepository.findAllByUserEmail(accountId) + return transactionRepository.findAllByAccountId(accountId) .stream() .filter(t -> TransactionType.INCOME.equals(t.getTransactionType())) .map(TransactionEntity::getAmount) @@ -91,11 +93,49 @@ public BigDecimal getIncome(Integer accountId) { } public BigDecimal getExpense(Integer accountId) { - return transactionRepository.findAllByUserEmail(accountId) + return transactionRepository.findAllByAccountId(accountId) .stream() .filter(t -> TransactionType.EXPENSE.equals(t.getTransactionType())) .map(TransactionEntity::getAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); } + + public BillResponseDTO getBill(Integer id) { + var result = transactionRepository.findAllByAccountId(id); + + BigDecimal totalBillsBeforeToday = result.stream() + .filter(transaction -> + transaction.getCategory().getName().equalsIgnoreCase("bill") && + transaction.getTransactionDate().toLocalDateTime().toLocalDate().isBefore(LocalDate.now()) + ) + .map(TransactionEntity::getAmount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + + BigDecimal totalUpComing = result.stream() + .filter(transaction -> + transaction.getCategory().getName().equalsIgnoreCase("bill") && + transaction.getTransactionDate().toLocalDateTime().toLocalDate().isAfter(LocalDate.now()) + ) + .map(TransactionEntity::getAmount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + BigDecimal totalBueSoon = result.stream() + .filter(transaction -> { + LocalDate date = transaction.getTransactionDate().toLocalDateTime().toLocalDate(); + return transaction.getCategory().getName().equalsIgnoreCase("bill") + && !date.isBefore(LocalDate.now()) + && !date.isAfter(LocalDate.now().plusDays(7)); + }) + + .map(TransactionEntity::getAmount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + + return new BillResponseDTO(totalBillsBeforeToday, totalUpComing, totalBueSoon); + } } diff --git a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java index 083121c..a0ea517 100644 --- a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java +++ b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java @@ -21,6 +21,8 @@ import java.math.BigDecimal; import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.*; import static org.junit.jupiter.api.Assertions.*; @@ -151,7 +153,7 @@ void getIncome_shouldReturnTotalIncome() { tr2.setTransactionType(TransactionType.INCOME); var accountId = 1; - when(transactionRepository.findAllByUserEmail(accountId)).thenReturn(List.of(tr1, tr2)); + when(transactionRepository.findAllByAccountId(accountId)).thenReturn(List.of(tr1, tr2)); var result = transactionService.getIncome(accountId); @@ -169,10 +171,90 @@ void getExpense_shouldReturnTotalExpense() { tr2.setTransactionType(TransactionType.EXPENSE); var accountId = 1; - when(transactionRepository.findAllByUserEmail(accountId)).thenReturn(List.of(tr1, tr2)); + when(transactionRepository.findAllByAccountId(accountId)).thenReturn(List.of(tr1, tr2)); var result = transactionService.getExpense(accountId); assertEquals(totalIncome, result); } + + @Test + void getBill_shouldReturnBillResponseDTO() { + var accountId = 1; + + var transaction1 = new TransactionEntity(); + var transaction2 = new TransactionEntity(); + var transaction3 = new TransactionEntity(); + + transaction1.setAmount(BigDecimal.valueOf(100)); + transaction2.setAmount(BigDecimal.valueOf(100)); + transaction3.setAmount(BigDecimal.valueOf(100)); + + LocalDateTime baseDate = LocalDate.now().atStartOfDay(); + + + var day1 = Timestamp.valueOf(baseDate.minusDays(8)); + transaction1.setTransactionDate(day1); + + var day2 = Timestamp.valueOf(baseDate.plusDays(2)); + transaction2.setTransactionDate(day2); + + var day3 = Timestamp.valueOf(baseDate.plusDays(8)); + transaction3.setTransactionDate(day3); + + CategoryEntity category = new CategoryEntity(1, "bill", "anyColor"); + + transaction1.setCategory(category); + transaction2.setCategory(category); + transaction3.setCategory(category); + + when(transactionRepository.findAllByAccountId(accountId)).thenReturn(List.of(transaction1, transaction2)); + + var result = transactionService.getBill(accountId); + + assertNotNull(result); + assertEquals(BigDecimal.valueOf(100), result.totalUpcoming()); + assertEquals(BigDecimal.valueOf(100), result.bill()); + assertEquals(BigDecimal.valueOf(100), result.bueSoon()); + } + + @Test + void getBill_shouldReturnEmptyBillResponseDTOWhenNoBills() { + var accountId = 1; + + var transaction1 = new TransactionEntity(); + var transaction2 = new TransactionEntity(); + var transaction3 = new TransactionEntity(); + + transaction1.setAmount(BigDecimal.valueOf(100)); + transaction2.setAmount(BigDecimal.valueOf(100)); + transaction3.setAmount(BigDecimal.valueOf(100)); + + LocalDateTime baseDate = LocalDate.now().atStartOfDay(); + + + var day1 = Timestamp.valueOf(baseDate.minusDays(8)); + transaction1.setTransactionDate(day1); + + var day2 = Timestamp.valueOf(baseDate.plusDays(2)); + transaction2.setTransactionDate(day2); + + var day3 = Timestamp.valueOf(baseDate.plusDays(8)); + transaction3.setTransactionDate(day3); + + CategoryEntity category = new CategoryEntity(1, "otherCategory", "anyColor"); + + transaction1.setCategory(category); + transaction2.setCategory(category); + transaction3.setCategory(category); + + when(transactionRepository.findAllByAccountId(accountId)).thenReturn(List.of(transaction1, transaction2)); + + var result = transactionService.getBill(accountId); + + assertNotNull(result); + assertEquals(BigDecimal.valueOf(0), result.totalUpcoming()); + assertEquals(BigDecimal.valueOf(0), result.bill()); + assertEquals(BigDecimal.valueOf(0), result.bueSoon()); + } }