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/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/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..c8a0d1e 100644 --- a/src/main/java/fun/trackmoney/account/service/AccountService.java +++ b/src/main/java/fun/trackmoney/account/service/AccountService.java @@ -11,7 +11,9 @@ import fun.trackmoney.user.repository.UserRepository; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.List; +import java.util.UUID; @Service public class AccountService { @@ -38,8 +40,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) { @@ -60,4 +62,17 @@ 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/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 + ) + ); + } } 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..55baca9 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, - Integer resetDay) { + Integer resetDay, + BigDecimal currentAmount) { } 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/budget/repository/BudgetsRepository.java b/src/main/java/fun/trackmoney/budget/repository/BudgetsRepository.java index 2aea451..846be5f 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 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 8121d77..815544a 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.findAllByAccountAccountId(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(), + budget.resetDay(), + currentAmount + ); + }) + .toList(); } public BudgetResponseDTO findById(Integer id) { 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/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/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/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..4dede65 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; @@ -43,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() { @@ -71,4 +80,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/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; 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..0e8f0c2 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); @@ -134,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); + } } 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()); + } } diff --git a/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java b/src/test/java/fun/trackmoney/budget/controller/BudgetsControllerTest.java index ff614bb..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 @@ -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 @@ -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 7bf4ae8..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 @@ -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)).findAllByAccountAccountId(accountEntity.getAccountId()); verify(budgetMapper, times(1)).entityListToResponseList(Collections.emptyList()); } @@ -127,19 +127,19 @@ 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); - when(budgetsRepository.findAll()).thenReturn(entities); + when(budgetsRepository.findAllByAccountAccountId(accountEntity.getAccountId())).thenReturn(entities); when(budgetMapper.entityListToResponseList(entities)).thenReturn(dtos); - List result = budgetsService.findAll(); + List result = budgetsService.findAllByAccountId(accountEntity.getAccountId()); assertNotNull(result); + assertNotNull(result.get(0).currentAmount()); assertEquals(1, result.size()); - assertEquals(dtos, result); - verify(budgetsRepository, times(1)).findAll(); + 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/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 diff --git a/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java b/src/test/java/fun/trackmoney/transaction/controller/TransactionControllerTest.java index 48e9893..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; @@ -91,7 +93,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); @@ -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()); + } } diff --git a/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java b/src/test/java/fun/trackmoney/transaction/service/TransactionServiceTest.java index 1415b3a..083121c 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)); @@ -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); + } } 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()); + } +}