File History: src/main/java/com/paymentlink/controller/api/ProductApiController.java

← View file content

File Content at Commit f0438c2

1 package com.paymentlink.controller.api;
2
3 import com.paymentlink.model.entity.Product;
4 import com.paymentlink.service.ProductService;
5 import org.springframework.http.HttpStatus;
6 import org.springframework.http.ResponseEntity;
7 import org.springframework.web.bind.annotation.*;
8
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 @RestController
14 @RequestMapping("/api/products")
15 public class ProductApiController {
16
17 private final ProductService productService;
18
19 public ProductApiController(ProductService productService) {
20 this.productService = productService;
21 }
22
23 /**
24 * GET /api/products - List products with optional filtering and pagination
25 */
26 @GetMapping
27 public ResponseEntity<Map<String, Object>> getProducts(
28 @RequestParam(required = false) String category,
29 @RequestParam(required = false) String search,
30 @RequestParam(required = false) Boolean inStock,
31 @RequestParam(defaultValue = "1") int page,
32 @RequestParam(defaultValue = "12") int size) {
33
34 try {
35 List<Product> products;
36
37 if (search != null && !search.isEmpty()) {
38 products = productService.searchProducts(search, category);
39 } else if (category != null && !category.isEmpty()) {
40 products = productService.getProductsByCategory(category);
41 } else {
42 products = productService.getAllProducts();
43 }
44
45 // Filter by stock if requested
46 if (Boolean.TRUE.equals(inStock)) {
47 products = products.stream()
48 .filter(p -> p.getStock() == null || p.getStock() > 0)
49 .toList();
50 }
51
52 // Calculate pagination
53 int totalProducts = products.size();
54 int totalPages = (int) Math.ceil((double) totalProducts / size);
55 int startIndex = (page - 1) * size;
56 int endIndex = Math.min(startIndex + size, totalProducts);
57
58 // Validate page number
59 if (page < 1) page = 1;
60 if (page > totalPages && totalPages > 0) page = totalPages;
61
62 // Get paginated results
63 List<Product> paginatedProducts = (startIndex < totalProducts)
64 ? products.subList(startIndex, endIndex)
65 : List.of();
66
67 Map<String, Object> response = new HashMap<>();
68 response.put("success", true);
69 response.put("products", paginatedProducts);
70
71 // Pagination metadata
72 Map<String, Object> pagination = new HashMap<>();
73 pagination.put("currentPage", page);
74 pagination.put("pageSize", size);
75 pagination.put("totalProducts", totalProducts);
76 pagination.put("totalPages", totalPages);
77 pagination.put("hasNextPage", page < totalPages);
78 pagination.put("hasPreviousPage", page > 1);
79 response.put("pagination", pagination);
80
81 return ResponseEntity.ok(response);
82
83 } catch (Exception e) {
84 Map<String, Object> error = new HashMap<>();
85 error.put("success", false);
86 error.put("error", e.getMessage());
87 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
88 }
89 }
90
91 /**
92 * GET /api/products/categories/list - Get all categories
93 */
94 @GetMapping("/categories/list")
95 public ResponseEntity<Map<String, Object>> getCategories() {
96 try {
97 List<String> categories = productService.getAllCategories();
98 Map<String, Object> response = new HashMap<>();
99 response.put("success", true);
100 response.put("categories", categories);
101 return ResponseEntity.ok(response);
102
103 } catch (Exception e) {
104 Map<String, Object> error = new HashMap<>();
105 error.put("success", false);
106 error.put("error", e.getMessage());
107 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
108 }
109 }
110
111 /**
112 * GET /api/products/{id} - Get product by ID
113 */
114 @GetMapping("/{id}")
115 public ResponseEntity<Map<String, Object>> getProductById(@PathVariable Long id) {
116 try {
117 return productService.getProductById(id)
118 .map(product -> {
119 Map<String, Object> response = new HashMap<>();
120 response.put("success", true);
121 response.put("product", product);
122 return ResponseEntity.ok(response);
123 })
124 .orElseGet(() -> {
125 Map<String, Object> error = new HashMap<>();
126 error.put("success", false);
127 error.put("error", "Product not found");
128 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
129 });
130
131 } catch (Exception e) {
132 Map<String, Object> error = new HashMap<>();
133 error.put("success", false);
134 error.put("error", e.getMessage());
135 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
136 }
137 }
138
139 /**
140 * POST /api/products - Create product
141 */
142 @PostMapping
143 public ResponseEntity<Map<String, Object>> createProduct(@RequestBody Product product) {
144 try {
145 if (product.getName() == null || product.getPrice() == null || product.getCurrency() == null) {
146 Map<String, Object> error = new HashMap<>();
147 error.put("success", false);
148 error.put("error", "Name, price, and currency are required");
149 return ResponseEntity.badRequest().body(error);
150 }
151
152 Product created = productService.createProduct(product);
153 Map<String, Object> response = new HashMap<>();
154 response.put("success", true);
155 response.put("product", created);
156 return ResponseEntity.status(HttpStatus.CREATED).body(response);
157
158 } catch (Exception e) {
159 Map<String, Object> error = new HashMap<>();
160 error.put("success", false);
161 error.put("error", e.getMessage());
162 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
163 }
164 }
165
166 /**
167 * PUT /api/products/{id} - Update product
168 */
169 @PutMapping("/{id}")
170 public ResponseEntity<Map<String, Object>> updateProduct(
171 @PathVariable Long id,
172 @RequestBody Product updates) {
173
174 try {
175 return productService.updateProduct(id, updates)
176 .map(product -> {
177 Map<String, Object> response = new HashMap<>();
178 response.put("success", true);
179 response.put("product", product);
180 return ResponseEntity.ok(response);
181 })
182 .orElseGet(() -> {
183 Map<String, Object> error = new HashMap<>();
184 error.put("success", false);
185 error.put("error", "Product not found");
186 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
187 });
188
189 } catch (Exception e) {
190 Map<String, Object> error = new HashMap<>();
191 error.put("success", false);
192 error.put("error", e.getMessage());
193 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
194 }
195 }
196
197 /**
198 * DELETE /api/products/{id} - Delete product
199 */
200 @DeleteMapping("/{id}")
201 public ResponseEntity<Map<String, Object>> deleteProduct(@PathVariable Long id) {
202 try {
203 boolean deleted = productService.deleteProduct(id);
204 if (deleted) {
205 Map<String, Object> response = new HashMap<>();
206 response.put("success", true);
207 response.put("message", "Product deleted");
208 return ResponseEntity.ok(response);
209 } else {
210 Map<String, Object> error = new HashMap<>();
211 error.put("success", false);
212 error.put("error", "Product not found");
213 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
214 }
215
216 } catch (Exception e) {
217 Map<String, Object> error = new HashMap<>();
218 error.put("success", false);
219 error.put("error", e.getMessage());
220 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
221 }
222 }
223 }
224
225

Commits

Commit Author Date Message File SHA Actions
f0438c2 <f69e50@finnacloud.com> 1766443042 +0300 12/22/2025, 10:37:22 PM increment once more 016fc06 Hide
188fc92 <f69e50@finnacloud.com> 1766442998 +0300 12/22/2025, 10:36:38 PM increment 016fc06 View
4617f76 <f69e50@finnacloud.com> 1766442953 +0300 12/22/2025, 10:35:53 PM rename branch from main to master oops 016fc06 View
e6d1548 <f69e50@finnacloud.com> 1766442769 +0300 12/22/2025, 10:32:49 PM add initial test workflow file 016fc06 View
9c24ca4 <f69e50@finnacloud.com> 1766442705 +0300 12/22/2025, 10:31:45 PM add CI configuration and test script for Jenkins build 016fc06 View
690c1f6 <f69e50@finnacloud.com> 1766368110 +0300 12/22/2025, 1:48:30 AM initialize backend structure with controllers, DTOs, and configuration files 016fc06 View