diff --git a/kbazaar/src/main/java/com/kampus/kbazaar/product/Product.java b/kbazaar/src/main/java/com/kampus/kbazaar/product/Product.java index b71f323..f7fadf2 100644 --- a/kbazaar/src/main/java/com/kampus/kbazaar/product/Product.java +++ b/kbazaar/src/main/java/com/kampus/kbazaar/product/Product.java @@ -29,4 +29,8 @@ public class Product { @Column(name = "quantity") private int quantity; + + public ProductResponse toResponse() { + return new ProductResponse(this.id, this.name, this.sku, this.price, this.quantity); + } } diff --git a/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductController.java b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductController.java index 465c63e..32f68a2 100644 --- a/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductController.java +++ b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductController.java @@ -5,7 +5,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; + import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -17,56 +19,37 @@ @RequestMapping("/api/v1") public class ProductController { - private ProductRepository productRepository; - public ProductController(ProductRepository productRepository) { - this.productRepository = productRepository; - } + private ProductService productService; - protected static final Product[] productsDB = - new Product[] { - new Product(1L, "Product 1", "sku-1", 100.0, 10), - }; + public ProductController(ProductService productService) { + this.productService = productService; + } @ApiResponses({ - @ApiResponse( - responseCode = "200", - description = "list all products", - content = { + @ApiResponse( + responseCode = "200", + description = "list all products", + content = { + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = ProductResponse.class))) + }), + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = Product.class))) - }), - @ApiResponse( - responseCode = "500", - description = "internal server error", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Error.class))) + schema = @Schema(implementation = Error.class))) }) @GetMapping("/products") - public ResponseEntity getProducts() { - List pros = productRepository.findAll(); - - System.out.println("Products:"); - System.out.println(pros.size()); - for (Product product : pros) { - System.out.println(product); - } - System.out.println(":done"); - - return ResponseEntity.ok(productsDB); + public List getProducts() { + return productService.getAll(); } @GetMapping("/products/{sku}") - public ResponseEntity getProductById(@PathVariable String sku) { - for (Product product : productsDB) { - if (product.getSku().equals(sku)) { - return ResponseEntity.ok(product); - } - } - - return ResponseEntity.notFound().build(); + public ProductResponse getProductById(@PathVariable String sku) { + return productService.getBySku(sku); } } diff --git a/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductRepository.java b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductRepository.java index 268bdcb..43fbf2b 100644 --- a/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductRepository.java +++ b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductRepository.java @@ -3,5 +3,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository -public interface ProductRepository extends JpaRepository {} +public interface ProductRepository extends JpaRepository { + + Optional findBySku(String sku); +} diff --git a/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductResponse.java b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductResponse.java new file mode 100644 index 0000000..27031a8 --- /dev/null +++ b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductResponse.java @@ -0,0 +1,3 @@ +package com.kampus.kbazaar.product; + +public record ProductResponse(Long id, String name, String sku, double price, int quantity) {} \ No newline at end of file diff --git a/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductService.java b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductService.java new file mode 100644 index 0000000..365c745 --- /dev/null +++ b/kbazaar/src/main/java/com/kampus/kbazaar/product/ProductService.java @@ -0,0 +1,35 @@ +package com.kampus.kbazaar.product; + +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class ProductService { + + private ProductRepository productRepository; + + public ProductService(ProductRepository productRepository) { + this.productRepository = productRepository; + } + + public List getAll() { + return productRepository + .findAll() + .stream() + .map(p -> new ProductResponse(p.getId(), p.getName(), p.getSku(), p.getPrice(), p.getQuantity())) + .toList(); + } + + public ProductResponse getBySku(String sku) { + Optional product = productRepository.findBySku(sku); + if (product.isEmpty()) { +// throw new ProductNotFoundException("Product not found"); +// TODO: handle exception + return null; + } + + return product.get().toResponse(); + } +} diff --git a/kbazaar/src/main/resources/sql/data/users.sql b/kbazaar/src/main/resources/sql/data/users.sql new file mode 100644 index 0000000..f4d7669 --- /dev/null +++ b/kbazaar/src/main/resources/sql/data/users.sql @@ -0,0 +1,5 @@ +INSERT INTO users (username, email, password) VALUES ('TechNinja', 'techninja@example.com', 'password123') ON CONFLICT DO NOTHING; +INSERT INTO users (username, email, password) VALUES ('CodeMaster', 'codemaster@example.com', 'securepassword') ON CONFLICT DO NOTHING; +INSERT INTO users (username, email, password) VALUES ('DataGuru', 'dataguru@example.com', 'strongpassword') ON CONFLICT DO NOTHING; +INSERT INTO users (username, email, password) VALUES ('CyberSavvy', 'cybersavvy@example.com', 'password2022') ON CONFLICT DO NOTHING; +INSERT INTO users (username, email, password) VALUES ('GeekChic', 'geekchic@example.com', 'geeky123') ON CONFLICT DO NOTHING; diff --git a/kbazaar/src/main/resources/sql/schema/user.sql b/kbazaar/src/main/resources/sql/schema/user.sql new file mode 100644 index 0000000..e659661 --- /dev/null +++ b/kbazaar/src/main/resources/sql/schema/user.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + username VARCHAR (255) UNIQUE NOT NULL, + email VARCHAR (255) NOT NULL, + password VARCHAR (255) NOT NULL +); \ No newline at end of file diff --git a/kbazaar/src/test/java/com/kampus/kbazaar/product/ProductServiceTest.java b/kbazaar/src/test/java/com/kampus/kbazaar/product/ProductServiceTest.java new file mode 100644 index 0000000..e31dc31 --- /dev/null +++ b/kbazaar/src/test/java/com/kampus/kbazaar/product/ProductServiceTest.java @@ -0,0 +1,90 @@ +package com.kampus.kbazaar.product; + +import jdk.jfr.Name; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +class ProductServiceTest { + + @Mock + private ProductRepository productRepository; + + @InjectMocks + private ProductService productService; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testShouldBeAbleToGetAllProducts() { + // Mock data + Product product1 = new Product(1L, "Google Pixel 5", "MOBILE-GOOGLE-PIXEL-5", 12990.00, 100); + Product product2 = new Product(2L, "Coca-Cola", "BEV-COCA-COLA", 20.00, 150); + List productList = Arrays.asList(product1, product2); + + // Mock repository method + when(productRepository.findAll()).thenReturn(productList); + + // Call service method + List result = productService.getAll(); + + // Assertions + assertEquals(2, result.size()); + assertEquals("Google Pixel 5", result.get(0).name()); + assertEquals("MOBILE-GOOGLE-PIXEL-5", result.get(1).sku()); + } + + @Test + void testShouldReturnEmptyListWhenNoProductFoundGetAllProducts() { + // Mock repository method returning empty list + when(productRepository.findAll()).thenReturn(Arrays.asList()); + + // Call service method + List result = productService.getAll(); + + // Assertions + assertTrue(result.isEmpty()); + } + + @Test + void testShouldBeAbleToGetProductBySku() { + // Mock data + Product product = new Product(1L, "Pens", "STATIONERY-PEN-BIC-BALLPOINT", 14.99, 100); + + // Mock repository method + when(productRepository.findBySku("STATIONERY-PEN-BIC-BALLPOINT")).thenReturn(Optional.of(product)); + + // Call service method + ProductResponse result = productService.getBySku("STATIONERY-PEN-BIC-BALLPOINT"); + + // Assertions + assertEquals("Pens", result.name()); + assertEquals(14.99, result.price()); + } + + @Test + void testShouldReturnNullWhenGetProductNonExistingSKU() { + // Mock repository method returning empty optional + when(productRepository.findBySku(anyString())).thenReturn(Optional.empty()); + + // Call service method + ProductResponse result = productService.getBySku("NonExistingSKU"); + + // Assertions + assertNull(result); + } +}