Search bugs are fixed. Added Global searching parameter
This commit is contained in:
@@ -73,7 +73,7 @@ public class SecurityConfig {
|
||||
.requestMatchers(HttpMethod.GET, "/api/orders/user/**").authenticated()
|
||||
.requestMatchers(HttpMethod.GET, "/api/wallet/balance/**").authenticated()
|
||||
.requestMatchers(HttpMethod.GET, "/api/wallet/transactions/**").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/wallet/topup").hasAnyRole("MASTER", "MANAGER", "STAFF")
|
||||
.requestMatchers(HttpMethod.POST, "/api/wallet/topup").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/coupons/redeem").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/feedback/**").authenticated()
|
||||
.requestMatchers(HttpMethod.GET, "/api/feedback/**").authenticated()
|
||||
@@ -107,7 +107,18 @@ public class SecurityConfig {
|
||||
List<String> origins = Arrays.asList(allowedOriginsStr.split(","));
|
||||
configuration.setAllowedOrigins(origins);
|
||||
configuration.setAllowedOriginPatterns(List.of(
|
||||
"http://localhost:*"
|
||||
"http://localhost:*",
|
||||
"http://127.0.0.1:*",
|
||||
"http://192.168.*:*",
|
||||
"http://10.*:*",
|
||||
"http://172.*:*",
|
||||
"http://*.local:*",
|
||||
"https://localhost:*",
|
||||
"https://127.0.0.1:*",
|
||||
"https://192.168.*:*",
|
||||
"https://10.*:*",
|
||||
"https://172.*:*",
|
||||
"https://*.local:*"
|
||||
));
|
||||
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
|
||||
|
||||
@@ -261,6 +261,12 @@ public class OrderController {
|
||||
if (tokenUserId != null && !tokenUserId.equals(existingOrder.getUserId()) && !isStaff()) {
|
||||
return ResponseEntity.status(403).body(Map.of("error", "Access denied"));
|
||||
}
|
||||
|
||||
// Cannot modify completed/delivered orders
|
||||
if ("COMPLETED".equalsIgnoreCase(existingOrder.getStatus()) || "DELIVERED".equalsIgnoreCase(existingOrder.getStatus())) {
|
||||
return ResponseEntity.status(400).body(Map.of("error", "Cannot modify a completed or delivered order"));
|
||||
}
|
||||
|
||||
BigDecimal oldAmount = existingOrder.getTotalAmount();
|
||||
BigDecimal newAmount = updatedOrder.getTotalAmount();
|
||||
|
||||
|
||||
@@ -43,12 +43,13 @@ public class TerminalController {
|
||||
public List<TerminalDTO> getAllTerminals() {
|
||||
return terminalService.getAllTerminals().stream()
|
||||
.map(t -> new TerminalDTO(
|
||||
t.getId(),
|
||||
t.getName(),
|
||||
t.getLocation(),
|
||||
"********",
|
||||
t.getId(),
|
||||
t.getName(),
|
||||
t.getLocation(),
|
||||
"********",
|
||||
"****",
|
||||
t.isPaired(),
|
||||
t.isBlocked(),
|
||||
t.getDeviceId() != null ? maskDeviceId(t.getDeviceId()) : null,
|
||||
t.getPairedAt()
|
||||
))
|
||||
@@ -149,30 +150,39 @@ public class TerminalController {
|
||||
@RequestParam("paymentId") String paymentId,
|
||||
@RequestHeader(value = "X-API-KEY", required = false) String apiKeyHeader,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
|
||||
|
||||
String apiKey = extractApiKey(apiKeyHeader, authHeader);
|
||||
if (apiKey == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid or missing token"));
|
||||
}
|
||||
|
||||
// 1. Verify API Key
|
||||
Optional<Terminal> terminal = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminal.isEmpty()) {
|
||||
Optional<Terminal> terminalOpt = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminalOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid API Key"));
|
||||
}
|
||||
Terminal terminal = terminalOpt.get();
|
||||
|
||||
// 2. Parse and Clean payment IDs
|
||||
// 2. Check if terminal is blocked
|
||||
if (terminal.isBlocked()) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of(
|
||||
"status", "BLOCKED",
|
||||
"message", "This terminal is out of order"
|
||||
));
|
||||
}
|
||||
|
||||
// 3. Parse and Clean payment IDs
|
||||
List<String> orderNumbers = parseAndCleanOrderNumbers(paymentId);
|
||||
if (orderNumbers.isEmpty()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "paymentId required"));
|
||||
}
|
||||
|
||||
// 3. Try to fetch the first order that exists
|
||||
// 4. Try to fetch the first order that exists
|
||||
for (String orderNum : orderNumbers) {
|
||||
Optional<Order> orderOpt = orderRepository.findByOrderNumber(orderNum);
|
||||
if (orderOpt.isPresent()) {
|
||||
Order order = orderOpt.get();
|
||||
|
||||
|
||||
// Check if order is expired/archived
|
||||
if (order.isArchived()) {
|
||||
continue; // Check other IDs if available, or return GONE
|
||||
@@ -183,7 +193,7 @@ public class TerminalController {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(Map.of("message", "This order has already been fulfilled and cannot be printed again."));
|
||||
}
|
||||
|
||||
|
||||
return ResponseEntity.ok(order);
|
||||
}
|
||||
}
|
||||
@@ -196,30 +206,39 @@ public class TerminalController {
|
||||
@PathVariable("orderNumber") String orderNumber,
|
||||
@RequestHeader(value = "X-API-KEY", required = false) String apiKeyHeader,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
|
||||
|
||||
String apiKey = extractApiKey(apiKeyHeader, authHeader);
|
||||
if (apiKey == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid or missing token"));
|
||||
}
|
||||
|
||||
// 1. Verify API Key
|
||||
Optional<Terminal> terminal = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminal.isEmpty()) {
|
||||
Optional<Terminal> terminalOpt = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminalOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid API Key"));
|
||||
}
|
||||
Terminal terminal = terminalOpt.get();
|
||||
|
||||
// 2. Parse and Clean order numbers
|
||||
// 2. Check if terminal is blocked
|
||||
if (terminal.isBlocked()) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of(
|
||||
"status", "BLOCKED",
|
||||
"message", "This terminal is out of order"
|
||||
));
|
||||
}
|
||||
|
||||
// 3. Parse and Clean order numbers
|
||||
List<String> orderNumbers = parseAndCleanOrderNumbers(orderNumber);
|
||||
if (orderNumbers.isEmpty()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "orderNumber required"));
|
||||
}
|
||||
|
||||
// 3. Try to fetch the first order that exists
|
||||
// 4. Try to fetch the first order that exists
|
||||
for (String orderNum : orderNumbers) {
|
||||
Optional<Order> orderOpt = orderRepository.findByOrderNumber(orderNum);
|
||||
if (orderOpt.isPresent()) {
|
||||
Order order = orderOpt.get();
|
||||
|
||||
|
||||
// Check if order is expired/archived
|
||||
if (order.isArchived()) {
|
||||
return ResponseEntity.status(HttpStatus.GONE)
|
||||
@@ -231,7 +250,7 @@ public class TerminalController {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(Map.of("message", "This order has already been fulfilled and cannot be printed again."));
|
||||
}
|
||||
|
||||
|
||||
return ResponseEntity.ok(order);
|
||||
}
|
||||
}
|
||||
@@ -245,7 +264,7 @@ public class TerminalController {
|
||||
@RequestBody Map<String, String> body,
|
||||
@RequestHeader(value = "X-API-KEY", required = false) String apiKeyHeader,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
|
||||
|
||||
String orderNumber = body.get("orderNumber");
|
||||
if (orderNumber == null || orderNumber.isBlank()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "orderNumber required"));
|
||||
@@ -255,20 +274,29 @@ public class TerminalController {
|
||||
if (apiKey == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid or missing token"));
|
||||
}
|
||||
|
||||
|
||||
// 1. Verify API Key
|
||||
Optional<Terminal> terminal = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminal.isEmpty()) {
|
||||
Optional<Terminal> terminalOpt = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminalOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid API Key"));
|
||||
}
|
||||
Terminal terminal = terminalOpt.get();
|
||||
|
||||
// 2. Parse and Clean order numbers
|
||||
// 2. Check if terminal is blocked
|
||||
if (terminal.isBlocked()) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of(
|
||||
"status", "BLOCKED",
|
||||
"message", "This terminal is out of order"
|
||||
));
|
||||
}
|
||||
|
||||
// 3. Parse and Clean order numbers
|
||||
List<String> orderNumbers = parseAndCleanOrderNumbers(orderNumber);
|
||||
if (orderNumbers.isEmpty()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "orderNumber required"));
|
||||
}
|
||||
|
||||
// 3. Process all found orders
|
||||
// 4. Process all found orders
|
||||
List<String> successfulOrders = new ArrayList<>();
|
||||
boolean alreadyCompleted = false;
|
||||
boolean archivedFound = false;
|
||||
@@ -277,7 +305,7 @@ public class TerminalController {
|
||||
Optional<Order> orderOpt = orderRepository.findByOrderNumber(orderNum);
|
||||
if (orderOpt.isPresent()) {
|
||||
Order order = orderOpt.get();
|
||||
|
||||
|
||||
if (order.isArchived()) {
|
||||
archivedFound = true;
|
||||
continue;
|
||||
@@ -297,8 +325,8 @@ public class TerminalController {
|
||||
}
|
||||
|
||||
if (!successfulOrders.isEmpty()) {
|
||||
String msg = alreadyCompleted && successfulOrders.size() == 1
|
||||
? "Order was already marked as delivered."
|
||||
String msg = alreadyCompleted && successfulOrders.size() == 1
|
||||
? "Order was already marked as delivered."
|
||||
: "Order(s) marked as delivered successfully: " + String.join(", ", successfulOrders);
|
||||
return ResponseEntity.ok(Map.of("success", true, "message", msg));
|
||||
}
|
||||
@@ -317,7 +345,7 @@ public class TerminalController {
|
||||
@PathVariable("orderNumber") String orderNumber,
|
||||
@RequestHeader(value = "X-API-KEY", required = false) String apiKeyHeader,
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader) {
|
||||
|
||||
|
||||
if (orderNumber == null || orderNumber.isBlank()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "orderNumber required"));
|
||||
}
|
||||
@@ -326,20 +354,29 @@ public class TerminalController {
|
||||
if (apiKey == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid or missing token"));
|
||||
}
|
||||
|
||||
|
||||
// 1. Verify API Key
|
||||
Optional<Terminal> terminal = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminal.isEmpty()) {
|
||||
Optional<Terminal> terminalOpt = terminalRepository.findByApiKey(apiKey);
|
||||
if (terminalOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("message", "Invalid API Key"));
|
||||
}
|
||||
Terminal terminal = terminalOpt.get();
|
||||
|
||||
// 2. Parse and Clean order numbers
|
||||
// 2. Check if terminal is blocked
|
||||
if (terminal.isBlocked()) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of(
|
||||
"status", "BLOCKED",
|
||||
"message", "This terminal is out of order"
|
||||
));
|
||||
}
|
||||
|
||||
// 3. Parse and Clean order numbers
|
||||
List<String> orderNumbers = parseAndCleanOrderNumbers(orderNumber);
|
||||
if (orderNumbers.isEmpty()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("message", "orderNumber required"));
|
||||
}
|
||||
|
||||
// 3. Process all found orders
|
||||
// 4. Process all found orders
|
||||
List<String> successfulOrders = new ArrayList<>();
|
||||
boolean alreadyCompleted = false;
|
||||
boolean archivedFound = false;
|
||||
@@ -348,7 +385,7 @@ public class TerminalController {
|
||||
Optional<Order> orderOpt = orderRepository.findByOrderNumber(orderNum);
|
||||
if (orderOpt.isPresent()) {
|
||||
Order order = orderOpt.get();
|
||||
|
||||
|
||||
if (order.isArchived()) {
|
||||
archivedFound = true;
|
||||
continue;
|
||||
@@ -368,8 +405,8 @@ public class TerminalController {
|
||||
}
|
||||
|
||||
if (!successfulOrders.isEmpty()) {
|
||||
String msg = alreadyCompleted && successfulOrders.size() == 1
|
||||
? "Order was already marked as delivered."
|
||||
String msg = alreadyCompleted && successfulOrders.size() == 1
|
||||
? "Order was already marked as delivered."
|
||||
: "Order(s) marked as delivered successfully: " + String.join(", ", successfulOrders);
|
||||
return ResponseEntity.ok(Map.of("success", true, "message", msg));
|
||||
}
|
||||
@@ -394,7 +431,8 @@ public class TerminalController {
|
||||
"status", "VALID",
|
||||
"terminalId", t.getId(),
|
||||
"name", t.getName(),
|
||||
"location", t.getLocation()
|
||||
"location", t.getLocation(),
|
||||
"blocked", t.isBlocked()
|
||||
));
|
||||
}
|
||||
|
||||
@@ -493,6 +531,20 @@ public class TerminalController {
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/block")
|
||||
public ResponseEntity<?> toggleBlockStatus(@PathVariable Long id) {
|
||||
boolean newStatus = terminalService.toggleBlockStatus(id);
|
||||
if (terminalService.getTerminalById(id).isPresent()) {
|
||||
return ResponseEntity.ok(Map.of(
|
||||
"success", true,
|
||||
"blocked", newStatus,
|
||||
"message", newStatus ? "Terminal blocked" : "Terminal unblocked"
|
||||
));
|
||||
} else {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// Helpers
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -30,6 +30,9 @@ public class Terminal {
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean paired = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean blocked = false;
|
||||
|
||||
@Column(name = "paired_at")
|
||||
private LocalDateTime pairedAt;
|
||||
|
||||
@@ -64,6 +67,9 @@ public class Terminal {
|
||||
public boolean isPaired() { return paired; }
|
||||
public void setPaired(boolean paired) { this.paired = paired; }
|
||||
|
||||
public boolean isBlocked() { return blocked; }
|
||||
public void setBlocked(boolean blocked) { this.blocked = blocked; }
|
||||
|
||||
public LocalDateTime getPairedAt() { return pairedAt; }
|
||||
public void setPairedAt(LocalDateTime pairedAt) { this.pairedAt = pairedAt; }
|
||||
}
|
||||
|
||||
@@ -9,19 +9,21 @@ public class TerminalDTO {
|
||||
private String apiKey;
|
||||
private String pin;
|
||||
private boolean paired;
|
||||
private boolean blocked;
|
||||
private String deviceId;
|
||||
private LocalDateTime pairedAt;
|
||||
|
||||
public TerminalDTO() {}
|
||||
|
||||
public TerminalDTO(Long id, String name, String location, String apiKey, String pin,
|
||||
boolean paired, String deviceId, LocalDateTime pairedAt) {
|
||||
boolean paired, boolean blocked, String deviceId, LocalDateTime pairedAt) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
this.apiKey = apiKey;
|
||||
this.pin = pin;
|
||||
this.paired = paired;
|
||||
this.blocked = blocked;
|
||||
this.deviceId = deviceId;
|
||||
this.pairedAt = pairedAt;
|
||||
}
|
||||
@@ -45,6 +47,9 @@ public class TerminalDTO {
|
||||
public boolean isPaired() { return paired; }
|
||||
public void setPaired(boolean paired) { this.paired = paired; }
|
||||
|
||||
public boolean isBlocked() { return blocked; }
|
||||
public void setBlocked(boolean blocked) { this.blocked = blocked; }
|
||||
|
||||
public String getDeviceId() { return deviceId; }
|
||||
public void setDeviceId(String deviceId) { this.deviceId = deviceId; }
|
||||
|
||||
|
||||
@@ -44,6 +44,15 @@ public class TerminalService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean toggleBlockStatus(Long id) {
|
||||
if (id == null) return false;
|
||||
return terminalRepository.findById(id).map(terminal -> {
|
||||
terminal.setBlocked(!terminal.isBlocked());
|
||||
terminalRepository.save(terminal);
|
||||
return terminal.isBlocked();
|
||||
}).orElse(false);
|
||||
}
|
||||
|
||||
public Terminal updateTerminal(Long id, Terminal details) {
|
||||
if (id == null) return null;
|
||||
return terminalRepository.findById(id).map(existing -> {
|
||||
|
||||
Reference in New Issue
Block a user