Add species filtering

This commit is contained in:
2026-04-14 20:02:03 -06:00
parent f68c23b209
commit 7db8e966fc
4 changed files with 25 additions and 13 deletions

View File

@@ -25,8 +25,9 @@ public class ServiceController {
@GetMapping
public ResponseEntity<Page<ServiceResponse>> getAllServices(
@RequestParam(required = false) String q,
@RequestParam(required = false) String species,
Pageable pageable) {
return ResponseEntity.ok(serviceService.getAllServices(q, pageable));
return ResponseEntity.ok(serviceService.getAllServices(q, species, pageable));
}
@GetMapping("/{id}")

View File

@@ -11,8 +11,8 @@ import org.springframework.stereotype.Repository;
@Repository
public interface ServiceRepository extends JpaRepository<Service, Long> {
@Query("SELECT s FROM Service s WHERE " +
"LOWER(s.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"LOWER(s.serviceDesc) LIKE LOWER(CONCAT('%', :q, '%'))")
Page<Service> searchServices(@Param("q") String query, Pageable pageable);
@Query("SELECT DISTINCT s FROM Service s LEFT JOIN s.species sp WHERE " +
"(:q IS NULL OR LOWER(s.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(COALESCE(s.serviceDesc, '')) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
"(:species IS NULL OR LOWER(sp) = LOWER(:species))")
Page<Service> searchServices(@Param("q") String q, @Param("species") String species, Pageable pageable);
}

View File

@@ -8,6 +8,7 @@ import com.petshop.backend.entity.Appointment;
import com.petshop.backend.entity.Pet;
import com.petshop.backend.entity.StoreLocation;
import com.petshop.backend.entity.User;
import com.petshop.backend.exception.BusinessException;
import com.petshop.backend.exception.ResourceNotFoundException;
import com.petshop.backend.repository.AdoptionRepository;
import com.petshop.backend.repository.AppointmentRepository;
@@ -28,6 +29,7 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@@ -108,6 +110,7 @@ public class AppointmentService {
User employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
validateStoreAccess(store.getStoreId(), authenticatedUser);
validatePetServiceCompatibility(pet, service);
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null);
Appointment appointment = new Appointment();
@@ -147,6 +150,7 @@ public class AppointmentService {
User employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
validateStoreAccess(store.getStoreId(), authenticatedUser);
validatePetServiceCompatibility(pet, service);
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), id);
appointment.setCustomer(customer);
@@ -254,6 +258,17 @@ public class AppointmentService {
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) {
if ("Booked".equalsIgnoreCase(request.getAppointmentStatus())) {
LocalDateTime appointmentDateTime = LocalDateTime.of(request.getAppointmentDate(), request.getAppointmentTime());

View File

@@ -20,14 +20,10 @@ public class ServiceService {
}
@Transactional(readOnly = true)
public Page<ServiceResponse> getAllServices(String query, Pageable pageable) {
Page<com.petshop.backend.entity.Service> services;
if (query != null && !query.trim().isEmpty()) {
services = serviceRepository.searchServices(query, pageable);
} else {
services = serviceRepository.findAll(pageable);
}
return services.map(this::mapToResponse);
public Page<ServiceResponse> getAllServices(String query, String species, Pageable pageable) {
String q = (query != null && !query.trim().isEmpty()) ? query.trim() : null;
String sp = (species != null && !species.trim().isEmpty()) ? species.trim() : null;
return serviceRepository.searchServices(q, sp, pageable).map(this::mapToResponse);
}
@Transactional(readOnly = true)