diff --git a/logs/pms-application.log b/logs/pms-application.log deleted file mode 100644 index 982a93d..0000000 --- a/logs/pms-application.log +++ /dev/null @@ -1,91 +0,0 @@ -2026-02-05 04:04:20 INFO o.h.PortfolioManagementSystemApplication - Starting PortfolioManagementSystemApplication using Java 22.0.2 with PID 7380 (C:\Users\Administrator\PortfolioManagementSystem\target\classes started by Administrator in C:\Users\Administrator\PortfolioManagementSystem) -2026-02-05 04:04:20 DEBUG o.h.PortfolioManagementSystemApplication - Running with Spring Boot v3.2.4, Spring v6.1.5 -2026-02-05 04:04:20 INFO o.h.PortfolioManagementSystemApplication - No active profile set, falling back to 1 default profile: "default" -2026-02-05 04:04:21 INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -2026-02-05 04:04:21 INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 83 ms. Found 3 JPA repository interfaces. -2026-02-05 04:04:22 INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8080 (http) -2026-02-05 04:04:22 INFO o.a.catalina.core.StandardService - Starting service [Tomcat] -2026-02-05 04:04:22 INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.19] -2026-02-05 04:04:22 INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext -2026-02-05 04:04:22 INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1929 ms -2026-02-05 04:04:23 INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] -2026-02-05 04:04:23 INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.4.4.Final -2026-02-05 04:04:23 INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled -2026-02-05 04:04:23 INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer -2026-02-05 04:04:23 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... -2026-02-05 04:04:24 INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@6249a08d -2026-02-05 04:04:24 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. -2026-02-05 04:04:25 INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) -2026-02-05 04:04:25 INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default' -2026-02-05 04:04:25 INFO o.s.d.j.r.query.QueryEnhancerFactory - Hibernate is in classpath; If applicable, HQL parser will be used. -2026-02-05 04:04:26 INFO o.h.controller.StockDataController - StockDataController initialized -2026-02-05 04:04:27 WARN o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning -2026-02-05 04:04:27 INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port 8080 (http) with context path '' -2026-02-05 04:04:27 INFO o.h.PortfolioManagementSystemApplication - Started PortfolioManagementSystemApplication in 7.558 seconds (process running for 8.09) -2026-02-05 04:28:01 INFO o.h.PortfolioManagementSystemApplication - Starting PortfolioManagementSystemApplication using Java 22.0.2 with PID 11668 (C:\Users\Administrator\PortfolioManagementSystem\target\classes started by Administrator in C:\Users\Administrator\PortfolioManagementSystem) -2026-02-05 04:28:01 DEBUG o.h.PortfolioManagementSystemApplication - Running with Spring Boot v3.2.4, Spring v6.1.5 -2026-02-05 04:28:01 INFO o.h.PortfolioManagementSystemApplication - No active profile set, falling back to 1 default profile: "default" -2026-02-05 04:28:02 INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -2026-02-05 04:28:02 INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 76 ms. Found 3 JPA repository interfaces. -2026-02-05 04:28:03 INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8080 (http) -2026-02-05 04:28:03 INFO o.a.catalina.core.StandardService - Starting service [Tomcat] -2026-02-05 04:28:03 INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.19] -2026-02-05 04:28:03 INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext -2026-02-05 04:28:03 INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1757 ms -2026-02-05 04:28:03 INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] -2026-02-05 04:28:03 INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.4.4.Final -2026-02-05 04:28:03 INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled -2026-02-05 04:28:04 INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer -2026-02-05 04:28:04 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... -2026-02-05 04:28:04 INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@a1e912f -2026-02-05 04:28:04 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. -2026-02-05 04:28:05 INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) -2026-02-05 04:28:06 INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default' -2026-02-05 04:28:06 INFO o.s.d.j.r.query.QueryEnhancerFactory - Hibernate is in classpath; If applicable, HQL parser will be used. -2026-02-05 04:28:06 INFO o.h.controller.StockDataController - StockDataController initialized -2026-02-05 04:28:07 WARN o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning -2026-02-05 04:28:07 WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop' -2026-02-05 04:28:07 INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default' -2026-02-05 04:28:07 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated... -2026-02-05 04:28:07 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed. -2026-02-05 04:28:07 INFO o.s.b.a.l.ConditionEvaluationReportLogger - - -Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. -2026-02-05 04:28:07 ERROR o.s.b.d.LoggingFailureAnalysisReporter - - -*************************** -APPLICATION FAILED TO START -*************************** - -Description: - -Web server failed to start. Port 8080 was already in use. - -Action: - -Identify and stop the process that's listening on port 8080 or configure this application to listen on another port. - -2026-02-05 04:28:58 INFO o.h.PortfolioManagementSystemApplication - Starting PortfolioManagementSystemApplication using Java 22.0.2 with PID 16728 (C:\Users\Administrator\PortfolioManagementSystem\target\classes started by Administrator in C:\Users\Administrator\PortfolioManagementSystem) -2026-02-05 04:28:58 DEBUG o.h.PortfolioManagementSystemApplication - Running with Spring Boot v3.2.4, Spring v6.1.5 -2026-02-05 04:28:58 INFO o.h.PortfolioManagementSystemApplication - No active profile set, falling back to 1 default profile: "default" -2026-02-05 04:28:59 INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -2026-02-05 04:28:59 INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 68 ms. Found 3 JPA repository interfaces. -2026-02-05 04:29:00 INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8080 (http) -2026-02-05 04:29:00 INFO o.a.catalina.core.StandardService - Starting service [Tomcat] -2026-02-05 04:29:00 INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.19] -2026-02-05 04:29:00 INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext -2026-02-05 04:29:00 INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1837 ms -2026-02-05 04:29:00 INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] -2026-02-05 04:29:00 INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.4.4.Final -2026-02-05 04:29:00 INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled -2026-02-05 04:29:01 INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer -2026-02-05 04:29:01 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... -2026-02-05 04:29:01 INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@12448de1 -2026-02-05 04:29:01 INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. -2026-02-05 04:29:03 INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) -2026-02-05 04:29:03 INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default' -2026-02-05 04:29:03 INFO o.s.d.j.r.query.QueryEnhancerFactory - Hibernate is in classpath; If applicable, HQL parser will be used. -2026-02-05 04:29:03 INFO o.h.controller.StockDataController - StockDataController initialized -2026-02-05 04:29:04 WARN o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning -2026-02-05 04:29:04 INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port 8080 (http) with context path '' -2026-02-05 04:29:04 INFO o.h.PortfolioManagementSystemApplication - Started PortfolioManagementSystemApplication in 6.64 seconds (process running for 7.13) diff --git a/src/main/java/org/hsbc/controller/PmsController.java b/src/main/java/org/hsbc/controller/PmsController.java index 451e09f..7f357e1 100644 --- a/src/main/java/org/hsbc/controller/PmsController.java +++ b/src/main/java/org/hsbc/controller/PmsController.java @@ -1,6 +1,7 @@ package org.hsbc.controller; import org.hsbc.entity.PmsEntity; +import org.hsbc.exception.InvalidPmsIdException; import org.hsbc.service.PmsService; import org.hsbc.service.PmsServiceimp; import org.slf4j.Logger; @@ -26,7 +27,7 @@ public List getAllAssets() { return service.getAllAssets(); } @GetMapping("/{id}") - public PmsEntity getAssetById(@PathVariable Long id) { + public PmsEntity getAssetById(@PathVariable Long id) throws InvalidPmsIdException { return service.getAssetById(id); } @@ -39,7 +40,7 @@ public PmsEntity addAsset(@RequestBody PmsEntity asset) { } @DeleteMapping("/remove/{id}") - public String removeAsset(@PathVariable Long id) { + public String removeAsset(@PathVariable Long id) throws InvalidPmsIdException { service.removeAsset(id); return "Asset removed successfully"; } @@ -47,17 +48,17 @@ public String removeAsset(@PathVariable Long id) { @PutMapping("/update-quantity/{id}") public PmsEntity updateQuantity( @PathVariable Long id, - @RequestParam int quantity) { + @RequestParam int quantity) throws InvalidPmsIdException { return service.updateQuantity(id, quantity); } @GetMapping("/pl/{id}") - public double getPL(@PathVariable Long id) { + public double getPL(@PathVariable Long id) throws InvalidPmsIdException { return service.calculatePL(id); } @GetMapping("/pl-percentage/{id}") - public double getPLPercentage(@PathVariable Long id) { + public double getPLPercentage(@PathVariable Long id) throws InvalidPmsIdException { return service.calculatePLPercentage(id); } diff --git a/src/main/java/org/hsbc/exception/InvalidException.java b/src/main/java/org/hsbc/exception/InvalidException.java deleted file mode 100644 index d6f3fda..0000000 --- a/src/main/java/org/hsbc/exception/InvalidException.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.hsbc.exception; - -public class InvalidException extends Exception { - - - - public InvalidException() { - } - - public InvalidException(String message) { - super(message); - } - - public InvalidException(String message, Throwable cause) { - super(message, cause); - } - - public InvalidException(Throwable cause) { - super(cause); - } - - public InvalidException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - -} diff --git a/src/main/java/org/hsbc/exception/InvalidPmsIdException.java b/src/main/java/org/hsbc/exception/InvalidPmsIdException.java new file mode 100644 index 0000000..3eec776 --- /dev/null +++ b/src/main/java/org/hsbc/exception/InvalidPmsIdException.java @@ -0,0 +1,25 @@ +package org.hsbc.exception; + +public class InvalidPmsIdException extends Exception { + + public InvalidPmsIdException() { + } + + public InvalidPmsIdException(String message) { + super(message); + } + + public InvalidPmsIdException(Throwable cause) { + super(cause); + } + + public InvalidPmsIdException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidPmsIdException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} \ No newline at end of file diff --git a/src/main/java/org/hsbc/exception/InvalidTransactionIdException.java b/src/main/java/org/hsbc/exception/InvalidTransactionIdException.java new file mode 100644 index 0000000..9ffec6d --- /dev/null +++ b/src/main/java/org/hsbc/exception/InvalidTransactionIdException.java @@ -0,0 +1,25 @@ +package org.hsbc.exception; + +public class InvalidTransactionIdException extends Exception { + + public InvalidTransactionIdException() { + } + + public InvalidTransactionIdException(String message) { + super(message); + } + + public InvalidTransactionIdException(Throwable cause) { + super(cause); + } + + public InvalidTransactionIdException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidTransactionIdException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} \ No newline at end of file diff --git a/src/main/java/org/hsbc/service/PmsService.java b/src/main/java/org/hsbc/service/PmsService.java index 19a70cb..b4fc673 100644 --- a/src/main/java/org/hsbc/service/PmsService.java +++ b/src/main/java/org/hsbc/service/PmsService.java @@ -1,23 +1,25 @@ package org.hsbc.service; -import org.hsbc.entity.PmsEntity; - import java.util.List; +import org.hsbc.entity.PmsEntity; +import org.hsbc.exception.InvalidPmsIdException; public interface PmsService { + PmsEntity addAsset(PmsEntity asset); - void removeAsset(Long id); + void removeAsset(Long id) throws InvalidPmsIdException; - PmsEntity updateQuantity(Long id, int newQuantity); + PmsEntity updateQuantity(Long id, int newQuantity) throws InvalidPmsIdException; - double calculatePL(Long id); + double calculatePL(Long id) throws InvalidPmsIdException; - double calculatePLPercentage(Long id); + double calculatePLPercentage(Long id) throws InvalidPmsIdException; double getTotalPortfolioValue(); + List getAllAssets(); - PmsEntity getAssetById(Long id); + PmsEntity getAssetById(Long id) throws InvalidPmsIdException; -} +} \ No newline at end of file diff --git a/src/main/java/org/hsbc/service/PmsServiceimp.java b/src/main/java/org/hsbc/service/PmsServiceimp.java index 74a23ca..7a34c10 100644 --- a/src/main/java/org/hsbc/service/PmsServiceimp.java +++ b/src/main/java/org/hsbc/service/PmsServiceimp.java @@ -1,14 +1,12 @@ package org.hsbc.service; import org.hsbc.entity.PmsEntity; -import org.hsbc.exception.InvalidException; +import org.hsbc.exception.InvalidPmsIdException; import org.hsbc.repo.PmsRepository; 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.util.List; import java.util.Optional; @@ -20,65 +18,63 @@ public class PmsServiceimp implements PmsService { @Autowired private PmsRepository repository; - // 1️⃣ Add Asset - @Override - public PmsEntity addAsset(PmsEntity asset) { - asset.setBuyingValue(asset.getBuyPrice() * asset.getQuantity()); - return repository.save(asset); - } + // 1️⃣ Add Asset + @Override + public PmsEntity addAsset(PmsEntity asset) { + asset.setBuyingValue(asset.getBuyPrice() * asset.getQuantity()); + return repository.save(asset); + } - // 2️⃣ Remove Asset - @Override - public void removeAsset(Long id) { - repository.deleteById(id); - } + // 2️⃣ Remove Asset + @Override + public void removeAsset(Long id) throws InvalidPmsIdException { + getAssetById(id); + repository.deleteById(id); + } - // 3️⃣ Update Quantity - @Override - public PmsEntity updateQuantity(Long id, int newQuantity) { - PmsEntity asset = repository.findById(id) - .orElseThrow(() -> new RuntimeException("Asset not found")); + // 3️⃣ Update Quantity + @Override + public PmsEntity updateQuantity(Long id, int newQuantity) throws InvalidPmsIdException { + PmsEntity asset = getAssetById(id); - asset.setQuantity(newQuantity); - asset.setBuyingValue(asset.getBuyPrice() * newQuantity); + asset.setQuantity(newQuantity); + asset.setBuyingValue(asset.getBuyPrice() * newQuantity); - return repository.save(asset); - } + return repository.save(asset); + } - // 4️⃣ Calculate Profit / Loss - @Override - public double calculatePL(Long id) { - PmsEntity asset = repository.findById(id) - .orElseThrow(() -> new RuntimeException("Asset not found")); + // 4️⃣ Calculate Profit / Loss + @Override + public double calculatePL(Long id) throws InvalidPmsIdException { + PmsEntity asset = getAssetById(id); - double buyingValue = asset.getBuyPrice() * asset.getQuantity(); - double currentValue = asset.getCurrentPrice() * asset.getQuantity(); + double buyingValue = asset.getBuyPrice() * asset.getQuantity(); + double currentValue = asset.getCurrentPrice() * asset.getQuantity(); - return currentValue - buyingValue; - } + return currentValue - buyingValue; + } - // 5️⃣ Calculate P/L Percentage - @Override - public double calculatePLPercentage(Long id) { - PmsEntity asset = repository.findById(id) - .orElseThrow(() -> new RuntimeException("Asset not found")); + // 5️⃣ Calculate P/L Percentage + @Override + public double calculatePLPercentage(Long id) throws InvalidPmsIdException { + PmsEntity asset = getAssetById(id); - double buyingValue = asset.getBuyPrice() * asset.getQuantity(); - double pl = calculatePL(id); + double buyingValue = asset.getBuyPrice() * asset.getQuantity(); + double pl = calculatePL(id); - if (buyingValue == 0) return 0; + if (buyingValue == 0) return 0; - return (pl / buyingValue) * 100; - } + return (pl / buyingValue) * 100; + } - // 6️⃣ Total Portfolio Value - @Override - public double getTotalPortfolioValue() { - return repository.findAll() - .stream() - .mapToDouble(a -> a.getCurrentPrice() * a.getQuantity()) - .sum(); - } + // 6️⃣ Total Portfolio Value + @Override + public double getTotalPortfolioValue() { + return repository.findAll() + .stream() + .mapToDouble(a -> a.getCurrentPrice() * a.getQuantity()) + .sum(); + } public PmsServiceimp(PmsRepository repository) { this.repository = repository; } @@ -88,12 +84,12 @@ public List getAllAssets() { return repository.findAll(); } @Override - public PmsEntity getAssetById(Long id) { - return repository.findById(id) - .orElseThrow(() -> new ResponseStatusException( - HttpStatus.NOT_FOUND, - "Asset not found with id " + id - )); + public PmsEntity getAssetById(Long id) throws InvalidPmsIdException { + Optional optAsset = repository.findById(id); + if (optAsset.isEmpty()) { + throw new InvalidPmsIdException("Asset not found with id " + id); + } + return optAsset.get(); } // // public PmsEntity findAllPms(long id) throws InvalidException { @@ -108,4 +104,4 @@ public PmsEntity getAssetById(Long id) { -} +} \ No newline at end of file diff --git a/src/main/java/org/hsbc/service/TransactionService.java b/src/main/java/org/hsbc/service/TransactionService.java index 02b8138..b897206 100644 --- a/src/main/java/org/hsbc/service/TransactionService.java +++ b/src/main/java/org/hsbc/service/TransactionService.java @@ -1,6 +1,7 @@ package org.hsbc.service; import org.hsbc.entity.TransactionEntity; +import org.hsbc.exception.InvalidTransactionIdException; import java.util.List; @@ -11,4 +12,10 @@ public interface TransactionService { List getTransactionsBySymbol(String symbol); -} + TransactionEntity getTransactionById(Long id) throws InvalidTransactionIdException; + + TransactionEntity updateTransaction(TransactionEntity transaction) throws InvalidTransactionIdException; + + void deleteTransaction(Long id) throws InvalidTransactionIdException; + +} \ No newline at end of file diff --git a/src/main/java/org/hsbc/service/TransactionSeviceimp.java b/src/main/java/org/hsbc/service/TransactionSeviceimp.java index 73d2fad..93814ec 100644 --- a/src/main/java/org/hsbc/service/TransactionSeviceimp.java +++ b/src/main/java/org/hsbc/service/TransactionSeviceimp.java @@ -1,13 +1,14 @@ package org.hsbc.service; import org.hsbc.entity.TransactionEntity; - +import org.hsbc.exception.InvalidTransactionIdException; import org.hsbc.repo.TransactionRepo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Optional; @Service public class TransactionSeviceimp implements TransactionService { @@ -34,4 +35,25 @@ public List getAllTransactions() { public List getTransactionsBySymbol(String symbol) { return repository.findBySymbol(symbol); } -} + + @Override + public TransactionEntity getTransactionById(Long id) throws InvalidTransactionIdException { + Optional optTransaction = repository.findById(id); + if (optTransaction.isEmpty()) { + throw new InvalidTransactionIdException("Transaction not found with id " + id); + } + return optTransaction.get(); + } + + @Override + public TransactionEntity updateTransaction(TransactionEntity transaction) throws InvalidTransactionIdException { + getTransactionById(transaction.getTransactionId()); // Validate existence + return repository.save(transaction); + } + + @Override + public void deleteTransaction(Long id) throws InvalidTransactionIdException { + getTransactionById(id); // Validate existence + repository.deleteById(id); + } +} \ No newline at end of file diff --git a/src/test/java/org/hsbc/service/PmsServiceimpTest.java b/src/test/java/org/hsbc/service/PmsServiceimpTest.java index 9f21ca0..06c1c2c 100644 --- a/src/test/java/org/hsbc/service/PmsServiceimpTest.java +++ b/src/test/java/org/hsbc/service/PmsServiceimpTest.java @@ -1,6 +1,14 @@ package org.hsbc.service; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + import org.hsbc.entity.PmsEntity; +import org.hsbc.exception.InvalidPmsIdException; import org.hsbc.repo.PmsRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -9,14 +17,8 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - @ExtendWith(MockitoExtension.class) -class PmsServiceimpTest { +public class PmsServiceimpTest { @Mock private PmsRepository repository; @@ -24,87 +26,90 @@ class PmsServiceimpTest { @InjectMocks private PmsServiceimp service; - private PmsEntity asset; + private PmsEntity asset1; @BeforeEach void setUp() { - asset = new PmsEntity(); - asset.setId(1L); - asset.setCompanyName("Apple"); - asset.setSymbol("AAPL"); - asset.setQuantity(10); - asset.setBuyPrice(100); - asset.setCurrentPrice(120); + // Setup dummy data + asset1 = new PmsEntity(); + asset1.setId(1L); + asset1.setSymbol("AAPL"); + asset1.setBuyPrice(150.0); + asset1.setCurrentPrice(170.0); + asset1.setQuantity(10); } - // 1️⃣ addAsset() - @Test - void testAddAsset() { - when(repository.save(any(PmsEntity.class))).thenReturn(asset); - - PmsEntity saved = service.addAsset(asset); - - assertEquals(1000, saved.getBuyingValue()); - verify(repository, times(1)).save(asset); - } + // --- Success Tests --- - // 2️⃣ removeAsset() @Test - void testRemoveAsset() { - doNothing().when(repository).deleteById(1L); + void testGetAssetById_Success() throws InvalidPmsIdException { + when(repository.findById(1L)).thenReturn(Optional.of(asset1)); - service.removeAsset(1L); + PmsEntity result = service.getAssetById(1L); - verify(repository, times(1)).deleteById(1L); + assertNotNull(result); + assertEquals("AAPL", result.getSymbol()); } - // 3️⃣ updateQuantity() @Test - void testUpdateQuantity() { - when(repository.findById(1L)).thenReturn(Optional.of(asset)); - when(repository.save(any(PmsEntity.class))).thenReturn(asset); + void testUpdateQuantity_Success() throws InvalidPmsIdException { + when(repository.findById(1L)).thenReturn(Optional.of(asset1)); + when(repository.save(any(PmsEntity.class))).thenReturn(asset1); PmsEntity updated = service.updateQuantity(1L, 20); assertEquals(20, updated.getQuantity()); - assertEquals(2000, updated.getBuyingValue()); + // Check if buying value updated: 150 * 20 = 3000 + assertEquals(3000.0, updated.getBuyingValue()); } - // 4️⃣ calculatePL() @Test - void testCalculatePL() { - when(repository.findById(1L)).thenReturn(Optional.of(asset)); + void testCalculatePL_Success() throws InvalidPmsIdException { + when(repository.findById(1L)).thenReturn(Optional.of(asset1)); + // Buy: 150 * 10 = 1500 + // Current: 170 * 10 = 1700 + // PL: 200 double pl = service.calculatePL(1L); - assertEquals(200, pl); + assertEquals(200.0, pl); } - // 5️⃣ calculatePLPercentage() @Test - void testCalculatePLPercentage() { - when(repository.findById(1L)).thenReturn(Optional.of(asset)); + void testRemoveAsset_Success() throws InvalidPmsIdException { + when(repository.findById(1L)).thenReturn(Optional.of(asset1)); - double plPercent = service.calculatePLPercentage(1L); + assertDoesNotThrow(() -> service.removeAsset(1L)); - assertEquals(20.0, plPercent); + verify(repository, times(1)).deleteById(1L); } - // 6️⃣ getTotalPortfolioValue() + // --- Exception Tests (Failure Scenarios) --- + @Test - void testGetTotalPortfolioValue() { - when(repository.findAll()).thenReturn(List.of(asset)); + void testGetAssetById_NotFound() { + when(repository.findById(99L)).thenReturn(Optional.empty()); + + assertThrows(InvalidPmsIdException.class, () -> { + service.getAssetById(99L); + }); + } - double total = service.getTotalPortfolioValue(); + @Test + void testUpdateQuantity_NotFound() { + when(repository.findById(99L)).thenReturn(Optional.empty()); - assertEquals(1200, total); + assertThrows(InvalidPmsIdException.class, () -> { + service.updateQuantity(99L, 5); + }); } - // ❌ Asset not found scenario @Test - void testAssetNotFound() { + void testCalculatePL_NotFound() { when(repository.findById(99L)).thenReturn(Optional.empty()); - assertThrows(RuntimeException.class, () -> service.calculatePL(99L)); + assertThrows(InvalidPmsIdException.class, () -> { + service.calculatePL(99L); + }); } -} +} \ No newline at end of file diff --git a/src/test/java/org/hsbc/service/TransactionServiceimpTest.java b/src/test/java/org/hsbc/service/TransactionServiceimpTest.java index 6d45296..b60946a 100644 --- a/src/test/java/org/hsbc/service/TransactionServiceimpTest.java +++ b/src/test/java/org/hsbc/service/TransactionServiceimpTest.java @@ -1,6 +1,7 @@ package org.hsbc.service; import org.hsbc.entity.TransactionEntity; +import org.hsbc.exception.InvalidTransactionIdException; import org.hsbc.repo.TransactionRepo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -11,9 +12,9 @@ import java.time.LocalDate; import java.util.List; +import java.util.Optional; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @@ -74,4 +75,77 @@ void testGetTransactionsBySymbol() { assertEquals("AAPL", list.get(0).getSymbol()); verify(repository, times(1)).findBySymbol("AAPL"); } + + // 4️⃣ getTransactionById() - Success + @Test + void testGetTransactionById_Success() throws InvalidTransactionIdException { + when(repository.findById(1L)).thenReturn(Optional.of(transaction)); + + TransactionEntity found = service.getTransactionById(1L); + + assertNotNull(found); + assertEquals(1L, found.getTransactionId()); + verify(repository, times(1)).findById(1L); + } + + // 5️⃣ getTransactionById() - Failure (Exception) + @Test + void testGetTransactionById_NotFound() { + when(repository.findById(99L)).thenReturn(Optional.empty()); + + assertThrows(InvalidTransactionIdException.class, () -> { + service.getTransactionById(99L); + }); + + verify(repository, times(1)).findById(99L); + } + + // 6️⃣ updateTransaction() - Success + @Test + void testUpdateTransaction_Success() throws InvalidTransactionIdException { + when(repository.findById(1L)).thenReturn(Optional.of(transaction)); + when(repository.save(any(TransactionEntity.class))).thenReturn(transaction); + + TransactionEntity updated = service.updateTransaction(transaction); + + assertNotNull(updated); + verify(repository, times(1)).save(transaction); + } + + // 7️⃣ updateTransaction() - Failure (Exception) + @Test + void testUpdateTransaction_NotFound() { + TransactionEntity newTrans = new TransactionEntity(); + newTrans.setTransactionId(99L); + + when(repository.findById(99L)).thenReturn(Optional.empty()); + + assertThrows(InvalidTransactionIdException.class, () -> { + service.updateTransaction(newTrans); + }); + + verify(repository, never()).save(any()); + } + + // 8️⃣ deleteTransaction() - Success + @Test + void testDeleteTransaction_Success() throws InvalidTransactionIdException { + when(repository.findById(1L)).thenReturn(Optional.of(transaction)); + + assertDoesNotThrow(() -> service.deleteTransaction(1L)); + + verify(repository, times(1)).deleteById(1L); + } + + // 9️⃣ deleteTransaction() - Failure (Exception) + @Test + void testDeleteTransaction_NotFound() { + when(repository.findById(99L)).thenReturn(Optional.empty()); + + assertThrows(InvalidTransactionIdException.class, () -> { + service.deleteTransaction(99L); + }); + + verify(repository, never()).deleteById(anyLong()); + } } \ No newline at end of file