Match Postman API contract for desktop app
- Change bulk delete from POST /bulk-delete to DELETE with body - Add search parameter support (q) to all list endpoints - Add customer registration endpoint - Add stores listing endpoint - Add analytics dashboard endpoint (admin only) - Update appointment availability to include storeId - Add CUSTOMER role to User entity - Implement search across all repositories
This commit is contained in:
@@ -22,8 +22,10 @@ public class AdoptionController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<AdoptionResponse>> getAllAdoptions(Pageable pageable) {
|
||||
return ResponseEntity.ok(adoptionService.getAllAdoptions(pageable));
|
||||
public ResponseEntity<Page<AdoptionResponse>> getAllAdoptions(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(adoptionService.getAllAdoptions(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@@ -49,7 +51,7 @@ public class AdoptionController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteAdoptions(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
adoptionService.bulkDeleteAdoptions(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.petshop.backend.controller;
|
||||
|
||||
import com.petshop.backend.dto.analytics.DashboardResponse;
|
||||
import com.petshop.backend.service.AnalyticsService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/analytics")
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
public class AnalyticsController {
|
||||
|
||||
private final AnalyticsService analyticsService;
|
||||
|
||||
public AnalyticsController(AnalyticsService analyticsService) {
|
||||
this.analyticsService = analyticsService;
|
||||
}
|
||||
|
||||
@GetMapping("/dashboard")
|
||||
public ResponseEntity<DashboardResponse> getDashboard(
|
||||
@RequestParam(defaultValue = "30") int days,
|
||||
@RequestParam(defaultValue = "10") int top) {
|
||||
return ResponseEntity.ok(analyticsService.getDashboardData(days, top));
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/appointments")
|
||||
public class AppointmentController {
|
||||
@@ -22,8 +25,10 @@ public class AppointmentController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<AppointmentResponse>> getAllAppointments(Pageable pageable) {
|
||||
return ResponseEntity.ok(appointmentService.getAllAppointments(pageable));
|
||||
public ResponseEntity<Page<AppointmentResponse>> getAllAppointments(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(appointmentService.getAllAppointments(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@@ -49,9 +54,18 @@ public class AppointmentController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteAppointments(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
appointmentService.bulkDeleteAppointments(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@GetMapping("/availability")
|
||||
public ResponseEntity<List<String>> checkAvailability(
|
||||
@RequestParam Long storeId,
|
||||
@RequestParam Long serviceId,
|
||||
@RequestParam String date) {
|
||||
LocalDate appointmentDate = LocalDate.parse(date);
|
||||
return ResponseEntity.ok(appointmentService.checkAvailability(storeId, serviceId, appointmentDate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.petshop.backend.controller;
|
||||
|
||||
import com.petshop.backend.dto.auth.LoginRequest;
|
||||
import com.petshop.backend.dto.auth.LoginResponse;
|
||||
import com.petshop.backend.dto.auth.RegisterRequest;
|
||||
import com.petshop.backend.dto.auth.UserInfoResponse;
|
||||
import com.petshop.backend.entity.User;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
@@ -16,6 +17,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -28,11 +30,47 @@ public class AuthController {
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final UserRepository userRepository;
|
||||
private final JwtUtil jwtUtil;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil) {
|
||||
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.userRepository = userRepository;
|
||||
this.jwtUtil = jwtUtil;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<?> register(@Valid @RequestBody RegisterRequest request) {
|
||||
if (userRepository.findByUsername(request.getEmail()).isPresent()) {
|
||||
Map<String, String> error = new HashMap<>();
|
||||
error.put("message", "Email already registered");
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
|
||||
}
|
||||
|
||||
User user = new User();
|
||||
user.setUsername(request.getEmail());
|
||||
user.setEmail(request.getEmail());
|
||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||
user.setFullName(request.getFirstName() + " " + request.getLastName());
|
||||
user.setRole(User.Role.CUSTOMER);
|
||||
user.setActive(true);
|
||||
|
||||
user = userRepository.save(user);
|
||||
|
||||
UserDetails userDetails = new org.springframework.security.core.userdetails.User(
|
||||
user.getUsername(),
|
||||
user.getPassword(),
|
||||
java.util.Collections.emptyList()
|
||||
);
|
||||
|
||||
String token = jwtUtil.generateToken(userDetails);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(new LoginResponse(
|
||||
token,
|
||||
user.getUsername(),
|
||||
user.getFullName(),
|
||||
user.getRole().name()
|
||||
));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
|
||||
@@ -51,7 +51,7 @@ public class CategoryController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteCategories(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
categoryService.bulkDeleteCategories(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -24,8 +24,10 @@ public class InventoryController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<InventoryResponse>> getAllInventory(Pageable pageable) {
|
||||
return ResponseEntity.ok(inventoryService.getAllInventory(pageable));
|
||||
public ResponseEntity<Page<InventoryResponse>> getAllInventory(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(inventoryService.getAllInventory(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@@ -51,7 +53,7 @@ public class InventoryController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteInventory(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
inventoryService.bulkDeleteInventory(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -51,7 +51,7 @@ public class PetController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeletePets(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
petService.bulkDeletePets(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ProductController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteProducts(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
productService.bulkDeleteProducts(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -24,8 +24,10 @@ public class ProductSupplierController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<ProductSupplierResponse>> getAllProductSuppliers(Pageable pageable) {
|
||||
return ResponseEntity.ok(productSupplierService.getAllProductSuppliers(pageable));
|
||||
public ResponseEntity<Page<ProductSupplierResponse>> getAllProductSuppliers(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(productSupplierService.getAllProductSuppliers(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{productId}/{supplierId}")
|
||||
@@ -56,7 +58,7 @@ public class ProductSupplierController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteProductSuppliers(@Valid @RequestBody BulkDeleteProductSupplierRequest request) {
|
||||
productSupplierService.bulkDeleteProductSuppliers(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -20,8 +20,10 @@ public class PurchaseOrderController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<PurchaseOrderResponse>> getAllPurchaseOrders(Pageable pageable) {
|
||||
return ResponseEntity.ok(purchaseOrderService.getAllPurchaseOrders(pageable));
|
||||
public ResponseEntity<Page<PurchaseOrderResponse>> getAllPurchaseOrders(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(purchaseOrderService.getAllPurchaseOrders(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
|
||||
@@ -21,8 +21,10 @@ public class SaleController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<SaleResponse>> getAllSales(Pageable pageable) {
|
||||
return ResponseEntity.ok(saleService.getAllSales(pageable));
|
||||
public ResponseEntity<Page<SaleResponse>> getAllSales(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(saleService.getAllSales(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ServiceController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteServices(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
serviceService.bulkDeleteServices(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.petshop.backend.controller;
|
||||
|
||||
import com.petshop.backend.dto.store.StoreResponse;
|
||||
import com.petshop.backend.service.StoreService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/stores")
|
||||
public class StoreController {
|
||||
|
||||
private final StoreService storeService;
|
||||
|
||||
public StoreController(StoreService storeService) {
|
||||
this.storeService = storeService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<StoreResponse>> getAllStores(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(storeService.getAllStores(q, pageable));
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class SupplierController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteSuppliers(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
supplierService.bulkDeleteSuppliers(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -24,8 +24,10 @@ public class UserController {
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<UserResponse>> getAllUsers(Pageable pageable) {
|
||||
return ResponseEntity.ok(userService.getAllUsers(pageable));
|
||||
public ResponseEntity<Page<UserResponse>> getAllUsers(
|
||||
@RequestParam(required = false) String q,
|
||||
Pageable pageable) {
|
||||
return ResponseEntity.ok(userService.getAllUsers(q, pageable));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@@ -51,7 +53,7 @@ public class UserController {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Void> bulkDeleteUsers(@Valid @RequestBody BulkDeleteRequest request) {
|
||||
userService.bulkDeleteUsers(request);
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -74,9 +74,8 @@ public class DashboardResponse {
|
||||
", dailySales=" + dailySales +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
class SalesSummary {
|
||||
public static class SalesSummary {
|
||||
private BigDecimal totalRevenue;
|
||||
private Long totalSales;
|
||||
private BigDecimal totalRefunds;
|
||||
@@ -148,7 +147,7 @@ class SalesSummary {
|
||||
}
|
||||
}
|
||||
|
||||
class InventorySummary {
|
||||
public static class InventorySummary {
|
||||
private Long totalProducts;
|
||||
private Long lowStockProducts;
|
||||
private Long outOfStockProducts;
|
||||
@@ -209,7 +208,7 @@ class InventorySummary {
|
||||
}
|
||||
}
|
||||
|
||||
class TopProduct {
|
||||
public static class TopProduct {
|
||||
private Long productId;
|
||||
private String productName;
|
||||
private Long quantitySold;
|
||||
@@ -281,7 +280,7 @@ class TopProduct {
|
||||
}
|
||||
}
|
||||
|
||||
class DailySales {
|
||||
public static class DailySales {
|
||||
private String date;
|
||||
private BigDecimal revenue;
|
||||
private Long salesCount;
|
||||
@@ -341,3 +340,4 @@ class DailySales {
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.petshop.backend.dto.auth;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RegisterRequest {
|
||||
@NotBlank(message = "First name is required")
|
||||
private String firstName;
|
||||
|
||||
@NotBlank(message = "Last name is required")
|
||||
private String lastName;
|
||||
|
||||
@NotBlank(message = "Email is required")
|
||||
@Email(message = "Email must be valid")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "Phone is required")
|
||||
private String phone;
|
||||
|
||||
@NotBlank(message = "Password is required")
|
||||
private String password;
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RegisterRequest that = (RegisterRequest) o;
|
||||
return Objects.equals(firstName, that.firstName) &&
|
||||
Objects.equals(lastName, that.lastName) &&
|
||||
Objects.equals(email, that.email) &&
|
||||
Objects.equals(phone, that.phone) &&
|
||||
Objects.equals(password, that.password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(firstName, lastName, email, phone, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RegisterRequest{" +
|
||||
"firstName='" + firstName + '\'' +
|
||||
", lastName='" + lastName + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", phone='" + phone + '\'' +
|
||||
", password='[PROTECTED]'" +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.petshop.backend.dto.store;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
public class StoreResponse {
|
||||
private Long id;
|
||||
private String storeName;
|
||||
private String storeLocation;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
public StoreResponse() {
|
||||
}
|
||||
|
||||
public StoreResponse(Long id, String storeName, String storeLocation, LocalDateTime createdAt) {
|
||||
this.id = id;
|
||||
this.storeName = storeName;
|
||||
this.storeLocation = storeLocation;
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getStoreName() {
|
||||
return storeName;
|
||||
}
|
||||
|
||||
public void setStoreName(String storeName) {
|
||||
this.storeName = storeName;
|
||||
}
|
||||
|
||||
public String getStoreLocation() {
|
||||
return storeLocation;
|
||||
}
|
||||
|
||||
public void setStoreLocation(String storeLocation) {
|
||||
this.storeLocation = storeLocation;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
StoreResponse that = (StoreResponse) o;
|
||||
return Objects.equals(id, that.id) && Objects.equals(storeName, that.storeName) && Objects.equals(storeLocation, that.storeLocation) && Objects.equals(createdAt, that.createdAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, storeName, storeLocation, createdAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StoreResponse{" +
|
||||
"id=" + id +
|
||||
", storeName='" + storeName + '\'' +
|
||||
", storeLocation='" + storeLocation + '\'' +
|
||||
", createdAt=" + createdAt +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class User {
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public enum Role {
|
||||
STAFF, ADMIN
|
||||
STAFF, ADMIN, CUSTOMER
|
||||
}
|
||||
|
||||
public User() {
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.Adoption;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AdoptionRepository extends JpaRepository<Adoption, Long> {
|
||||
|
||||
@Query("SELECT a FROM Adoption a WHERE " +
|
||||
"LOWER(a.customer.customerName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<Adoption> searchAdoptions(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.Appointment;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
@@ -15,4 +17,13 @@ public interface AppointmentRepository extends JpaRepository<Appointment, Long>
|
||||
|
||||
@Query("SELECT a FROM Appointment a WHERE a.appointmentDate = :date AND a.appointmentTime = :time")
|
||||
List<Appointment> findByDateAndTime(@Param("date") LocalDate date, @Param("time") LocalTime time);
|
||||
|
||||
@Query("SELECT a FROM Appointment a WHERE a.service.id = :serviceId AND a.appointmentDate = :date AND a.status != 'Cancelled'")
|
||||
List<Appointment> findByServiceAndDate(@Param("serviceId") Long serviceId, @Param("date") LocalDate date);
|
||||
|
||||
@Query("SELECT DISTINCT a FROM Appointment a LEFT JOIN a.pets p WHERE " +
|
||||
"LOWER(a.customer.customerName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(a.service.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<Appointment> searchAppointments(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.Inventory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
@@ -13,4 +15,9 @@ public interface InventoryRepository extends JpaRepository<Inventory, Long> {
|
||||
|
||||
@Query("SELECT i FROM Inventory i WHERE i.product.id = :productId AND i.store.id = :storeId")
|
||||
Optional<Inventory> findByProductIdAndStoreId(@Param("productId") Long productId, @Param("storeId") Long storeId);
|
||||
|
||||
@Query("SELECT i FROM Inventory i WHERE " +
|
||||
"LOWER(i.product.productName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(i.store.storeName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<Inventory> searchInventory(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.ProductSupplier;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ProductSupplierRepository extends JpaRepository<ProductSupplier, ProductSupplier.ProductSupplierId> {
|
||||
|
||||
@Query("SELECT ps FROM ProductSupplier ps WHERE " +
|
||||
"LOWER(ps.product.productName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(ps.supplier.supplierName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<ProductSupplier> searchProductSuppliers(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.PurchaseOrder;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PurchaseOrderRepository extends JpaRepository<PurchaseOrder, Long> {
|
||||
|
||||
@Query("SELECT po FROM PurchaseOrder po WHERE " +
|
||||
"LOWER(po.supplier.supplierName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(po.notes) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<PurchaseOrder> searchPurchaseOrders(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.Sale;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface SaleRepository extends JpaRepository<Sale, Long> {
|
||||
|
||||
@Query("SELECT s FROM Sale s WHERE " +
|
||||
"LOWER(s.customer.customerName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(s.employee.fullName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(s.store.storeName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<Sale> searchSales(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.Store;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface StoreRepository extends JpaRepository<Store, Long> {
|
||||
|
||||
@Query("SELECT s FROM Store s WHERE " +
|
||||
"LOWER(s.storeName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(s.storeLocation) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<Store> searchStores(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.petshop.backend.repository;
|
||||
|
||||
import com.petshop.backend.entity.User;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -10,4 +14,10 @@ import java.util.Optional;
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
Optional<User> findByUsername(String username);
|
||||
boolean existsByUsername(String username);
|
||||
|
||||
@Query("SELECT u FROM User u WHERE " +
|
||||
"LOWER(u.username) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(u.fullName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||
"LOWER(u.email) LIKE LOWER(CONCAT('%', :q, '%'))")
|
||||
Page<User> searchUsers(@Param("q") String query, Pageable pageable);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class SecurityConfig {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/v1/auth/login").permitAll()
|
||||
.requestMatchers("/api/v1/auth/login", "/api/v1/auth/register").permitAll()
|
||||
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/dropdowns/suppliers").hasRole("ADMIN")
|
||||
.requestMatchers("/api/v1/inventory/**").hasRole("ADMIN")
|
||||
|
||||
@@ -28,8 +28,14 @@ public class AdoptionService {
|
||||
this.customerRepository = customerRepository;
|
||||
}
|
||||
|
||||
public Page<AdoptionResponse> getAllAdoptions(Pageable pageable) {
|
||||
return adoptionRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<AdoptionResponse> getAllAdoptions(String query, Pageable pageable) {
|
||||
Page<Adoption> adoptions;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
adoptions = adoptionRepository.searchAdoptions(query, pageable);
|
||||
} else {
|
||||
adoptions = adoptionRepository.findAll(pageable);
|
||||
}
|
||||
return adoptions.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public AdoptionResponse getAdoptionById(Long id) {
|
||||
|
||||
141
src/main/java/com/petshop/backend/service/AnalyticsService.java
Normal file
141
src/main/java/com/petshop/backend/service/AnalyticsService.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.analytics.DashboardResponse;
|
||||
import com.petshop.backend.entity.Inventory;
|
||||
import com.petshop.backend.entity.Product;
|
||||
import com.petshop.backend.entity.Refund;
|
||||
import com.petshop.backend.entity.Sale;
|
||||
import com.petshop.backend.repository.InventoryRepository;
|
||||
import com.petshop.backend.repository.ProductRepository;
|
||||
import com.petshop.backend.repository.RefundRepository;
|
||||
import com.petshop.backend.repository.SaleRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class AnalyticsService {
|
||||
|
||||
private final SaleRepository saleRepository;
|
||||
private final RefundRepository refundRepository;
|
||||
private final InventoryRepository inventoryRepository;
|
||||
private final ProductRepository productRepository;
|
||||
|
||||
public AnalyticsService(SaleRepository saleRepository, RefundRepository refundRepository,
|
||||
InventoryRepository inventoryRepository, ProductRepository productRepository) {
|
||||
this.saleRepository = saleRepository;
|
||||
this.refundRepository = refundRepository;
|
||||
this.inventoryRepository = inventoryRepository;
|
||||
this.productRepository = productRepository;
|
||||
}
|
||||
|
||||
public DashboardResponse getDashboardData(int days, int top) {
|
||||
LocalDateTime startDate = LocalDateTime.now().minusDays(days);
|
||||
|
||||
List<Sale> sales = saleRepository.findAll().stream()
|
||||
.filter(sale -> sale.getSaleDate().isAfter(startDate))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Refund> refunds = refundRepository.findAll().stream()
|
||||
.filter(refund -> refund.getRefundDate().isAfter(startDate))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
DashboardResponse.SalesSummary salesSummary = calculateSalesSummary(sales, refunds);
|
||||
DashboardResponse.InventorySummary inventorySummary = calculateInventorySummary();
|
||||
List<DashboardResponse.TopProduct> topProducts = calculateTopProducts(sales, top);
|
||||
List<DashboardResponse.DailySales> dailySales = calculateDailySales(sales, days);
|
||||
|
||||
return new DashboardResponse(salesSummary, inventorySummary, topProducts, dailySales);
|
||||
}
|
||||
|
||||
private DashboardResponse.SalesSummary calculateSalesSummary(List<Sale> sales, List<Refund> refunds) {
|
||||
BigDecimal totalRevenue = sales.stream()
|
||||
.map(Sale::getTotal)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
Long totalSales = (long) sales.size();
|
||||
|
||||
BigDecimal totalRefunds = refunds.stream()
|
||||
.map(Refund::getRefundAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
Long totalRefundCount = (long) refunds.size();
|
||||
|
||||
return new DashboardResponse.SalesSummary(totalRevenue, totalSales, totalRefunds, totalRefundCount);
|
||||
}
|
||||
|
||||
private DashboardResponse.InventorySummary calculateInventorySummary() {
|
||||
List<Inventory> allInventory = inventoryRepository.findAll();
|
||||
|
||||
Long totalProducts = productRepository.count();
|
||||
|
||||
Long lowStockProducts = allInventory.stream()
|
||||
.filter(inv -> inv.getQuantity() > 0 && inv.getQuantity() <= inv.getReorderLevel())
|
||||
.map(inv -> inv.getProduct().getId())
|
||||
.distinct()
|
||||
.count();
|
||||
|
||||
Long outOfStockProducts = allInventory.stream()
|
||||
.filter(inv -> inv.getQuantity() == 0)
|
||||
.map(inv -> inv.getProduct().getId())
|
||||
.distinct()
|
||||
.count();
|
||||
|
||||
return new DashboardResponse.InventorySummary(totalProducts, lowStockProducts, outOfStockProducts);
|
||||
}
|
||||
|
||||
private List<DashboardResponse.TopProduct> calculateTopProducts(List<Sale> sales, int top) {
|
||||
Map<Long, DashboardResponse.TopProduct> productSalesMap = new HashMap<>();
|
||||
|
||||
for (Sale sale : sales) {
|
||||
for (var item : sale.getItems()) {
|
||||
Long productId = item.getProduct().getId();
|
||||
String productName = item.getProduct().getProductName();
|
||||
Long quantitySold = Long.valueOf(item.getQuantity());
|
||||
BigDecimal revenue = item.getSubtotal();
|
||||
|
||||
productSalesMap.compute(productId, (key, existing) -> {
|
||||
if (existing == null) {
|
||||
return new DashboardResponse.TopProduct(productId, productName, quantitySold, revenue);
|
||||
} else {
|
||||
existing.setQuantitySold(existing.getQuantitySold() + quantitySold);
|
||||
existing.setRevenue(existing.getRevenue().add(revenue));
|
||||
return existing;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return productSalesMap.values().stream()
|
||||
.sorted((p1, p2) -> p2.getRevenue().compareTo(p1.getRevenue()))
|
||||
.limit(top)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<DashboardResponse.DailySales> calculateDailySales(List<Sale> sales, int days) {
|
||||
Map<LocalDate, DashboardResponse.DailySales> dailySalesMap = new LinkedHashMap<>();
|
||||
|
||||
LocalDate startDate = LocalDate.now().minusDays(days - 1);
|
||||
for (int i = 0; i < days; i++) {
|
||||
LocalDate date = startDate.plusDays(i);
|
||||
String dateStr = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
|
||||
dailySalesMap.put(date, new DashboardResponse.DailySales(dateStr, BigDecimal.ZERO, 0L));
|
||||
}
|
||||
|
||||
for (Sale sale : sales) {
|
||||
LocalDate saleDate = sale.getSaleDate().toLocalDate();
|
||||
if (dailySalesMap.containsKey(saleDate)) {
|
||||
DashboardResponse.DailySales dailySale = dailySalesMap.get(saleDate);
|
||||
dailySale.setRevenue(dailySale.getRevenue().add(sale.getTotal()));
|
||||
dailySale.setSalesCount(dailySale.getSalesCount() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(dailySalesMap.values());
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -36,8 +39,14 @@ public class AppointmentService {
|
||||
this.petRepository = petRepository;
|
||||
}
|
||||
|
||||
public Page<AppointmentResponse> getAllAppointments(Pageable pageable) {
|
||||
return appointmentRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<AppointmentResponse> getAllAppointments(String query, Pageable pageable) {
|
||||
Page<Appointment> appointments;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
appointments = appointmentRepository.searchAppointments(query, pageable);
|
||||
} else {
|
||||
appointments = appointmentRepository.findAll(pageable);
|
||||
}
|
||||
return appointments.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public AppointmentResponse getAppointmentById(Long id) {
|
||||
@@ -107,6 +116,30 @@ public class AppointmentService {
|
||||
appointmentRepository.deleteAllById(request.getIds());
|
||||
}
|
||||
|
||||
public List<String> checkAvailability(Long storeId, Long serviceId, LocalDate date) {
|
||||
com.petshop.backend.entity.Service service = serviceRepository.findById(serviceId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Service not found with id: " + serviceId));
|
||||
|
||||
List<Appointment> existingAppointments = appointmentRepository.findByServiceAndDate(serviceId, date);
|
||||
Set<LocalTime> bookedTimes = existingAppointments.stream()
|
||||
.map(Appointment::getAppointmentTime)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<String> availableSlots = new ArrayList<>();
|
||||
LocalTime startTime = LocalTime.of(9, 0);
|
||||
LocalTime endTime = LocalTime.of(17, 0);
|
||||
|
||||
LocalTime currentTime = startTime;
|
||||
while (currentTime.isBefore(endTime)) {
|
||||
if (!bookedTimes.contains(currentTime)) {
|
||||
availableSlots.add(currentTime.toString());
|
||||
}
|
||||
currentTime = currentTime.plusMinutes(30);
|
||||
}
|
||||
|
||||
return availableSlots;
|
||||
}
|
||||
|
||||
private Set<Pet> fetchPets(List<Long> petIds) {
|
||||
Set<Pet> pets = new HashSet<>();
|
||||
for (Long petId : petIds) {
|
||||
|
||||
@@ -30,8 +30,14 @@ public class InventoryService {
|
||||
this.storeRepository = storeRepository;
|
||||
}
|
||||
|
||||
public Page<InventoryResponse> getAllInventory(Pageable pageable) {
|
||||
return inventoryRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<InventoryResponse> getAllInventory(String query, Pageable pageable) {
|
||||
Page<Inventory> inventory;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
inventory = inventoryRepository.searchInventory(query, pageable);
|
||||
} else {
|
||||
inventory = inventoryRepository.findAll(pageable);
|
||||
}
|
||||
return inventory.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public InventoryResponse getInventoryById(Long id) {
|
||||
|
||||
@@ -28,8 +28,14 @@ public class ProductSupplierService {
|
||||
this.supplierRepository = supplierRepository;
|
||||
}
|
||||
|
||||
public Page<ProductSupplierResponse> getAllProductSuppliers(Pageable pageable) {
|
||||
return productSupplierRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<ProductSupplierResponse> getAllProductSuppliers(String query, Pageable pageable) {
|
||||
Page<ProductSupplier> productSuppliers;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
productSuppliers = productSupplierRepository.searchProductSuppliers(query, pageable);
|
||||
} else {
|
||||
productSuppliers = productSupplierRepository.findAll(pageable);
|
||||
}
|
||||
return productSuppliers.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public ProductSupplierResponse getProductSupplierById(Long productId, Long supplierId) {
|
||||
|
||||
@@ -22,8 +22,14 @@ public class PurchaseOrderService {
|
||||
this.purchaseOrderRepository = purchaseOrderRepository;
|
||||
}
|
||||
|
||||
public Page<PurchaseOrderResponse> getAllPurchaseOrders(Pageable pageable) {
|
||||
return purchaseOrderRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<PurchaseOrderResponse> getAllPurchaseOrders(String query, Pageable pageable) {
|
||||
Page<PurchaseOrder> purchaseOrders;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
purchaseOrders = purchaseOrderRepository.searchPurchaseOrders(query, pageable);
|
||||
} else {
|
||||
purchaseOrders = purchaseOrderRepository.findAll(pageable);
|
||||
}
|
||||
return purchaseOrders.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public PurchaseOrderResponse getPurchaseOrderById(Long id) {
|
||||
|
||||
@@ -36,8 +36,14 @@ public class SaleService {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public Page<SaleResponse> getAllSales(Pageable pageable) {
|
||||
return saleRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<SaleResponse> getAllSales(String query, Pageable pageable) {
|
||||
Page<Sale> sales;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
sales = saleRepository.searchSales(query, pageable);
|
||||
} else {
|
||||
sales = saleRepository.findAll(pageable);
|
||||
}
|
||||
return sales.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public SaleResponse getSaleById(Long id) {
|
||||
|
||||
37
src/main/java/com/petshop/backend/service/StoreService.java
Normal file
37
src/main/java/com/petshop/backend/service/StoreService.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.store.StoreResponse;
|
||||
import com.petshop.backend.entity.Store;
|
||||
import com.petshop.backend.repository.StoreRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class StoreService {
|
||||
|
||||
private final StoreRepository storeRepository;
|
||||
|
||||
public StoreService(StoreRepository storeRepository) {
|
||||
this.storeRepository = storeRepository;
|
||||
}
|
||||
|
||||
public Page<StoreResponse> getAllStores(String query, Pageable pageable) {
|
||||
Page<Store> stores;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
stores = storeRepository.searchStores(query, pageable);
|
||||
} else {
|
||||
stores = storeRepository.findAll(pageable);
|
||||
}
|
||||
return stores.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
private StoreResponse mapToResponse(Store store) {
|
||||
return new StoreResponse(
|
||||
store.getId(),
|
||||
store.getStoreName(),
|
||||
store.getStoreLocation(),
|
||||
store.getCreatedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,14 @@ public class UserService {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
public Page<UserResponse> getAllUsers(Pageable pageable) {
|
||||
return userRepository.findAll(pageable).map(this::mapToResponse);
|
||||
public Page<UserResponse> getAllUsers(String query, Pageable pageable) {
|
||||
Page<User> users;
|
||||
if (query != null && !query.trim().isEmpty()) {
|
||||
users = userRepository.searchUsers(query, pageable);
|
||||
} else {
|
||||
users = userRepository.findAll(pageable);
|
||||
}
|
||||
return users.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
public UserResponse getUserById(Long id) {
|
||||
|
||||
Reference in New Issue
Block a user