From c13056ae7f9a6454876bb5cc2048c90ead58d64d Mon Sep 17 00:00:00 2001 From: mirrerror Date: Mon, 20 Nov 2023 09:03:34 +0200 Subject: [PATCH] added date filtering for transactions, refactor code --- .../controller/ExpenseController.java | 29 ++++++--- .../controller/IncomeController.java | 28 ++++++--- .../repository/ExpenseRepository.java | 13 ++++ .../repository/IncomeRepository.java | 13 ++++ .../service/CredentialService.java | 18 ++++++ .../service/ExpenseService.java | 59 +++++++++++-------- .../service/ITransactionService.java | 6 ++ .../service/IncomeService.java | 38 ++++++++++-- .../util/TransactionFilter.java | 30 ++++++++++ 9 files changed, 188 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/faf223/expensetrackerfaf/service/CredentialService.java create mode 100644 src/main/java/com/faf223/expensetrackerfaf/util/TransactionFilter.java diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java index 079cd0f..ec91ea7 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/ExpenseController.java @@ -2,6 +2,7 @@ package com.faf223.expensetrackerfaf.controller; import com.faf223.expensetrackerfaf.dto.ExpenseCreationDTO; import com.faf223.expensetrackerfaf.dto.ExpenseDTO; +import com.faf223.expensetrackerfaf.dto.IncomeDTO; import com.faf223.expensetrackerfaf.dto.mappers.ExpenseMapper; import com.faf223.expensetrackerfaf.model.Expense; import com.faf223.expensetrackerfaf.model.ExpenseCategory; @@ -97,24 +98,34 @@ public class ExpenseController { @GetMapping("/personal-expenses") public ResponseEntity> getExpensesByUser(@RequestParam Optional date, - @RequestParam Optional month) { + @RequestParam Optional month, + @RequestParam Optional startYear, + @RequestParam Optional endYear, + @RequestParam Optional lastUnit) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails) { String email = userDetails.getUsername(); - List expenses; + List expenses = Collections.emptyList(); - expenses = date.map(localDate -> expenseService.getTransactionsByDate(localDate, email).stream().map(expenseMapper::toDto).toList()) - .orElseGet(() -> month.map(value -> expenseService.getTransactionsByMonth(value, email).stream().map(expenseMapper::toDto).toList()) - .orElseGet(() -> expenseService.getTransactionsByEmail(email).stream().map(expenseMapper::toDto).toList())); + if(date.isPresent()) + expenses = expenseService.getTransactionsByDate(date.get(), email).stream().map(expenseMapper::toDto).toList(); + else if(month.isPresent()) + expenses = expenseService.getTransactionsByMonth(month.get(), email).stream().map(expenseMapper::toDto).toList(); + else if(startYear.isPresent() && endYear.isPresent()) + expenses = expenseService.getYearIntervalTransactions(email, startYear.get(), endYear.get()).stream().map(expenseMapper::toDto).toList(); + else if(lastUnit.isPresent()) { + + if(lastUnit.get().equalsIgnoreCase("week")) + expenses = expenseService.getLastWeekTransactions(email).stream().map(expenseMapper::toDto).toList(); + else if(lastUnit.get().equalsIgnoreCase("month")) + expenses = expenseService.getLastMonthTransactions(email).stream().map(expenseMapper::toDto).toList(); - if (!expenses.isEmpty()) { - return ResponseEntity.ok(expenses); - } else { - return ResponseEntity.ok(Collections.emptyList()); } + + return ResponseEntity.ok(expenses); } throw new TransactionsNotFoundException("The expenses have not been found"); diff --git a/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java b/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java index 24208f3..0e2a888 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java +++ b/src/main/java/com/faf223/expensetrackerfaf/controller/IncomeController.java @@ -97,24 +97,34 @@ public class IncomeController { @GetMapping("/personal-incomes") public ResponseEntity> getExpensesByUser(@RequestParam Optional date, - @RequestParam Optional month) { + @RequestParam Optional month, + @RequestParam Optional startYear, + @RequestParam Optional endYear, + @RequestParam Optional lastUnit) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails) { String email = userDetails.getUsername(); - List incomes; + List incomes = Collections.emptyList(); - incomes = date.map(localDate -> incomeService.getTransactionsByDate(localDate, email).stream().map(incomeMapper::toDto).toList()) - .orElseGet(() -> month.map(value -> incomeService.getTransactionsByMonth(value, email).stream().map(incomeMapper::toDto).toList()) - .orElseGet(() -> incomeService.getTransactionsByEmail(email).stream().map(incomeMapper::toDto).toList())); + if(date.isPresent()) + incomes = incomeService.getTransactionsByDate(date.get(), email).stream().map(incomeMapper::toDto).toList(); + else if(month.isPresent()) + incomes = incomeService.getTransactionsByMonth(month.get(), email).stream().map(incomeMapper::toDto).toList(); + else if(startYear.isPresent() && endYear.isPresent()) + incomes = incomeService.getYearIntervalTransactions(email, startYear.get(), endYear.get()).stream().map(incomeMapper::toDto).toList(); + else if(lastUnit.isPresent()) { + + if(lastUnit.get().equalsIgnoreCase("week")) + incomes = incomeService.getLastWeekTransactions(email).stream().map(incomeMapper::toDto).toList(); + else if(lastUnit.get().equalsIgnoreCase("month")) + incomes = incomeService.getLastMonthTransactions(email).stream().map(incomeMapper::toDto).toList(); - if (!incomes.isEmpty()) { - return ResponseEntity.ok(incomes); - } else { - return ResponseEntity.ok(Collections.emptyList()); } + + return ResponseEntity.ok(incomes); } throw new TransactionsNotFoundException("The expenses have not been found"); diff --git a/src/main/java/com/faf223/expensetrackerfaf/repository/ExpenseRepository.java b/src/main/java/com/faf223/expensetrackerfaf/repository/ExpenseRepository.java index e9bbaa7..90a6ac5 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/repository/ExpenseRepository.java +++ b/src/main/java/com/faf223/expensetrackerfaf/repository/ExpenseRepository.java @@ -3,6 +3,7 @@ package com.faf223.expensetrackerfaf.repository; import com.faf223.expensetrackerfaf.model.Expense; import com.faf223.expensetrackerfaf.model.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.query.Procedure; import org.springframework.stereotype.Repository; import java.time.LocalDate; @@ -14,4 +15,16 @@ public interface ExpenseRepository extends JpaRepository { List findByDate(LocalDate date); List findByDateBetween(LocalDate start, LocalDate end); + + @Procedure(procedureName = "get_expenses_by_month") + List filterByMonth(int month); + + @Procedure(procedureName = "get_last_week_expenses") + List findLastWeek(); + + @Procedure(procedureName = "get_last_month_expenses") + List findLastMonth(); + + @Procedure(procedureName = "get_expenses_by_year_interval") + List filterByYearInterval(int start, int end); } diff --git a/src/main/java/com/faf223/expensetrackerfaf/repository/IncomeRepository.java b/src/main/java/com/faf223/expensetrackerfaf/repository/IncomeRepository.java index 48b038d..013131d 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/repository/IncomeRepository.java +++ b/src/main/java/com/faf223/expensetrackerfaf/repository/IncomeRepository.java @@ -3,6 +3,7 @@ package com.faf223.expensetrackerfaf.repository; import com.faf223.expensetrackerfaf.model.Income; import com.faf223.expensetrackerfaf.model.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.query.Procedure; import org.springframework.stereotype.Repository; import java.time.LocalDate; @@ -14,4 +15,16 @@ public interface IncomeRepository extends JpaRepository { List findByDate(LocalDate date); List findByDateBetween(LocalDate start, LocalDate end); + + @Procedure(procedureName = "get_incomes_by_month") + List filterByMonth(int month); + + @Procedure(procedureName = "get_last_week_incomes") + List findLastWeek(); + + @Procedure(procedureName = "get_last_month_incomes") + List findLastMonth(); + + @Procedure(procedureName = "get_incomes_by_year_interval") + List filterByYearInterval(int start, int end); } diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/CredentialService.java b/src/main/java/com/faf223/expensetrackerfaf/service/CredentialService.java new file mode 100644 index 0000000..cd68ab2 --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/service/CredentialService.java @@ -0,0 +1,18 @@ +package com.faf223.expensetrackerfaf.service; + +import com.faf223.expensetrackerfaf.model.Credential; +import com.faf223.expensetrackerfaf.repository.CredentialRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CredentialService { + + private final CredentialRepository credentialRepository; + + public Credential findByEmail(String email) { + return credentialRepository.findByEmail(email).orElse(null); + } + +} diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java b/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java index 119fd7a..bc0a690 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/ExpenseService.java @@ -4,6 +4,7 @@ import com.faf223.expensetrackerfaf.model.*; import com.faf223.expensetrackerfaf.repository.CredentialRepository; import com.faf223.expensetrackerfaf.repository.ExpenseRepository; import com.faf223.expensetrackerfaf.repository.UserRepository; +import com.faf223.expensetrackerfaf.util.TransactionFilter; import com.faf223.expensetrackerfaf.util.exceptions.UserNotAuthenticatedException; import com.faf223.expensetrackerfaf.util.exceptions.UserNotFoundException; import lombok.RequiredArgsConstructor; @@ -25,6 +26,7 @@ public class ExpenseService implements ITransactionService { private final ExpenseRepository expenseRepository; private final CredentialRepository credentialRepository; private final UserRepository userRepository; + private final TransactionFilter transactionFilter; public void createOrUpdate(IMoneyTransaction expense) { expenseRepository.save((Expense) expense); @@ -47,37 +49,47 @@ public class ExpenseService implements ITransactionService { @Override public List getTransactionsByDate(LocalDate date, String email) { - return getTransactionsByDate(date) - .stream() - .filter(transaction -> { - Optional credential = credentialRepository.findByEmail(email); - if(credential.isEmpty()) - throw new UserNotFoundException("The user has not been found"); - return credential.get().getUser().equals(transaction.getUser()); - }) - .toList(); + return (List) transactionFilter.filterByEmail(getTransactionsByDate(date), email); } - // TODO: store transaction month in a separate field in the DB and change this logic @Override public List getTransactionsByMonth(Month month) { - LocalDate startOfMonth = LocalDate.of(LocalDate.now().getYear(), month, 1); - LocalDate endOfMonth = startOfMonth.plusMonths(1).minusDays(1); - - return expenseRepository.findByDateBetween(startOfMonth, endOfMonth); + return expenseRepository.filterByMonth(month.getValue()); } @Override public List getTransactionsByMonth(Month month, String email) { - return getTransactionsByMonth(month) - .stream() - .filter(transaction -> { - Optional credential = credentialRepository.findByEmail(email); - if(credential.isEmpty()) - throw new UserNotFoundException("The user has not been found"); - return credential.get().getUser().equals(transaction.getUser()); - }) - .toList(); + return (List) transactionFilter.filterByEmail(getTransactionsByMonth(month), email); + } + + @Override + public List getLastWeekTransactions() { + return expenseRepository.findLastWeek(); + } + + @Override + public List getLastWeekTransactions(String email) { + return (List) transactionFilter.filterByEmail(getLastWeekTransactions(), email); + } + + @Override + public List getLastMonthTransactions() { + return expenseRepository.findLastMonth(); + } + + @Override + public List getLastMonthTransactions(String email) { + return (List) transactionFilter.filterByEmail(getLastMonthTransactions(), email); + } + + @Override + public List getYearIntervalTransactions(int start, int end) { + return expenseRepository.filterByYearInterval(start, end); + } + + @Override + public List getYearIntervalTransactions(String email, int start, int end) { + return (List) transactionFilter.filterByEmail(getYearIntervalTransactions(start, end), email); } public List getTransactions() { @@ -113,4 +125,5 @@ public class ExpenseService implements ITransactionService { throw new UserNotAuthenticatedException("You are not authenticated"); } + } \ No newline at end of file diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/ITransactionService.java b/src/main/java/com/faf223/expensetrackerfaf/service/ITransactionService.java index 051c3fe..54097c2 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/ITransactionService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/ITransactionService.java @@ -17,6 +17,12 @@ public interface ITransactionService { List getTransactionsByDate(LocalDate date, String email); List getTransactionsByMonth(Month month); List getTransactionsByMonth(Month month, String email); + List getLastWeekTransactions(); + List getLastWeekTransactions(String email); + List getLastMonthTransactions(); + List getLastMonthTransactions(String email); + List getYearIntervalTransactions(int start, int end); + List getYearIntervalTransactions(String email, int start, int end); IMoneyTransaction getTransactionById(long id); void deleteTransactionById(long it); boolean belongsToUser(IMoneyTransaction transaction); diff --git a/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java b/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java index 97fe35e..d778ac8 100644 --- a/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java +++ b/src/main/java/com/faf223/expensetrackerfaf/service/IncomeService.java @@ -7,6 +7,7 @@ import com.faf223.expensetrackerfaf.model.User; import com.faf223.expensetrackerfaf.repository.CredentialRepository; import com.faf223.expensetrackerfaf.repository.IncomeRepository; import com.faf223.expensetrackerfaf.repository.UserRepository; +import com.faf223.expensetrackerfaf.util.TransactionFilter; import com.faf223.expensetrackerfaf.util.exceptions.UserNotAuthenticatedException; import com.faf223.expensetrackerfaf.util.exceptions.UserNotFoundException; import lombok.RequiredArgsConstructor; @@ -28,6 +29,7 @@ public class IncomeService implements ITransactionService { private final IncomeRepository incomeRepository; private final CredentialRepository credentialRepository; private final UserRepository userRepository; + private final TransactionFilter transactionFilter; public void createOrUpdate(IMoneyTransaction income) { incomeRepository.save((Income) income); @@ -65,13 +67,9 @@ public class IncomeService implements ITransactionService { .toList(); } - // TODO: store transaction month in a separate field in the DB and change this logic @Override public List getTransactionsByMonth(Month month) { - LocalDate startOfMonth = LocalDate.of(LocalDate.now().getYear(), month, 1); - LocalDate endOfMonth = startOfMonth.plusMonths(1).minusDays(1); - - return incomeRepository.findByDateBetween(startOfMonth, endOfMonth); + return incomeRepository.filterByMonth(month.getValue()); } @Override @@ -87,6 +85,36 @@ public class IncomeService implements ITransactionService { .toList(); } + @Override + public List getLastWeekTransactions() { + return incomeRepository.findLastWeek(); + } + + @Override + public List getLastWeekTransactions(String email) { + return (List) transactionFilter.filterByEmail(getLastWeekTransactions(), email); + } + + @Override + public List getLastMonthTransactions() { + return incomeRepository.findLastMonth(); + } + + @Override + public List getLastMonthTransactions(String email) { + return (List) transactionFilter.filterByEmail(getLastMonthTransactions(), email); + } + + @Override + public List getYearIntervalTransactions(int start, int end) { + return incomeRepository.filterByYearInterval(start, end); + } + + @Override + public List getYearIntervalTransactions(String email, int start, int end) { + return (List) transactionFilter.filterByEmail(getYearIntervalTransactions(start, end), email); + } + public Income getTransactionById(long id) { return incomeRepository.findById(id).orElse(null); } diff --git a/src/main/java/com/faf223/expensetrackerfaf/util/TransactionFilter.java b/src/main/java/com/faf223/expensetrackerfaf/util/TransactionFilter.java new file mode 100644 index 0000000..3f27dd7 --- /dev/null +++ b/src/main/java/com/faf223/expensetrackerfaf/util/TransactionFilter.java @@ -0,0 +1,30 @@ +package com.faf223.expensetrackerfaf.util; + +import com.faf223.expensetrackerfaf.model.Credential; +import com.faf223.expensetrackerfaf.model.IMoneyTransaction; +import com.faf223.expensetrackerfaf.service.CredentialService; +import com.faf223.expensetrackerfaf.util.exceptions.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class TransactionFilter { + + private final CredentialService credentialService; + + public List filterByEmail(List transactions, String email) { + return transactions + .stream() + .filter(transaction -> { + Credential credential = credentialService.findByEmail(email); + if(credential == null) + throw new UserNotFoundException("The user has not been found"); + return credential.getUser().equals(transaction.getUser()); + }) + .toList(); + } + +}