diff --git a/src/main/java/org/example/vet1177/controller/PetController.java b/src/main/java/org/example/vet1177/controller/PetController.java index 191088e..fc43601 100644 --- a/src/main/java/org/example/vet1177/controller/PetController.java +++ b/src/main/java/org/example/vet1177/controller/PetController.java @@ -4,9 +4,13 @@ import org.example.vet1177.dto.request.pet.PetRequest; import org.example.vet1177.dto.response.pet.PetResponse; import org.example.vet1177.entities.Pet; +import org.example.vet1177.entities.User; import org.example.vet1177.services.PetService; +import org.example.vet1177.services.UserService; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.UUID; @RestController @@ -14,11 +18,14 @@ public class PetController { private final PetService petService; + private final UserService userService; - public PetController(PetService petService) { + public PetController(PetService petService, UserService userService) { this.petService = petService; + this.userService = userService; } + //POST / pets - skapa nytt djur @PostMapping public PetResponse createPet( // TODO: Ersätt med användare från autentiserad kontext (t.ex. JWT / Spring Security) @@ -27,17 +34,68 @@ public PetResponse createPet( @Valid @RequestBody PetRequest request ) { Pet saved = petService.createPet(currentUserId, ownerId, request); + return toResponse(saved); + } + + // GET / pets/{petId} - hämta ett specifikt djur + @GetMapping("/{petId}") + public ResponseEntity getPetById( + @RequestHeader UUID currentUserId, + @PathVariable UUID petId + ) { + User currentUser = userService.getUserEntityById(currentUserId); + Pet pet = petService.getPetById(petId, currentUser); + return ResponseEntity.ok(toResponse(pet)); + } + // GET/pets/owner/{ownerId} - hämta alla djur för en ägare + @GetMapping("/owner/{ownerId}") + public ResponseEntity> getPetsByOwner( + @RequestHeader UUID currentUserId, + @PathVariable UUID ownerId + ) { + List pets = petService.getPetsByOwner(currentUserId, ownerId) + .stream() + .map(this::toResponse) + .toList(); + return ResponseEntity.ok(pets); + } + + // PUT /pets/{petId} - uppdatera ett djur + @PutMapping("/{petId}") + public ResponseEntity updatePet( + @RequestHeader UUID currentUserId, + @PathVariable UUID petId, + @Valid @RequestBody PetRequest request + ) { + Pet updated = petService.updatePet(currentUserId, petId, request); + return ResponseEntity.ok(toResponse(updated)); + } + + // DELETE /pets/{petId} - radera ett djur + @DeleteMapping("/{petId}") + public ResponseEntity deletePet( + @RequestHeader UUID currentUserId, + @PathVariable UUID petId + ) { + User currentUser = userService.getUserEntityById(currentUserId); + petService.deletePet(petId, currentUser); + return ResponseEntity.noContent().build(); + } + + //Helper + private PetResponse toResponse(Pet pet) { return new PetResponse( - saved.getId(), - saved.getOwner().getId(), - saved.getName(), - saved.getSpecies(), - saved.getBreed(), - saved.getDateOfBirth(), - saved.getWeightKg(), - saved.getCreatedAt(), - saved.getUpdatedAt() + pet.getId(), + pet.getOwner().getId(), + pet.getName(), + pet.getSpecies(), + pet.getBreed(), + pet.getDateOfBirth(), + pet.getWeightKg(), + pet.getCreatedAt(), + pet.getUpdatedAt() ); } + } \ No newline at end of file diff --git a/src/main/java/org/example/vet1177/services/PetService.java b/src/main/java/org/example/vet1177/services/PetService.java index d086a01..c505ea3 100644 --- a/src/main/java/org/example/vet1177/services/PetService.java +++ b/src/main/java/org/example/vet1177/services/PetService.java @@ -5,6 +5,9 @@ import org.example.vet1177.entities.Pet; import org.example.vet1177.entities.Role; import org.example.vet1177.entities.User; +import org.example.vet1177.exception.BusinessRuleException; +import org.example.vet1177.exception.ForbiddenException; +import org.example.vet1177.exception.ResourceNotFoundException; import org.example.vet1177.policy.PetPolicy; import org.example.vet1177.repository.MedicalRecordRepository; import org.example.vet1177.repository.PetRepository; @@ -40,18 +43,17 @@ public Pet createPet(UUID currentUserId, UUID ownerId, PetRequest request) { User currentUser = getUserById(currentUserId); if (!petPolicy.canCreate(currentUser)) { - throw new RuntimeException("Du kan inte lägga till ett djur"); + throw new ForbiddenException("Du kan inte lägga till ett djur"); } - User owner; if (currentUser.getRole() == Role.ADMIN) { if (ownerId == null) { - throw new RuntimeException("Admin måste ange ownerId"); + throw new BusinessRuleException("Admin måste ange ownerId"); } owner = getUserById(ownerId); if (owner.getRole() != Role.OWNER) { - throw new RuntimeException("ownerId måste tillhöra en användare med rollen OWNER"); + throw new BusinessRuleException("ownerId måste tillhöra en användare med rollen OWNER"); } } else { owner = currentUser; @@ -68,7 +70,7 @@ public Pet createPet(UUID currentUserId, UUID ownerId, PetRequest request) { // - Måste vara ADMIN eller OWNER för att se pet public Pet getPetById(UUID petId, User currentUser) { Pet pet = petRepository.findById(petId) - .orElseThrow(() -> new RuntimeException("Pet not found")); + .orElseThrow(() -> new ResourceNotFoundException("Pet", petId)); if (petPolicy.canView(currentUser, pet)) { return pet; @@ -76,7 +78,7 @@ public Pet getPetById(UUID petId, User currentUser) { if (currentUser.getRole() == Role.VET) { if (currentUser.getClinic() == null) { - throw new RuntimeException("Veterinären saknar koppling till klinik"); + throw new ForbiddenException("Veterinären saknar koppling till klinik"); } boolean vetHasAccess = medicalRecordRepository .existsByPetIdAndClinicId(petId, currentUser.getClinic().getId()); @@ -86,14 +88,14 @@ public Pet getPetById(UUID petId, User currentUser) { } } - throw new RuntimeException("Du har inte behörighet att se detta djur"); + throw new ForbiddenException("Du har inte behörighet att se detta djur"); } // Lista djur som tillhör ägaren public List getPetsByOwner(UUID currentUserId, UUID ownerId) { User currentUser = getUserById(currentUserId); if (!petPolicy.canViewOwnerPets(currentUser, ownerId)){ - throw new RuntimeException("Du saknar behörighet"); + throw new ForbiddenException("Du saknar behörighet"); } return petRepository.findByOwnerId(ownerId); } @@ -104,7 +106,7 @@ public Pet updatePet(UUID currentUserId, UUID petId, PetRequest request) { Pet existingPet = getPetByIdOrThrow(petId); if (!petPolicy.canUpdate(currentUser, existingPet)) { - throw new RuntimeException("Du saknar behörighet för att uppdatera info om djuret"); + throw new ForbiddenException("Du saknar behörighet för att uppdatera info om djuret"); } existingPet.setName(request.getName()); @@ -121,16 +123,16 @@ public Pet updatePet(UUID currentUserId, UUID petId, PetRequest request) { @Transactional public void deletePet(UUID petId, User currentUser) { Pet pet = petRepository.findById(petId) - .orElseThrow(() -> new RuntimeException("Djuret finns inte")); + .orElseThrow(() -> new ResourceNotFoundException("Pet", petId)); if (!petPolicy.canDelete(currentUser, pet)) { - throw new RuntimeException("Du har inte behörighet att radera detta djur"); + throw new ForbiddenException("Du har inte behörighet att radera detta djur"); } try { petRepository.delete(pet); petRepository.flush(); } catch (DataIntegrityViolationException e) { - throw new RuntimeException("Djuret kan inte raderas eftersom journaler finns kopplade"); + throw new BusinessRuleException("Djuret kan inte raderas eftersom journaler finns kopplade"); } } @@ -139,11 +141,11 @@ public void deletePet(UUID petId, User currentUser) { //HELPERS private User getUserById(UUID userId) { return userRepository.findById(userId) - .orElseThrow(()-> new RuntimeException("Användare ej hittad")); + .orElseThrow(()-> new ResourceNotFoundException("User", userId)); } private Pet getPetByIdOrThrow(UUID petId) { return petRepository.findById(petId) - .orElseThrow(() -> new RuntimeException("Djuret ej hittat")); + .orElseThrow(() -> new ResourceNotFoundException("Pet", petId)); } private void applyPetRequest(Pet target, PetRequest request) {