Add species filtering
This commit is contained in:
@@ -25,8 +25,9 @@ public class ServiceController {
|
|||||||
@GetMapping
|
@GetMapping
|
||||||
public ResponseEntity<Page<ServiceResponse>> getAllServices(
|
public ResponseEntity<Page<ServiceResponse>> getAllServices(
|
||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
|
@RequestParam(required = false) String species,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(serviceService.getAllServices(q, pageable));
|
return ResponseEntity.ok(serviceService.getAllServices(q, species, pageable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import org.springframework.stereotype.Repository;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface ServiceRepository extends JpaRepository<Service, Long> {
|
public interface ServiceRepository extends JpaRepository<Service, Long> {
|
||||||
|
|
||||||
@Query("SELECT s FROM Service s WHERE " +
|
@Query("SELECT DISTINCT s FROM Service s LEFT JOIN s.species sp WHERE " +
|
||||||
"LOWER(s.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"(:q IS NULL OR LOWER(s.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(COALESCE(s.serviceDesc, '')) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
|
||||||
"LOWER(s.serviceDesc) LIKE LOWER(CONCAT('%', :q, '%'))")
|
"(:species IS NULL OR LOWER(sp) = LOWER(:species))")
|
||||||
Page<Service> searchServices(@Param("q") String query, Pageable pageable);
|
Page<Service> searchServices(@Param("q") String q, @Param("species") String species, Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.petshop.backend.entity.Appointment;
|
|||||||
import com.petshop.backend.entity.Pet;
|
import com.petshop.backend.entity.Pet;
|
||||||
import com.petshop.backend.entity.StoreLocation;
|
import com.petshop.backend.entity.StoreLocation;
|
||||||
import com.petshop.backend.entity.User;
|
import com.petshop.backend.entity.User;
|
||||||
|
import com.petshop.backend.exception.BusinessException;
|
||||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||||
import com.petshop.backend.repository.AdoptionRepository;
|
import com.petshop.backend.repository.AdoptionRepository;
|
||||||
import com.petshop.backend.repository.AppointmentRepository;
|
import com.petshop.backend.repository.AppointmentRepository;
|
||||||
@@ -28,6 +29,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -108,6 +110,7 @@ public class AppointmentService {
|
|||||||
User employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
User employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
||||||
|
|
||||||
validateStoreAccess(store.getStoreId(), authenticatedUser);
|
validateStoreAccess(store.getStoreId(), authenticatedUser);
|
||||||
|
validatePetServiceCompatibility(pet, service);
|
||||||
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null);
|
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null);
|
||||||
|
|
||||||
Appointment appointment = new Appointment();
|
Appointment appointment = new Appointment();
|
||||||
@@ -147,6 +150,7 @@ public class AppointmentService {
|
|||||||
User employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
User employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
||||||
|
|
||||||
validateStoreAccess(store.getStoreId(), authenticatedUser);
|
validateStoreAccess(store.getStoreId(), authenticatedUser);
|
||||||
|
validatePetServiceCompatibility(pet, service);
|
||||||
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), id);
|
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), id);
|
||||||
|
|
||||||
appointment.setCustomer(customer);
|
appointment.setCustomer(customer);
|
||||||
@@ -254,6 +258,17 @@ public class AppointmentService {
|
|||||||
return trimmed.isEmpty() ? null : trimmed;
|
return trimmed.isEmpty() ? null : trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validatePetServiceCompatibility(Pet pet, com.petshop.backend.entity.Service service) {
|
||||||
|
if (pet == null) return;
|
||||||
|
Set<String> allowed = service.getSpecies();
|
||||||
|
if (allowed == null || allowed.isEmpty()) return;
|
||||||
|
boolean compatible = allowed.stream().anyMatch(s -> s.equalsIgnoreCase(pet.getPetSpecies()));
|
||||||
|
if (!compatible) {
|
||||||
|
throw new BusinessException(
|
||||||
|
"Service \"" + service.getServiceName() + "\" is not available for " + pet.getPetSpecies());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void validateAppointmentRequest(AppointmentRequest request) {
|
private void validateAppointmentRequest(AppointmentRequest request) {
|
||||||
if ("Booked".equalsIgnoreCase(request.getAppointmentStatus())) {
|
if ("Booked".equalsIgnoreCase(request.getAppointmentStatus())) {
|
||||||
LocalDateTime appointmentDateTime = LocalDateTime.of(request.getAppointmentDate(), request.getAppointmentTime());
|
LocalDateTime appointmentDateTime = LocalDateTime.of(request.getAppointmentDate(), request.getAppointmentTime());
|
||||||
|
|||||||
@@ -20,14 +20,10 @@ public class ServiceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public Page<ServiceResponse> getAllServices(String query, Pageable pageable) {
|
public Page<ServiceResponse> getAllServices(String query, String species, Pageable pageable) {
|
||||||
Page<com.petshop.backend.entity.Service> services;
|
String q = (query != null && !query.trim().isEmpty()) ? query.trim() : null;
|
||||||
if (query != null && !query.trim().isEmpty()) {
|
String sp = (species != null && !species.trim().isEmpty()) ? species.trim() : null;
|
||||||
services = serviceRepository.searchServices(query, pageable);
|
return serviceRepository.searchServices(q, sp, pageable).map(this::mapToResponse);
|
||||||
} else {
|
|
||||||
services = serviceRepository.findAll(pageable);
|
|
||||||
}
|
|
||||||
return services.map(this::mapToResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
|
|||||||
Reference in New Issue
Block a user