From 4845aeb479f06b0e453605a089b2796630adbbe8 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Wed, 8 Apr 2026 08:11:20 -0600 Subject: [PATCH] restrict adoption pets --- .../backend/controller/DropdownController.java | 2 +- .../petshop/backend/repository/PetRepository.java | 8 ++++++++ .../petshop/backend/service/AdoptionService.java | 10 ++++++---- .../AdoptionDialogController.java | 14 ++++++++++++++ 4 files changed, 29 insertions(+), 5 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 3b0a2009..acf77b52 100644 --- a/backend/src/main/java/com/petshop/backend/controller/DropdownController.java +++ b/backend/src/main/java/com/petshop/backend/controller/DropdownController.java @@ -52,7 +52,7 @@ public class DropdownController { @PreAuthorize("hasAnyRole('STAFF', 'ADMIN')") public ResponseEntity> getAdoptionPets() { return ResponseEntity.ok( - petRepository.findAllByPetStatusIgnoreCaseOrderByPetNameAsc("Available").stream() + petRepository.findAdoptablePetsOrderByPetNameAsc().stream() .map(p -> new DropdownOption(p.getPetId(), p.getPetName())) .collect(Collectors.toList()) ); diff --git a/backend/src/main/java/com/petshop/backend/repository/PetRepository.java b/backend/src/main/java/com/petshop/backend/repository/PetRepository.java index 73f05460..970050e1 100644 --- a/backend/src/main/java/com/petshop/backend/repository/PetRepository.java +++ b/backend/src/main/java/com/petshop/backend/repository/PetRepository.java @@ -15,6 +15,14 @@ import java.util.Optional; public interface PetRepository extends JpaRepository { List findAllByPetStatusIgnoreCaseOrderByPetNameAsc(String petStatus); + @Query("SELECT p FROM Pet p " + + "WHERE LOWER(p.petStatus) = 'available' " + + "AND NOT EXISTS (" + + " SELECT 1 FROM Adoption a " + + " WHERE a.pet = p AND LOWER(a.adoptionStatus) = 'completed'" + + ") " + + "ORDER BY p.petName ASC") + List findAdoptablePetsOrderByPetNameAsc(); List findAllByOwner_IdOrderByPetNameAsc(Long ownerId); Optional findByIdAndOwner_Id(Long id, Long ownerId); diff --git a/backend/src/main/java/com/petshop/backend/service/AdoptionService.java b/backend/src/main/java/com/petshop/backend/service/AdoptionService.java index ab528b79..0e3c7a95 100644 --- a/backend/src/main/java/com/petshop/backend/service/AdoptionService.java +++ b/backend/src/main/java/com/petshop/backend/service/AdoptionService.java @@ -80,7 +80,7 @@ public class AdoptionService { .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getSourceStoreId())) : null; String adoptionStatus = normalizeAdoptionStatus(request.getAdoptionStatus()); - validatePetAvailability(pet, null); + validatePetAvailability(pet, null, null); Adoption adoption = new Adoption(); adoption.setPet(pet); @@ -111,7 +111,8 @@ public class AdoptionService { .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getSourceStoreId())) : null; String adoptionStatus = normalizeAdoptionStatus(request.getAdoptionStatus()); - validatePetAvailability(pet, adoption.getAdoptionId()); + Long currentPetId = adoption.getPet() != null ? adoption.getPet().getPetId() : null; + validatePetAvailability(pet, adoption.getAdoptionId(), currentPetId); adoption.setPet(pet); adoption.setCustomer(customer); @@ -201,7 +202,8 @@ public class AdoptionService { throw new IllegalArgumentException("Adoption status must be Pending, Completed, or Cancelled"); } - private void validatePetAvailability(Pet pet, Long adoptionId) { + private void validatePetAvailability(Pet pet, Long adoptionId, Long currentPetId) { + boolean samePetAsCurrentAdoption = currentPetId != null && currentPetId.equals(pet.getPetId()); boolean adoptedElsewhere = adoptionId == null ? adoptionRepository.existsByPet_IdAndAdoptionStatusIgnoreCase(pet.getPetId(), ADOPTION_STATUS_COMPLETED) : adoptionRepository.existsByPet_IdAndAdoptionStatusIgnoreCaseAndAdoptionIdNot(pet.getPetId(), ADOPTION_STATUS_COMPLETED, adoptionId); @@ -209,7 +211,7 @@ public class AdoptionService { throw new IllegalArgumentException("Selected pet has already been adopted"); } - if (!PET_STATUS_AVAILABLE.equalsIgnoreCase(pet.getPetStatus()) && adoptionId == null) { + if (!samePetAsCurrentAdoption && !PET_STATUS_AVAILABLE.equalsIgnoreCase(pet.getPetStatus())) { throw new IllegalArgumentException("Selected pet is not available for adoption"); } } 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 0240c128..534d9feb 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 @@ -74,6 +74,7 @@ public class AdoptionDialogController { Platform.runLater(() -> { if (pets != null) { ObservableList petsObs = FXCollections.observableArrayList(pets); + ensureSelectedPetOption(petsObs); cbPet.setItems(petsObs); applySelectedPet(); } @@ -318,4 +319,17 @@ public class AdoptionDialogController { } return null; } + + private void ensureSelectedPetOption(ObservableList options) { + if (selectedAdoption == null || selectedAdoption.getPetId() <= 0 || options == null) { + return; + } + DropdownOption existing = findOptionById(options, (long) selectedAdoption.getPetId()); + if (existing == null) { + DropdownOption option = new DropdownOption(); + option.setId((long) selectedAdoption.getPetId()); + option.setLabel(selectedAdoption.getPetName()); + options.add(0, option); + } + } }