added filter options to appointments in the backend and andriod

This commit is contained in:
Alex
2026-04-07 06:34:28 -06:00
parent b7f97c45a5
commit 6f646a7cf0
8 changed files with 261 additions and 96 deletions

View File

@@ -36,20 +36,29 @@ public class AppointmentController {
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
public ResponseEntity<Page<AppointmentResponse>> getAllAppointments(
@RequestParam(required = false) String q,
@RequestParam(required = false) Long storeId,
@RequestParam(required = false) String status,
@RequestParam(required = false) String date,
@RequestParam(required = false) Long customerId,
@RequestParam(required = false) Long employeeId,
Pageable pageable) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String role = authentication.getAuthorities().stream()
.findFirst()
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
.orElse(null);
Long customerId = null;
Long effectiveCustomerId = customerId;
if (role != null && role.equals("CUSTOMER")) {
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
customerId = user.getId();
effectiveCustomerId = user.getId();
}
return ResponseEntity.ok(appointmentService.getAllAppointments(q, pageable, customerId));
LocalDate appointmentDate = (date != null && !date.isBlank()) ? LocalDate.parse(date) : null;
return ResponseEntity.ok(appointmentService.getAllAppointments(
q, effectiveCustomerId, employeeId, storeId, status, appointmentDate, pageable));
}
@GetMapping("/{id}")

View File

@@ -22,20 +22,25 @@ public interface AppointmentRepository extends JpaRepository<Appointment, Long>
List<Appointment> findByStoreAndDate(@Param("storeId") Long storeId, @Param("date") LocalDate date);
@Query("SELECT a FROM Appointment a LEFT JOIN a.pet p WHERE " +
"(:q IS NULL OR (" +
"LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"LOWER(a.customer.lastName) 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);
Page<Appointment> findByCustomerId(Long customerId, Pageable pageable);
@Query("SELECT a FROM Appointment a LEFT JOIN a.pet p WHERE a.customer.id = :customerId AND (" +
"LOWER(a.customer.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"LOWER(a.customer.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"LOWER(a.service.serviceName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')))")
Page<Appointment> searchAppointmentsByCustomer(@Param("customerId") Long customerId, @Param("q") String query, Pageable pageable);
"LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%'))" +
")) AND " +
"(:customerId IS NULL OR a.customer.id = :customerId) AND " +
"(:employeeId IS NULL OR a.employee.id = :employeeId) AND " +
"(:storeId IS NULL OR a.store.storeId = :storeId) AND " +
"(:status IS NULL OR LOWER(a.appointmentStatus) = LOWER(:status)) AND " +
"(:date IS NULL OR a.appointmentDate = :date)")
Page<Appointment> searchAppointments(
@Param("q") String query,
@Param("customerId") Long customerId,
@Param("employeeId") Long employeeId,
@Param("storeId") Long storeId,
@Param("status") String status,
@Param("date") LocalDate date,
Pageable pageable);
@Query("SELECT a FROM Appointment a JOIN FETCH a.service WHERE a.employee.id = :employeeId AND a.appointmentDate = :date AND LOWER(a.appointmentStatus) NOT IN ('cancelled', 'missed')")
List<Appointment> findByEmployeeIdAndAppointmentDate(@Param("employeeId") Long employeeId, @Param("date") LocalDate date);

View File

@@ -45,22 +45,27 @@ public class AppointmentService {
}
@Transactional(readOnly = true)
public Page<AppointmentResponse> getAllAppointments(String query, Pageable pageable, Long customerId) {
Page<Appointment> appointments;
public Page<AppointmentResponse> getAllAppointments(
String query,
Long customerId,
Long employeeId,
Long storeId,
String status,
LocalDate date,
Pageable pageable) {
if (customerId != null) {
if (query != null && !query.trim().isEmpty()) {
appointments = appointmentRepository.searchAppointmentsByCustomer(customerId, query, pageable);
} else {
appointments = appointmentRepository.findByCustomerId(customerId, pageable);
}
} else {
if (query != null && !query.trim().isEmpty()) {
appointments = appointmentRepository.searchAppointments(query, pageable);
} else {
appointments = appointmentRepository.findAll(pageable);
}
}
String normalizedQuery = normalizeFilter(query);
String normalizedStatus = normalizeFilter(status);
Page<Appointment> appointments = appointmentRepository.searchAppointments(
normalizedQuery,
customerId,
employeeId,
storeId,
normalizedStatus,
date,
pageable
);
return appointments.map(this::mapToResponse);
}
@@ -204,6 +209,14 @@ public class AppointmentService {
return availableSlots;
}
private String normalizeFilter(String value) {
if (value == null) {
return null;
}
String trimmed = value.trim();
return trimmed.isEmpty() ? null : trimmed;
}
private void validateAppointmentRequest(AppointmentRequest request) {
if ("Booked".equalsIgnoreCase(request.getAppointmentStatus())) {
LocalDateTime appointmentDateTime = LocalDateTime.of(request.getAppointmentDate(), request.getAppointmentTime());