Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,12 @@ build/
### VS Code ###
.vscode/
Backend/RECOMMENDATION_SERVICE.md


# ----------------------------
# Log files
# ----------------------------
logs/
*.log
*.log.*

922 changes: 225 additions & 697 deletions logs/pms-application.log

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<!-- Mockito -->
<dependency>
Expand Down
62 changes: 62 additions & 0 deletions src/main/java/org/hsbc/exception/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.hsbc.exception;

import java.time.LocalDateTime;

public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;

public ErrorResponse() {
}

public ErrorResponse(int status, String error, String message, String path) {
this.timestamp = LocalDateTime.now();
this.status = status;
this.error = error;
this.message = message;
this.path = path;
}

public LocalDateTime getTimestamp() {
return timestamp;
}

public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}

public int getStatus() {
return status;
}

public void setStatus(int status) {
this.status = status;
}

public String getError() {
return error;
}

public void setError(String error) {
this.error = error;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}
}
64 changes: 64 additions & 0 deletions src/main/java/org/hsbc/exception/GlobalExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.hsbc.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex,
WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
HttpStatus.NOT_FOUND.getReasonPhrase(),
ex.getMessage(),
request.getDescription(false).replace("uri=", ""));
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}

@ExceptionHandler(InsufficientBalanceException.class)
public ResponseEntity<ErrorResponse> handleInsufficientBalanceException(InsufficientBalanceException ex,
WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
HttpStatus.BAD_REQUEST.getReasonPhrase(),
ex.getMessage(),
request.getDescription(false).replace("uri=", ""));
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(InvalidPmsIdException.class)
public ResponseEntity<ErrorResponse> handleInvalidPmsIdException(InvalidPmsIdException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
HttpStatus.NOT_FOUND.getReasonPhrase(),
ex.getMessage(),
request.getDescription(false).replace("uri=", ""));
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}

@ExceptionHandler(InvalidTransactionIdException.class)
public ResponseEntity<ErrorResponse> handleInvalidTransactionIdException(InvalidTransactionIdException ex,
WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
HttpStatus.NOT_FOUND.getReasonPhrase(),
ex.getMessage(),
request.getDescription(false).replace("uri=", ""));
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
ex.getMessage(),
request.getDescription(false).replace("uri=", ""));
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hsbc.exception;

public class InsufficientBalanceException extends RuntimeException {
public InsufficientBalanceException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.hsbc.exception;

public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
57 changes: 57 additions & 0 deletions src/main/java/org/hsbc/logging/LoggingAspect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.hsbc.logging;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

private static final Logger log =
LoggerFactory.getLogger(LoggingAspect.class);

// 🔹 Apply to all controller & service methods
@Pointcut("execution(* org.hsbc.controller..*(..)) || execution(* org.hsbc.service..*(..))")
public void applicationMethods() {}

@Around("applicationMethods()")
public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {

String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();

log.info("➡️ ENTER: {}.{}() with arguments = {}",
className,
methodName,
joinPoint.getArgs());

long start = System.currentTimeMillis();

try {
Object result = joinPoint.proceed();

long timeTaken = System.currentTimeMillis() - start;

log.info("✅ EXIT: {}.{}() | Time = {} ms | Result = {}",
className,
methodName,
timeTaken,
result);

return result;

} catch (Exception ex) {

log.error("❌ EXCEPTION in {}.{}() | Message = {}",
className,
methodName,
ex.getMessage(),
ex);

throw ex;
}
}
}
65 changes: 29 additions & 36 deletions src/main/java/org/hsbc/service/PmsServiceimp.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.hsbc.service;


//Import statemnts
import org.hsbc.entity.PmsEntity;
import org.hsbc.entity.TransactionEntity;
Expand All @@ -9,43 +8,37 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;


import java.time.LocalDate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;

@Service
public class PmsServiceimp implements PmsService {
private static final Logger log =
LoggerFactory.getLogger(PmsServiceimp.class);
@Autowired
private PmsRepository repository;

@Autowired
private WalletService walletService;

@Autowired
private TransactionService transactionService;

// 1️⃣ Add Asset
@Override
public PmsEntity addAsset(PmsEntity asset) {
// Calculate total cost
double totalCost = asset.getBuyPrice() * asset.getQuantity();

// Check and deduct from wallet (this will throw exception if insufficient balance)
walletService.deductMoney(totalCost);

// Set purchase date and buying value
asset.setPurchaseDate(LocalDate.now());
asset.setBuyingValue(totalCost);

return repository.save(asset);
}
private static final Logger log = LoggerFactory.getLogger(PmsServiceimp.class);
@Autowired
private PmsRepository repository;

@Autowired
private WalletService walletService;

// 1️⃣ Add Asset
@Override
public PmsEntity addAsset(PmsEntity asset) {
// Calculate total cost
double totalCost = asset.getBuyPrice() * asset.getQuantity();

// Check and deduct from wallet (this will throw exception if insufficient
// balance)
walletService.deductMoney(totalCost);

// Set purchase date and buying value
asset.setPurchaseDate(LocalDate.now());
asset.setBuyingValue(totalCost);

return repository.save(asset);
}

// 2️⃣ Remove Asset
@Override
Expand Down Expand Up @@ -84,7 +77,8 @@ public double calculatePLPercentage(Long id) throws InvalidPmsIdException {
double buyingValue = asset.getBuyPrice() * asset.getQuantity();
double pl = calculatePL(id);

if (buyingValue == 0) return 0;
if (buyingValue == 0)
return 0;

return (pl / buyingValue) * 100;
}
Expand All @@ -97,6 +91,7 @@ public double getTotalPortfolioValue() {
.mapToDouble(a -> a.getCurrentPrice() * a.getQuantity())
.sum();
}

public PmsServiceimp(PmsRepository repository) {
this.repository = repository;
}
Expand All @@ -105,6 +100,7 @@ public PmsServiceimp(PmsRepository repository) {
public List<PmsEntity> getAllAssets() {
return repository.findAll();
}

@Override
public PmsEntity getAssetById(Long id) throws InvalidPmsIdException {
Optional<PmsEntity> optAsset = repository.findById(id);
Expand All @@ -124,10 +120,7 @@ public PmsEntity updateCurrentPrice(String symbol, double newPrice) {
return repository.save(asset);
}
}
throw new ResponseStatusException(
HttpStatus.NOT_FOUND,
"Asset not found with symbol " + symbol
);
throw new org.hsbc.exception.ResourceNotFoundException("Asset not found with symbol " + symbol);
}

@Override
Expand Down
15 changes: 5 additions & 10 deletions src/main/java/org/hsbc/service/WalletServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@
import org.hsbc.repo.WalletRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

@Service
public class WalletServiceImpl implements WalletService{
public class WalletServiceImpl implements WalletService {

private static final Logger log =
LoggerFactory.getLogger(WalletServiceImpl.class);
private static final Logger log = LoggerFactory.getLogger(WalletServiceImpl.class);

private final WalletRepository repository;

Expand All @@ -22,8 +19,7 @@ public WalletServiceImpl(WalletRepository repository) {

private WalletEntity getWallet() {
return repository.findById(1L)
.orElseThrow(() -> new ResponseStatusException(
HttpStatus.NOT_FOUND, "Wallet not found"));
.orElseThrow(() -> new org.hsbc.exception.ResourceNotFoundException("Wallet not found"));
}

@Override
Expand All @@ -44,15 +40,14 @@ public double deductMoney(double amount) {
WalletEntity wallet = getWallet();

if (wallet.getBalance() < amount) {
throw new ResponseStatusException(
HttpStatus.BAD_REQUEST, "Insufficient balance");
throw new org.hsbc.exception.InsufficientBalanceException("Insufficient balance");
}

wallet.setBalance(wallet.getBalance() - amount);
repository.save(wallet);
return wallet.getBalance();
}

@Override
public WalletEntity getWalletSummary() {
return getWallet();
Expand Down
Loading
Loading