From 7b6c7d18eb93088d4767104a054578acddb922e5 Mon Sep 17 00:00:00 2001 From: ylongtay <145927097+ylongtay@users.noreply.github.com> Date: Fri, 29 Mar 2024 14:46:19 +0800 Subject: [PATCH] SIS-28 completed --- ThunderClient/EndpointTests.json | 221 +++++++++++++++--- .../controllers/ProductController.java | 88 +++++-- .../repositories/ProductRepository.java | 24 +- .../serviceImpls/ProductServiceImpl.java | 101 ++++---- .../services/ProductService.java | 14 +- 5 files changed, 334 insertions(+), 114 deletions(-) diff --git a/ThunderClient/EndpointTests.json b/ThunderClient/EndpointTests.json index 44d6926..370824e 100644 --- a/ThunderClient/EndpointTests.json +++ b/ThunderClient/EndpointTests.json @@ -1,28 +1,35 @@ { "client": "Thunder Client", "collectionName": "SmartInventory", - "dateExported": "2024-03-25T07:31:20.903Z", + "dateExported": "2024-03-29T06:44:41.033Z", "version": "1.1", "folders": [ { - "_id": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Customer", "containerId": "", - "created": "2024-03-24T04:28:29.833Z", + "created": "2024-03-29T06:19:27.787Z", "sortNum": 10000 + }, + { + "_id": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Product", + "containerId": "", + "created": "2024-03-29T06:21:13.542Z", + "sortNum": 20000 } ], "requests": [ { - "_id": "9e08f024-8b20-4f4d-b49f-b45d3c5a8bac", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "5ab63b29-5cca-49b0-aaa6-b4096cd063f6", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Create Customer", "url": "http://localhost:9090/customers", "method": "POST", "sortNum": 30000, - "created": "2024-03-24T04:29:24.892Z", - "modified": "2024-03-24T07:13:21.478Z", + "created": "2024-03-29T06:19:27.788Z", + "modified": "2024-03-29T06:19:27.788Z", "headers": [], "params": [], "body": { @@ -33,29 +40,29 @@ "tests": [] }, { - "_id": "77ac4300-178d-4d25-ab90-7132d09ba81f", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "6ad34b41-f511-42f8-9871-b05ce1326906", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Get All Customers", "url": "http://localhost:9090/customers", "method": "GET", "sortNum": 40000, - "created": "2024-03-24T04:29:30.285Z", - "modified": "2024-03-24T04:38:04.649Z", + "created": "2024-03-29T06:19:27.789Z", + "modified": "2024-03-29T06:19:27.789Z", "headers": [], "params": [], "tests": [] }, { - "_id": "171a9cf1-4dcb-443a-bf62-3c32cab85409", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "80fa1d7b-791c-4a7e-ae07-a14fd39056a8", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Get 1 Customer", "url": "http://localhost:9090/customers/{uuid}", "method": "GET", "sortNum": 50000, - "created": "2024-03-24T04:29:42.726Z", - "modified": "2024-03-24T14:49:05.718Z", + "created": "2024-03-29T06:19:27.790Z", + "modified": "2024-03-29T06:19:27.790Z", "headers": [], "params": [ { @@ -67,15 +74,15 @@ "tests": [] }, { - "_id": "7d08442c-1f3c-4482-95d1-9d5cfa782411", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "24ccf681-63a9-43ac-ab16-dab10996caa6", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Search by FirstName", "url": "http://localhost:9090/customers/search?firstName=e", "method": "GET", "sortNum": 55000, - "created": "2024-03-24T08:58:37.049Z", - "modified": "2024-03-24T09:19:19.062Z", + "created": "2024-03-29T06:19:27.793Z", + "modified": "2024-03-29T06:19:27.793Z", "headers": [], "params": [ { @@ -87,15 +94,15 @@ "tests": [] }, { - "_id": "a2f8e24c-f9c2-49f1-8d37-bdb64b4c6286", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "fe9bb8f8-1dfa-4c5a-9461-4176d29429f3", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Update Customer", "url": "http://localhost:9090/customers/{uuid}", "method": "PUT", "sortNum": 60000, - "created": "2024-03-24T04:29:48.079Z", - "modified": "2024-03-24T06:30:25.441Z", + "created": "2024-03-29T06:19:27.791Z", + "modified": "2024-03-29T06:19:27.791Z", "headers": [], "params": [ { @@ -112,15 +119,15 @@ "tests": [] }, { - "_id": "40e4584b-eb1a-43c6-8eb2-8cf2f13beb4a", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "999623d2-4d6f-4e4e-8a38-08e87cf93898", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Delete Customer", "url": "http://localhost:9090/customers/{id}", "method": "DELETE", "sortNum": 70000, - "created": "2024-03-24T04:29:54.857Z", - "modified": "2024-03-24T06:30:32.997Z", + "created": "2024-03-29T06:19:27.792Z", + "modified": "2024-03-29T06:19:27.792Z", "headers": [], "params": [ { @@ -132,15 +139,15 @@ "tests": [] }, { - "_id": "460ee27b-cfe3-448e-ab60-8f402c8acd0b", - "colId": "5c57004c-dd7a-4942-ab04-3da3fb363ce1", - "containerId": "f5054f57-4880-45fa-b08a-f4d9b5359c2c", + "_id": "92d5c718-598b-4f66-b30e-459e1470f723", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "605122de-fb92-469e-ae99-ed47c68b3d96", "name": "Add Review to Customer", "url": "http://localhost:9090/customers/{id}/reviews", "method": "POST", "sortNum": 80000, - "created": "2024-03-24T14:43:48.836Z", - "modified": "2024-03-24T14:47:53.708Z", + "created": "2024-03-29T06:19:27.794Z", + "modified": "2024-03-29T06:19:27.794Z", "headers": [], "params": [ { @@ -155,6 +162,144 @@ "form": [] }, "tests": [] + }, + { + "_id": "384b3198-6b05-46e8-b1d4-f417dabcd3cf", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Create Product", + "url": "http://localhost:9090/products", + "method": "POST", + "sortNum": 90000, + "created": "2024-03-29T06:21:49.579Z", + "modified": "2024-03-29T06:27:27.003Z", + "headers": [], + "params": [], + "body": { + "type": "json", + "raw": "{\n \"category\": \"Electronics\",\n \"name\": \"iPhone 15\",\n \"description\": \"Latest High-end smartphone\",\n \"price\": 1999.99,\n \"stockQuantity\": 40\n}", + "form": [] + }, + "tests": [] + }, + { + "_id": "5f776c4e-cd3b-4aae-a55d-d9e3df5f7225", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Get All Products", + "url": "http://localhost:9090/products", + "method": "GET", + "sortNum": 100000, + "created": "2024-03-29T06:27:49.406Z", + "modified": "2024-03-29T06:30:48.289Z", + "headers": [], + "params": [], + "tests": [] + }, + { + "_id": "55a70043-6bf7-451d-b62b-8ac0a1b825f6", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Get 1 Product", + "url": "http://localhost:9090/products/{id}", + "method": "GET", + "sortNum": 110000, + "created": "2024-03-29T06:27:57.526Z", + "modified": "2024-03-29T06:32:00.602Z", + "headers": [], + "params": [ + { + "name": "id", + "value": "7", + "isPath": true + } + ], + "tests": [] + }, + { + "_id": "24969b8e-21da-4985-ab11-120cc26e3949", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Search by name", + "url": "http://localhost:9090/products/search?name=iPhone 15", + "method": "GET", + "sortNum": 120000, + "created": "2024-03-29T06:28:04.237Z", + "modified": "2024-03-29T06:32:42.915Z", + "headers": [], + "params": [ + { + "name": "name", + "value": "iPhone 15", + "isPath": false + } + ], + "tests": [] + }, + { + "_id": "3890c062-8bf4-40a8-b938-a96cff06d136", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Search by Category", + "url": "http://localhost:9090/products/search/category?category=Elec", + "method": "GET", + "sortNum": 125000, + "created": "2024-03-29T06:28:58.671Z", + "modified": "2024-03-29T06:36:21.520Z", + "headers": [], + "params": [ + { + "name": "category", + "value": "Elec", + "isPath": false + } + ], + "tests": [] + }, + { + "_id": "284be03e-7cea-4fb1-b181-593b29ebf95d", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Update Product", + "url": "http://localhost:9090/products/{id}", + "method": "PUT", + "sortNum": 130000, + "created": "2024-03-29T06:28:09.610Z", + "modified": "2024-03-29T06:38:03.934Z", + "headers": [], + "params": [ + { + "name": "id", + "value": "7", + "isPath": true + } + ], + "body": { + "type": "json", + "raw": "{\n \"category\": \"Electronics\",\n \"name\": \"iPhone 15\",\n \"description\": \"Latest High-end smartphone\",\n \"price\": 2499.99,\n \"stockQuantity\": 40\n}", + "form": [] + }, + "tests": [] + }, + { + "_id": "6eccdb31-ed53-45bf-8ced-a548d706cd7b", + "colId": "e34b9201-d6f7-4614-a21c-21c245c1032e", + "containerId": "b5e69375-1661-4eb4-ba9c-9e01213e091c", + "name": "Delete Product", + "url": "http://localhost:9090/products/{id}", + "method": "DELETE", + "sortNum": 140000, + "created": "2024-03-29T06:28:13.074Z", + "modified": "2024-03-29T06:39:17.903Z", + "headers": [], + "params": [ + { + "name": "id", + "value": "6", + "isPath": true + } + ], + "tests": [] } ] } \ No newline at end of file diff --git a/src/main/java/sg/com/smartinventory/controllers/ProductController.java b/src/main/java/sg/com/smartinventory/controllers/ProductController.java index 07f49a0..d43b40e 100644 --- a/src/main/java/sg/com/smartinventory/controllers/ProductController.java +++ b/src/main/java/sg/com/smartinventory/controllers/ProductController.java @@ -1,10 +1,17 @@ package sg.com.smartinventory.controllers; +import java.util.ArrayList; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import jakarta.validation.Valid; @@ -14,21 +21,68 @@ @RestController @RequestMapping("/products") public class ProductController { - private ProductService productService; - - // @Autowired - public ProductController(ProductService productService) { - this.productService = productService; - } - - // CREATE. - @PostMapping("") - public ResponseEntity createProduct(@Valid @RequestBody Product product) { - // if(bindingResult.hasErrors()) { - // return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - // } - - Product newProduct = productService.createProduct(product); - return new ResponseEntity<>(newProduct, HttpStatus.CREATED); - } + private ProductService productService; + + // @Autowired + public ProductController(ProductService productService) { + this.productService = productService; + } + + // CREATE. + @PostMapping("") + public ResponseEntity createProduct(@Valid @RequestBody Product product) { + // if(bindingResult.hasErrors()) { + // return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + // } + + Product newProduct = productService.createProduct(product); + return new ResponseEntity<>(newProduct, HttpStatus.CREATED); + } + + // Get All + @GetMapping({ "", "/" }) + public ResponseEntity> getAllProducts() { + ArrayList allProducts = productService.getAllProducts(); + return new ResponseEntity<>(allProducts, HttpStatus.OK); + } + + // READ (id) + @GetMapping("/{id}") + public ResponseEntity getProduct(@PathVariable long id) { + Product foundProduct = productService.getProduct(id); + return new ResponseEntity<>(foundProduct, HttpStatus.OK); + } + + // READ (search by name) + @GetMapping("/search") + public ResponseEntity> searchProduct(@RequestParam String name) { + ArrayList products = productService.searchProduct(name); + return new ResponseEntity<>(products, HttpStatus.OK); + } + + // READ (search by category) + @GetMapping("/search/category") + public ResponseEntity> searchCategory(@RequestParam String category) { + ArrayList foundCategory = productService.searchProductCat(category); + return new ResponseEntity<>(foundCategory, HttpStatus.OK); + } + + // UPDATE + @PutMapping("/{id}") + public ResponseEntity updateProduct(@PathVariable Long id, @RequestBody Product product) { + // try { + Product updateProduct = productService.updateProduct(id, product); + return new ResponseEntity<>(updateProduct, HttpStatus.OK); + // } catch (ProductNotFoundException ex) { + // return new ResponseEntity<>(HttpStatus.NOT_FOUND); + // } -> Not needed already throw error in serviceImpls + } + + // Delete - refactor try catch block by adding throw in ProductServiceImpl + @DeleteMapping("/{id}") + public ResponseEntity deleteProduct(@PathVariable long id) { + productService.deleteProduct(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + } \ No newline at end of file diff --git a/src/main/java/sg/com/smartinventory/repositories/ProductRepository.java b/src/main/java/sg/com/smartinventory/repositories/ProductRepository.java index ce18b85..a83eb07 100644 --- a/src/main/java/sg/com/smartinventory/repositories/ProductRepository.java +++ b/src/main/java/sg/com/smartinventory/repositories/ProductRepository.java @@ -10,21 +10,21 @@ // This is a very powerful feature of Spring Data JPA. It will automatically do a property check and traverse the supported nested properties, translating them into the relevant queries. // We can also create custom queries using the JPA criteria API by simply creating a method with a certain naming convention specified by the query creation mechanism. public interface ProductRepository extends JpaRepository { - // Custom query to find all products with a certain ID. - // List findById(long id); + // Custom query to find all products with a certain ID. + // List findById(long id); - // Custom query to find all products with a certain category. - List findByCategory(String category); + // Custom query to find all products with a certain category. + List findByCategoryContaining(String category); - // Custom query to find all products with a certain name. - List findByName(String name); + // Custom query to find all products with a certain name. + List findByName(String name); - // Custom query to find all products with a certain description. - List findByDescription(String description); + // Custom query to find all products with a certain description. + List findByDescription(String description); - // Custom query to find all products with a certain price. - List findByPrice(double price); + // Custom query to find all products with a certain price. + List findByPrice(double price); - // Custom query to find all products with a certain stock quantity. - List findByStockQuantity(int stockQuantity); + // Custom query to find all products with a certain stock quantity. + List findByStockQuantity(int stockQuantity); } \ No newline at end of file diff --git a/src/main/java/sg/com/smartinventory/serviceImpls/ProductServiceImpl.java b/src/main/java/sg/com/smartinventory/serviceImpls/ProductServiceImpl.java index c1abeeb..f0ba617 100644 --- a/src/main/java/sg/com/smartinventory/serviceImpls/ProductServiceImpl.java +++ b/src/main/java/sg/com/smartinventory/serviceImpls/ProductServiceImpl.java @@ -12,55 +12,72 @@ @Service public class ProductServiceImpl implements ProductService { - private ProductRepository productRepository; + private ProductRepository productRepository; - // @Autowired - public ProductServiceImpl(ProductRepository productRepository) { - this.productRepository = productRepository; - } + // @Autowired + public ProductServiceImpl(ProductRepository productRepository) { + this.productRepository = productRepository; + } - @Override - public Product createProduct(Product product) { - Product newProduct = productRepository.save(product); + // - - - POST METHODS + @Override + public Product createProduct(Product product) { + Product newProduct = productRepository.save(product); - return newProduct; - } + return newProduct; + } - @Override - public Product getProduct(Long id) { - // Optional optionalProduct = productRepository.findById(id); - // if(optionalProduct.isPresent()) { - // Product foundProduct = optionalProduct.get(); - // return foundProduct; - // } - // throw new ProductNotFoundException(id); - return productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException(id)); - } + // - - - GET METHODS + @Override + public Product getProduct(Long id) { + // Optional optionalProduct = productRepository.findById(id); + // if(optionalProduct.isPresent()) { + // Product foundProduct = optionalProduct.get(); + // return foundProduct; + // } + // throw new ProductNotFoundException(id); + return productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException(id)); + } - @Override - public ArrayList getAllProducts() { - List allProducts = productRepository.findAll(); - return (ArrayList) allProducts; - } + @Override + public ArrayList getAllProducts() { + List allProducts = productRepository.findAll(); + return (ArrayList) allProducts; + } - @Override - public Product updateProduct(Long id, Product product) { - // Retrieve the product from the database. - Product productToUpdate = productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException(id)); + @Override + public ArrayList searchProduct(String name) { + List products = productRepository.findByName(name); + return (ArrayList) products; + } - // Update the product retrieved from the database. - productToUpdate.setCategory(product.getCategory()); - productToUpdate.setName(product.getName()); - productToUpdate.setDescription(product.getDescription()); - productToUpdate.setPrice(product.getPrice()); - productToUpdate.setStockQuantity(product.getStockQuantity()); + @Override + public ArrayList searchProductCat(String category) { + List products = productRepository.findByCategoryContaining(category); + return (ArrayList) products; + } - // Save the updated product back to the database. - return productRepository.save(productToUpdate); - } + // - - - PUT METHODS + @Override + public Product updateProduct(Long id, Product product) { + // Retrieve the product from the database. + Product productToUpdate = productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException(id)); - @Override - public void deleteProduct(long id) { - productRepository.deleteById(id); - } + // Update the product retrieved from the database. + productToUpdate.setCategory(product.getCategory()); + productToUpdate.setName(product.getName()); + productToUpdate.setDescription(product.getDescription()); + productToUpdate.setPrice(product.getPrice()); + productToUpdate.setStockQuantity(product.getStockQuantity()); + + // Save the updated product back to the database. + return productRepository.save(productToUpdate); + } + + // - - - DELETE METHODS + @Override // use long primitive type as args cannot be null + public void deleteProduct(long id) { + productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException(id)); + productRepository.deleteById(id); + } } \ No newline at end of file diff --git a/src/main/java/sg/com/smartinventory/services/ProductService.java b/src/main/java/sg/com/smartinventory/services/ProductService.java index 9db88ab..bdf3df6 100644 --- a/src/main/java/sg/com/smartinventory/services/ProductService.java +++ b/src/main/java/sg/com/smartinventory/services/ProductService.java @@ -5,13 +5,17 @@ import sg.com.smartinventory.entities.Product; public interface ProductService { - Product createProduct(Product product); + Product createProduct(Product product); - Product getProduct(Long id); + Product getProduct(Long id); - ArrayList getAllProducts(); + ArrayList getAllProducts(); - Product updateProduct(Long id, Product product); + ArrayList searchProduct(String name); - void deleteProduct(long id); + ArrayList searchProductCat(String category); + + Product updateProduct(Long id, Product product); + + void deleteProduct(long id); } \ No newline at end of file