diff --git a/API-Gateway/src/main/java/org/training/api/gateway/ApiGatewayApplication.java b/API-Gateway/src/main/java/org/training/api/gateway/ApiGatewayApplication.java index 5d16c71..10ecf84 100644 --- a/API-Gateway/src/main/java/org/training/api/gateway/ApiGatewayApplication.java +++ b/API-Gateway/src/main/java/org/training/api/gateway/ApiGatewayApplication.java @@ -4,10 +4,38 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +/** + * Main entry point for the API Gateway microservice. + * + *

This class bootstraps the Spring Boot application and registers it as a Eureka client + * for service discovery. The API Gateway serves as the single entry point for all client + * requests, routing them to the appropriate microservices.

+ * + *

Key responsibilities:

+ * + * + * @author Training Team + * @version 1.0 + * @see org.training.api.gateway.config.SecurityConfig + */ @SpringBootApplication @EnableEurekaClient public class ApiGatewayApplication { + /** + * Main method that starts the API Gateway application. + * + *

This method initializes the Spring application context and starts the embedded + * web server. The gateway will automatically register with the Eureka service registry + * upon startup.

+ * + * @param args command-line arguments passed to the application (typically empty) + */ public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } diff --git a/API-Gateway/src/main/java/org/training/api/gateway/config/SecurityConfig.java b/API-Gateway/src/main/java/org/training/api/gateway/config/SecurityConfig.java index a028a68..2dd8137 100644 --- a/API-Gateway/src/main/java/org/training/api/gateway/config/SecurityConfig.java +++ b/API-Gateway/src/main/java/org/training/api/gateway/config/SecurityConfig.java @@ -6,24 +6,65 @@ import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; +/** + * Security configuration class for the API Gateway. + * + *

This class configures Spring Security for the reactive web application, + * implementing OAuth2 authentication and JWT token validation. It defines + * which endpoints are publicly accessible and which require authentication.

+ * + *

Security features configured:

+ * + * + * @author Training Team + * @version 1.0 + * @see org.springframework.security.config.web.server.ServerHttpSecurity + */ @Configuration @EnableWebFluxSecurity public class SecurityConfig { + /** + * Configures the security filter chain for the API Gateway. + * + *

This method sets up the security rules for incoming HTTP requests:

+ * + * + * @param http the {@link ServerHttpSecurity} object used to configure security + * @return the configured {@link SecurityWebFilterChain} bean + */ @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { + // Configure authorization rules for different endpoints http .authorizeExchange() - //ALLOWING REGISTER API FOR DIRECT ACCESS + // Allow unauthenticated access to the registration endpoint + // so new users can create accounts .pathMatchers("/api/users/register").permitAll() - //ALL OTHER APIS ARE AUTHENTICATED + // Require authentication for all other API endpoints .anyExchange().authenticated() .and() + // Disable CSRF protection for stateless REST API + // (tokens are used instead of session cookies) .csrf().disable() + // Enable OAuth2 login for interactive authentication .oauth2Login() .and() + // Configure JWT validation for API requests .oauth2ResourceServer() .jwt(); return http.build(); } -} \ No newline at end of file +} diff --git a/API-Gateway/src/test/java/org/training/api/gateway/ApiGatewayApplicationTests.java b/API-Gateway/src/test/java/org/training/api/gateway/ApiGatewayApplicationTests.java index ebb306d..1a6bd21 100644 --- a/API-Gateway/src/test/java/org/training/api/gateway/ApiGatewayApplicationTests.java +++ b/API-Gateway/src/test/java/org/training/api/gateway/ApiGatewayApplicationTests.java @@ -5,9 +5,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * Integration tests for the API Gateway application. + * + *

This test class verifies that the Spring application context + * loads correctly with all required beans and configurations.

+ * + * @author Training Team + * @version 1.0 + */ @SpringBootTest class ApiGatewayApplicationTests { + /** + * Verifies that the Spring application context loads successfully. + * + *

This test ensures that all Spring beans are properly configured + * and the application can start without errors. A failure in this test + * typically indicates configuration issues or missing dependencies.

+ */ @Test void contextLoads() { assertTrue(true); diff --git a/Account-Service/src/main/java/org/training/account/service/AccountServiceApplication.java b/Account-Service/src/main/java/org/training/account/service/AccountServiceApplication.java index 1949174..1139222 100644 --- a/Account-Service/src/main/java/org/training/account/service/AccountServiceApplication.java +++ b/Account-Service/src/main/java/org/training/account/service/AccountServiceApplication.java @@ -4,10 +4,40 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; +/** + * Main entry point for the Account Service microservice. + * + *

This microservice manages bank account operations including account creation, + * status updates, balance inquiries, and account closure. It communicates with + * other microservices (User Service, Transaction Service, Sequence Generator) + * via Feign clients for inter-service communication.

+ * + *

Key responsibilities:

+ * + * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.service.AccountService + * @see org.training.account.service.controller.AccountController + */ @SpringBootApplication @EnableFeignClients public class AccountServiceApplication { + /** + * Main method that starts the Account Service application. + * + *

This method initializes the Spring application context, enables Feign + * clients for inter-service communication, and starts the embedded web server.

+ * + * @param args command-line arguments passed to the application (typically empty) + */ public static void main(String[] args) { SpringApplication.run(AccountServiceApplication.class, args); } diff --git a/Account-Service/src/main/java/org/training/account/service/configuration/FeignClientErrorDecoder.java b/Account-Service/src/main/java/org/training/account/service/configuration/FeignClientErrorDecoder.java index 6563d92..24f3043 100644 --- a/Account-Service/src/main/java/org/training/account/service/configuration/FeignClientErrorDecoder.java +++ b/Account-Service/src/main/java/org/training/account/service/configuration/FeignClientErrorDecoder.java @@ -13,6 +13,24 @@ import java.nio.charset.StandardCharsets; import java.util.Objects; +/** + * Custom error decoder for Feign client responses. + * + *

This class implements the Feign {@link ErrorDecoder} interface to provide + * custom error handling for HTTP responses from external services. It extracts + * error information from the response body and converts it into appropriate + * exception types.

+ * + *

The decoder handles:

+ * + * + * @author Training Team + * @version 1.0 + * @see feign.codec.ErrorDecoder + */ @Slf4j public class FeignClientErrorDecoder implements ErrorDecoder { @@ -69,4 +87,4 @@ private GlobalException extractGlobalException(Response response) { } return globalException; } -} \ No newline at end of file +} diff --git a/Account-Service/src/main/java/org/training/account/service/configuration/FeignConfiguration.java b/Account-Service/src/main/java/org/training/account/service/configuration/FeignConfiguration.java index c6cedd4..5d29f84 100644 --- a/Account-Service/src/main/java/org/training/account/service/configuration/FeignConfiguration.java +++ b/Account-Service/src/main/java/org/training/account/service/configuration/FeignConfiguration.java @@ -5,6 +5,17 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * Configuration class for Feign clients in the Account Service. + * + *

This configuration extends the default Feign client configuration and provides + * custom error handling for inter-service communication. It registers a custom + * error decoder to properly handle and translate errors from external services.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.configuration.FeignClientErrorDecoder + */ @Configuration public class FeignConfiguration extends FeignClientProperties.FeignClientConfiguration { diff --git a/Account-Service/src/main/java/org/training/account/service/controller/AccountController.java b/Account-Service/src/main/java/org/training/account/service/controller/AccountController.java index 6b01311..261cadd 100644 --- a/Account-Service/src/main/java/org/training/account/service/controller/AccountController.java +++ b/Account-Service/src/main/java/org/training/account/service/controller/AccountController.java @@ -13,12 +13,40 @@ import java.util.List; +/** + * REST controller for managing bank account operations. + * + *

This controller exposes endpoints for creating, reading, updating, and closing + * bank accounts. It handles all account-related HTTP requests and delegates business + * logic to the {@link AccountService}.

+ * + *

Base URL: /accounts

+ * + *

Available endpoints:

+ * + * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.service.AccountService + */ @Slf4j @RequiredArgsConstructor @RestController @RequestMapping("/accounts") public class AccountController { + /** + * Service for handling account business logic. + */ private final AccountService accountService; /** diff --git a/Account-Service/src/main/java/org/training/account/service/exception/AccountClosingException.java b/Account-Service/src/main/java/org/training/account/service/exception/AccountClosingException.java index 13c7bd0..da7cb5f 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/AccountClosingException.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/AccountClosingException.java @@ -1,7 +1,23 @@ package org.training.account.service.exception; +/** + * Exception thrown when an account cannot be closed. + * + *

This exception is thrown when an account closure operation fails due to + * business rule violations. For example, attempting to close an account that + * still has a non-zero balance. It results in an HTTP 400 Bad Request response.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.exception.GlobalException + */ public class AccountClosingException extends GlobalException{ + /** + * Constructs an AccountClosingException with the specified error message. + * + * @param errorMessage the detailed error message describing why the account cannot be closed + */ public AccountClosingException(String errorMessage) { super(GlobalErrorCode.BAD_REQUEST, errorMessage); } diff --git a/Account-Service/src/main/java/org/training/account/service/exception/AccountStatusException.java b/Account-Service/src/main/java/org/training/account/service/exception/AccountStatusException.java index 9949fc6..f11878e 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/AccountStatusException.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/AccountStatusException.java @@ -1,6 +1,24 @@ package org.training.account.service.exception; +/** + * Exception thrown when an account status prevents an operation. + * + *

This exception is thrown when an operation cannot be performed due to + * the current status of an account. For example, attempting to perform + * transactions on an inactive or closed account. It results in an HTTP 400 + * Bad Request response.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.exception.GlobalException + */ public class AccountStatusException extends GlobalException { + + /** + * Constructs an AccountStatusException with the specified error message. + * + * @param errorMessage the detailed error message describing the status issue + */ public AccountStatusException(String errorMessage) { super(errorMessage, GlobalErrorCode.BAD_REQUEST); } diff --git a/Account-Service/src/main/java/org/training/account/service/exception/ErrorResponse.java b/Account-Service/src/main/java/org/training/account/service/exception/ErrorResponse.java index ec37d50..664abec 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/ErrorResponse.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/ErrorResponse.java @@ -5,13 +5,29 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for error responses. + * + *

This class represents the structure of error responses returned by the API + * when an exception occurs. It provides a consistent format for error information + * that clients can parse and handle appropriately.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class ErrorResponse { + /** + * The error code (e.g., "400", "404", "409"). + */ private String errorCode; + /** + * A human-readable error message describing what went wrong. + */ private String message; } diff --git a/Account-Service/src/main/java/org/training/account/service/exception/GlobalErrorCode.java b/Account-Service/src/main/java/org/training/account/service/exception/GlobalErrorCode.java index 07b51b6..2d9758e 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/GlobalErrorCode.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/GlobalErrorCode.java @@ -1,11 +1,28 @@ package org.training.account.service.exception; +/** + * Constants class containing standard HTTP error codes used throughout the application. + * + *

This utility class provides centralized error code constants that are used + * when creating exception responses. Using constants ensures consistency across + * all error handling in the service.

+ * + * @author Training Team + * @version 1.0 + */ public class GlobalErrorCode { + /** + * Private constructor to prevent instantiation of this utility class. + */ private GlobalErrorCode() {} + /** HTTP 404 Not Found - Resource does not exist. */ public static final String NOT_FOUND = "404"; + + /** HTTP 409 Conflict - Resource already exists or state conflict. */ public static final String CONFLICT = "409"; + /** HTTP 400 Bad Request - Invalid request parameters or state. */ public static final String BAD_REQUEST = "400"; } diff --git a/Account-Service/src/main/java/org/training/account/service/exception/GlobalException.java b/Account-Service/src/main/java/org/training/account/service/exception/GlobalException.java index 4ddaafe..883e02e 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/GlobalException.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/GlobalException.java @@ -1,21 +1,53 @@ package org.training.account.service.exception; +/** + * Base exception class for all custom exceptions in the Account Service. + * + *

This runtime exception serves as the parent class for all application-specific + * exceptions. It carries an error code and message that can be used to provide + * meaningful error responses to API clients.

+ * + * @author Training Team + * @version 1.0 + */ public class GlobalException extends RuntimeException{ + /** + * The error code associated with this exception (e.g., "400", "404", "409"). + */ private final String errorCode; + /** + * A human-readable error message describing the exception. + */ private final String errorMessage; + /** + * Constructs a new GlobalException with the specified error code and message. + * + * @param errorCode the error code for this exception + * @param errorMessage the detailed error message + */ public GlobalException(String errorCode, String errorMessage) { this.errorCode = errorCode; this.errorMessage = errorMessage; } + /** + * Returns the error code associated with this exception. + * + * @return the error code + */ public String getErrorCode() { return errorCode; } + /** + * Returns the error message associated with this exception. + * + * @return the error message + */ public String getErrorMessage() { return errorMessage; } -} \ No newline at end of file +} diff --git a/Account-Service/src/main/java/org/training/account/service/exception/GlobalExceptionHandler.java b/Account-Service/src/main/java/org/training/account/service/exception/GlobalExceptionHandler.java index ac70343..5e9646c 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/GlobalExceptionHandler.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/GlobalExceptionHandler.java @@ -10,6 +10,23 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +/** + * Global exception handler for the Account Service. + * + *

This class provides centralized exception handling across all controllers + * in the Account Service. It intercepts exceptions thrown during request processing + * and converts them into appropriate HTTP responses with error details.

+ * + *

Handled exceptions:

+ * + * + * @author Training Team + * @version 1.0 + * @see org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler + */ @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { @@ -53,4 +70,4 @@ public ResponseEntity handleGlobalException(GlobalException globalExcept .message(globalException.getErrorMessage()) .build()); } -} \ No newline at end of file +} diff --git a/Account-Service/src/main/java/org/training/account/service/exception/InSufficientFunds.java b/Account-Service/src/main/java/org/training/account/service/exception/InSufficientFunds.java index 9195fe6..059cab8 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/InSufficientFunds.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/InSufficientFunds.java @@ -1,10 +1,30 @@ package org.training.account.service.exception; +/** + * Exception thrown when an account has insufficient funds for an operation. + * + *

This exception is thrown when a transaction or operation requires more + * funds than are available in the account. For example, attempting to activate + * an account without the minimum required balance of Rs.1000.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.exception.GlobalException + */ public class InSufficientFunds extends GlobalException{ + + /** + * Constructs an InSufficientFunds exception with a default message. + */ public InSufficientFunds() { super("Insufficient funds", GlobalErrorCode.NOT_FOUND); } + /** + * Constructs an InSufficientFunds exception with a custom message. + * + * @param message the detailed error message + */ public InSufficientFunds(String message) { super(message, GlobalErrorCode.NOT_FOUND); } diff --git a/Account-Service/src/main/java/org/training/account/service/exception/ResourceConflict.java b/Account-Service/src/main/java/org/training/account/service/exception/ResourceConflict.java index 4364643..4ac6bdf 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/ResourceConflict.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/ResourceConflict.java @@ -1,11 +1,30 @@ package org.training.account.service.exception; +/** + * Exception thrown when a resource conflict occurs. + * + *

This exception is thrown when an operation would create a duplicate resource + * or violate a uniqueness constraint. For example, attempting to create an account + * that already exists for a user. It results in an HTTP 409 Conflict response.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.exception.GlobalException + */ public class ResourceConflict extends GlobalException{ + /** + * Constructs a ResourceConflict exception with a default message. + */ public ResourceConflict() { super("Account already exists", GlobalErrorCode.CONFLICT); } + /** + * Constructs a ResourceConflict exception with a custom message. + * + * @param message the detailed error message + */ public ResourceConflict(String message) { super(message, GlobalErrorCode.CONFLICT); } diff --git a/Account-Service/src/main/java/org/training/account/service/exception/ResourceNotFound.java b/Account-Service/src/main/java/org/training/account/service/exception/ResourceNotFound.java index 8983a9a..eb6d325 100644 --- a/Account-Service/src/main/java/org/training/account/service/exception/ResourceNotFound.java +++ b/Account-Service/src/main/java/org/training/account/service/exception/ResourceNotFound.java @@ -1,11 +1,30 @@ package org.training.account.service.exception; +/** + * Exception thrown when a requested resource cannot be found. + * + *

This exception is thrown when an operation attempts to access a resource + * (such as an account or user) that does not exist in the system. It results + * in an HTTP 404 Not Found response.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.exception.GlobalException + */ public class ResourceNotFound extends GlobalException{ + /** + * Constructs a ResourceNotFound exception with a default message. + */ public ResourceNotFound() { super("Resource not found on the server", GlobalErrorCode.NOT_FOUND); } + /** + * Constructs a ResourceNotFound exception with a custom message. + * + * @param message the detailed error message + */ public ResourceNotFound(String message) { super(message, GlobalErrorCode.NOT_FOUND); } diff --git a/Account-Service/src/main/java/org/training/account/service/external/SequenceService.java b/Account-Service/src/main/java/org/training/account/service/external/SequenceService.java index 54238b5..e7cd68b 100644 --- a/Account-Service/src/main/java/org/training/account/service/external/SequenceService.java +++ b/Account-Service/src/main/java/org/training/account/service/external/SequenceService.java @@ -4,6 +4,18 @@ import org.springframework.web.bind.annotation.PostMapping; import org.training.account.service.model.dto.external.SequenceDto; +/** + * Feign client interface for communicating with the Sequence Generator Service. + * + *

This interface defines the contract for making HTTP requests to the Sequence Generator + * microservice. It enables the Account Service to obtain unique, sequential account numbers + * when creating new bank accounts.

+ * + *

The client is configured to use the "sequence-generator" name for service discovery.

+ * + * @author Training Team + * @version 1.0 + */ @FeignClient(name = "sequence-generator") public interface SequenceService { diff --git a/Account-Service/src/main/java/org/training/account/service/external/TransactionService.java b/Account-Service/src/main/java/org/training/account/service/external/TransactionService.java index 497582b..c98a30e 100644 --- a/Account-Service/src/main/java/org/training/account/service/external/TransactionService.java +++ b/Account-Service/src/main/java/org/training/account/service/external/TransactionService.java @@ -8,6 +8,19 @@ import java.util.List; +/** + * Feign client interface for communicating with the Transaction Service. + * + *

This interface defines the contract for making HTTP requests to the Transaction Service + * microservice. It enables the Account Service to retrieve transaction history for accounts.

+ * + *

The client is configured to use the "transaction-service" name for service discovery + * and applies custom error handling via {@link FeignConfiguration}.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.configuration.FeignConfiguration + */ @FeignClient(name = "transaction-service", configuration = FeignConfiguration.class) public interface TransactionService { diff --git a/Account-Service/src/main/java/org/training/account/service/external/UserService.java b/Account-Service/src/main/java/org/training/account/service/external/UserService.java index 447d7cd..a9b7a10 100644 --- a/Account-Service/src/main/java/org/training/account/service/external/UserService.java +++ b/Account-Service/src/main/java/org/training/account/service/external/UserService.java @@ -7,6 +7,20 @@ import org.training.account.service.configuration.FeignConfiguration; import org.training.account.service.model.dto.external.UserDto; +/** + * Feign client interface for communicating with the User Service. + * + *

This interface defines the contract for making HTTP requests to the User Service + * microservice. It uses Spring Cloud OpenFeign for declarative REST client definition, + * enabling seamless inter-service communication.

+ * + *

The client is configured to use the "user-service" name for service discovery + * and applies custom error handling via {@link FeignConfiguration}.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.configuration.FeignConfiguration + */ @FeignClient(name = "user-service", configuration = FeignConfiguration.class) public interface UserService { @@ -18,4 +32,4 @@ public interface UserService { */ @GetMapping("/api/users/{userId}") ResponseEntity readUserById(@PathVariable Long userId); -} \ No newline at end of file +} diff --git a/Account-Service/src/main/java/org/training/account/service/model/AccountStatus.java b/Account-Service/src/main/java/org/training/account/service/model/AccountStatus.java index e1a2e5b..da8c198 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/AccountStatus.java +++ b/Account-Service/src/main/java/org/training/account/service/model/AccountStatus.java @@ -1,5 +1,30 @@ package org.training.account.service.model; +/** + * Enumeration representing the possible statuses of a bank account. + * + *

An account transitions through these statuses during its lifecycle:

+ * + * + * @author Training Team + * @version 1.0 + */ public enum AccountStatus { - PENDING, ACTIVE, BLOCKED, CLOSED + + /** Account is pending activation, requires minimum balance deposit. */ + PENDING, + + /** Account is active and can perform all transactions. */ + ACTIVE, + + /** Account is blocked and cannot perform transactions. */ + BLOCKED, + + /** Account is permanently closed. */ + CLOSED } diff --git a/Account-Service/src/main/java/org/training/account/service/model/AccountType.java b/Account-Service/src/main/java/org/training/account/service/model/AccountType.java index f71bd0d..0594d03 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/AccountType.java +++ b/Account-Service/src/main/java/org/training/account/service/model/AccountType.java @@ -1,5 +1,26 @@ package org.training.account.service.model; +/** + * Enumeration representing the types of bank accounts available. + * + *

Each account type has different characteristics and rules:

+ * + * + * @author Training Team + * @version 1.0 + */ public enum AccountType { - SAVINGS_ACCOUNT, FIXED_DEPOSIT, LOAN_ACCOUNT + + /** Standard savings account for regular banking operations. */ + SAVINGS_ACCOUNT, + + /** Fixed deposit account with funds locked for a specific term. */ + FIXED_DEPOSIT, + + /** Loan account for managing loan transactions. */ + LOAN_ACCOUNT } diff --git a/Account-Service/src/main/java/org/training/account/service/model/Constants.java b/Account-Service/src/main/java/org/training/account/service/model/Constants.java index 0ee98e9..cc72e71 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/Constants.java +++ b/Account-Service/src/main/java/org/training/account/service/model/Constants.java @@ -1,9 +1,26 @@ package org.training.account.service.model; +/** + * Constants class containing application-wide constant values. + * + *

This utility class holds constant values used throughout the Account Service, + * such as the account number prefix. The class cannot be instantiated.

+ * + * @author Training Team + * @version 1.0 + */ public class Constants { + /** + * Private constructor to prevent instantiation of this utility class. + */ private Constants() { - } + + /** + * The prefix used for generating account numbers. + * All account numbers start with this prefix followed by a sequential number. + * Example: "0600140000001" + */ public static final String ACC_PREFIX = "060014"; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/dto/AccountDto.java b/Account-Service/src/main/java/org/training/account/service/model/dto/AccountDto.java index 37e75fe..94e3f01 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/dto/AccountDto.java +++ b/Account-Service/src/main/java/org/training/account/service/model/dto/AccountDto.java @@ -7,21 +7,50 @@ import java.math.BigDecimal; +/** + * Data Transfer Object for account information. + * + *

This DTO is used to transfer account data between the controller layer + * and service layer, as well as for API request/response payloads. It provides + * a simplified view of the Account entity suitable for external communication.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.model.entity.Account + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class AccountDto { + /** + * Unique identifier for the account. + */ private Long accountId; + /** + * The unique account number (e.g., "0600140000001"). + */ private String accountNumber; + /** + * The type of account as a string (SAVINGS_ACCOUNT, FIXED_DEPOSIT, LOAN_ACCOUNT). + */ private String accountType; + /** + * The current status of the account as a string (PENDING, ACTIVE, BLOCKED, CLOSED). + */ private String accountStatus; + /** + * The current available balance in the account. + */ private BigDecimal availableBalance; + /** + * The ID of the user who owns this account. + */ private Long userId; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/dto/AccountStatusUpdate.java b/Account-Service/src/main/java/org/training/account/service/model/dto/AccountStatusUpdate.java index 389bc49..706fd29 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/dto/AccountStatusUpdate.java +++ b/Account-Service/src/main/java/org/training/account/service/model/dto/AccountStatusUpdate.java @@ -3,7 +3,22 @@ import lombok.Data; import org.training.account.service.model.AccountStatus; +/** + * Data Transfer Object for account status update requests. + * + *

This DTO is used when updating the status of an existing account. + * It contains only the new status value to be applied to the account.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.model.AccountStatus + */ @Data public class AccountStatusUpdate { + + /** + * The new status to be applied to the account. + * Valid values: PENDING, ACTIVE, BLOCKED, CLOSED + */ AccountStatus accountStatus; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/dto/external/SequenceDto.java b/Account-Service/src/main/java/org/training/account/service/model/dto/external/SequenceDto.java index a74b595..8ddf1bb 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/dto/external/SequenceDto.java +++ b/Account-Service/src/main/java/org/training/account/service/model/dto/external/SequenceDto.java @@ -2,10 +2,21 @@ import lombok.Data; +/** + * Data Transfer Object representing sequence information from the Sequence Generator Service. + * + *

This DTO is used to receive sequence data from the Sequence Generator Service via Feign client. + * It contains the generated account number that will be used when creating new bank accounts.

+ * + * @author Training Team + * @version 1.0 + */ @Data public class SequenceDto { + /** Unique identifier for the sequence record. */ private long sequenceId; + /** The generated account number to be used for a new account. */ private long accountNumber; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/dto/external/TransactionResponse.java b/Account-Service/src/main/java/org/training/account/service/model/dto/external/TransactionResponse.java index 02670d9..de47ff7 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/dto/external/TransactionResponse.java +++ b/Account-Service/src/main/java/org/training/account/service/model/dto/external/TransactionResponse.java @@ -8,23 +8,39 @@ import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * Data Transfer Object representing transaction information from the Transaction Service. + * + *

This DTO is used to receive transaction data from the Transaction Service via Feign client. + * It contains the details of individual transactions associated with an account.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class TransactionResponse { + /** Unique reference ID for the transaction. */ private String referenceId; + /** The account ID associated with this transaction. */ private String accountId; + /** The type of transaction (e.g., DEPOSIT, WITHDRAWAL, TRANSFER). */ private String transactionType; + /** The amount involved in the transaction. */ private BigDecimal amount; + /** The date and time when the transaction occurred. */ private LocalDateTime localDateTime; + /** The status of the transaction (e.g., SUCCESS, FAILED, PENDING). */ private String transactionStatus; + /** Additional comments or notes about the transaction. */ private String comments; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/dto/external/UserDto.java b/Account-Service/src/main/java/org/training/account/service/model/dto/external/UserDto.java index 1ccebe5..a5a64f7 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/dto/external/UserDto.java +++ b/Account-Service/src/main/java/org/training/account/service/model/dto/external/UserDto.java @@ -5,24 +5,41 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object representing user information from the User Service. + * + *

This DTO is used to receive user data from the User Service via Feign client. + * It contains the essential user information needed by the Account Service to + * validate user existence before creating accounts.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class UserDto { + /** Unique identifier for the user. */ private Long userId; + /** User's first name. */ private String firstName; + /** User's last name. */ private String lastName; + /** User's email address. */ private String emailId; + /** User's password (typically not populated in responses). */ private String password; + /** Unique identification number assigned to the user (UUID format). */ private String identificationNumber; + /** Keycloak authentication ID linking the user to the identity provider. */ private String authId; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/dto/response/Response.java b/Account-Service/src/main/java/org/training/account/service/model/dto/response/Response.java index 3e61f0b..74c2906 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/dto/response/Response.java +++ b/Account-Service/src/main/java/org/training/account/service/model/dto/response/Response.java @@ -5,13 +5,29 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Generic response DTO for API operations. + * + *

This class represents a standard response structure for API operations + * that don't return specific data. It provides a response code and message + * to indicate the result of the operation.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Response { + /** + * The response code indicating success or failure (e.g., "200", "OK"). + */ private String responseCode; + /** + * A human-readable message describing the result of the operation. + */ private String message; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/entity/Account.java b/Account-Service/src/main/java/org/training/account/service/model/entity/Account.java index 19f9532..9128daf 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/entity/Account.java +++ b/Account-Service/src/main/java/org/training/account/service/model/entity/Account.java @@ -12,6 +12,16 @@ import java.math.BigDecimal; import java.time.LocalDate; +/** + * Entity class representing a bank account. + * + *

This entity stores all account-related information including the account number, + * type, status, balance, and associated user. It is persisted to the database and + * serves as the core data model for the Account Service.

+ * + * @author Training Team + * @version 1.0 + */ @Entity @Data @AllArgsConstructor @@ -19,22 +29,46 @@ @Builder public class Account { + /** + * Unique identifier for the account, auto-generated by the database. + */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long accountId; + /** + * The unique account number (e.g., "0600140000001"). + * Generated using the Sequence Generator service with a bank prefix. + */ private String accountNumber; + /** + * The type of account (SAVINGS_ACCOUNT, FIXED_DEPOSIT, LOAN_ACCOUNT). + */ @Enumerated(EnumType.STRING) private AccountType accountType; + /** + * The current status of the account (PENDING, ACTIVE, BLOCKED, CLOSED). + */ @Enumerated(EnumType.STRING) private AccountStatus accountStatus; + /** + * The date when the account was opened. + * Automatically set to the current date when the account is created. + */ @CreationTimestamp private LocalDate openingDate; + /** + * The current available balance in the account. + */ private BigDecimal availableBalance; + /** + * The ID of the user who owns this account. + * References the User entity in the User Service. + */ private Long userId; } diff --git a/Account-Service/src/main/java/org/training/account/service/model/mapper/AccountMapper.java b/Account-Service/src/main/java/org/training/account/service/model/mapper/AccountMapper.java index 23b846b..05a1755 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/mapper/AccountMapper.java +++ b/Account-Service/src/main/java/org/training/account/service/model/mapper/AccountMapper.java @@ -6,9 +6,29 @@ import java.util.Objects; +/** + * Mapper class for converting between {@link Account} entities and {@link AccountDto} objects. + * + *

This mapper extends {@link BaseMapper} and provides specific implementation + * for converting account data between the persistence layer (entities) and the + * API layer (DTOs). It uses Spring's BeanUtils for property copying.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.model.mapper.BaseMapper + */ public class AccountMapper extends BaseMapper { - + /** + * Converts an {@link AccountDto} to an {@link Account} entity. + * + *

Uses Spring's BeanUtils to copy properties from the DTO to a new entity. + * Returns an empty Account if the DTO is null.

+ * + * @param dto the AccountDto to convert + * @param args optional additional arguments (not used) + * @return the converted Account entity + */ @Override public Account convertToEntity(AccountDto dto, Object... args) { Account account = new Account(); @@ -18,9 +38,18 @@ public Account convertToEntity(AccountDto dto, Object... args) { return account; } + /** + * Converts an {@link Account} entity to an {@link AccountDto}. + * + *

Uses Spring's BeanUtils to copy properties from the entity to a new DTO. + * Returns an empty AccountDto if the entity is null.

+ * + * @param entity the Account entity to convert + * @param args optional additional arguments (not used) + * @return the converted AccountDto + */ @Override public AccountDto convertToDto(Account entity, Object... args) { - AccountDto accountDto = new AccountDto(); if(!Objects.isNull(entity)) { BeanUtils.copyProperties(entity, accountDto); diff --git a/Account-Service/src/main/java/org/training/account/service/model/mapper/BaseMapper.java b/Account-Service/src/main/java/org/training/account/service/model/mapper/BaseMapper.java index 3021f12..97534d0 100644 --- a/Account-Service/src/main/java/org/training/account/service/model/mapper/BaseMapper.java +++ b/Account-Service/src/main/java/org/training/account/service/model/mapper/BaseMapper.java @@ -3,24 +3,79 @@ import java.util.Collection; import java.util.List; +/** + * Abstract base class for mapping between entity and DTO objects. + * + *

This generic mapper provides a template for converting between entity objects + * (used for database persistence) and Data Transfer Objects (used for API communication). + * Concrete implementations must provide the specific conversion logic.

+ * + * @param the entity type + * @param the DTO type + * + * @author Training Team + * @version 1.0 + */ public abstract class BaseMapper { + /** + * Converts a DTO to an entity. + * + * @param dto the DTO to convert + * @param args optional additional arguments for conversion + * @return the converted entity + */ public abstract E convertToEntity(D dto, Object... args); + /** + * Converts an entity to a DTO. + * + * @param entity the entity to convert + * @param args optional additional arguments for conversion + * @return the converted DTO + */ public abstract D convertToDto(E entity, Object... args); + /** + * Converts a collection of DTOs to a collection of entities. + * + * @param dto the collection of DTOs to convert + * @param args optional additional arguments for conversion + * @return a collection of converted entities + */ public Collection convertToEntity(Collection dto, Object... args) { return dto.stream().map(d -> convertToEntity(d, args)).toList(); } + /** + * Converts a collection of entities to a collection of DTOs. + * + * @param entities the collection of entities to convert + * @param args optional additional arguments for conversion + * @return a collection of converted DTOs + */ public Collection convertToDto(Collection entities, Object... args) { return entities.stream().map(entity -> convertToDto(entity, args)).toList(); } + /** + * Converts a collection of DTOs to a list of entities. + * + * @param dto the collection of DTOs to convert + * @param args optional additional arguments for conversion + * @return a list of converted entities + */ public List convertToEntityList(Collection dto, Object... args) { return convertToEntity(dto, args).stream().toList(); } + /** + * Converts a collection of entities to a list of DTOs. + * + * @param entities the collection of entities to convert + * @param args optional additional arguments for conversion + * @return a list of converted DTOs + */ public List convertToDtoList(Collection entities, Object... args) { return convertToDto(entities, args).stream().toList(); } diff --git a/Account-Service/src/main/java/org/training/account/service/repository/AccountRepository.java b/Account-Service/src/main/java/org/training/account/service/repository/AccountRepository.java index 8184b2b..f599b12 100644 --- a/Account-Service/src/main/java/org/training/account/service/repository/AccountRepository.java +++ b/Account-Service/src/main/java/org/training/account/service/repository/AccountRepository.java @@ -6,6 +6,18 @@ import java.util.Optional; +/** + * Repository interface for managing {@link Account} entities. + * + *

This repository provides data access operations for bank accounts, + * extending JpaRepository for standard CRUD operations and adding custom + * query methods for account-specific lookups.

+ * + * @author Training Team + * @version 1.0 + * @see org.springframework.data.jpa.repository.JpaRepository + * @see org.training.account.service.model.entity.Account + */ public interface AccountRepository extends JpaRepository { /** diff --git a/Account-Service/src/main/java/org/training/account/service/service/AccountService.java b/Account-Service/src/main/java/org/training/account/service/service/AccountService.java index 0a8c590..c81c528 100644 --- a/Account-Service/src/main/java/org/training/account/service/service/AccountService.java +++ b/Account-Service/src/main/java/org/training/account/service/service/AccountService.java @@ -7,6 +7,18 @@ import java.util.List; +/** + * Service interface for bank account operations. + * + *

This interface defines the contract for all account-related business operations + * including account creation, status management, balance inquiries, and account closure. + * Implementations handle the business logic and coordinate with repositories and + * external services.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.service.implementation.AccountServiceImpl + */ public interface AccountService { /** diff --git a/Account-Service/src/main/java/org/training/account/service/service/implementation/AccountServiceImpl.java b/Account-Service/src/main/java/org/training/account/service/service/implementation/AccountServiceImpl.java index 13728fb..88f84f3 100644 --- a/Account-Service/src/main/java/org/training/account/service/service/implementation/AccountServiceImpl.java +++ b/Account-Service/src/main/java/org/training/account/service/service/implementation/AccountServiceImpl.java @@ -28,19 +28,59 @@ import static org.training.account.service.model.Constants.ACC_PREFIX; +/** + * Implementation of the {@link AccountService} interface. + * + *

This service handles all account-related business operations including + * account creation, status updates, balance inquiries, and account closure. + * It coordinates with external services (User Service, Transaction Service, + * Sequence Generator) via Feign clients.

+ * + *

Key features:

+ *
    + *
  • Validates user existence before creating accounts
  • + *
  • Generates unique account numbers using the Sequence Generator service
  • + *
  • Enforces minimum balance requirements for account activation
  • + *
  • Prevents duplicate accounts for the same user and account type
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.account.service.service.AccountService + */ @Slf4j @Service @RequiredArgsConstructor public class AccountServiceImpl implements AccountService { + /** + * Feign client for communicating with the User Service. + */ private final UserService userService; + + /** + * Repository for account data persistence operations. + */ private final AccountRepository accountRepository; + + /** + * Feign client for generating unique account numbers. + */ private final SequenceService sequenceService; + + /** + * Feign client for retrieving transaction data. + */ private final TransactionService transactionService; + /** + * Mapper for converting between Account entities and DTOs. + */ private final AccountMapper accountMapper = new AccountMapper(); - + /** + * Success response code loaded from application properties. + */ @Value("${spring.application.ok}") private String success; @@ -213,4 +253,4 @@ public AccountDto readAccountByUserId(Long userId) { return accountDto; }).orElseThrow(ResourceNotFound::new); } -} \ No newline at end of file +} diff --git a/Account-Service/src/test/java/org/training/account/service/AccountServiceApplicationTests.java b/Account-Service/src/test/java/org/training/account/service/AccountServiceApplicationTests.java index 6f3a83e..3e0bf52 100644 --- a/Account-Service/src/test/java/org/training/account/service/AccountServiceApplicationTests.java +++ b/Account-Service/src/test/java/org/training/account/service/AccountServiceApplicationTests.java @@ -5,9 +5,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * Integration tests for the Account Service application. + * + *

This test class verifies that the Spring application context + * loads correctly with all required beans and configurations.

+ * + * @author Training Team + * @version 1.0 + */ @SpringBootTest class AccountServiceApplicationTests { + /** + * Verifies that the Spring application context loads successfully. + * + *

This test ensures that all Spring beans are properly configured + * and the application can start without errors. A failure in this test + * typically indicates configuration issues or missing dependencies.

+ */ @Test void contextLoads() { assertTrue(true); diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/FundTransferApplication.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/FundTransferApplication.java index f396bc2..57d76b6 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/FundTransferApplication.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/FundTransferApplication.java @@ -4,10 +4,38 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; +/** + * Main entry point for the Fund Transfer microservice. + * + *

This microservice handles fund transfer operations between bank accounts. + * It coordinates with the Account Service for balance updates and the Transaction + * Service for recording transaction history.

+ * + *

Key responsibilities:

+ *
    + *
  • Processing internal fund transfers between accounts
  • + *
  • Validating account status and balance before transfers
  • + *
  • Recording fund transfer history
  • + *
  • Generating unique transaction references
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.fundtransfer.service.FundTransferService + * @see org.training.fundtransfer.controller.FundTransferController + */ @SpringBootApplication @EnableFeignClients public class FundTransferApplication { + /** + * Main method that starts the Fund Transfer application. + * + *

Initializes the Spring Boot application context and starts the embedded + * web server. The service registers itself with Eureka for service discovery.

+ * + * @param args command line arguments passed to the application + */ public static void main(String[] args) { SpringApplication.run(FundTransferApplication.class, args); } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientConfiguration.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientConfiguration.java index 9974be9..e455920 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientConfiguration.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientConfiguration.java @@ -5,6 +5,15 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * Configuration class for Feign clients in the Fund Transfer Service. + * + *

This configuration provides custom error handling for Feign client + * calls to other microservices (Account Service, Transaction Service).

+ * + * @author Training Team + * @version 1.0 + */ @Configuration public class FeignClientConfiguration extends FeignClientProperties.FeignClientConfiguration { diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientErrorDecoder.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientErrorDecoder.java index 93c34fe..a90e282 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientErrorDecoder.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/configuration/FeignClientErrorDecoder.java @@ -13,6 +13,16 @@ import java.nio.charset.StandardCharsets; import java.util.Objects; +/** + * Custom error decoder for Feign client responses. + * + *

This decoder intercepts error responses from Feign client calls and + * converts them into appropriate exceptions. It extracts error details + * from the response body and creates GlobalException instances.

+ * + * @author Training Team + * @version 1.0 + */ @Slf4j public class FeignClientErrorDecoder implements ErrorDecoder { diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/controller/FundTransferController.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/controller/FundTransferController.java index 95d30b2..e9a4eba 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/controller/FundTransferController.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/controller/FundTransferController.java @@ -11,11 +11,30 @@ import java.util.List; +/** + * REST controller for fund transfer operations. + * + *

This controller exposes endpoints for initiating fund transfers between accounts + * and retrieving transfer history. It handles HTTP requests and delegates business + * logic to the {@link FundTransferService}.

+ * + *

Available endpoints:

+ *
    + *
  • POST /fund-transfers - Initiate a new fund transfer
  • + *
  • GET /fund-transfers/{referenceId} - Get transfer details by reference ID
  • + *
  • GET /fund-transfers?accountId={id} - Get all transfers for an account
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.fundtransfer.service.FundTransferService + */ @RestController @RequiredArgsConstructor @RequestMapping("/fund-transfers") public class FundTransferController { + /** Service for handling fund transfer business logic. */ private final FundTransferService fundTransferService; /** diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/AccountUpdateException.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/AccountUpdateException.java index e8cc86f..651daba 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/AccountUpdateException.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/AccountUpdateException.java @@ -1,7 +1,23 @@ package org.training.fundtransfer.exception; +/** + * Exception thrown when an account cannot be updated for a fund transfer. + * + *

This exception is thrown when a transfer cannot proceed due to account + * status issues, such as the account being pending or inactive.

+ * + * @author Training Team + * @version 1.0 + */ public class AccountUpdateException extends GlobalException{ - public AccountUpdateException(String errorCode, String message) { + + /** + * Constructs an AccountUpdateException. + * + * @param message the error message describing the account update issue + * @param errorCode the error code (typically "406") + */ + public AccountUpdateException(String message, String errorCode) { super(errorCode, message); } } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ErrorResponse.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ErrorResponse.java index 0b10e39..b6f0688 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ErrorResponse.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ErrorResponse.java @@ -5,13 +5,25 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for error responses. + * + *

This class represents the structure of error responses returned by the API + * when an exception occurs. It provides a consistent format for error information + * that clients can parse and handle appropriately.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class ErrorResponse { + /** The error code (e.g., "400", "404", "406"). */ private String errorCode; + /** A human-readable error message describing what went wrong. */ private String message; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalErrorCode.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalErrorCode.java index d097f44..af95992 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalErrorCode.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalErrorCode.java @@ -1,7 +1,20 @@ package org.training.fundtransfer.exception; +/** + * Constants class containing standard HTTP error codes used throughout the Fund Transfer Service. + * + *

This utility class provides centralized error code constants that are used + * when creating exception responses. Using constants ensures consistency across + * all error handling in the service.

+ * + * @author Training Team + * @version 1.0 + */ public class GlobalErrorCode { + /** HTTP 404 Not Found - Resource does not exist. */ public static final String NOT_FOUND = "404"; + + /** HTTP 406 Not Acceptable - Request cannot be processed due to business rules. */ public static final String NOT_ACCEPTABLE = "406"; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalException.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalException.java index bc6c152..9a13d3d 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalException.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalException.java @@ -5,16 +5,33 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Base exception class for all custom exceptions in the Fund Transfer Service. + * + *

This runtime exception serves as the parent class for all application-specific + * exceptions. It carries an error code and message that can be used to provide + * meaningful error responses to API clients.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class GlobalException extends RuntimeException{ + /** The error code associated with this exception (e.g., "400", "404", "406"). */ private String errorCode; + /** A human-readable error message describing the exception. */ private String message; + /** + * Constructs a GlobalException with only a message. + * + * @param message the detailed error message + */ public GlobalException(String message) { this.message = message; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalExceptionHandler.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalExceptionHandler.java index eb5b9f8..6e6711e 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalExceptionHandler.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/GlobalExceptionHandler.java @@ -10,9 +10,20 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +/** + * Global exception handler for the Fund Transfer Service. + * + *

This class provides centralized exception handling across all controllers + * in the Fund Transfer Service. It intercepts exceptions thrown during request + * processing and converts them into appropriate HTTP responses with error details.

+ * + * @author Training Team + * @version 1.0 + */ @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + /** Error code for bad request responses (400). */ @Value("${spring.application.bad_request}") private String badRequest; diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/InsufficientBalance.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/InsufficientBalance.java index f87d5ec..de1e7f2 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/InsufficientBalance.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/InsufficientBalance.java @@ -1,7 +1,23 @@ package org.training.fundtransfer.exception; +/** + * Exception thrown when an account has insufficient balance for a fund transfer. + * + *

This exception is thrown when a transfer request cannot be completed + * because the source account does not have enough available balance.

+ * + * @author Training Team + * @version 1.0 + */ public class InsufficientBalance extends GlobalException{ - public InsufficientBalance(String errorCode, String message) { + + /** + * Constructs an InsufficientBalance exception. + * + * @param message the error message describing the insufficient balance + * @param errorCode the error code (typically "406") + */ + public InsufficientBalance(String message, String errorCode) { super(errorCode, message); } } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ResourceNotFound.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ResourceNotFound.java index a4ce694..1a504e5 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ResourceNotFound.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/exception/ResourceNotFound.java @@ -1,7 +1,23 @@ package org.training.fundtransfer.exception; +/** + * Exception thrown when a requested resource is not found. + * + *

This exception is thrown when an account or fund transfer record + * cannot be found in the system.

+ * + * @author Training Team + * @version 1.0 + */ public class ResourceNotFound extends GlobalException { - public ResourceNotFound(String errorCode, String message) { + + /** + * Constructs a ResourceNotFound exception. + * + * @param message the error message describing what was not found + * @param errorCode the error code (typically "404") + */ + public ResourceNotFound(String message, String errorCode) { super(errorCode, message); } } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/external/AccountService.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/external/AccountService.java index 932aaca..717e8a2 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/external/AccountService.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/external/AccountService.java @@ -10,6 +10,16 @@ import org.training.fundtransfer.model.dto.Account; import org.training.fundtransfer.model.dto.response.Response; +/** + * Feign client interface for communicating with the Account Service. + * + *

This client provides methods to retrieve and update account information + * as part of fund transfer operations. It uses Eureka service discovery + * to locate the Account Service.

+ * + * @author Training Team + * @version 1.0 + */ @FeignClient(name = "account-service", configuration = FeignClientConfiguration.class) public interface AccountService { diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/external/TransactionService.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/external/TransactionService.java index 8e5ff89..3bb0a5d 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/external/TransactionService.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/external/TransactionService.java @@ -11,6 +11,16 @@ import java.util.List; +/** + * Feign client interface for communicating with the Transaction Service. + * + *

This client provides methods to create transaction records as part of + * fund transfer operations. It uses Eureka service discovery to locate + * the Transaction Service.

+ * + * @author Training Team + * @version 1.0 + */ @FeignClient(name = "transaction-service", configuration = FeignClientConfiguration.class) public interface TransactionService { diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransactionStatus.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransactionStatus.java index ea48425..9ee6108 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransactionStatus.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransactionStatus.java @@ -1,6 +1,22 @@ package org.training.fundtransfer.model; +/** + * Enumeration representing the possible statuses of a fund transfer transaction. + * + * @author Training Team + * @version 1.0 + */ public enum TransactionStatus { - PENDING, PROCESSING, SUCCESS, FAILED + /** Transfer is waiting to be processed. */ + PENDING, + + /** Transfer is currently being processed. */ + PROCESSING, + + /** Transfer completed successfully. */ + SUCCESS, + + /** Transfer failed due to an error. */ + FAILED } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransferType.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransferType.java index 1676041..d584fb3 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransferType.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/TransferType.java @@ -1,6 +1,22 @@ package org.training.fundtransfer.model; +/** + * Enumeration representing the types of fund transfers supported by the system. + * + * @author Training Team + * @version 1.0 + */ public enum TransferType { - WITHDRAWAL, INTERNAL, EXTERNAL, CHEQUE + /** Cash withdrawal from an account. */ + WITHDRAWAL, + + /** Transfer between accounts within the same bank. */ + INTERNAL, + + /** Transfer to accounts in other banks. */ + EXTERNAL, + + /** Transfer via cheque deposit. */ + CHEQUE } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Account.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Account.java index dc932fc..c7dbff4 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Account.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Account.java @@ -7,21 +7,36 @@ import java.math.BigDecimal; +/** + * Data Transfer Object representing account information from the Account Service. + * + *

This DTO is used to receive account data when communicating with the + * Account Service via Feign client for fund transfer operations.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Account { + /** Unique identifier for the account. */ private Long accountId; + /** Account number used for transfers. */ private String accountNumber; + /** Type of account (e.g., SAVINGS, CHECKING). */ private String accountType; + /** Current status of the account (e.g., ACTIVE, INACTIVE). */ private String accountStatus; + /** Available balance for transfers. */ private BigDecimal availableBalance; + /** ID of the user who owns this account. */ private Long userId; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/FundTransferDto.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/FundTransferDto.java index 566b4d2..477c919 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/FundTransferDto.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/FundTransferDto.java @@ -10,23 +10,39 @@ import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * Data Transfer Object for fund transfer information. + * + *

This DTO is used to transfer fund transfer data between layers + * and in API responses.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class FundTransferDto { + /** Unique reference ID for tracking the transaction. */ private String transactionReference; + /** Account number from which funds are transferred. */ private String fromAccount; + /** Account number to which funds are transferred. */ private String toAccount; + /** Amount of money being transferred. */ private BigDecimal amount; + /** Current status of the transfer. */ private TransactionStatus status; + /** Type of transfer. */ private TransferType transferType; + /** Timestamp when the transfer was initiated. */ private LocalDateTime transferredOn; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Transaction.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Transaction.java index 999488b..2da8081 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Transaction.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/Transaction.java @@ -7,17 +7,30 @@ import java.math.BigDecimal; +/** + * Data Transfer Object for transaction information sent to the Transaction Service. + * + *

This DTO is used when creating transaction records in the Transaction Service + * as part of a fund transfer operation.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Transaction { + /** Account number associated with this transaction. */ private String accountId; + /** Type of transaction (e.g., INTERNAL_TRANSFER). */ private String transactionType; + /** Transaction amount (negative for debits, positive for credits). */ private BigDecimal amount; + /** Description of the transaction. */ private String description; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/request/FundTransferRequest.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/request/FundTransferRequest.java index 454d43f..e488326 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/request/FundTransferRequest.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/request/FundTransferRequest.java @@ -7,15 +7,27 @@ import java.math.BigDecimal; +/** + * Request DTO for initiating a fund transfer. + * + *

This DTO contains the required information to process a fund transfer + * between two accounts.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class FundTransferRequest { + /** Account number from which funds will be transferred. */ private String fromAccount; + /** Account number to which funds will be transferred. */ private String toAccount; + /** Amount of money to transfer. */ private BigDecimal amount; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/FundTransferResponse.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/FundTransferResponse.java index fa76b68..059f2a4 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/FundTransferResponse.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/FundTransferResponse.java @@ -5,13 +5,24 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Response DTO returned after a fund transfer operation. + * + *

Contains the transaction ID for tracking and a message indicating + * the result of the transfer operation.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class FundTransferResponse { + /** Unique transaction ID for tracking the transfer. */ private String transactionId; + /** Message describing the result of the transfer. */ private String message; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/Response.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/Response.java index 5312b70..e51592d 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/Response.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/dto/response/Response.java @@ -5,13 +5,24 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Generic response DTO for API operations. + * + *

This DTO provides a standard response format with a response code + * and message for various API operations.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Response { + /** Response code indicating the result (e.g., "200", "400"). */ private String responseCode; + /** Human-readable message describing the result. */ private String message; } diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/entity/FundTransfer.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/entity/FundTransfer.java index eff0c47..09ae46f 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/entity/FundTransfer.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/entity/FundTransfer.java @@ -12,6 +12,16 @@ import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * Entity class representing a fund transfer record in the banking system. + * + *

This entity stores information about fund transfers between accounts, + * including the source and destination accounts, transfer amount, status, + * and type of transfer.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @@ -19,24 +29,32 @@ @Entity public class FundTransfer { + /** Unique identifier for the fund transfer record. */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long fundTransferId; + /** Unique reference ID for tracking the transaction. */ private String transactionReference; + /** Account number from which funds are transferred. */ private String fromAccount; + /** Account number to which funds are transferred. */ private String toAccount; + /** Amount of money being transferred. */ private BigDecimal amount; + /** Current status of the transfer (PENDING, PROCESSING, SUCCESS, FAILED). */ @Enumerated(EnumType.STRING) private TransactionStatus status; + /** Type of transfer (INTERNAL, EXTERNAL, WITHDRAWAL, CHEQUE). */ @Enumerated(EnumType.STRING) private TransferType transferType; + /** Timestamp when the transfer was initiated. */ @CreationTimestamp private LocalDateTime transferredOn; -} \ No newline at end of file +} diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/BaseMapper.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/BaseMapper.java index 718eeb4..20c4032 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/BaseMapper.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/BaseMapper.java @@ -5,6 +5,18 @@ import java.util.Set; import java.util.stream.Collectors; +/** + * Abstract base class for entity-DTO mapping operations. + * + *

This class provides a generic framework for converting between entity objects + * and their corresponding Data Transfer Objects (DTOs). Concrete implementations + * must provide the specific conversion logic for their entity-DTO pairs.

+ * + * @param the entity type + * @param the DTO type + * @author Training Team + * @version 1.0 + */ public abstract class BaseMapper { /** diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/FundTransferMapper.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/FundTransferMapper.java index 98fa601..fa2b1dd 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/FundTransferMapper.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/model/mapper/FundTransferMapper.java @@ -6,6 +6,17 @@ import java.util.Objects; +/** + * Mapper class for converting between {@link FundTransfer} entities and {@link FundTransferDto} objects. + * + *

This mapper extends {@link BaseMapper} and provides specific implementation + * for converting fund transfer data between the persistence layer (entities) and + * the API layer (DTOs).

+ * + * @author Training Team + * @version 1.0 + * @see org.training.fundtransfer.model.mapper.BaseMapper + */ public class FundTransferMapper extends BaseMapper { /** diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/repository/FundTransferRepository.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/repository/FundTransferRepository.java index 7db31b3..7db0a3c 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/repository/FundTransferRepository.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/repository/FundTransferRepository.java @@ -6,6 +6,17 @@ import java.util.List; import java.util.Optional; +/** + * Repository interface for {@link FundTransfer} entity persistence operations. + * + *

This repository extends JpaRepository to provide standard CRUD operations + * and adds custom query methods for finding fund transfers by transaction + * reference and account.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.fundtransfer.model.entity.FundTransfer + */ public interface FundTransferRepository extends JpaRepository { /** diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/service/FundTransferService.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/service/FundTransferService.java index e8fe5b8..e3e3166 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/service/FundTransferService.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/service/FundTransferService.java @@ -6,6 +6,16 @@ import java.util.List; +/** + * Service interface defining fund transfer operations. + * + *

This interface defines the contract for fund transfer business operations + * including initiating transfers and retrieving transfer history.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.fundtransfer.service.implementation.FundTransferServiceImpl + */ public interface FundTransferService { /** diff --git a/Fund-Transfer/src/main/java/org/training/fundtransfer/service/implementation/FundTransferServiceImpl.java b/Fund-Transfer/src/main/java/org/training/fundtransfer/service/implementation/FundTransferServiceImpl.java index ec9b911..3b083d9 100644 --- a/Fund-Transfer/src/main/java/org/training/fundtransfer/service/implementation/FundTransferServiceImpl.java +++ b/Fund-Transfer/src/main/java/org/training/fundtransfer/service/implementation/FundTransferServiceImpl.java @@ -28,18 +28,44 @@ import java.util.Objects; import java.util.UUID; +/** + * Implementation of the {@link FundTransferService} interface. + * + *

This service handles all fund transfer business logic including validation, + * balance updates, and transaction recording. It coordinates with the Account Service + * and Transaction Service to complete transfers.

+ * + *

Key features:

+ *
    + *
  • Internal fund transfers between accounts
  • + *
  • Account status and balance validation
  • + *
  • Transaction reference generation
  • + *
  • Transfer history tracking
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.fundtransfer.service.FundTransferService + */ @Slf4j @Service @RequiredArgsConstructor public class FundTransferServiceImpl implements FundTransferService { + /** Feign client for Account Service communication. */ private final AccountService accountService; + + /** Repository for fund transfer data persistence. */ private final FundTransferRepository fundTransferRepository; + + /** Feign client for Transaction Service communication. */ private final TransactionService transactionService; + /** Response code for successful operations. */ @Value("${spring.application.ok}") private String ok; + /** Mapper for converting between FundTransfer entities and DTOs. */ private final FundTransferMapper fundTransferMapper = new FundTransferMapper(); /** diff --git a/README.md b/README.md index 178c8bc..652f742 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,452 @@ -

🌟 Spring-Boot-Microservices-Banking-Application 🌟

-

📋 Table of Contents

- -- [🔍 About](#-about) -- [🏛️ Architecture](#-architecture) -- [🚀 Microservices](#-microservices) -- [🚀 Getting Started](#-getting-started) -- [📖 Documentation](#-documentation) -- [⌚ Future Enhancement](#-future-enhancement) -- [🤝 Contribution](#-contribution) -- [📞 Contact Information](#-contact-information) - -## 🔍 About -

- The Banking Application is built using a microservices architecture, incorporating the Spring Boot framework along with other Spring technologies such as Spring Data JPA, Spring Cloud, and Spring Security, alongside tools like Maven for dependency management. These technologies play a crucial role in establishing essential components like Service Registry, API Gateway, and more.

- Moreover, they enable us to develop independent microservices such as the user service for user management, the account service for account generation and other related functionalities, the fund transfer service for various transfer operations, and the transaction service for viewing transactions and facilitating withdrawals and deposits. These technologies not only streamline development but also enhance scalability and maintainability, ensuring a robust and efficient banking system. -

- -## 🏛️ Architecture - -- **Service Registry:** The microservices uses the discovery service for service registration and service discovery, this helps the microservices to discovery and communicate with other services, without needing to hardcode the endpoints while communicating with other microservices. - -- **API Gateway:** This microservices uses the API gateway to centralize the API endpoint, where all the endpoints have common entry point to all the endpoints. The API Gateway also facilitates the Security inclusion where the Authorization and Authentication for the Application. - -- **Database per Microservice:** Each of the microservice have there own dedicated database. Here for this application for all the microservices we are incorparating the MySQL database. This helps us to isolate each of the services from each other which facilitates each services to have their own data schemas and scale each of the database when required. - - -

🚀 Microservices

- -- **👤 User Service:** The user microservice provides functionalities for user management. This includes user registration, updating user details, viewing user information, and accessing all accounts associated with the user. Additionally, this microservice handles user authentication and authorization processes. - -- **💼 Account Service:** The account microservice manages account-related APIs. It enables users to modify account details, view all accounts linked to the user profile, access transaction histories for each account, and supports the account closure process. - -- **💸 Fund Transfer Service:** The fund transfer microservice facilitates various fund transfer-related functionalities. Users can initiate fund transfers between different accounts, access detailed fund transfer records, and view specific details of any fund transfer transaction. - -- **💳 Transactions Service:** The transaction service offers a range of transaction-related services. Users can view transactions based on specific accounts or transaction reference IDs, as well as make deposits or withdrawals from their accounts. - -

🚀 Getting Started

- -To get started, follow these steps to run the application on your local application: - -- Make sure you have Java 17 installed on your system. You can download it from the official Oracle website. -- Select an Integrated Development Environment (IDE) such as Eclipse, Spring Tool Suite, or IntelliJ IDEA. Configure the IDE according to your preferences. -- Clone the repository containing the microservices onto your local system using Git. Navigate to the directory where you have cloned the repository. -- Navigate to each microservice directory within the cloned repository and run the application. You can do this by using your IDE or running specific commands depending on the build tool used (e.g., Maven or Gradle). -- Set up Keycloak for authentication and authorization. Refer to the detailed configuration guide provided [here](https://devscribbles.hashnode.dev/mastering-microservices-authentication-and-authorization-with-keycloak) for step-by-step instructions on configuring Keycloak for your microservices. -- Some microservices and APIs may depend on others being up and running. Ensure that all necessary microservices and APIs are up and functioning correctly to avoid any issues in the application workflow. - -

📖 Documentation

-

📂 Microservices Documentation

- -For detailed information about each microservice, refer to their respective README files: - -- [👤 User Service](./User-Service/README.md) -- [💼 Account Service](./Account-Service/README.md) -- [💸 Fund Transfer Service](./Fund-Transfer/README.md) -- [💳 Transactions Service](./Transaction-Service/README.md) - -

📖 API Documentation

- -For a detailed guide on API endpoints and usage instructions, explore our comprehensive [API Documentation](https://app.theneo.io/student/spring-boot-microservices-banking-application). This centralized resource offers a holistic view of the entire banking application, making it easier to understand and interact with various services. - -

📚 Java Documentation (JavaDocs)

- -Explore the linked [Java Documentation](https://kartik1502.github.io/Spring-Boot-Microservices-Banking-Application/) to delve into detailed information about classes, methods, and variables across all microservices. These resources are designed to empower developers by providing clear insights into the codebase and facilitating seamless development and maintenance tasks. - -## ⌚ Future Enhancement - -As part of our ongoing commitment to improving the banking application, we are planning several enhancements to enrich user experience and expand functionality: - -- Implementing a robust notification system will keep users informed about important account activities, such as transaction updates, account statements, and security alerts. Integration with email and SMS will ensure timely and relevant communication. -- Adding deposit and investment functionalities will enable users to manage their savings and investments directly through the banking application. Features such as fixed deposits, recurring deposits, and investment portfolio tracking will empower users to make informed financial decisions. -- and more.... - -

🤝 Contribution

- -Contributions to this project are welcome! Feel free to open issues, submit pull requests, or provide feedback to enhance the functionality and usability of this banking application. Follow the basic PR specification while creating a PR. - -Let's build a robust and efficient banking system together using Spring Boot microservices! - -Happy Banking! 🏦💰 - -

📞 Contact Information

- -If you have any questions, feedback, or need assistance with this project, please feel free to reach out to me: - -[![WhatsApp](https://img.shields.io/badge/WhatsApp-25D366?style=for-the-badge&logo=whatsapp&logoColor=white)](https://wa.me/6361921186) -[![GMAIL](https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:kartikkulkarni1411@gmail.com) - -We appreciate your interest in our project and look forward to hearing from you. Happy coding! \ No newline at end of file +# Spring Boot Microservices Banking Application + +A comprehensive banking application built using microservices architecture with Spring Boot, Spring Cloud, and Spring Security OAuth2 with Keycloak integration. + +## Table of Contents + +- [About](#about) +- [Architecture](#architecture) +- [Microservices](#microservices) +- [Project Structure](#project-structure) +- [Requirements](#requirements) +- [Installation](#installation) +- [Configuration](#configuration) +- [Running the Application](#running-the-application) +- [API Documentation](#api-documentation) +- [API Examples](#api-examples) +- [Authentication](#authentication) +- [Future Enhancements](#future-enhancements) +- [Contributing](#contributing) + +## About + +The Banking Application is built using a microservices architecture, incorporating the Spring Boot framework along with other Spring technologies such as Spring Data JPA, Spring Cloud, and Spring Security. The application provides core banking functionalities including user management, account management, fund transfers, and transaction processing. + +Key features include OAuth2/JWT authentication with Keycloak, service discovery with Eureka, centralized API routing through an API Gateway, and independent databases for each microservice ensuring data isolation and scalability. + +## Architecture + +The application follows a microservices architecture pattern with the following key components: + +**Service Registry (Eureka)**: All microservices register themselves with the Eureka server for service discovery. This enables services to communicate with each other without hardcoding endpoints, providing dynamic service location and load balancing capabilities. + +**API Gateway**: Serves as the single entry point for all client requests. It handles request routing to appropriate microservices, implements OAuth2 security with Keycloak integration, and provides centralized authentication and authorization. + +**Database per Microservice**: Each microservice maintains its own MySQL database, ensuring data isolation, independent scaling, and loose coupling between services. This pattern allows each service to evolve its data schema independently. + +**Feign Clients**: Inter-service communication is handled through declarative Feign clients with Eureka service discovery, enabling type-safe HTTP communication between microservices. + +## Microservices + +| Service | Port | Description | +|---------|------|-------------| +| Service-Registry | 8761 | Eureka server for service discovery and registration | +| API-Gateway | 8080 | Central entry point with OAuth2 security and request routing | +| User-Service | 8082 | User management, registration, and Keycloak integration | +| Account-Service | 8081 | Account creation, management, and balance operations | +| Fund-Transfer | 8083 | Fund transfer operations between accounts | +| Transaction-Service | 8084 | Transaction recording, history, deposits, and withdrawals | +| Sequence-Generator | 8085 | Generates unique sequence numbers for accounts and transactions | + +### User Service + +Manages user lifecycle including registration, profile updates, and authentication. Users are stored in both Keycloak (for credentials) and MySQL (for application data). New users require admin approval before activation. + +### Account Service + +Handles bank account operations including account creation, balance inquiries, account updates, and closure. Each account is linked to a user and maintains its own transaction history. + +### Fund Transfer Service + +Facilitates money transfers between accounts. Validates source and destination accounts, checks available balance, and creates corresponding transaction records. + +### Transaction Service + +Records all financial transactions including deposits, withdrawals, and transfers. Provides transaction history queries by account number or reference ID. + +## Project Structure + +``` +BankingMicroservices/ +|-- API-Gateway/ # API Gateway service +| +-- src/main/java/org/training/gateway/ +| |-- ApiGatewayApplication.java +| +-- configuration/ +| +-- SecurityConfig.java +|-- Service-Registry/ # Eureka Server +| +-- src/main/java/org/training/serviceregistry/ +| +-- ServiceRegistryApplication.java +|-- Sequence-Generator/ # Sequence generation service +| +-- src/main/java/org/training/sequence/ +| |-- controller/ +| |-- service/ +| |-- repository/ +| +-- model/ +|-- User-Service/ # User management service +| +-- src/main/java/org/training/user/ +| |-- controller/ +| |-- service/ +| |-- repository/ +| |-- model/ +| |-- external/ +| +-- exception/ +|-- Account-Service/ # Account management service +| +-- src/main/java/org/training/account/ +| |-- controller/ +| |-- service/ +| |-- repository/ +| |-- model/ +| |-- external/ +| +-- exception/ +|-- Fund-Transfer/ # Fund transfer service +| +-- src/main/java/org/training/fundtransfer/ +| |-- controller/ +| |-- service/ +| |-- repository/ +| |-- model/ +| |-- external/ +| +-- exception/ ++-- Transaction-Service/ # Transaction service + +-- src/main/java/org/training/transactions/ + |-- controller/ + |-- service/ + |-- repository/ + |-- model/ + |-- external/ + +-- exception/ +``` + +## Requirements + +- Java 17 or higher +- Maven 3.6+ +- MySQL 8.0+ +- Keycloak 21+ (for authentication) +- Docker (optional, for containerized deployment) + +## Installation + +1. **Clone the repository** + ```bash + git clone https://github.com/samfert-codeium/BankingMicroservices.git + cd BankingMicroservices + ``` + +2. **Set up MySQL databases** + + Create separate databases for each microservice: + ```sql + CREATE DATABASE user_service_db; + CREATE DATABASE account_service_db; + CREATE DATABASE fund_transfer_db; + CREATE DATABASE transaction_service_db; + CREATE DATABASE sequence_generator_db; + ``` + +3. **Set up Keycloak** + + - Download and start Keycloak server on port 8571 + - Create a realm named `banking-service` + - Create two clients: + - `banking-service-client`: For OAuth2 user login (authorization_code grant) + - `banking-service-api-client`: For admin operations (client_credentials grant) + +4. **Build all microservices** + ```bash + mvn clean install + ``` + +## Configuration + +Each microservice has its own `application.yml` configuration file. Key configurations include: + +**Database Configuration** (example for User-Service): +```yaml +spring: + datasource: + url: jdbc:mysql://localhost:3306/user_service_db + username: your_username + password: your_password + jpa: + hibernate: + ddl-auto: update +``` + +**Eureka Client Configuration**: +```yaml +eureka: + client: + service-url: + defaultZone: http://localhost:8761/eureka/ +``` + +**Keycloak Configuration** (API-Gateway): +```yaml +spring: + security: + oauth2: + client: + provider: + keycloak: + issuer-uri: http://localhost:8571/realms/banking-service + resourceserver: + jwt: + jwk-set-uri: http://localhost:8571/realms/banking-service/protocol/openid-connect/certs +``` + +## Running the Application + +Start the microservices in the following order: + +1. **Start Service Registry** (must be first) + ```bash + cd Service-Registry + mvn spring-boot:run + ``` + Access Eureka dashboard at: http://localhost:8761 + +2. **Start Sequence Generator** + ```bash + cd Sequence-Generator + mvn spring-boot:run + ``` + +3. **Start User Service** + ```bash + cd User-Service + mvn spring-boot:run + ``` + +4. **Start Account Service** + ```bash + cd Account-Service + mvn spring-boot:run + ``` + +5. **Start Transaction Service** + ```bash + cd Transaction-Service + mvn spring-boot:run + ``` + +6. **Start Fund Transfer Service** + ```bash + cd Fund-Transfer + mvn spring-boot:run + ``` + +7. **Start API Gateway** (start last) + ```bash + cd API-Gateway + mvn spring-boot:run + ``` + +All API requests should go through the API Gateway at http://localhost:8080 + +## API Documentation + +### User Service Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | /api/users/register | Register a new user (public) | +| GET | /api/users/{id} | Get user by ID | +| GET | /api/users | Get all users | +| PATCH | /api/users/{id} | Update user status | + +### Account Service Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | /api/accounts | Create a new account | +| GET | /api/accounts | Get account by account number | +| GET | /api/accounts/user/{userId} | Get all accounts for a user | +| PUT | /api/accounts | Update account details | +| PATCH | /api/accounts | Update account status | + +### Fund Transfer Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | /api/fund-transfers | Initiate a fund transfer | +| GET | /api/fund-transfers/{referenceId} | Get transfer by reference ID | +| GET | /api/fund-transfers | Get all fund transfers | + +### Transaction Service Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | /api/transactions | Create a transaction | +| POST | /api/transactions/internal | Create internal transfer transaction | +| GET | /api/transactions/{referenceId} | Get transaction by reference ID | +| GET | /api/transactions/account/{accountId} | Get transactions by account | + +## API Examples + +### Register a New User + +```bash +curl -X POST http://localhost:8080/api/users/register \ + -H "Content-Type: application/json" \ + -d '{ + "firstName": "John", + "lastName": "Doe", + "email": "john.doe@example.com", + "password": "SecurePass123!", + "contactNo": "+1234567890" + }' +``` + +Response: +```json +{ + "responseCode": "201", + "message": "User registered successfully. Awaiting admin approval." +} +``` + +### Create an Account + +```bash +curl -X POST http://localhost:8080/api/accounts \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "userId": 1, + "accountType": "SAVINGS", + "availableBalance": 1000.00 + }' +``` + +Response: +```json +{ + "accountId": 1, + "accountNumber": "ACC1234567890", + "accountType": "SAVINGS", + "accountStatus": "ACTIVE", + "availableBalance": 1000.00, + "userId": 1 +} +``` + +### Initiate a Fund Transfer + +```bash +curl -X POST http://localhost:8080/api/fund-transfers \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "fromAccount": "ACC1234567890", + "toAccount": "ACC0987654321", + "amount": 250.00, + "description": "Payment for services" + }' +``` + +Response: +```json +{ + "transactionId": "TXN-2024-001", + "message": "Fund transfer completed successfully" +} +``` + +### Make a Deposit + +```bash +curl -X POST http://localhost:8080/api/transactions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "accountId": "ACC1234567890", + "transactionType": "DEPOSIT", + "amount": 500.00, + "description": "Cash deposit" + }' +``` + +### Get Transaction History + +```bash +curl -X GET "http://localhost:8080/api/transactions/account/ACC1234567890" \ + -H "Authorization: Bearer " +``` + +Response: +```json +[ + { + "referenceId": "TXN-2024-001", + "accountId": "ACC1234567890", + "transactionType": "DEPOSIT", + "amount": 500.00, + "localDateTime": "2024-01-15T10:30:00", + "transactionStatus": "SUCCESS", + "comments": "Cash deposit" + } +] +``` + +## Authentication + +The application uses Keycloak for OAuth2/JWT authentication. The authentication flow works as follows: + +1. Users register through the public `/api/users/register` endpoint +2. New users are created in Keycloak with `enabled=false` and in MySQL with `status=PENDING` +3. An administrator must approve the user by updating their status to `APPROVED` +4. Upon approval, the user is enabled in Keycloak and can log in +5. Authenticated users receive a JWT token to access protected endpoints + +### User Status Flow + +``` +PENDING -> APPROVED (user can login) +PENDING -> REJECTED (user cannot login) +APPROVED -> DISABLED (user temporarily blocked) +``` + +### Obtaining an Access Token + +After admin approval, users can obtain a token through Keycloak: + +```bash +curl -X POST "http://localhost:8571/realms/banking-service/protocol/openid-connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=password" \ + -d "client_id=banking-service-client" \ + -d "username=john.doe@example.com" \ + -d "password=SecurePass123!" +``` + +## Future Enhancements + +- Notification system for transaction alerts via email and SMS +- Fixed deposits and recurring deposit functionality +- Investment portfolio management +- Mobile banking application +- Real-time transaction monitoring dashboard +- Multi-currency support +- Scheduled payments and standing orders + +## Contributing + +Contributions are welcome! Please follow these steps: + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +Please ensure your code follows the existing code style and includes appropriate Javadoc documentation. + +## License + +This project is available for educational and development purposes. + +--- + +For detailed API documentation, visit our [API Documentation Portal](https://app.theneo.io/student/spring-boot-microservices-banking-application). + +For Java documentation (Javadocs), see the [Java Documentation](https://kartik1502.github.io/Spring-Boot-Microservices-Banking-Application/) diff --git a/Sequence-Generator/src/main/java/org/training/sequence/generator/SequenceGeneratorApplication.java b/Sequence-Generator/src/main/java/org/training/sequence/generator/SequenceGeneratorApplication.java index d623b28..5ef9a9e 100644 --- a/Sequence-Generator/src/main/java/org/training/sequence/generator/SequenceGeneratorApplication.java +++ b/Sequence-Generator/src/main/java/org/training/sequence/generator/SequenceGeneratorApplication.java @@ -3,9 +3,35 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +/** + * Main entry point for the Sequence Generator microservice. + * + *

This microservice is responsible for generating unique sequential account numbers + * for the banking application. It provides a centralized service that ensures account + * numbers are unique and sequential across all account creation requests.

+ * + *

Key responsibilities:

+ *
    + *
  • Generating unique, sequential account numbers
  • + *
  • Persisting sequence state to ensure uniqueness across restarts
  • + *
  • Providing REST API for account number generation
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.sequence.generator.service.SequenceService + */ @SpringBootApplication public class SequenceGeneratorApplication { + /** + * Main method that starts the Sequence Generator application. + * + *

This method initializes the Spring application context and starts the + * embedded web server to handle sequence generation requests.

+ * + * @param args command-line arguments passed to the application (typically empty) + */ public static void main(String[] args) { SpringApplication.run(SequenceGeneratorApplication.class, args); } diff --git a/Sequence-Generator/src/main/java/org/training/sequence/generator/controller/SequenceController.java b/Sequence-Generator/src/main/java/org/training/sequence/generator/controller/SequenceController.java index 7f36e40..d9659da 100644 --- a/Sequence-Generator/src/main/java/org/training/sequence/generator/controller/SequenceController.java +++ b/Sequence-Generator/src/main/java/org/training/sequence/generator/controller/SequenceController.java @@ -7,17 +7,40 @@ import org.training.sequence.generator.model.entity.Sequence; import org.training.sequence.generator.service.SequenceService; +/** + * REST controller for sequence generation operations. + * + *

This controller exposes endpoints for generating unique account numbers. + * It serves as the entry point for other microservices (primarily the Account Service) + * to request new account numbers when creating new bank accounts.

+ * + *

Base URL: /sequence

+ * + * @author Training Team + * @version 1.0 + * @see org.training.sequence.generator.service.SequenceService + */ @RestController @RequiredArgsConstructor @RequestMapping("/sequence") public class SequenceController { + /** + * Service for handling sequence generation business logic. + */ private final SequenceService sequenceService; /** - * Generates an account number. - * - * @return The generated account number. + * Generates a new unique account number. + * + *

This endpoint creates and returns a new sequential account number. + * Each call to this endpoint increments the sequence counter and returns + * the new value, ensuring uniqueness across all generated account numbers.

+ * + *

HTTP Method: POST

+ *

URL: /sequence

+ * + * @return a {@link Sequence} object containing the newly generated account number */ @PostMapping public Sequence generateAccountNumber() { diff --git a/Sequence-Generator/src/main/java/org/training/sequence/generator/model/entity/Sequence.java b/Sequence-Generator/src/main/java/org/training/sequence/generator/model/entity/Sequence.java index 94e8170..4b1b27c 100644 --- a/Sequence-Generator/src/main/java/org/training/sequence/generator/model/entity/Sequence.java +++ b/Sequence-Generator/src/main/java/org/training/sequence/generator/model/entity/Sequence.java @@ -10,6 +10,20 @@ import javax.persistence.GenerationType; import javax.persistence.Id; +/** + * Entity class representing a sequence record for account number generation. + * + *

This entity stores the current state of the account number sequence, + * allowing the system to generate unique, sequential account numbers. + * The sequence is persisted to the database to ensure continuity across + * application restarts.

+ * + *

The entity uses a single record approach where the account number + * is incremented each time a new account is created.

+ * + * @author Training Team + * @version 1.0 + */ @Entity @Data @Builder @@ -17,9 +31,17 @@ @NoArgsConstructor public class Sequence { + /** + * The unique identifier for the sequence record. + * Auto-generated using database identity strategy. + */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long sequenceId; + /** + * The current account number in the sequence. + * This value is incremented each time a new account number is generated. + */ private long accountNumber; } diff --git a/Sequence-Generator/src/main/java/org/training/sequence/generator/reporitory/SequenceRepository.java b/Sequence-Generator/src/main/java/org/training/sequence/generator/reporitory/SequenceRepository.java index 5572149..2e2f74d 100644 --- a/Sequence-Generator/src/main/java/org/training/sequence/generator/reporitory/SequenceRepository.java +++ b/Sequence-Generator/src/main/java/org/training/sequence/generator/reporitory/SequenceRepository.java @@ -4,11 +4,39 @@ import org.springframework.data.jpa.repository.Query; import org.training.sequence.generator.model.entity.Sequence; +/** + * Repository interface for managing {@link Sequence} entities. + * + *

This repository provides data access operations for the sequence table, + * which is used to generate unique account numbers. It extends JpaRepository + * to inherit standard CRUD operations and adds custom query methods.

+ * + * @author Training Team + * @version 1.0 + * @see org.springframework.data.jpa.repository.JpaRepository + * @see org.training.sequence.generator.model.entity.Sequence + */ public interface SequenceRepository extends JpaRepository { + /** + * Counts the total number of sequence records in the database. + * + *

This method uses a custom JPQL query to count all sequence entries. + * It is useful for determining if the sequence has been initialized.

+ * + * @return the total count of sequence records + */ @Query("SELECT COUNT(s) from Sequence s") int countAll(); + /** + * Retrieves the most recent sequence record based on sequence ID. + * + *

This method finds the sequence record with the highest sequence ID, + * which represents the latest generated account number.

+ * + * @return the most recent {@link Sequence} entity, or null if none exists + */ Sequence findFirstByOrderBySequenceIdDesc(); } diff --git a/Sequence-Generator/src/main/java/org/training/sequence/generator/service/SequenceService.java b/Sequence-Generator/src/main/java/org/training/sequence/generator/service/SequenceService.java index eb61822..e78a2b3 100644 --- a/Sequence-Generator/src/main/java/org/training/sequence/generator/service/SequenceService.java +++ b/Sequence-Generator/src/main/java/org/training/sequence/generator/service/SequenceService.java @@ -2,7 +2,27 @@ import org.training.sequence.generator.model.entity.Sequence; +/** + * Service interface for sequence generation operations. + * + *

This interface defines the contract for generating unique account numbers. + * Implementations of this interface are responsible for creating and managing + * the sequence of account numbers used throughout the banking application.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.sequence.generator.service.implementation.SequenceServiceImpl + */ public interface SequenceService { + /** + * Creates and returns a new unique account number. + * + *

This method generates the next sequential account number and persists + * the updated sequence state. Each call to this method should return a + * unique, incrementing account number.

+ * + * @return a {@link Sequence} object containing the newly generated account number + */ Sequence create(); } diff --git a/Sequence-Generator/src/main/java/org/training/sequence/generator/service/implementation/SequenceServiceImpl.java b/Sequence-Generator/src/main/java/org/training/sequence/generator/service/implementation/SequenceServiceImpl.java index abad2c5..6911a68 100644 --- a/Sequence-Generator/src/main/java/org/training/sequence/generator/service/implementation/SequenceServiceImpl.java +++ b/Sequence-Generator/src/main/java/org/training/sequence/generator/service/implementation/SequenceServiceImpl.java @@ -7,24 +7,54 @@ import org.training.sequence.generator.reporitory.SequenceRepository; import org.training.sequence.generator.service.SequenceService; +/** + * Implementation of the {@link SequenceService} interface. + * + *

This service handles the generation of unique, sequential account numbers + * for the banking application. It uses a single-record approach where one + * sequence record is maintained and its account number is incremented with + * each new request.

+ * + *

The implementation ensures thread-safe generation of account numbers + * by relying on database-level operations for incrementing the sequence.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.sequence.generator.service.SequenceService + */ @Slf4j @Service @RequiredArgsConstructor public class SequenceServiceImpl implements SequenceService { + /** + * Repository for persisting and retrieving sequence data. + */ private final SequenceRepository sequenceRepository; /** - * Create a new account number. - * - * @return The newly created account number. + * Creates and returns a new unique account number. + * + *

This method implements the following logic:

+ *
    + *
  1. Attempts to find the existing sequence record with ID 1
  2. + *
  3. If found, increments the account number and saves the updated record
  4. + *
  5. If not found (first run), creates a new sequence starting at 1
  6. + *
+ * + *

The method logs the account number creation for audit purposes.

+ * + * @return a {@link Sequence} object containing the newly generated account number */ @Override public Sequence create() { - log.info("creating a account number"); + + // Try to find existing sequence record and increment it, + // or create a new one starting at 1 if this is the first request return sequenceRepository.findById(1L) .map(sequence -> { + // Increment the account number for the next account sequence.setAccountNumber(sequence.getAccountNumber() + 1); return sequenceRepository.save(sequence); }).orElseGet(() -> sequenceRepository.save(Sequence.builder().accountNumber(1L).build())); diff --git a/Service-Registry/src/main/java/org/training/service/registry/ServiceRegistryApplication.java b/Service-Registry/src/main/java/org/training/service/registry/ServiceRegistryApplication.java index 41a501d..8f6f66b 100644 --- a/Service-Registry/src/main/java/org/training/service/registry/ServiceRegistryApplication.java +++ b/Service-Registry/src/main/java/org/training/service/registry/ServiceRegistryApplication.java @@ -4,10 +4,41 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; +/** + * Main entry point for the Service Registry (Eureka Server) microservice. + * + *

This class bootstraps the Eureka Server application, which acts as the central + * service registry for the banking microservices architecture. All microservices + * register themselves with this server and use it to discover other services.

+ * + *

Key responsibilities:

+ *
    + *
  • Maintaining a registry of all available microservice instances
  • + *
  • Providing service discovery capabilities to client microservices
  • + *
  • Health monitoring of registered services
  • + *
  • Load balancing support through service instance information
  • + *
+ * + *

The Eureka Server dashboard is typically accessible at the configured port + * (default: 8761) and provides a web interface to view registered services.

+ * + * @author Training Team + * @version 1.0 + * @see org.springframework.cloud.netflix.eureka.server.EnableEurekaServer + */ @SpringBootApplication @EnableEurekaServer public class ServiceRegistryApplication { + /** + * Main method that starts the Service Registry application. + * + *

This method initializes the Spring application context and starts the + * Eureka Server. Once started, other microservices can register with this + * server and discover each other's locations.

+ * + * @param args command-line arguments passed to the application (typically empty) + */ public static void main(String[] args) { SpringApplication.run(ServiceRegistryApplication.class, args); } diff --git a/Service-Registry/src/test/java/org/training/service/registry/ServiceRegistryApplicationTests.java b/Service-Registry/src/test/java/org/training/service/registry/ServiceRegistryApplicationTests.java index c68762a..51cb0ba 100644 --- a/Service-Registry/src/test/java/org/training/service/registry/ServiceRegistryApplicationTests.java +++ b/Service-Registry/src/test/java/org/training/service/registry/ServiceRegistryApplicationTests.java @@ -5,9 +5,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * Integration tests for the Service Registry (Eureka Server) application. + * + *

This test class verifies that the Eureka Server application context + * loads correctly with all required beans and configurations.

+ * + * @author Training Team + * @version 1.0 + */ @SpringBootTest class ServiceRegistryApplicationTests { + /** + * Verifies that the Spring application context loads successfully. + * + *

This test ensures that the Eureka Server is properly configured + * and can start without errors. A failure in this test typically + * indicates configuration issues or missing dependencies.

+ */ @Test void contextLoads() { assertTrue(true); diff --git a/Transaction-Service/src/main/java/org/training/transactions/TransactionServiceApplication.java b/Transaction-Service/src/main/java/org/training/transactions/TransactionServiceApplication.java index a729304..66f76b4 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/TransactionServiceApplication.java +++ b/Transaction-Service/src/main/java/org/training/transactions/TransactionServiceApplication.java @@ -5,11 +5,39 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; +/** + * Main entry point for the Transaction Service microservice. + * + *

This microservice handles transaction recording and history for bank accounts. + * It processes deposits, withdrawals, and internal transfers, maintaining a complete + * audit trail of all financial operations.

+ * + *

Key responsibilities:

+ *
    + *
  • Recording individual transactions (deposits, withdrawals)
  • + *
  • Processing internal transfer transactions
  • + *
  • Providing transaction history by account
  • + *
  • Tracking transactions by reference ID
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.transactions.service.TransactionService + * @see org.training.transactions.controller.TransactionController + */ @SpringBootApplication @EnableFeignClients @EnableEurekaClient public class TransactionServiceApplication { + /** + * Main method that starts the Transaction Service application. + * + *

Initializes the Spring Boot application context and starts the embedded + * web server. The service registers itself with Eureka for service discovery.

+ * + * @param args command line arguments passed to the application + */ public static void main(String[] args) { SpringApplication.run(TransactionServiceApplication.class, args); } diff --git a/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientConfiguration.java b/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientConfiguration.java index dfc4b76..65fe799 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientConfiguration.java +++ b/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientConfiguration.java @@ -5,6 +5,15 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * Configuration class for Feign clients in the Transaction Service. + * + *

This configuration provides custom error handling for Feign client + * calls to other microservices (Account Service).

+ * + * @author Training Team + * @version 1.0 + */ @Configuration public class FeignClientConfiguration extends FeignClientProperties.FeignClientConfiguration { diff --git a/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientErrorDecoder.java b/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientErrorDecoder.java index 809aea1..5976a28 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientErrorDecoder.java +++ b/Transaction-Service/src/main/java/org/training/transactions/configuration/FeignClientErrorDecoder.java @@ -12,6 +12,16 @@ import java.io.Reader; import java.nio.charset.StandardCharsets; +/** + * Custom error decoder for Feign client responses. + * + *

This decoder intercepts error responses from Feign client calls and + * converts them into appropriate exceptions. It extracts error details + * from the response body and creates GlobalException instances.

+ * + * @author Training Team + * @version 1.0 + */ @Slf4j public class FeignClientErrorDecoder implements ErrorDecoder { @@ -67,4 +77,4 @@ private GlobalException extractGlobalException(Response response) { } return globalException; } -} \ No newline at end of file +} diff --git a/Transaction-Service/src/main/java/org/training/transactions/controller/TransactionController.java b/Transaction-Service/src/main/java/org/training/transactions/controller/TransactionController.java index a5de3f3..942520c 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/controller/TransactionController.java +++ b/Transaction-Service/src/main/java/org/training/transactions/controller/TransactionController.java @@ -12,12 +12,32 @@ import java.util.List; +/** + * REST controller for transaction operations. + * + *

This controller exposes endpoints for creating transactions and retrieving + * transaction history. It handles HTTP requests and delegates business logic + * to the {@link TransactionService}.

+ * + *

Available endpoints:

+ *
    + *
  • POST /transactions - Create a new transaction (deposit/withdrawal)
  • + *
  • POST /transactions/internal - Process internal transfer transactions
  • + *
  • GET /transactions?accountId={id} - Get transaction history for an account
  • + *
  • GET /transactions/{referenceId} - Get transactions by reference ID
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.transactions.service.TransactionService + */ @Slf4j @RestController @RequiredArgsConstructor @RequestMapping("/transactions") public class TransactionController { + /** Service for handling transaction business logic. */ private final TransactionService transactionService; /** diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/AccountStatusException.java b/Transaction-Service/src/main/java/org/training/transactions/exception/AccountStatusException.java index 72fedef..fa6c364 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/AccountStatusException.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/AccountStatusException.java @@ -1,7 +1,21 @@ package org.training.transactions.exception; +/** + * Exception thrown when an account status prevents a transaction. + * + *

This exception is thrown when a transaction cannot be processed + * because the account is inactive or closed.

+ * + * @author Training Team + * @version 1.0 + */ public class AccountStatusException extends GlobalException { + /** + * Constructs an AccountStatusException. + * + * @param message the error message describing the account status issue + */ public AccountStatusException(String message) { super(message, GlobalErrorCode.BAD_REQUEST); } diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/ErrorResponse.java b/Transaction-Service/src/main/java/org/training/transactions/exception/ErrorResponse.java index b84ad7c..9fcdf27 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/ErrorResponse.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/ErrorResponse.java @@ -5,13 +5,25 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for error responses. + * + *

This class represents the structure of error responses returned by the API + * when an exception occurs. It provides a consistent format for error information + * that clients can parse and handle appropriately.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class ErrorResponse { + /** The error code (e.g., "400", "404"). */ private String errorCode; + /** A human-readable error message describing what went wrong. */ private String message; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalErrorCode.java b/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalErrorCode.java index eb21ac3..3445cb1 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalErrorCode.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalErrorCode.java @@ -1,7 +1,20 @@ package org.training.transactions.exception; +/** + * Constants class containing standard HTTP error codes used throughout the Transaction Service. + * + *

This utility class provides centralized error code constants that are used + * when creating exception responses. Using constants ensures consistency across + * all error handling in the service.

+ * + * @author Training Team + * @version 1.0 + */ public class GlobalErrorCode { + /** HTTP 404 Not Found - Resource does not exist. */ public static final String NOT_FOUND = "404"; + + /** HTTP 400 Bad Request - Invalid request parameters. */ public static final String BAD_REQUEST = "400"; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalException.java b/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalException.java index ac772bd..131d368 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalException.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalException.java @@ -4,15 +4,32 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Base exception class for all custom exceptions in the Transaction Service. + * + *

This runtime exception serves as the parent class for all application-specific + * exceptions. It carries an error code and message that can be used to provide + * meaningful error responses to API clients.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor public class GlobalException extends RuntimeException { + /** The error code associated with this exception (e.g., "400", "404"). */ private String errorCode; + /** A human-readable error message describing the exception. */ private String message; + /** + * Constructs a GlobalException with only a message. + * + * @param message the detailed error message + */ public GlobalException(String message) { this.message = message; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalExceptionHandler.java b/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalExceptionHandler.java index 8db87d2..0c8d62e 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalExceptionHandler.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/GlobalExceptionHandler.java @@ -6,6 +6,16 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +/** + * Global exception handler for the Transaction Service. + * + *

This class provides centralized exception handling across all controllers + * in the Transaction Service. It intercepts exceptions thrown during request + * processing and converts them into appropriate HTTP responses with error details.

+ * + * @author Training Team + * @version 1.0 + */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/InsufficientBalance.java b/Transaction-Service/src/main/java/org/training/transactions/exception/InsufficientBalance.java index e1e91b4..e054737 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/InsufficientBalance.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/InsufficientBalance.java @@ -1,7 +1,21 @@ package org.training.transactions.exception; +/** + * Exception thrown when an account has insufficient balance for a transaction. + * + *

This exception is thrown when a withdrawal or transfer cannot be completed + * because the account does not have enough available balance.

+ * + * @author Training Team + * @version 1.0 + */ public class InsufficientBalance extends GlobalException { + /** + * Constructs an InsufficientBalance exception. + * + * @param message the error message describing the insufficient balance + */ public InsufficientBalance(String message) { super(message, GlobalErrorCode.BAD_REQUEST); } diff --git a/Transaction-Service/src/main/java/org/training/transactions/exception/ResourceNotFound.java b/Transaction-Service/src/main/java/org/training/transactions/exception/ResourceNotFound.java index 2236b55..349e535 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/exception/ResourceNotFound.java +++ b/Transaction-Service/src/main/java/org/training/transactions/exception/ResourceNotFound.java @@ -1,8 +1,23 @@ package org.training.transactions.exception; +/** + * Exception thrown when a requested resource is not found. + * + *

This exception is thrown when an account or transaction record + * cannot be found in the system.

+ * + * @author Training Team + * @version 1.0 + */ public class ResourceNotFound extends GlobalException { - public ResourceNotFound(String errorCode, String message) { + /** + * Constructs a ResourceNotFound exception. + * + * @param message the error message describing what was not found + * @param errorCode the error code (typically "404") + */ + public ResourceNotFound(String message, String errorCode) { super(errorCode, message); } } diff --git a/Transaction-Service/src/main/java/org/training/transactions/external/AccountService.java b/Transaction-Service/src/main/java/org/training/transactions/external/AccountService.java index 58a226e..675227c 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/external/AccountService.java +++ b/Transaction-Service/src/main/java/org/training/transactions/external/AccountService.java @@ -7,6 +7,16 @@ import org.training.transactions.model.external.Account; import org.training.transactions.model.response.Response; +/** + * Feign client interface for communicating with the Account Service. + * + *

This client provides methods to retrieve and update account information + * as part of transaction operations. It uses Eureka service discovery + * to locate the Account Service.

+ * + * @author Training Team + * @version 1.0 + */ @FeignClient(name = "account-service", configuration = FeignClientConfiguration.class) public interface AccountService { diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/TransactionStatus.java b/Transaction-Service/src/main/java/org/training/transactions/model/TransactionStatus.java index e2731ae..f1984ff 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/TransactionStatus.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/TransactionStatus.java @@ -1,6 +1,16 @@ package org.training.transactions.model; +/** + * Enumeration representing the possible statuses of a transaction. + * + * @author Training Team + * @version 1.0 + */ public enum TransactionStatus { - COMPLETED, PENDING + /** Transaction has been completed successfully. */ + COMPLETED, + + /** Transaction is pending processing. */ + PENDING } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/TransactionType.java b/Transaction-Service/src/main/java/org/training/transactions/model/TransactionType.java index bdd7f0d..862e372 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/TransactionType.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/TransactionType.java @@ -1,6 +1,22 @@ package org.training.transactions.model; +/** + * Enumeration representing the types of transactions supported by the system. + * + * @author Training Team + * @version 1.0 + */ public enum TransactionType { - DEPOSIT, WITHDRAWAL, INTERNAL_TRANSFER, EXTERNAL_TRANSFER + /** Money deposited into an account. */ + DEPOSIT, + + /** Money withdrawn from an account. */ + WITHDRAWAL, + + /** Transfer between accounts within the same bank. */ + INTERNAL_TRANSFER, + + /** Transfer to accounts in other banks. */ + EXTERNAL_TRANSFER } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/dto/TransactionDto.java b/Transaction-Service/src/main/java/org/training/transactions/model/dto/TransactionDto.java index de3b46c..caca88d 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/dto/TransactionDto.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/dto/TransactionDto.java @@ -8,17 +8,30 @@ import java.math.BigDecimal; +/** + * Data Transfer Object for transaction information. + * + *

This DTO is used to receive transaction data from API requests + * for creating new transactions.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class TransactionDto { + /** Account number associated with this transaction. */ private String accountId; + /** Type of transaction (DEPOSIT, WITHDRAWAL, etc.). */ private String transactionType; + /** Transaction amount. */ private BigDecimal amount; + /** Description or comments for the transaction. */ private String description; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/entity/Transaction.java b/Transaction-Service/src/main/java/org/training/transactions/model/entity/Transaction.java index fe0f837..f78910a 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/entity/Transaction.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/entity/Transaction.java @@ -12,6 +12,16 @@ import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * Entity class representing a transaction record in the banking system. + * + *

This entity stores information about financial transactions including + * deposits, withdrawals, and internal transfers. Each transaction is linked + * to an account and has a unique reference ID for tracking.

+ * + * @author Training Team + * @version 1.0 + */ @Entity @Data @AllArgsConstructor @@ -19,24 +29,32 @@ @Builder public class Transaction { + /** Unique identifier for the transaction record. */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long transactionId; + /** Unique reference ID for tracking the transaction. */ private String referenceId; + /** Account number associated with this transaction. */ private String accountId; + /** Type of transaction (DEPOSIT, WITHDRAWAL, INTERNAL_TRANSFER, etc.). */ @Enumerated(EnumType.STRING) private TransactionType transactionType; + /** Transaction amount (negative for debits, positive for credits). */ private BigDecimal amount; + /** Timestamp when the transaction was created. */ @CreationTimestamp private LocalDateTime transactionDate; + /** Current status of the transaction (COMPLETED, PENDING). */ @Enumerated(EnumType.STRING) private TransactionStatus status; + /** Additional comments or description for the transaction. */ private String comments; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/external/Account.java b/Transaction-Service/src/main/java/org/training/transactions/model/external/Account.java index 43f6b80..a971019 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/external/Account.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/external/Account.java @@ -7,21 +7,36 @@ import java.math.BigDecimal; +/** + * Data Transfer Object representing account information from the Account Service. + * + *

This DTO is used to receive account data when communicating with the + * Account Service via Feign client for transaction operations.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Account { + /** Unique identifier for the account. */ private Long accountId; + /** Account number used for transactions. */ private String accountNumber; + /** Type of account (e.g., SAVINGS, CHECKING). */ private String accountType; + /** Current status of the account (e.g., ACTIVE, INACTIVE). */ private String accountStatus; + /** Available balance for transactions. */ private BigDecimal availableBalance; + /** ID of the user who owns this account. */ private Long userId; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/mapper/BaseMapper.java b/Transaction-Service/src/main/java/org/training/transactions/model/mapper/BaseMapper.java index 3db5196..8099624 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/mapper/BaseMapper.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/mapper/BaseMapper.java @@ -4,10 +4,36 @@ import java.util.List; import java.util.stream.Collectors; +/** + * Abstract base class for entity-DTO mapping operations. + * + *

This class provides a generic framework for converting between entity objects + * and their corresponding Data Transfer Objects (DTOs). Concrete implementations + * must provide the specific conversion logic for their entity-DTO pairs.

+ * + * @param the entity type + * @param the DTO type + * @author Training Team + * @version 1.0 + */ public abstract class BaseMapper { + /** + * Converts a DTO to its corresponding entity. + * + * @param dto the DTO to convert + * @param args optional additional arguments for conversion + * @return the converted entity + */ public abstract E convertToEntity(D dto, Object... args); + /** + * Converts an entity to its corresponding DTO. + * + * @param entity the entity to convert + * @param args optional additional arguments for conversion + * @return the converted DTO + */ public abstract D convertToDto(E entity, Object... args); public Collection convertToEntity(Collection dto, Object... args) { diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/mapper/TransactionMapper.java b/Transaction-Service/src/main/java/org/training/transactions/model/mapper/TransactionMapper.java index 30eb3d2..18937f1 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/mapper/TransactionMapper.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/mapper/TransactionMapper.java @@ -6,8 +6,26 @@ import java.util.Objects; +/** + * Mapper class for converting between {@link Transaction} entities and {@link TransactionDto} objects. + * + *

This mapper extends {@link BaseMapper} and provides specific implementation + * for converting transaction data between the persistence layer (entities) and + * the API layer (DTOs).

+ * + * @author Training Team + * @version 1.0 + * @see org.training.transactions.model.mapper.BaseMapper + */ public class TransactionMapper extends BaseMapper { + /** + * Converts a {@link TransactionDto} to a {@link Transaction} entity. + * + * @param dto the TransactionDto to convert + * @param args optional additional arguments (not used) + * @return the converted Transaction entity + */ @Override public Transaction convertToEntity(TransactionDto dto, Object... args) { @@ -18,6 +36,13 @@ public Transaction convertToEntity(TransactionDto dto, Object... args) { return transaction; } + /** + * Converts a {@link Transaction} entity to a {@link TransactionDto}. + * + * @param entity the Transaction entity to convert + * @param args optional additional arguments (not used) + * @return the converted TransactionDto + */ @Override public TransactionDto convertToDto(Transaction entity, Object... args) { @@ -25,5 +50,6 @@ public TransactionDto convertToDto(Transaction entity, Object... args) { if(!Objects.isNull(entity)) { BeanUtils.copyProperties(entity, transactionDto); } - return transactionDto; } + return transactionDto; + } } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/response/Response.java b/Transaction-Service/src/main/java/org/training/transactions/model/response/Response.java index 329de48..192d5c1 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/response/Response.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/response/Response.java @@ -5,13 +5,24 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Generic response DTO for API operations. + * + *

This DTO provides a standard response format with a response code + * and message for various API operations.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Response { + /** Response code indicating the result (e.g., "200", "400"). */ private String responseCode; + /** Human-readable message describing the result. */ private String message; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/model/response/TransactionRequest.java b/Transaction-Service/src/main/java/org/training/transactions/model/response/TransactionRequest.java index 7f69080..4401679 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/model/response/TransactionRequest.java +++ b/Transaction-Service/src/main/java/org/training/transactions/model/response/TransactionRequest.java @@ -8,23 +8,39 @@ import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * Response DTO for transaction history queries. + * + *

This DTO is used to return transaction details in API responses + * when querying transaction history.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class TransactionRequest { + /** Unique reference ID for tracking the transaction. */ private String referenceId; + /** Account number associated with this transaction. */ private String accountId; + /** Type of transaction (DEPOSIT, WITHDRAWAL, etc.). */ private String transactionType; + /** Transaction amount. */ private BigDecimal amount; + /** Timestamp when the transaction occurred. */ private LocalDateTime localDateTime; + /** Current status of the transaction. */ private String transactionStatus; + /** Additional comments or description. */ private String comments; } diff --git a/Transaction-Service/src/main/java/org/training/transactions/repository/TransactionRepository.java b/Transaction-Service/src/main/java/org/training/transactions/repository/TransactionRepository.java index a5bd09c..24410e5 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/repository/TransactionRepository.java +++ b/Transaction-Service/src/main/java/org/training/transactions/repository/TransactionRepository.java @@ -5,6 +5,17 @@ import java.util.List; +/** + * Repository interface for {@link Transaction} entity persistence operations. + * + *

This repository extends JpaRepository to provide standard CRUD operations + * and adds custom query methods for finding transactions by account ID and + * reference ID.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.transactions.model.entity.Transaction + */ public interface TransactionRepository extends JpaRepository { /** diff --git a/Transaction-Service/src/main/java/org/training/transactions/service/TransactionService.java b/Transaction-Service/src/main/java/org/training/transactions/service/TransactionService.java index 7743556..12af15a 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/service/TransactionService.java +++ b/Transaction-Service/src/main/java/org/training/transactions/service/TransactionService.java @@ -6,6 +6,16 @@ import java.util.List; +/** + * Service interface defining transaction operations. + * + *

This interface defines the contract for transaction business operations + * including creating transactions and retrieving transaction history.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.transactions.service.implementation.TransactionServiceImpl + */ public interface TransactionService { /** diff --git a/Transaction-Service/src/main/java/org/training/transactions/service/implementation/TransactionServiceImpl.java b/Transaction-Service/src/main/java/org/training/transactions/service/implementation/TransactionServiceImpl.java index 6f69187..26512c4 100644 --- a/Transaction-Service/src/main/java/org/training/transactions/service/implementation/TransactionServiceImpl.java +++ b/Transaction-Service/src/main/java/org/training/transactions/service/implementation/TransactionServiceImpl.java @@ -27,16 +27,40 @@ import java.util.UUID; import java.util.stream.Collectors; +/** + * Implementation of the {@link TransactionService} interface. + * + *

This service handles all transaction business logic including creating + * transactions, processing internal transfers, and retrieving transaction history. + * It coordinates with the Account Service for balance updates.

+ * + *

Key features:

+ *
    + *
  • Deposit and withdrawal transactions
  • + *
  • Internal transfer transaction recording
  • + *
  • Account balance validation
  • + *
  • Transaction history retrieval
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.transactions.service.TransactionService + */ @Slf4j @Service @RequiredArgsConstructor public class TransactionServiceImpl implements TransactionService { + /** Repository for transaction data persistence. */ private final TransactionRepository transactionRepository; + + /** Feign client for Account Service communication. */ private final AccountService accountService; + /** Mapper for converting between Transaction entities and DTOs. */ private final TransactionMapper transactionMapper = new TransactionMapper(); + /** Response code for successful operations. */ @Value("${spring.application.ok}") private String ok; diff --git a/User-Service/src/main/java/org/training/user/service/UserServiceApplication.java b/User-Service/src/main/java/org/training/user/service/UserServiceApplication.java index 70d2cbf..37ee34d 100644 --- a/User-Service/src/main/java/org/training/user/service/UserServiceApplication.java +++ b/User-Service/src/main/java/org/training/user/service/UserServiceApplication.java @@ -5,11 +5,47 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; +/** + * Main entry point for the User Service microservice. + * + *

This microservice manages user operations including user registration, + * profile management, and status updates. It integrates with Keycloak for + * authentication and authorization, storing user credentials in Keycloak + * while maintaining application-specific user data in MySQL.

+ * + *

Key responsibilities:

+ *
    + *
  • User registration with Keycloak integration
  • + *
  • User profile management (personal information, contact details)
  • + *
  • User status management (PENDING, APPROVED, DISABLED, REJECTED)
  • + *
  • User lookup by ID, email, or account number
  • + *
  • Admin approval workflow for new user registrations
  • + *
+ * + *

The service uses a dual storage approach:

+ *
    + *
  • Keycloak: Credentials, email, verification status
  • + *
  • MySQL: Application data (userId, contactNo, identificationNumber, status, userProfile)
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.service.UserService + * @see org.training.user.service.controller.UserController + */ @SpringBootApplication @EnableFeignClients @EnableEurekaClient public class UserServiceApplication { + /** + * Main method that starts the User Service application. + * + *

Initializes the Spring Boot application context and starts the embedded + * web server. The service registers itself with Eureka for service discovery.

+ * + * @param args command line arguments passed to the application + */ public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } diff --git a/User-Service/src/main/java/org/training/user/service/config/KeyCloakManager.java b/User-Service/src/main/java/org/training/user/service/config/KeyCloakManager.java index ae9d158..4729e0b 100644 --- a/User-Service/src/main/java/org/training/user/service/config/KeyCloakManager.java +++ b/User-Service/src/main/java/org/training/user/service/config/KeyCloakManager.java @@ -4,10 +4,22 @@ import org.keycloak.admin.client.resource.RealmResource; import org.springframework.stereotype.Component; +/** + * Manager class for obtaining Keycloak client instances. + * + *

This component provides access to the Keycloak Admin Client configured + * for the banking-service realm. It abstracts the Keycloak connection details + * and provides a simple interface for services to interact with Keycloak.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.config.KeyCloakProperties + */ @Component @RequiredArgsConstructor public class KeyCloakManager { + /** Configuration properties for Keycloak connection. */ private final KeyCloakProperties keyCloakProperties; /** diff --git a/User-Service/src/main/java/org/training/user/service/config/KeyCloakProperties.java b/User-Service/src/main/java/org/training/user/service/config/KeyCloakProperties.java index 52fb3d2..3c9f8f8 100644 --- a/User-Service/src/main/java/org/training/user/service/config/KeyCloakProperties.java +++ b/User-Service/src/main/java/org/training/user/service/config/KeyCloakProperties.java @@ -6,22 +6,45 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +/** + * Configuration properties for Keycloak Admin Client. + * + *

This component holds the configuration properties needed to connect to Keycloak + * and provides a singleton instance of the Keycloak Admin Client. It uses the + * client_credentials grant type for administrative operations.

+ * + *

Configuration is loaded from application properties:

+ *
    + *
  • app.config.keycloak.server-url - Keycloak server URL
  • + *
  • app.config.keycloak.realm - The banking-service realm
  • + *
  • app.config.keycloak.client-id - Client ID for admin operations
  • + *
  • app.config.keycloak.client-secret - Client secret for authentication
  • + *
+ * + * @author Training Team + * @version 1.0 + */ @Slf4j @Component public class KeyCloakProperties { + /** Keycloak server URL (e.g., http://localhost:8571). */ @Value("${app.config.keycloak.server-url}") private String serverUrl; + /** The Keycloak realm name (banking-service). */ @Value("${app.config.keycloak.realm}") private String realm; + /** Client ID for Keycloak admin operations. */ @Value("${app.config.keycloak.client-id}") private String clientId; + /** Client secret for authentication. */ @Value("${app.config.keycloak.client-secret}") private String clientSecret; + /** Singleton instance of the Keycloak Admin Client. */ private static Keycloak keycloakInstance = null; /** diff --git a/User-Service/src/main/java/org/training/user/service/controller/UserController.java b/User-Service/src/main/java/org/training/user/service/controller/UserController.java index 1ca6139..80fcbf8 100644 --- a/User-Service/src/main/java/org/training/user/service/controller/UserController.java +++ b/User-Service/src/main/java/org/training/user/service/controller/UserController.java @@ -14,6 +14,27 @@ import java.util.List; +/** + * REST controller for user management operations. + * + *

This controller exposes endpoints for user registration, retrieval, and updates. + * It handles HTTP requests and delegates business logic to the {@link UserService}.

+ * + *

Available endpoints:

+ *
    + *
  • POST /api/users/register - Register a new user (public endpoint)
  • + *
  • GET /api/users - Retrieve all users
  • + *
  • GET /api/users/{userId} - Retrieve user by ID
  • + *
  • GET /api/users/auth/{authId} - Retrieve user by Keycloak auth ID
  • + *
  • GET /api/users/accounts/{accountId} - Retrieve user by account ID
  • + *
  • PATCH /api/users/{id} - Update user status (admin approval)
  • + *
  • PUT /api/users/{id} - Update user profile information
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.service.UserService + */ @Slf4j @RestController @RequestMapping("/api/users") diff --git a/User-Service/src/main/java/org/training/user/service/exception/EmptyFields.java b/User-Service/src/main/java/org/training/user/service/exception/EmptyFields.java index 626854b..4db8ff3 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/EmptyFields.java +++ b/User-Service/src/main/java/org/training/user/service/exception/EmptyFields.java @@ -1,6 +1,23 @@ package org.training.user.service.exception; +/** + * Exception thrown when required fields are empty or incomplete. + * + *

This exception is thrown when a user profile has empty fields that must + * be filled before certain operations (like status approval) can proceed.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.exception.GlobalException + */ public class EmptyFields extends GlobalException{ + + /** + * Constructs an EmptyFields exception with the specified message and error code. + * + * @param message the detailed error message + * @param errorCode the error code for this exception + */ public EmptyFields(String message, String errorCode) { super(message, errorCode); } diff --git a/User-Service/src/main/java/org/training/user/service/exception/ErrorResponse.java b/User-Service/src/main/java/org/training/user/service/exception/ErrorResponse.java index c1c0f8f..4806e4d 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/ErrorResponse.java +++ b/User-Service/src/main/java/org/training/user/service/exception/ErrorResponse.java @@ -5,13 +5,25 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for error responses. + * + *

This class represents the structure of error responses returned by the API + * when an exception occurs. It provides a consistent format for error information + * that clients can parse and handle appropriately.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class ErrorResponse { + /** The error code (e.g., "400", "404", "409"). */ private String errorCode; + /** A human-readable error message describing what went wrong. */ private String errorMessage; } diff --git a/User-Service/src/main/java/org/training/user/service/exception/GlobalError.java b/User-Service/src/main/java/org/training/user/service/exception/GlobalError.java index bda280e..e69d8ba 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/GlobalError.java +++ b/User-Service/src/main/java/org/training/user/service/exception/GlobalError.java @@ -1,6 +1,17 @@ package org.training.user.service.exception; +/** + * Constants class containing standard HTTP error codes used throughout the User Service. + * + *

This utility class provides centralized error code constants that are used + * when creating exception responses. Using constants ensures consistency across + * all error handling in the service.

+ * + * @author Training Team + * @version 1.0 + */ public class GlobalError { + /** HTTP 404 Not Found - Resource does not exist. */ public static final String NOT_FOUND = "404"; } diff --git a/User-Service/src/main/java/org/training/user/service/exception/GlobalException.java b/User-Service/src/main/java/org/training/user/service/exception/GlobalException.java index 686fe2a..4740a65 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/GlobalException.java +++ b/User-Service/src/main/java/org/training/user/service/exception/GlobalException.java @@ -4,15 +4,32 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Base exception class for all custom exceptions in the User Service. + * + *

This runtime exception serves as the parent class for all application-specific + * exceptions. It carries an error code and message that can be used to provide + * meaningful error responses to API clients.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor public class GlobalException extends RuntimeException{ + /** A human-readable error message describing the exception. */ private String message; + /** The error code associated with this exception (e.g., "400", "404", "409"). */ private String errorCode; + /** + * Constructs a GlobalException with only a message. + * + * @param message the detailed error message + */ public GlobalException(String message) { this.message = message; } diff --git a/User-Service/src/main/java/org/training/user/service/exception/GlobalExceptionHandler.java b/User-Service/src/main/java/org/training/user/service/exception/GlobalExceptionHandler.java index 6b555af..8f61d0a 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/GlobalExceptionHandler.java +++ b/User-Service/src/main/java/org/training/user/service/exception/GlobalExceptionHandler.java @@ -10,15 +10,35 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +/** + * Global exception handler for the User Service. + * + *

This class provides centralized exception handling across all controllers + * in the User Service. It intercepts exceptions thrown during request processing + * and converts them into appropriate HTTP responses with error details.

+ * + *

Handled exceptions:

+ *
    + *
  • {@link MethodArgumentNotValidException} - Validation errors
  • + *
  • {@link GlobalException} - Custom application exceptions
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler + */ @RestControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + /** Error code for bad request responses (400). */ @Value("${spring.application.bad_request}") private String errorCodeBadRequest; + /** Error code for conflict responses (409). */ @Value("${spring.application.conflict}") private String errorCodeConflict; + /** Error code for not found responses (404). */ @Value("${spring.application.not_found}") private String errorCodeNotFound; diff --git a/User-Service/src/main/java/org/training/user/service/exception/ResourceConflictException.java b/User-Service/src/main/java/org/training/user/service/exception/ResourceConflictException.java index 2d163e7..7ebc607 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/ResourceConflictException.java +++ b/User-Service/src/main/java/org/training/user/service/exception/ResourceConflictException.java @@ -1,23 +1,29 @@ package org.training.user.service.exception; +/** + * Exception thrown when a resource conflict occurs. + * + *

This exception is thrown when an operation would create a duplicate resource + * or violate a uniqueness constraint. For example, attempting to register a user + * with an email that is already registered. It results in an HTTP 409 Conflict response.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.exception.GlobalException + */ public class ResourceConflictException extends GlobalException{ /** - * Constructs a new runtime exception with {@code null} as its - * detail message. The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause}. + * Constructs a ResourceConflictException with a default message. */ public ResourceConflictException() { super("Resource already present on the server!!!"); } /** - * Constructs a new runtime exception with the specified detail message. - * The cause is not initialized, and may subsequently be initialized by a - * call to {@link #initCause}. + * Constructs a ResourceConflictException with a custom message. * - * @param message the detail message. The detail message is saved for - * later retrieval by the {@link #getMessage()} method. + * @param message the detailed error message */ public ResourceConflictException(String message) { super(message); diff --git a/User-Service/src/main/java/org/training/user/service/exception/ResourceNotFound.java b/User-Service/src/main/java/org/training/user/service/exception/ResourceNotFound.java index 8d9d6b8..7f0a75f 100644 --- a/User-Service/src/main/java/org/training/user/service/exception/ResourceNotFound.java +++ b/User-Service/src/main/java/org/training/user/service/exception/ResourceNotFound.java @@ -1,11 +1,30 @@ package org.training.user.service.exception; +/** + * Exception thrown when a requested resource cannot be found. + * + *

This exception is thrown when an operation attempts to access a resource + * (such as a user) that does not exist in the system. It results in an + * HTTP 404 Not Found response.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.exception.GlobalException + */ public class ResourceNotFound extends GlobalException{ + /** + * Constructs a ResourceNotFound exception with a default message. + */ public ResourceNotFound() { super("Resource not found on the server", GlobalError.NOT_FOUND); } + /** + * Constructs a ResourceNotFound exception with a custom message. + * + * @param message the detailed error message + */ public ResourceNotFound(String message) { super(message, GlobalError.NOT_FOUND); } diff --git a/User-Service/src/main/java/org/training/user/service/external/AccountService.java b/User-Service/src/main/java/org/training/user/service/external/AccountService.java index b9e50c3..03567e2 100644 --- a/User-Service/src/main/java/org/training/user/service/external/AccountService.java +++ b/User-Service/src/main/java/org/training/user/service/external/AccountService.java @@ -7,6 +7,17 @@ import org.springframework.web.bind.annotation.RequestParam; import org.training.user.service.model.external.Account; +/** + * Feign client interface for communicating with the Account Service. + * + *

This interface defines the contract for making HTTP requests to the Account Service + * microservice. It enables the User Service to retrieve account information for users.

+ * + *

The client is configured to use the "account-service" name for service discovery.

+ * + * @author Training Team + * @version 1.0 + */ @FeignClient(name = "account-service", configuration = FeignClientProperties.FeignClientConfiguration.class) public interface AccountService { diff --git a/User-Service/src/main/java/org/training/user/service/model/Status.java b/User-Service/src/main/java/org/training/user/service/model/Status.java index 15c804a..074fe84 100644 --- a/User-Service/src/main/java/org/training/user/service/model/Status.java +++ b/User-Service/src/main/java/org/training/user/service/model/Status.java @@ -1,6 +1,26 @@ package org.training.user.service.model; +/** + * Enumeration representing the possible statuses of a user account. + * + *

Users follow an approval workflow where they start as PENDING after registration + * and must be approved by an administrator to become APPROVED. Users can also be + * DISABLED or REJECTED.

+ * + * @author Training Team + * @version 1.0 + */ public enum Status { - PENDING, APPROVED, DISABLED, REJECTED + /** User is awaiting admin approval after registration. */ + PENDING, + + /** User has been approved and can access the system. */ + APPROVED, + + /** User account has been disabled by an administrator. */ + DISABLED, + + /** User registration has been rejected by an administrator. */ + REJECTED } diff --git a/User-Service/src/main/java/org/training/user/service/model/dto/CreateUser.java b/User-Service/src/main/java/org/training/user/service/model/dto/CreateUser.java index 40fb0ba..7ebe054 100644 --- a/User-Service/src/main/java/org/training/user/service/model/dto/CreateUser.java +++ b/User-Service/src/main/java/org/training/user/service/model/dto/CreateUser.java @@ -5,19 +5,33 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for user registration requests. + * + *

This DTO contains the information required to create a new user account. + * It is used by the public registration endpoint (/api/users/register).

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class CreateUser { + /** User's first name. */ private String firstName; + /** User's last name. */ private String lastName; + /** User's contact phone number. */ private String contactNumber; + /** User's email address (used as username in Keycloak). */ private String emailId; + /** User's password for authentication. */ private String password; } diff --git a/User-Service/src/main/java/org/training/user/service/model/dto/UserDto.java b/User-Service/src/main/java/org/training/user/service/model/dto/UserDto.java index 8633423..faae34c 100644 --- a/User-Service/src/main/java/org/training/user/service/model/dto/UserDto.java +++ b/User-Service/src/main/java/org/training/user/service/model/dto/UserDto.java @@ -6,23 +6,39 @@ import lombok.NoArgsConstructor; import org.training.user.service.model.Status; +/** + * Data Transfer Object for user information. + * + *

This DTO is used to transfer user data between layers and to external services. + * It contains the essential user information including profile details.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class UserDto { + /** Unique identifier for the user. */ private Long userId; + /** User's email address. */ private String emailId; + /** User's password (typically not populated in responses). */ private String password; + /** Unique identification number (UUID) assigned at registration. */ private String identificationNumber; + /** Keycloak authentication ID. */ private String authId; + /** Current status of the user account. */ private Status status; + /** User's profile information. */ private UserProfileDto userProfileDto; } diff --git a/User-Service/src/main/java/org/training/user/service/model/dto/UserProfileDto.java b/User-Service/src/main/java/org/training/user/service/model/dto/UserProfileDto.java index 3cc980c..c29cc47 100644 --- a/User-Service/src/main/java/org/training/user/service/model/dto/UserProfileDto.java +++ b/User-Service/src/main/java/org/training/user/service/model/dto/UserProfileDto.java @@ -5,23 +5,40 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for user profile information. + * + *

This DTO contains the user's personal profile information that is stored + * separately from authentication data. It is used in API responses and + * nested within UserDto.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class UserProfileDto { + /** User's first name. */ private String firstName; + /** User's last name. */ private String lastName; + /** User's gender. */ private String gender; + /** User's residential address. */ private String address; + /** User's occupation or profession. */ private String occupation; + /** User's marital status. */ private String martialStatus; + /** User's nationality. */ private String nationality; } diff --git a/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdate.java b/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdate.java index e2ec1f4..3876f8a 100644 --- a/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdate.java +++ b/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdate.java @@ -5,25 +5,42 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Data Transfer Object for user profile update requests. + * + *

This DTO contains the fields that can be updated for an existing user's profile. + * It is used by the PUT /api/users/{id} endpoint.

+ * + * @author Training Team + * @version 1.0 + */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class UserUpdate { + /** User's first name. */ private String firstName; + /** User's last name. */ private String lastName; + /** User's contact phone number. */ private String contactNo; + /** User's residential address. */ private String address; + /** User's gender. */ private String gender; + /** User's occupation or profession. */ private String occupation; + /** User's marital status. */ private String martialStatus; + /** User's nationality. */ private String nationality; } diff --git a/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdateStatus.java b/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdateStatus.java index 5c65516..57ec3c2 100644 --- a/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdateStatus.java +++ b/User-Service/src/main/java/org/training/user/service/model/dto/UserUpdateStatus.java @@ -6,11 +6,23 @@ import lombok.NoArgsConstructor; import org.training.user.service.model.Status; +/** + * Data Transfer Object for user status update requests. + * + *

This DTO is used by administrators to update a user's status, typically + * for approving or rejecting user registrations. It is used by the + * PATCH /api/users/{id} endpoint.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.model.Status + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class UserUpdateStatus { + /** The new status to set for the user. */ private Status status; } diff --git a/User-Service/src/main/java/org/training/user/service/model/dto/response/Response.java b/User-Service/src/main/java/org/training/user/service/model/dto/response/Response.java index bb4a580..6865cd9 100644 --- a/User-Service/src/main/java/org/training/user/service/model/dto/response/Response.java +++ b/User-Service/src/main/java/org/training/user/service/model/dto/response/Response.java @@ -5,13 +5,25 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Generic response DTO for API operations. + * + *

This class represents a standard response structure for API operations + * that don't return specific data. It provides a response code and message + * to indicate the result of the operation.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Response { + /** The response code indicating success or failure (e.g., "200", "OK"). */ private String responseCode; + /** A human-readable message describing the result of the operation. */ private String responseMessage; } diff --git a/User-Service/src/main/java/org/training/user/service/model/entity/User.java b/User-Service/src/main/java/org/training/user/service/model/entity/User.java index cf0de9c..fb8df18 100644 --- a/User-Service/src/main/java/org/training/user/service/model/entity/User.java +++ b/User-Service/src/main/java/org/training/user/service/model/entity/User.java @@ -10,6 +10,22 @@ import javax.persistence.*; import java.time.LocalDate; +/** + * Entity class representing a user in the banking system. + * + *

This entity stores application-specific user data in MySQL. User credentials + * and authentication data are stored separately in Keycloak, linked via the authId field.

+ * + *

The dual storage approach separates concerns:

+ *
    + *
  • Keycloak: Credentials, email verification, enabled status
  • + *
  • MySQL (this entity): Contact info, identification, status, profile
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.model.entity.UserProfile + */ @Entity @AllArgsConstructor @NoArgsConstructor @@ -17,25 +33,33 @@ @Data public class User { + /** Unique identifier for the user (auto-generated). */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long userId; + /** User's email address (also stored in Keycloak). */ private String emailId; + /** User's contact phone number. */ private String contactNo; + /** Keycloak authentication ID linking to the identity provider. */ private String authId; + /** Unique identification number (UUID) assigned at registration. */ private String identificationNumber; + /** Date when the user account was created. */ @CreationTimestamp private LocalDate creationOn; + /** Current status of the user (PENDING, APPROVED, DISABLED, REJECTED). */ @Enumerated(EnumType.STRING) private Status status; + /** User's profile containing additional personal information. */ @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "user_profile_id", referencedColumnName = "userProfileId") private UserProfile userProfile; -} \ No newline at end of file +} diff --git a/User-Service/src/main/java/org/training/user/service/model/entity/UserProfile.java b/User-Service/src/main/java/org/training/user/service/model/entity/UserProfile.java index e0a983f..f6c21bf 100644 --- a/User-Service/src/main/java/org/training/user/service/model/entity/UserProfile.java +++ b/User-Service/src/main/java/org/training/user/service/model/entity/UserProfile.java @@ -10,6 +10,16 @@ import javax.persistence.GenerationType; import javax.persistence.Id; +/** + * Entity class representing a user's profile information. + * + *

This entity stores additional personal information about a user that is not + * required for authentication. It has a one-to-one relationship with the User entity.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.model.entity.User + */ @Entity @Data @AllArgsConstructor @@ -17,21 +27,29 @@ @Builder public class UserProfile { + /** Unique identifier for the user profile (auto-generated). */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long userProfileId; + /** User's first name. */ private String firstName; + /** User's last name. */ private String lastName; + /** User's gender. */ private String gender; + /** User's residential address. */ private String address; + /** User's occupation or profession. */ private String occupation; + /** User's marital status. */ private String martialStatus; + /** User's nationality. */ private String nationality; } diff --git a/User-Service/src/main/java/org/training/user/service/model/external/Account.java b/User-Service/src/main/java/org/training/user/service/model/external/Account.java index a73e0c2..5fefc39 100644 --- a/User-Service/src/main/java/org/training/user/service/model/external/Account.java +++ b/User-Service/src/main/java/org/training/user/service/model/external/Account.java @@ -7,21 +7,36 @@ import java.math.BigDecimal; +/** + * Data Transfer Object representing account information from the Account Service. + * + *

This DTO is used to receive account data from the Account Service via Feign client. + * It contains the essential account information needed by the User Service.

+ * + * @author Training Team + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Account { + /** Unique identifier for the account. */ private Long accountId; + /** The account number (unique identifier for banking operations). */ private String accountNumber; + /** The type of account (e.g., SAVINGS, CURRENT). */ private String accountType; + /** The current status of the account (e.g., ACTIVE, BLOCKED, CLOSED). */ private String accountStatus; + /** The available balance in the account. */ private BigDecimal availableBalance; + /** The ID of the user who owns this account. */ private Long userId; } diff --git a/User-Service/src/main/java/org/training/user/service/model/mapper/BaseMapper.java b/User-Service/src/main/java/org/training/user/service/model/mapper/BaseMapper.java index 89934d1..02c2249 100644 --- a/User-Service/src/main/java/org/training/user/service/model/mapper/BaseMapper.java +++ b/User-Service/src/main/java/org/training/user/service/model/mapper/BaseMapper.java @@ -5,10 +5,36 @@ import java.util.Set; import java.util.stream.Collectors; +/** + * Abstract base class for entity-DTO mapping operations. + * + *

This class provides a generic framework for converting between entity objects + * and their corresponding Data Transfer Objects (DTOs). Concrete implementations + * must provide the specific conversion logic for their entity-DTO pairs.

+ * + * @param the entity type + * @param the DTO type + * @author Training Team + * @version 1.0 + */ public abstract class BaseMapper { + /** + * Converts a DTO to its corresponding entity. + * + * @param dto the DTO to convert + * @param args optional additional arguments for conversion + * @return the converted entity + */ public abstract E convertToEntity(D dto, Object... args); + /** + * Converts an entity to its corresponding DTO. + * + * @param entity the entity to convert + * @param args optional additional arguments for conversion + * @return the converted DTO + */ public abstract D convertToDto(E entity, Object... args); public Collection convertToEntity(Collection dto, Object... args) { diff --git a/User-Service/src/main/java/org/training/user/service/model/mapper/UserMapper.java b/User-Service/src/main/java/org/training/user/service/model/mapper/UserMapper.java index 9ddbff9..08abea1 100644 --- a/User-Service/src/main/java/org/training/user/service/model/mapper/UserMapper.java +++ b/User-Service/src/main/java/org/training/user/service/model/mapper/UserMapper.java @@ -9,10 +9,32 @@ import java.util.Objects; +/** + * Mapper class for converting between {@link User} entities and {@link UserDto} objects. + * + *

This mapper extends {@link BaseMapper} and provides specific implementation + * for converting user data between the persistence layer (entities) and the + * API layer (DTOs). It handles nested UserProfile conversion as well.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.model.mapper.BaseMapper + */ public class UserMapper extends BaseMapper{ + /** ModelMapper instance for object mapping. */ private final ModelMapper mapper = new ModelMapper(); + /** + * Converts a {@link UserDto} to a {@link User} entity. + * + *

Uses Spring's BeanUtils to copy properties from the DTO to a new entity. + * Also handles nested UserProfileDto to UserProfile conversion.

+ * + * @param dto the UserDto to convert + * @param args optional additional arguments (not used) + * @return the converted User entity + */ @Override public User convertToEntity(UserDto dto, Object... args) { @@ -28,6 +50,16 @@ public User convertToEntity(UserDto dto, Object... args) { return user; } + /** + * Converts a {@link User} entity to a {@link UserDto}. + * + *

Uses Spring's BeanUtils to copy properties from the entity to a new DTO. + * Also handles nested UserProfile to UserProfileDto conversion.

+ * + * @param entity the User entity to convert + * @param args optional additional arguments (not used) + * @return the converted UserDto + */ @Override public UserDto convertToDto(User entity, Object... args) { diff --git a/User-Service/src/main/java/org/training/user/service/repository/UserRepository.java b/User-Service/src/main/java/org/training/user/service/repository/UserRepository.java index fc83ce6..674bb52 100644 --- a/User-Service/src/main/java/org/training/user/service/repository/UserRepository.java +++ b/User-Service/src/main/java/org/training/user/service/repository/UserRepository.java @@ -5,6 +5,16 @@ import java.util.Optional; +/** + * Repository interface for User entity persistence operations. + * + *

This interface extends JpaRepository to provide CRUD operations for User entities. + * It also defines custom query methods for finding users by specific criteria.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.model.entity.User + */ public interface UserRepository extends JpaRepository { /** diff --git a/User-Service/src/main/java/org/training/user/service/service/KeycloakService.java b/User-Service/src/main/java/org/training/user/service/service/KeycloakService.java index 6d15ab8..b4455d6 100644 --- a/User-Service/src/main/java/org/training/user/service/service/KeycloakService.java +++ b/User-Service/src/main/java/org/training/user/service/service/KeycloakService.java @@ -4,6 +4,20 @@ import java.util.List; +/** + * Service interface for Keycloak authentication operations. + * + *

This interface defines the contract for interacting with Keycloak as the + * identity provider. It provides methods for user management operations in + * Keycloak including creation, retrieval, and updates.

+ * + *

The service uses the Keycloak Admin Client to perform administrative + * operations on the banking-service realm.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.service.implementation.KeycloakServiceImpl + */ public interface KeycloakService { /** diff --git a/User-Service/src/main/java/org/training/user/service/service/UserService.java b/User-Service/src/main/java/org/training/user/service/service/UserService.java index 62db177..bd70fd5 100644 --- a/User-Service/src/main/java/org/training/user/service/service/UserService.java +++ b/User-Service/src/main/java/org/training/user/service/service/UserService.java @@ -8,6 +8,17 @@ import java.util.List; +/** + * Service interface defining user management operations. + * + *

This interface defines the contract for user-related business operations + * including registration, retrieval, and status management. Implementations + * coordinate with Keycloak for authentication and the database for user data.

+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.service.implementation.UserServiceImpl + */ public interface UserService { /** diff --git a/User-Service/src/main/java/org/training/user/service/service/implementation/KeycloakServiceImpl.java b/User-Service/src/main/java/org/training/user/service/service/implementation/KeycloakServiceImpl.java index 6886ce5..075b6dd 100644 --- a/User-Service/src/main/java/org/training/user/service/service/implementation/KeycloakServiceImpl.java +++ b/User-Service/src/main/java/org/training/user/service/service/implementation/KeycloakServiceImpl.java @@ -11,10 +11,31 @@ import java.util.List; import java.util.stream.Collectors; +/** + * Implementation of the {@link KeycloakService} interface. + * + *

This service provides the actual implementation for Keycloak operations + * using the Keycloak Admin Client. It manages user lifecycle operations in + * the Keycloak identity provider.

+ * + *

Operations include:

+ *
    + *
  • Creating new users in Keycloak
  • + *
  • Searching users by email
  • + *
  • Retrieving user details by auth ID
  • + *
  • Updating user properties (enabled, emailVerified)
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.service.KeycloakService + * @see org.training.user.service.config.KeyCloakManager + */ @Service @RequiredArgsConstructor public class KeycloakServiceImpl implements KeycloakService { + /** Manager for obtaining Keycloak client instances. */ private final KeyCloakManager keyCloakManager; /** diff --git a/User-Service/src/main/java/org/training/user/service/service/implementation/UserServiceImpl.java b/User-Service/src/main/java/org/training/user/service/service/implementation/UserServiceImpl.java index 7e416ba..4b00653 100644 --- a/User-Service/src/main/java/org/training/user/service/service/implementation/UserServiceImpl.java +++ b/User-Service/src/main/java/org/training/user/service/service/implementation/UserServiceImpl.java @@ -32,16 +32,42 @@ import java.util.function.Function; import java.util.stream.Collectors; +/** + * Implementation of the {@link UserService} interface. + * + *

This service handles all user-related business logic including registration, + * profile management, and status updates. It coordinates between Keycloak for + * authentication and the local database for application-specific user data.

+ * + *

Key features:

+ *
    + *
  • User registration with Keycloak integration (dual storage)
  • + *
  • Admin approval workflow for new registrations
  • + *
  • User profile updates and status management
  • + *
  • Integration with Account Service for user-account lookups
  • + *
+ * + * @author Training Team + * @version 1.0 + * @see org.training.user.service.service.UserService + * @see org.training.user.service.service.KeycloakService + */ @Slf4j @Service @RequiredArgsConstructor @Transactional public class UserServiceImpl implements UserService { + /** Repository for user data persistence. */ private final UserRepository userRepository; + + /** Service for Keycloak authentication operations. */ private final KeycloakService keycloakService; + + /** Feign client for Account Service communication. */ private final AccountService accountService; + /** Mapper for converting between User entities and DTOs. */ private UserMapper userMapper = new UserMapper(); @Value("${spring.application.success}") diff --git a/User-Service/src/main/java/org/training/user/service/utils/FieldChecker.java b/User-Service/src/main/java/org/training/user/service/utils/FieldChecker.java index bf4288a..d3a23fe 100644 --- a/User-Service/src/main/java/org/training/user/service/utils/FieldChecker.java +++ b/User-Service/src/main/java/org/training/user/service/utils/FieldChecker.java @@ -2,10 +2,24 @@ import java.util.Arrays; +/** + * Utility class for checking field values in objects. + * + *

This class provides utility methods for validating object fields, + * particularly useful for checking if required fields are populated + * before performing certain operations like user approval.

+ * + * @author Training Team + * @version 1.0 + */ public class FieldChecker { /** * Checks if an object has empty fields. + * + *

Recursively checks all declared fields of the object. Returns true if + * any field is null (except for enum fields). For nested objects, it + * recursively checks their fields as well.

* * @param object the object to check * @return true if the object has empty fields, false otherwise