From c0e8b97ca3ae2a11f8f5bd5c5030fb0797eb8636 Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Wed, 28 May 2025 08:54:00 -0300 Subject: [PATCH 01/13] chore: add enpoint to verify jwt token --- .../auth/controller/AuthController.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/fun/trackmoney/auth/controller/AuthController.java b/src/main/java/fun/trackmoney/auth/controller/AuthController.java index 5b497f0..bc02f2d 100644 --- a/src/main/java/fun/trackmoney/auth/controller/AuthController.java +++ b/src/main/java/fun/trackmoney/auth/controller/AuthController.java @@ -8,6 +8,7 @@ import fun.trackmoney.utils.response.ApiResponse; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,7 +19,7 @@ * Provides endpoints for user registration. */ @RestController -@RequestMapping("auth/") +@RequestMapping("auth") public class AuthController { private final AuthService authService; @@ -39,7 +40,7 @@ public AuthController(AuthService authService) { * @return A ResponseEntity containing an ApiResponse * with the result of the registration operation. */ - @PostMapping("register") + @PostMapping("/register") public ResponseEntity> register( @RequestBody @Valid UserRequestDTO userDto) { return ResponseEntity.ok().body( @@ -52,7 +53,7 @@ public ResponseEntity> register( ); } - @PostMapping("login") + @PostMapping("/login") public ResponseEntity> login(@RequestBody LoginRequestDTO loginDto) { return ResponseEntity.ok().body( new ApiResponse<>( @@ -63,4 +64,16 @@ public ResponseEntity> login(@RequestBody LoginReq ) ); } + + @GetMapping("/verify") + public ResponseEntity> verify() { + return ResponseEntity.ok().body( + new ApiResponse<>( + true, + "Token is valid!", + true, + null + ) + ); + } } From 7ff79bc433961bd6e454fa6d5e54c14d6d32ae08 Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Wed, 28 May 2025 15:22:45 -0300 Subject: [PATCH 02/13] refactor: add enpoints income and expense --- .../account/controller/AccountController.java | 11 ++++++-- .../account/repository/AccountRepository.java | 7 +++++ .../account/service/AccountService.java | 5 ++-- .../controller/TransactionController.java | 13 +++++++++ .../repository/TransactionRepository.java | 6 +++++ .../service/TransactionService.java | 27 +++++++++++++++++-- .../java/fun/trackmoney/utils/AuthUtils.java | 13 +++++++++ .../controller/AccountControllerTest.java | 11 ++++++-- .../account/service/AccountServiceTest.java | 5 ++-- 9 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/main/java/fun/trackmoney/utils/AuthUtils.java diff --git a/src/main/java/fun/trackmoney/account/controller/AccountController.java b/src/main/java/fun/trackmoney/account/controller/AccountController.java index a711afd..db7f3b4 100644 --- a/src/main/java/fun/trackmoney/account/controller/AccountController.java +++ b/src/main/java/fun/trackmoney/account/controller/AccountController.java @@ -4,6 +4,7 @@ import fun.trackmoney.account.dtos.AccountResponseDTO; import fun.trackmoney.account.dtos.AccountUpdateRequestDTO; import fun.trackmoney.account.service.AccountService; +import fun.trackmoney.utils.AuthUtils; import fun.trackmoney.utils.response.ApiResponse; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -17,15 +18,18 @@ import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.UUID; @RestController @RequestMapping("/accounts") public class AccountController { private final AccountService accountService; + private final AuthUtils authUtils; - public AccountController(AccountService accountService) { + public AccountController(AccountService accountService, AuthUtils authUtils) { this.accountService = accountService; + this.authUtils = authUtils; } @PostMapping @@ -35,13 +39,16 @@ public ResponseEntity> createAccount(@RequestBod true, "Account successfully created.", createdAccount, null), HttpStatus.CREATED); } + @GetMapping public ResponseEntity>> findAllAccounts() { - List accounts = accountService.findAllAccount(); + UUID email = authUtils.getCurrentUser().getUserId(); + List accounts = accountService.findAllAccount(email); return ResponseEntity.ok(new ApiResponse<>( true, "Account list retrieved successfully.", accounts, null)); } + @GetMapping("/{id}") public ResponseEntity> findAccountById(@PathVariable Integer id) { AccountResponseDTO account = accountService.findAccountById(id); diff --git a/src/main/java/fun/trackmoney/account/repository/AccountRepository.java b/src/main/java/fun/trackmoney/account/repository/AccountRepository.java index 982a863..df7c5b8 100644 --- a/src/main/java/fun/trackmoney/account/repository/AccountRepository.java +++ b/src/main/java/fun/trackmoney/account/repository/AccountRepository.java @@ -2,6 +2,13 @@ import fun.trackmoney.account.entity.AccountEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.UUID; public interface AccountRepository extends JpaRepository { + @Query("SELECT a FROM AccountEntity a WHERE a.user.userId = :userId") + List findAllByUserEmail(@Param("userId") UUID userId); } diff --git a/src/main/java/fun/trackmoney/account/service/AccountService.java b/src/main/java/fun/trackmoney/account/service/AccountService.java index 5c616ca..02c8f0e 100644 --- a/src/main/java/fun/trackmoney/account/service/AccountService.java +++ b/src/main/java/fun/trackmoney/account/service/AccountService.java @@ -12,6 +12,7 @@ import org.springframework.stereotype.Service; import java.util.List; +import java.util.UUID; @Service public class AccountService { @@ -38,8 +39,8 @@ public AccountResponseDTO createAccount(AccountRequestDTO dto) { .save(account)); } - public List findAllAccount() { - return accountMapper.accountEntityListToAccountResponseList(accountRepository.findAll()); + public List findAllAccount(UUID userId) { + return accountMapper.accountEntityListToAccountResponseList(accountRepository.findAllByUserEmail(userId)); } public AccountResponseDTO findAccountById(Integer id) { diff --git a/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java b/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java index 79da7b4..ea0bdf4 100644 --- a/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java +++ b/src/main/java/fun/trackmoney/transaction/controller/TransactionController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.math.BigDecimal; import java.util.List; @RestController @@ -48,6 +49,18 @@ public ResponseEntity> findTransactionById(@ new ApiResponse<>(true,"Get transaction by id", transactionService.findById(id),null)); } + @GetMapping("/income/{id}") + public ResponseEntity> getIncome(@PathVariable Integer id) { + return ResponseEntity.ok().body( + new ApiResponse<>(true,"Get income", transactionService.getIncome(id),null)); + } + + @GetMapping("/expense/{id}") + public ResponseEntity> getExpense(@PathVariable Integer id) { + return ResponseEntity.ok().body( + new ApiResponse<>(true,"Get expense", transactionService.getExpense(id),null)); + } + @PutMapping("/{id}") public ResponseEntity> updateTransaction(@PathVariable Integer id, @RequestBody TransactionUpdateDTO dto) { diff --git a/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java b/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java index 4e59014..dca4c67 100644 --- a/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java +++ b/src/main/java/fun/trackmoney/transaction/repository/TransactionRepository.java @@ -2,6 +2,12 @@ import fun.trackmoney.transaction.entity.TransactionEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface TransactionRepository extends JpaRepository { + @Query("SELECT a FROM TransactionEntity a WHERE a.account.accountId = :accountId") + List findAllByUserEmail(@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 0cdb454..a069f2b 100644 --- a/src/main/java/fun/trackmoney/transaction/service/TransactionService.java +++ b/src/main/java/fun/trackmoney/transaction/service/TransactionService.java @@ -5,6 +5,7 @@ import fun.trackmoney.account.service.AccountService; import fun.trackmoney.category.entity.CategoryEntity; import fun.trackmoney.category.service.CategoryService; +import fun.trackmoney.enums.TransactionType; import fun.trackmoney.transaction.dto.CreateTransactionDTO; import fun.trackmoney.transaction.dto.TransactionResponseDTO; import fun.trackmoney.transaction.dto.TransactionUpdateDTO; @@ -14,7 +15,9 @@ import fun.trackmoney.transaction.repository.TransactionRepository; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.List; +import java.util.Objects; @Service public class TransactionService { @@ -25,8 +28,10 @@ public class TransactionService { private final AccountMapper accountMapper; private final CategoryService categoryService; - public TransactionService(TransactionRepository transactionRepository, TransactionMapper transactionMapper, - AccountService accountService, AccountMapper accountMapper, + public TransactionService(TransactionRepository transactionRepository, + TransactionMapper transactionMapper, + AccountService accountService, + AccountMapper accountMapper, CategoryService categoryService) { this.transactionRepository = transactionRepository; this.transactionMapper = transactionMapper; @@ -71,4 +76,22 @@ public TransactionResponseDTO update(Integer id, TransactionUpdateDTO dto) { public void delete(Integer id) { transactionRepository.deleteById(id); } + + public BigDecimal getIncome(Integer accountId) { + return transactionRepository.findAllByUserEmail(accountId) + .stream() + .filter(t -> TransactionType.INCOME.equals(t.getTransactionType())) + .map(TransactionEntity::getAmount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } + + public BigDecimal getExpense(Integer accountId) { + return transactionRepository.findAllByUserEmail(accountId) + .stream() + .filter(t -> TransactionType.EXPENSE.equals(t.getTransactionType())) + .map(TransactionEntity::getAmount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } } diff --git a/src/main/java/fun/trackmoney/utils/AuthUtils.java b/src/main/java/fun/trackmoney/utils/AuthUtils.java new file mode 100644 index 0000000..e421551 --- /dev/null +++ b/src/main/java/fun/trackmoney/utils/AuthUtils.java @@ -0,0 +1,13 @@ +package fun.trackmoney.utils; + +import fun.trackmoney.user.entity.UserEntity; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +@Component +public class AuthUtils { + + public UserEntity getCurrentUser() { + return (UserEntity) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } +} diff --git a/src/test/java/fun/trackmoney/account/controller/AccountControllerTest.java b/src/test/java/fun/trackmoney/account/controller/AccountControllerTest.java index 816d7b2..07e0b1a 100644 --- a/src/test/java/fun/trackmoney/account/controller/AccountControllerTest.java +++ b/src/test/java/fun/trackmoney/account/controller/AccountControllerTest.java @@ -5,6 +5,8 @@ import fun.trackmoney.account.dtos.AccountUpdateRequestDTO; import fun.trackmoney.account.service.AccountService; import fun.trackmoney.user.dtos.UserResponseDTO; +import fun.trackmoney.user.entity.UserEntity; +import fun.trackmoney.utils.AuthUtils; import fun.trackmoney.utils.response.ApiResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,6 +28,9 @@ class AccountControllerTest { @Mock private AccountService accountService; + @Mock + private AuthUtils authUtils; + @InjectMocks private AccountController accountController; @@ -61,8 +66,10 @@ void testFindAllAccounts() { new AccountResponseDTO(1, userResponseDTO, "Conta Corrente", BigDecimal.valueOf(1000), true), new AccountResponseDTO(2, userResponseDTO, "Conta Poupança", BigDecimal.valueOf(500), false) ); - - when(accountService.findAllAccount()).thenReturn(accounts); + UUID uuid = UUID.randomUUID(); + UserEntity user = new UserEntity(uuid, "", "", ""); + when(authUtils.getCurrentUser()).thenReturn(user); + when(accountService.findAllAccount(uuid)).thenReturn(accounts); ResponseEntity>> response = accountController.findAllAccounts(); diff --git a/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java b/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java index efbf715..ef9ce3c 100644 --- a/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java +++ b/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java @@ -60,16 +60,17 @@ void testCreateAccount() { @Test void testFindAllAccounts() { + UUID uuid = UUID.randomUUID(); List entities = List.of(new AccountEntity(), new AccountEntity()); List responseDTOs = List.of( new AccountResponseDTO(1, null, "Conta 1", BigDecimal.valueOf(100), false), new AccountResponseDTO(2, null, "Conta 2", BigDecimal.valueOf(200), true) ); - when(accountRepository.findAll()).thenReturn(entities); + when(accountRepository.findAllByUserEmail(uuid)).thenReturn(entities); when(accountMapper.accountEntityListToAccountResponseList(entities)).thenReturn(responseDTOs); - List result = accountService.findAllAccount(); + List result = accountService.findAllAccount(uuid); assertEquals(2, result.size()); assertEquals(responseDTOs, result); From c93b2f1ce4d1c0b4830d9a2ec0c64316e8e7abaa Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Thu, 29 May 2025 15:52:29 -0300 Subject: [PATCH 03/13] chore: add the GET all budget by account Id --- .../budget/controller/BudgetsController.java | 6 ++--- .../budget/dtos/BudgetResponseDTO.java | 1 + .../budget/repository/BudgetsRepository.java | 3 +++ .../budget/service/BudgetsService.java | 22 +++++++++++++++++-- .../controller/BudgetsControllerTest.java | 6 ++--- .../budget/service/BudgetsServiceTest.java | 10 ++++----- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/main/java/fun/trackmoney/budget/controller/BudgetsController.java b/src/main/java/fun/trackmoney/budget/controller/BudgetsController.java index ad5e867..302e69f 100644 --- a/src/main/java/fun/trackmoney/budget/controller/BudgetsController.java +++ b/src/main/java/fun/trackmoney/budget/controller/BudgetsController.java @@ -33,9 +33,9 @@ public ResponseEntity> create(@RequestBody Budget new ApiResponse<>(true, "Budget created", budgetsService.create(dto), null)); } - @GetMapping - public ResponseEntity>> findAll() { - var list = budgetsService.findAll(); + @GetMapping("/findAll/{accountId}") + public ResponseEntity>> findAllByAccountId(@PathVariable Integer accountId) { + var list = budgetsService.findAllByAccountId(accountId); return ResponseEntity.status(HttpStatus.OK).body( new ApiResponse<>(true, "Get all Budget",list , null)); } diff --git a/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java b/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java index bbd7b87..7568536 100644 --- a/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java +++ b/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java @@ -9,5 +9,6 @@ public record BudgetResponseDTO (Integer budgetId, CategoryEntity category, AccountResponseDTO account, BigDecimal targetAmount, + BigDecimal currentAmount, Integer resetDay) { } diff --git a/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java b/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java index 2aea451..949ae22 100644 --- a/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java +++ b/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java @@ -3,5 +3,8 @@ import fun.trackmoney.budget.entity.BudgetsEntity; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface BudgetsRepository extends JpaRepository { + List findAllByAccount_AccountId(Integer accountId); } diff --git a/src/main/java/fun/trackmoney/budget/service/BudgetsService.java b/src/main/java/fun/trackmoney/budget/service/BudgetsService.java index 8121d77..f5bcc31 100644 --- a/src/main/java/fun/trackmoney/budget/service/BudgetsService.java +++ b/src/main/java/fun/trackmoney/budget/service/BudgetsService.java @@ -12,6 +12,7 @@ import fun.trackmoney.user.service.UserService; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.List; @Service @@ -47,8 +48,25 @@ public BudgetResponseDTO create(BudgetCreateDTO dto) { return budgetMapper.entityToResponseDTO(budgetsRepository.save(budgets)); } - public List findAll() { - return budgetMapper.entityListToResponseList(budgetsRepository.findAll()); + public List findAllByAccountId(Integer accountId) { + return budgetMapper.entityListToResponseList( + budgetsRepository.findAllByAccount_AccountId(accountId) + ).stream() + .map(budget -> { + BigDecimal currentAmount = budget.currentAmount() == null + ? BigDecimal.valueOf(100) + : budget.currentAmount(); + + return new BudgetResponseDTO( + budget.budgetId(), + budget.category(), + budget.account(), + budget.targetAmount(), + currentAmount, + budget.resetDay() + ); + }) + .toList(); } public BudgetResponseDTO findById(Integer id) { diff --git a/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java b/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java index ff614bb..7b79655 100644 --- a/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java +++ b/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java @@ -62,9 +62,9 @@ void create_shouldReturnCreatedAndBudgetResponse() { @Test void findAll_shouldReturnOkAndListOfBudgetResponses() { List budgetList = Collections.singletonList(responseDTO); - when(budgetsService.findAll()).thenReturn(budgetList); + when(budgetsService.findAllByAccountId(createDTO.accountId())).thenReturn(budgetList); - ResponseEntity>> response = budgetsController.findAll(); + ResponseEntity>> response = budgetsController.findAllByAccountId(createDTO.accountId()); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); @@ -72,7 +72,7 @@ void findAll_shouldReturnOkAndListOfBudgetResponses() { assertEquals("Get all Budget", response.getBody().getMessage()); assertEquals(budgetList, response.getBody().getData()); assertNull(response.getBody().getErrors()); - verify(budgetsService, times(1)).findAll(); + verify(budgetsService, times(1)).findAllByAccountId(createDTO.accountId()); } @Test diff --git a/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java b/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java index 7bf4ae8..ccc2c2b 100644 --- a/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java +++ b/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java @@ -114,11 +114,11 @@ void findAll_shouldReturnEmptyList_whenNoBudgetsExist() { when(budgetsRepository.findAll()).thenReturn(Collections.emptyList()); when(budgetMapper.entityListToResponseList(Collections.emptyList())).thenReturn(Collections.emptyList()); - List result = budgetsService.findAll(); + List result = budgetsService.findAllByAccountId(accountEntity.getAccountId()); assertNotNull(result); assertTrue(result.isEmpty()); - verify(budgetsRepository, times(1)).findAll(); + verify(budgetsRepository, times(1)).findAllByAccount_AccountId(accountEntity.getAccountId()); verify(budgetMapper, times(1)).entityListToResponseList(Collections.emptyList()); } @@ -131,15 +131,15 @@ void findAll_shouldReturnListOfBudgetResponseDTO() { List entities = List.of(entity); List dtos = List.of(dto); - when(budgetsRepository.findAll()).thenReturn(entities); + when(budgetsRepository.findAllByAccount_AccountId(accountEntity.getAccountId())).thenReturn(entities); when(budgetMapper.entityListToResponseList(entities)).thenReturn(dtos); - List result = budgetsService.findAll(); + List result = budgetsService.findAllByAccountId(accountEntity.getAccountId()); assertNotNull(result); assertEquals(1, result.size()); assertEquals(dtos, result); - verify(budgetsRepository, times(1)).findAll(); + verify(budgetsRepository, times(1)).findAllByAccount_AccountId(accountEntity.getAccountId()); verify(budgetMapper, times(1)).entityListToResponseList(entities); } From 8329b7edcde4c72a13ea53a2285701f59487556b Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 15:20:29 -0300 Subject: [PATCH 04/13] chore: add the column currentAmmount in budget nad color in category --- .../budget/entity/BudgetsEntity.java | 22 +++++++++++++++++++ .../category/entity/CategoryEntity.java | 14 ++++++++++++ ...reate_initial_schema_with_uuid_support.sql | 5 +++++ 3 files changed, 41 insertions(+) create mode 100644 src/main/resources/db/migration/V3__create_initial_schema_with_uuid_support.sql diff --git a/src/main/java/fun/trackmoney/budget/entity/BudgetsEntity.java b/src/main/java/fun/trackmoney/budget/entity/BudgetsEntity.java index 887b047..56016b2 100644 --- a/src/main/java/fun/trackmoney/budget/entity/BudgetsEntity.java +++ b/src/main/java/fun/trackmoney/budget/entity/BudgetsEntity.java @@ -38,6 +38,8 @@ public class BudgetsEntity { @Column(name = "reset_day") private Integer resetDay; + private BigDecimal currentAmount; + public AccountEntity getAccount() { return account; } @@ -58,6 +60,18 @@ public BudgetsEntity(Integer budgetId, this.resetDay = resetDay; } + public BudgetsEntity(Integer budgetId, + CategoryEntity category, + AccountEntity account, + UserEntity userEntity, + BigDecimal targetAmount, + Integer resetDay, + BigDecimal currentAmount) { + this(budgetId, category, userEntity, targetAmount, resetDay); + this.currentAmount = currentAmount; + this.account = account; + } + public void setAccount(AccountEntity account) { this.account = account; } @@ -105,4 +119,12 @@ public UserEntity getUserEntity() { public void setUserEntity(UserEntity userEntity) { this.userEntity = userEntity; } + + public BigDecimal getCurrentAmount() { + return currentAmount; + } + + public void setCurrentAmount(BigDecimal currentAmount) { + this.currentAmount = currentAmount; + } } diff --git a/src/main/java/fun/trackmoney/category/entity/CategoryEntity.java b/src/main/java/fun/trackmoney/category/entity/CategoryEntity.java index 3765696..68d1cdc 100644 --- a/src/main/java/fun/trackmoney/category/entity/CategoryEntity.java +++ b/src/main/java/fun/trackmoney/category/entity/CategoryEntity.java @@ -28,6 +28,7 @@ public class CategoryEntity { */ private String name; + private String color; /** * Default constructor for creating an instance of {@link CategoryEntity}. * This constructor is required for JPA persistence. @@ -46,6 +47,19 @@ public CategoryEntity(Integer categoryId, String name) { this.name = name; } + public CategoryEntity(Integer categoryId, String name, String color) { + this(categoryId,name); + this.color = color; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + /** * Gets the category ID. * diff --git a/src/main/resources/db/migration/V3__create_initial_schema_with_uuid_support.sql b/src/main/resources/db/migration/V3__create_initial_schema_with_uuid_support.sql new file mode 100644 index 0000000..c3bb561 --- /dev/null +++ b/src/main/resources/db/migration/V3__create_initial_schema_with_uuid_support.sql @@ -0,0 +1,5 @@ +ALTER TABLE tb_category +ADD COLUMN color VARCHAR(50) NOT NULL; + +ALTER TABLE tb_budget +ADD COLUMN current_amount NUMERIC(19, 4) NOT NULL DEFAULT 0.0000; From 64c8425102c194be83cd1e3d3476d8bfc690db6c Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 16:35:52 -0300 Subject: [PATCH 05/13] chore: update account balance when creating a new transaction --- .../trackmoney/account/mapper/AccountMapper.java | 2 ++ .../trackmoney/account/service/AccountService.java | 13 +++++++++++++ .../transaction/dto/TransactionUpdateDTO.java | 5 ++++- .../transaction/service/TransactionService.java | 6 +++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/fun/trackmoney/account/mapper/AccountMapper.java b/src/main/java/fun/trackmoney/account/mapper/AccountMapper.java index 2c32895..a418ec3 100644 --- a/src/main/java/fun/trackmoney/account/mapper/AccountMapper.java +++ b/src/main/java/fun/trackmoney/account/mapper/AccountMapper.java @@ -19,4 +19,6 @@ public interface AccountMapper { List accountEntityListToAccountResponseList(List entities); AccountEntity accountResponseToEntity(AccountResponseDTO accountById); + + AccountUpdateRequestDTO toAccountRequest(AccountEntity account); } diff --git a/src/main/java/fun/trackmoney/account/service/AccountService.java b/src/main/java/fun/trackmoney/account/service/AccountService.java index 02c8f0e..5f4c171 100644 --- a/src/main/java/fun/trackmoney/account/service/AccountService.java +++ b/src/main/java/fun/trackmoney/account/service/AccountService.java @@ -11,6 +11,7 @@ import fun.trackmoney.user.repository.UserRepository; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.List; import java.util.UUID; @@ -61,4 +62,16 @@ public AccountResponseDTO updateAccountById(Integer id, AccountUpdateRequestDTO public void deleteById(Integer id) { accountRepository.deleteById(id); } + + public void updateAccountBalance(BigDecimal balance, Integer accountId, Boolean isCredit) { + var account = accountRepository.findById(accountId).orElseThrow(() -> new AccountNotFoundException("Account not found!")); + + if (isCredit) { + account.setBalance(account.getBalance().add(balance)); + } else{ + account.setBalance(account.getBalance().subtract(balance)); + } + + accountRepository.save(account); + } } diff --git a/src/main/java/fun/trackmoney/transaction/dto/TransactionUpdateDTO.java b/src/main/java/fun/trackmoney/transaction/dto/TransactionUpdateDTO.java index ba181ea..332bb01 100644 --- a/src/main/java/fun/trackmoney/transaction/dto/TransactionUpdateDTO.java +++ b/src/main/java/fun/trackmoney/transaction/dto/TransactionUpdateDTO.java @@ -1,9 +1,12 @@ package fun.trackmoney.transaction.dto; +import fun.trackmoney.enums.TransactionType; + import java.math.BigDecimal; public record TransactionUpdateDTO(String description, BigDecimal amount, Integer accountId, - Integer categoryId) { + Integer categoryId, + TransactionType transactionType) { } diff --git a/src/main/java/fun/trackmoney/transaction/service/TransactionService.java b/src/main/java/fun/trackmoney/transaction/service/TransactionService.java index a069f2b..4dede65 100644 --- a/src/main/java/fun/trackmoney/transaction/service/TransactionService.java +++ b/src/main/java/fun/trackmoney/transaction/service/TransactionService.java @@ -48,8 +48,12 @@ public TransactionResponseDTO createTransaction(CreateTransactionDTO transaction transactionEntity.setAccount(account); transactionEntity.setCategory(category); + var response = transactionMapper.toResponseDTO(transactionRepository.save(transactionEntity)); - return transactionMapper.toResponseDTO(transactionRepository.save(transactionEntity)); + accountService.updateAccountBalance(transactionDTO.amount(), account.getAccountId(), + TransactionType.INCOME.equals(transactionDTO.transactionType())); + + return response; } public List findAllTransaction() { From 374700c8c09fe930c4d28032c12018f8e6c7a418 Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 16:43:08 -0300 Subject: [PATCH 06/13] chore: fix the check style error --- .../java/fun/trackmoney/account/service/AccountService.java | 3 ++- .../fun/trackmoney/budget/repository/BudgetsRepository.java | 2 +- .../java/fun/trackmoney/budget/service/BudgetsService.java | 2 +- .../fun/trackmoney/budget/service/BudgetsServiceTest.java | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/fun/trackmoney/account/service/AccountService.java b/src/main/java/fun/trackmoney/account/service/AccountService.java index 5f4c171..c8a0d1e 100644 --- a/src/main/java/fun/trackmoney/account/service/AccountService.java +++ b/src/main/java/fun/trackmoney/account/service/AccountService.java @@ -64,7 +64,8 @@ public void deleteById(Integer id) { } public void updateAccountBalance(BigDecimal balance, Integer accountId, Boolean isCredit) { - var account = accountRepository.findById(accountId).orElseThrow(() -> new AccountNotFoundException("Account not found!")); + var account = accountRepository.findById(accountId) + .orElseThrow(() -> new AccountNotFoundException("Account not found!")); if (isCredit) { account.setBalance(account.getBalance().add(balance)); diff --git a/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java b/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java index 949ae22..846be5f 100644 --- a/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java +++ b/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java @@ -6,5 +6,5 @@ import java.util.List; public interface BudgetsRepository extends JpaRepository { - List findAllByAccount_AccountId(Integer accountId); + List findAllByAccountAccountId(Integer accountId); } diff --git a/src/main/java/fun/trackmoney/budget/service/BudgetsService.java b/src/main/java/fun/trackmoney/budget/service/BudgetsService.java index f5bcc31..26ed10e 100644 --- a/src/main/java/fun/trackmoney/budget/service/BudgetsService.java +++ b/src/main/java/fun/trackmoney/budget/service/BudgetsService.java @@ -50,7 +50,7 @@ public BudgetResponseDTO create(BudgetCreateDTO dto) { public List findAllByAccountId(Integer accountId) { return budgetMapper.entityListToResponseList( - budgetsRepository.findAllByAccount_AccountId(accountId) + budgetsRepository.findAllByAccountAccountId(accountId) ).stream() .map(budget -> { BigDecimal currentAmount = budget.currentAmount() == null diff --git a/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java b/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java index ccc2c2b..6e08f12 100644 --- a/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java +++ b/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java @@ -118,7 +118,7 @@ void findAll_shouldReturnEmptyList_whenNoBudgetsExist() { assertNotNull(result); assertTrue(result.isEmpty()); - verify(budgetsRepository, times(1)).findAllByAccount_AccountId(accountEntity.getAccountId()); + verify(budgetsRepository, times(1)).findAllByAccountAccountId(accountEntity.getAccountId()); verify(budgetMapper, times(1)).entityListToResponseList(Collections.emptyList()); } @@ -131,7 +131,7 @@ void findAll_shouldReturnListOfBudgetResponseDTO() { List entities = List.of(entity); List dtos = List.of(dto); - when(budgetsRepository.findAllByAccount_AccountId(accountEntity.getAccountId())).thenReturn(entities); + when(budgetsRepository.findAllByAccountAccountId(accountEntity.getAccountId())).thenReturn(entities); when(budgetMapper.entityListToResponseList(entities)).thenReturn(dtos); List result = budgetsService.findAllByAccountId(accountEntity.getAccountId()); @@ -139,7 +139,7 @@ void findAll_shouldReturnListOfBudgetResponseDTO() { assertNotNull(result); assertEquals(1, result.size()); assertEquals(dtos, result); - verify(budgetsRepository, times(1)).findAllByAccount_AccountId(accountEntity.getAccountId()); + verify(budgetsRepository, times(1)).findAllByAccountAccountId(accountEntity.getAccountId()); verify(budgetMapper, times(1)).entityListToResponseList(entities); } From 624048aa759ea6d8dcccbaf971d283b662d08ac8 Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 17:04:14 -0300 Subject: [PATCH 07/13] chore: fix the test error --- .../fun/trackmoney/budget/dtos/BudgetResponseDTO.java | 4 ++-- .../fun/trackmoney/budget/service/BudgetsService.java | 4 ++-- .../budget/controller/BudgetsControllerTest.java | 4 ++-- .../fun/trackmoney/budget/service/BudgetsServiceTest.java | 8 ++++---- .../transaction/controller/TransactionControllerTest.java | 2 +- .../transaction/service/TransactionServiceTest.java | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java b/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java index 7568536..55baca9 100644 --- a/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java +++ b/src/main/java/fun/trackmoney/budget/dtos/BudgetResponseDTO.java @@ -9,6 +9,6 @@ public record BudgetResponseDTO (Integer budgetId, CategoryEntity category, AccountResponseDTO account, BigDecimal targetAmount, - BigDecimal currentAmount, - Integer resetDay) { + Integer resetDay, + BigDecimal currentAmount) { } diff --git a/src/main/java/fun/trackmoney/budget/service/BudgetsService.java b/src/main/java/fun/trackmoney/budget/service/BudgetsService.java index 26ed10e..815544a 100644 --- a/src/main/java/fun/trackmoney/budget/service/BudgetsService.java +++ b/src/main/java/fun/trackmoney/budget/service/BudgetsService.java @@ -62,8 +62,8 @@ public List findAllByAccountId(Integer accountId) { budget.category(), budget.account(), budget.targetAmount(), - currentAmount, - budget.resetDay() + budget.resetDay(), + currentAmount ); }) .toList(); diff --git a/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java b/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java index 7b79655..7738417 100644 --- a/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java +++ b/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java @@ -41,7 +41,7 @@ void setUp() { UUID userId = UUID.randomUUID(); budgetId = 1; createDTO = new BudgetCreateDTO(10, userId, 20, BigDecimal.valueOf(1000), 5); - responseDTO = new BudgetResponseDTO(budgetId, null, null, BigDecimal.valueOf(1000), 5); + responseDTO = new BudgetResponseDTO(budgetId, null, null, BigDecimal.valueOf(1000), 5, BigDecimal.valueOf(1000)); } @Test @@ -107,7 +107,7 @@ void deleteById_shouldReturnOkAndSuccessMessage() { void updateById_shouldReturnOkAndUpdatedBudgetResponse() { int updateId = 1; BudgetCreateDTO updateDTO = new BudgetCreateDTO(11, UUID.randomUUID(), 21, BigDecimal.valueOf(1500), 6); - BudgetResponseDTO updatedResponseDTO = new BudgetResponseDTO(updateId, null, null, BigDecimal.valueOf(1500), 6); + BudgetResponseDTO updatedResponseDTO = new BudgetResponseDTO(updateId, null, null, BigDecimal.valueOf(1500), 6, BigDecimal.valueOf(1500)); when(budgetsService.update(updateDTO, updateId)).thenReturn(updatedResponseDTO); ResponseEntity> response = budgetsController.updateById(updateId, updateDTO); diff --git a/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java b/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java index 6e08f12..09e29b4 100644 --- a/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java +++ b/src/test/java/fun/trackmoney/budget/service/BudgetsServiceTest.java @@ -70,7 +70,7 @@ void setUp() { accountResponseDTO = new AccountResponseDTO(20, userResponseDTO, "true", BigDecimal.valueOf(1000), true); accountEntity = new AccountEntity(); categoryEntity = new CategoryEntity(); - budgetResponseDTO = new BudgetResponseDTO(1, categoryEntity, accountResponseDTO, BigDecimal.valueOf(1000), 5); + budgetResponseDTO = new BudgetResponseDTO(1, categoryEntity, accountResponseDTO, BigDecimal.valueOf(1000), 5, BigDecimal.valueOf(1000)); } @Test @@ -127,7 +127,7 @@ void findAll_shouldReturnListOfBudgetResponseDTO() { BudgetsEntity entity = new BudgetsEntity(); BudgetResponseDTO dto = new BudgetResponseDTO(1, new CategoryEntity(), new AccountResponseDTO(1, userResponseDTO, "test", BigDecimal.valueOf(100), true), - BigDecimal.TEN, 10); + BigDecimal.TEN, 10, null); List entities = List.of(entity); List dtos = List.of(dto); @@ -137,8 +137,8 @@ void findAll_shouldReturnListOfBudgetResponseDTO() { List result = budgetsService.findAllByAccountId(accountEntity.getAccountId()); assertNotNull(result); + assertNotNull(result.get(0).currentAmount()); assertEquals(1, result.size()); - assertEquals(dtos, result); verify(budgetsRepository, times(1)).findAllByAccountAccountId(accountEntity.getAccountId()); verify(budgetMapper, times(1)).entityListToResponseList(entities); } @@ -179,7 +179,7 @@ void update_shouldReturnUpdatedBudgetResponseDTO_whenBudgetExists() { AccountEntity updatedAccountEntity = new AccountEntity(); CategoryEntity updatedCategory = new CategoryEntity(); BudgetResponseDTO updatedResponse = new BudgetResponseDTO(budgetIdToUpdate, updatedCategory, - updatedAccountDTO, BigDecimal.valueOf(1500), 6); + updatedAccountDTO, BigDecimal.valueOf(1500), 6, BigDecimal.valueOf(1000)); BudgetsEntity updatedEntity = new BudgetsEntity(); updatedEntity.setBudgetId(budgetIdToUpdate); diff --git a/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java b/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java index 48e9893..0dc30a3 100644 --- a/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java +++ b/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java @@ -91,7 +91,7 @@ void findTransactionById_shouldReturnTransaction() { @Test void updateTransaction_shouldReturnUpdatedTransaction() { // Arrange - TransactionUpdateDTO dto = new TransactionUpdateDTO("Updated", BigDecimal.valueOf(50), 1, 2); + TransactionUpdateDTO dto = new TransactionUpdateDTO("Updated", BigDecimal.valueOf(50), 1, 2, TransactionType.EXPENSE); TransactionResponseDTO updated = new TransactionResponseDTO(1, "Updated", BigDecimal.valueOf(50), null); when(transactionService.update(1, dto)).thenReturn(updated); diff --git a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java index 1415b3a..7421809 100644 --- a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java +++ b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java @@ -119,7 +119,7 @@ void update_shouldUpdateAndReturnTransactionResponseDTO() { CategoryEntity categoryEntity = new CategoryEntity(); TransactionResponseDTO dtoResponse = new TransactionResponseDTO(1, "Updated", BigDecimal.valueOf(200), null); - TransactionUpdateDTO dto = new TransactionUpdateDTO("Updated", BigDecimal.valueOf(200), 1, 2); + TransactionUpdateDTO dto = new TransactionUpdateDTO("Updated", BigDecimal.valueOf(200), 1, 2, TransactionType.EXPENSE); UserResponseDTO user = new UserResponseDTO(UUID.randomUUID(), "Jane", "jane@mail.com"); when(transactionRepository.findById(1)).thenReturn(Optional.of(entity)); From 3d0648f05bd42758499bb0f4836d739ee922d68c Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 17:21:56 -0300 Subject: [PATCH 08/13] test: add unit test for AuthController.verify --- .../trackmoney/auth/controller/AuthControllerTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/fun/trackmoney/auth/controller/AuthControllerTest.java b/src/test/java/fun/trackmoney/auth/controller/AuthControllerTest.java index 272a892..1cc2dc6 100644 --- a/src/test/java/fun/trackmoney/auth/controller/AuthControllerTest.java +++ b/src/test/java/fun/trackmoney/auth/controller/AuthControllerTest.java @@ -55,4 +55,12 @@ void shouldReturnTokenOnLogin() { assertEquals("Login successful!", response.getBody().getMessage()); assertEquals("jwt-token", response.getBody().getData().token()); } + + @Test + void shouldTrueWhenJwtIsValid() { + var response = authController.verify(); + + assertTrue(response.getBody().getSuccess()); + assertTrue(response.getBody().getData()); + } } From 1ee519e4ae0bc771d83ca531b21dbc62c5539329 Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 17:25:02 -0300 Subject: [PATCH 09/13] test: add unit test for AuthUtils --- .../fun/trackmoney/utils/AuthUtilsTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/test/java/fun/trackmoney/utils/AuthUtilsTest.java diff --git a/src/test/java/fun/trackmoney/utils/AuthUtilsTest.java b/src/test/java/fun/trackmoney/utils/AuthUtilsTest.java new file mode 100644 index 0000000..3bf20f9 --- /dev/null +++ b/src/test/java/fun/trackmoney/utils/AuthUtilsTest.java @@ -0,0 +1,47 @@ +package fun.trackmoney.utils; + +import fun.trackmoney.user.entity.UserEntity; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +class AuthUtilsTest { + + private final AuthUtils authUtils = new AuthUtils(); + + @AfterEach + void clearContext() { + SecurityContextHolder.clearContext(); + } + + @Test + void getCurrentUser_shouldReturnUserEntity() { + // Arrange + UserEntity mockUser = new UserEntity(); + mockUser.setUserId(UUID.randomUUID()); + mockUser.setName("John Doe"); + mockUser.setEmail("john@example.com"); + + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(mockUser, null, null); + + SecurityContext context = Mockito.mock(SecurityContext.class); + Mockito.when(context.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(context); + + // Act + UserEntity result = authUtils.getCurrentUser(); + + // Assert + assertNotNull(result); + assertEquals(mockUser.getUserId(), result.getUserId()); + assertEquals(mockUser.getEmail(), result.getEmail()); + } +} From 641fb9f14d5df80dc4645fdcd8352af311e9104e Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Fri, 30 May 2025 17:39:30 -0300 Subject: [PATCH 10/13] test: add unit test for transactionService .getIncome and .getExpense --- .../service/TransactionServiceTest.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java index 7421809..083121c 100644 --- a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java +++ b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java @@ -139,4 +139,40 @@ void delete_shouldCallRepositoryDeleteById() { transactionService.delete(1); verify(transactionRepository).deleteById(1); } + + @Test + void getIncome_shouldReturnTotalIncome() { + BigDecimal totalIncome = BigDecimal.valueOf(100); + var tr1 = new TransactionEntity(); + tr1.setTransactionType(TransactionType.INCOME); + tr1.setAmount(BigDecimal.valueOf(50)); + var tr2 = new TransactionEntity(); + tr2.setAmount(BigDecimal.valueOf(50)); + tr2.setTransactionType(TransactionType.INCOME); + + var accountId = 1; + when(transactionRepository.findAllByUserEmail(accountId)).thenReturn(List.of(tr1, tr2)); + + var result = transactionService.getIncome(accountId); + + assertEquals(totalIncome, result); + } + + @Test + void getExpense_shouldReturnTotalExpense() { + BigDecimal totalIncome = BigDecimal.valueOf(100); + var tr1 = new TransactionEntity(); + tr1.setTransactionType(TransactionType.EXPENSE); + tr1.setAmount(BigDecimal.valueOf(50)); + var tr2 = new TransactionEntity(); + tr2.setAmount(BigDecimal.valueOf(50)); + tr2.setTransactionType(TransactionType.EXPENSE); + + var accountId = 1; + when(transactionRepository.findAllByUserEmail(accountId)).thenReturn(List.of(tr1, tr2)); + + var result = transactionService.getExpense(accountId); + + assertEquals(totalIncome, result); + } } From 3f1d362db1d9408947c99ab440fe9fc70c6c667c Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Sat, 31 May 2025 18:28:12 -0300 Subject: [PATCH 11/13] test: add unit test for AccountService .updateAccountBalance --- .../account/service/AccountServiceTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java b/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java index ef9ce3c..0e8f0c2 100644 --- a/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java +++ b/src/test/java/fun/trackmoney/account/service/AccountServiceTest.java @@ -135,4 +135,26 @@ void testDeleteAccountById() { verify(accountRepository, times(1)).deleteById(1); } + + @Test + void testUpdateAccountBalanceSum() { + AccountEntity account = new AccountEntity(1, null, "Test Account", BigDecimal.valueOf(100), true); + when(accountRepository.findById(1)).thenReturn(Optional.of(account)); + when(accountRepository.save(account)).thenReturn(account); + + accountService.updateAccountBalance(BigDecimal.valueOf(100), 1, true); + assertEquals(new BigDecimal("200"), account.getBalance()); + verify(accountRepository, times(1)).save(account); + } + + @Test + void testUpdateAccountBalanceSub() { + AccountEntity account = new AccountEntity(1, null, "Test Account", BigDecimal.valueOf(100), true); + when(accountRepository.findById(1)).thenReturn(Optional.of(account)); + when(accountRepository.save(account)).thenReturn(any()); + + accountService.updateAccountBalance(BigDecimal.valueOf(100), 1, false); + assertEquals(new BigDecimal("0"), account.getBalance()); + verify(accountRepository, times(1)).save(account); + } } From 4abf14ac246f47a4914fbab06a3f98ae97bb283b Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Sat, 31 May 2025 19:48:12 -0300 Subject: [PATCH 12/13] test: add unit test for TransactionController .getIncome and .getExpense --- .../controller/TransactionControllerTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java b/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java index 0dc30a3..75a9ee1 100644 --- a/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java +++ b/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java @@ -5,8 +5,10 @@ import fun.trackmoney.transaction.dto.TransactionResponseDTO; import fun.trackmoney.transaction.dto.TransactionUpdateDTO; import fun.trackmoney.transaction.service.TransactionService; +import fun.trackmoney.utils.response.ApiResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; import java.math.BigDecimal; @@ -117,4 +119,44 @@ void deleteTransaction_shouldReturnSuccessMessage() { verify(transactionService).delete(1); } + + @Test + void getIncome_shouldReturnCorrectApiResponse() { + Integer id = 1; + BigDecimal income = new BigDecimal("1200.00"); + + when(transactionService.getIncome(id)).thenReturn(income); + + var response = transactionController.getIncome(id); + + assertNotNull(response); + assertEquals(HttpStatus.OK, response.getStatusCode()); + + ApiResponse body = response.getBody(); + assertNotNull(body); + assertTrue(body.getSuccess()); + assertEquals("Get income", body.getMessage()); + assertEquals(income, body.getData()); + assertNull(body.getErrors()); + } + + @Test + void getExpense_shouldReturnCorrectApiResponse() { + Integer id = 2; + BigDecimal expense = new BigDecimal("800.00"); + + when(transactionService.getExpense(id)).thenReturn(expense); + + var response = transactionController.getExpense(id); + + assertNotNull(response); + assertEquals(HttpStatus.OK, response.getStatusCode()); + + ApiResponse body = response.getBody(); + assertNotNull(body); + assertTrue(body.getSuccess()); + assertEquals("Get expense", body.getMessage()); + assertEquals(expense, body.getData()); + assertNull(body.getErrors()); + } } From d47632edacd8a4289ded1c40a4c4a68950a4df9a Mon Sep 17 00:00:00 2001 From: Felipe Melo Date: Sat, 31 May 2025 20:22:32 -0300 Subject: [PATCH 13/13] test: adjust the unit CategoryService --- .../fun/trackmoney/category/service/CategoryServiceTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/fun/trackmoney/category/service/CategoryServiceTest.java b/src/test/java/fun/trackmoney/category/service/CategoryServiceTest.java index ed9bc0b..91747c4 100644 --- a/src/test/java/fun/trackmoney/category/service/CategoryServiceTest.java +++ b/src/test/java/fun/trackmoney/category/service/CategoryServiceTest.java @@ -54,6 +54,7 @@ void findById_shouldReturnCategory_whenIdExists() { CategoryEntity expectedCategory = new CategoryEntity(); expectedCategory.setCategoryId(categoryId); expectedCategory.setName("Food"); + expectedCategory.setColor("#fffff"); when(categoryRepository.findById(categoryId)).thenReturn(Optional.of(expectedCategory)); @@ -63,6 +64,7 @@ void findById_shouldReturnCategory_whenIdExists() { // Assert assertEquals(expectedCategory.getCategoryId(), actualCategory.getCategoryId()); assertEquals(expectedCategory.getName(), actualCategory.getName()); + assertEquals(expectedCategory.getColor(), actualCategory.getColor()); } @Test