From 706cd94d140fa71b2a9bb9b0376b21e74bca05f9 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sun, 5 Apr 2026 23:58:21 -0600 Subject: [PATCH] Allow cross-store staff selection --- .../controller/DropdownController.java | 13 ++++++--- .../repository/EmployeeStoreRepository.java | 3 +++ .../controller/DropdownControllerTest.java | 27 +++++++++++++++++++ .../api/endpoints/DropdownApi.java | 8 ++++++ .../AdoptionDialogController.java | 7 ++++- .../AppointmentDialogController.java | 9 ++++--- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/petshop/backend/controller/DropdownController.java b/backend/src/main/java/com/petshop/backend/controller/DropdownController.java index 409891bc..d0a69036 100644 --- a/backend/src/main/java/com/petshop/backend/controller/DropdownController.java +++ b/backend/src/main/java/com/petshop/backend/controller/DropdownController.java @@ -156,13 +156,20 @@ public class DropdownController { ); } - @GetMapping("/stores/{storeId}/employees") + @GetMapping({"/stores/{storeId}/employees", "/employees"}) @PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')") - public ResponseEntity> getStoreEmployees(@PathVariable Long storeId) { + public ResponseEntity> getStoreEmployees(@PathVariable(required = false) Long storeId) { + List employees; + if (storeId == null || storeId == 0) { + employees = employeeStoreRepository.findActiveAllOrderByEmployeeEmployeeIdAsc(); + } else { + employees = employeeStoreRepository.findActiveByStoreStoreIdOrderByEmployeeEmployeeIdAsc(storeId); + } return ResponseEntity.ok( - employeeStoreRepository.findActiveByStoreStoreIdOrderByEmployeeEmployeeIdAsc(storeId).stream() + employees.stream() .filter(this::isAssignableEmployee) .map(this::toEmployeeOption) + .distinct() .collect(Collectors.toList()) ); } diff --git a/backend/src/main/java/com/petshop/backend/repository/EmployeeStoreRepository.java b/backend/src/main/java/com/petshop/backend/repository/EmployeeStoreRepository.java index 0cc3f771..16a59cea 100644 --- a/backend/src/main/java/com/petshop/backend/repository/EmployeeStoreRepository.java +++ b/backend/src/main/java/com/petshop/backend/repository/EmployeeStoreRepository.java @@ -15,4 +15,7 @@ public interface EmployeeStoreRepository extends JpaRepository findActiveByStoreStoreIdOrderByEmployeeEmployeeIdAsc(@Param("storeId") Long storeId); + + @Query("SELECT es FROM EmployeeStore es WHERE es.employee.isActive = true ORDER BY es.employee.employeeId ASC") + List findActiveAllOrderByEmployeeEmployeeIdAsc(); } diff --git a/backend/src/test/java/com/petshop/backend/controller/DropdownControllerTest.java b/backend/src/test/java/com/petshop/backend/controller/DropdownControllerTest.java index fa0a0ebe..e62430e6 100644 --- a/backend/src/test/java/com/petshop/backend/controller/DropdownControllerTest.java +++ b/backend/src/test/java/com/petshop/backend/controller/DropdownControllerTest.java @@ -125,6 +125,33 @@ class DropdownControllerTest { assertEquals(Long.valueOf(7L), response.getBody().get(0).getId()); } + @Test + void getStoreEmployeesReturnsAllStaffWhenStoreIdIsNull() { + StoreLocation store = new StoreLocation(); + store.setStoreId(1L); + + Employee staffEmployee = new Employee(); + staffEmployee.setEmployeeId(7L); + staffEmployee.setUserId(7L); + staffEmployee.setFirstName("Alex"); + staffEmployee.setLastName("Jones"); + staffEmployee.setIsActive(true); + + User staffUser = new User(); + staffUser.setId(7L); + staffUser.setRole(User.Role.STAFF); + staffUser.setActive(true); + + when(employeeStoreRepository.findActiveAllOrderByEmployeeEmployeeIdAsc()) + .thenReturn(List.of(new EmployeeStore(staffEmployee, store))); + when(userRepository.findById(7L)).thenReturn(Optional.of(staffUser)); + + var response = controller.getStoreEmployees(null); + + assertEquals(1, response.getBody().size()); + assertEquals(Long.valueOf(7L), response.getBody().get(0).getId()); + } + @Test void getStoreEmployeesExcludesInactiveStaffUsers() { StoreLocation store = new StoreLocation(); diff --git a/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java b/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java index 05b2785c..127d75db 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java +++ b/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/DropdownApi.java @@ -121,4 +121,12 @@ public class DropdownApi { } return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); } + + public List getEmployees() throws Exception { + String response = apiClient.getRawResponse("/api/v1/dropdowns/employees"); + if (response == null || response.isEmpty()) { + throw new IllegalStateException("Empty response from all employees endpoint"); + } + return apiClient.getObjectMapper().readValue(response, new TypeReference>() {}); + } } diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java index 3a331711..56f682c6 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java @@ -95,7 +95,12 @@ public class AdoptionDialogController { new Thread(() -> { try { Long storeId = UserSession.getInstance().getStoreId(); - List employees = storeId != null && storeId > 0 ? DropdownApi.getInstance().getStoreEmployees(storeId) : List.of(); + List employees; + if (storeId != null && storeId > 0) { + employees = DropdownApi.getInstance().getStoreEmployees(storeId); + } else { + employees = DropdownApi.getInstance().getEmployees(); + } Platform.runLater(() -> { cbEmployee.setItems(FXCollections.observableArrayList(employees)); applySelectedEmployee(); diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java index 472ca7b4..69cfd412 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java @@ -427,9 +427,12 @@ public class AppointmentDialogController { new Thread(() -> { try { Long storeId = UserSession.getInstance().getStoreId(); - List employees = storeId != null && storeId > 0 - ? DropdownApi.getInstance().getStoreEmployees(storeId) - : List.of(); + List employees; + if (storeId != null && storeId > 0) { + employees = DropdownApi.getInstance().getStoreEmployees(storeId); + } else { + employees = DropdownApi.getInstance().getEmployees(); + } Platform.runLater(() -> { cbEmployee.setItems(FXCollections.observableArrayList(employees)); applySelectedEmployee();