| Version 1 (modified by , 7 days ago) ( diff ) |
|---|
Advanced Application Development
Transactional
Adding a listing as a favorite
@Transactional
public void addFavorite(Long userId, Long listingId) {
Client client = clientRepository.findByUserId(userId)
.orElseThrow(() -> new RuntimeException("Client not found"));
Listing listing = listingRepository.findById(listingId)
.orElseThrow(() -> new RuntimeException("Listing not found"));
FavoriteListing favorite = new FavoriteListing(client, listing);
favoriteRepository.save(favorite);
logger.info("Added favorite - User: {}, Listing: {}", userId, listingId);
}
Removing a listing from favorites
@Transactional
public void removeFavorite(Long userId, Long listingId) {
Client client = clientRepository.findByUserId(userId)
.orElseThrow(() -> new RuntimeException("Client not found"));
Listing listing = listingRepository.findById(listingId)
.orElseThrow(() -> new RuntimeException("Listing not found"));
FavoriteListing favorite = favoriteRepository.findByClientAndListing(client, listing)
.orElseThrow(() -> new RuntimeException("Favorite not found"));
favoriteRepository.delete(favorite);
logger.info("Removed favorite - User: {}, Listing: {}", userId, listingId);
}
Getting information from the favorite_listings table
@Transactional(readOnly = true)
public List<ListingDTO> getFavoritedListings(Long userId) {
return favoriteRepository.findFavoritedListingDTOs(userId);
}
@Transactional(readOnly = true)
public boolean isFavorited(Long userId, Long listingId) {
Client client = clientRepository.findByUserId(userId)
.orElse(null);
if (client == null) return false;
Listing listing = listingRepository.findById(listingId)
.orElse(null);
if (listing == null) return false;
return favoriteRepository.findByClientAndListing(client, listing).isPresent();
}
Creating a review
@Transactional
public ReviewDTO createReview(Long reviewerId, Long targetUserId, CreateReviewRequest request) {
logger.info("==== START createReview ====");
// Validate rating
if (request.getRating() == null || request.getRating() < 1 || request.getRating() > 5) {
logger.error(" VALIDATION FAILED: Invalid rating: {}", request.getRating());
throw new RuntimeException("Rating must be between 1 and 5");
}
// Check if reviewer exists
User reviewer = userRepository.findById(reviewerId)
.orElseThrow(() -> {
logger.error(" Reviewer not found with ID: {}", reviewerId);
return new RuntimeException("Reviewer not found");
});
// Check if target user exists
User targetUser = userRepository.findById(targetUserId)
.orElseThrow(() -> {
logger.error(" Target user not found with ID: {}", targetUserId);
return new RuntimeException("Target user not found");
});
// Check if review already exists and is not deleted
logger.info("Checking if reviewer {} has already reviewed user {}", reviewerId, targetUserId);
var existingReview = userReviewRepository.findTopByReviewReviewerUserIdAndTargetUserIdAndReviewIsDeletedFalseOrderByReviewCreatedAtDesc(reviewerId, targetUserId);
if (existingReview.isPresent()) {
Review existingReviewEntity = existingReview.get().getReview();
logger.info("Found existing review with ID: {}", existingReviewEntity.getReviewId());
logger.info("Existing review isDeleted status: {}", existingReviewEntity.getIsDeleted());
if (!existingReviewEntity.getIsDeleted()) {
logger.error(" User {} has already reviewed user {} and review is NOT deleted", reviewerId, targetUserId);
throw new RuntimeException("You have already reviewed this user");
} else {
logger.info(" User {} has a deleted review for user {} - can create a new one", reviewerId, targetUserId);
}
} else {
logger.info(" No existing review found - safe to create new review");
}
// Create Review entity
Review review = new Review(reviewer, request.getRating(), request.getComment());
// Save Review to database with flush
review = reviewRepository.saveAndFlush(review);
logger.info("Review ID after save: {}", review.getReviewId());
if (review.getReviewId() == null) {
logger.error(" CRITICAL: Review ID is NULL after save!");
throw new RuntimeException("Failed to save review - ID is null");
}
// Create UserReview entry
UserReview userReview = new UserReview();
logger.info("Setting Review on UserReview (will copy ID via @MapsId)...");
userReview.setReview(review);
logger.info("UserReview reviewId after setReview: {}", userReview.getReviewId());
userReview.setTargetUserId(targetUserId);
// Save UserReview to database with flush
userReview = userReviewRepository.saveAndFlush(userReview);
logger.info(" UserReview saved successfully");
// Create and return DTO
ReviewDTO reviewDTO = new ReviewDTO(review);
logger.info(" ReviewDTO created successfully");
return reviewDTO;
}
Deleting a review
@Transactional
public void deleteReview(Long reviewId, Long userId) {
logger.info("=== START deleteReview (SOFT DELETE) ===");
// Fetch review
logger.info("Fetching review with ID: {}", reviewId);
Review review = reviewRepository.findById(reviewId)
.orElseThrow(() -> {
logger.error(" Review not found with ID: {}", reviewId);
return new RuntimeException("Review not found");
});
logger.info(" Review found: reviewer={}, rating={}", review.getReviewer().getUsername(), review.getRating());
// Check authorization
if (!review.getReviewer().getUserId().equals(userId)) {
logger.error(" User {} is not authorized to delete review {}. Reviewer is {}", userId, reviewId, review.getReviewer().getUserId());
throw new RuntimeException("You can only delete your own reviews");
}
// Soft delete: mark as deleted instead of physically removing
review.setIsDeleted(true);
review.setUpdatedAt(LocalDateTime.now());
reviewRepository.save(review);
logger.info("=== END deleteReview - SUCCESS ===");
}
Creating a new pet
@Transactional
public AnimalResponseDTO addPet(Long userId,@RequestBody CreatePetRequest request) {
// Validate required fields
if (request.getName() == null || request.getName().isBlank()) {
throw new RuntimeException("Pet name is required");
}
if (request.getSex() == null || request.getSex().isBlank()) {
throw new RuntimeException("Pet sex is required");
}
if (request.getType() == null || request.getType().isBlank()) {
throw new RuntimeException("Pet type is required");
}
if (request.getSpecies() == null || request.getSpecies().isBlank()) {
throw new RuntimeException("Pet species is required");
}
// Get user
User user = userRepository.findById(userId)
.orElseThrow(() -> {
logger.error(" User not found with ID: {}", userId);
return new RuntimeException("User not found");
});
logger.info("Adding pet for user ID: {}", userId);
// Check if user is already an owner, if not, promote them
Owner owner = ownerRepository.findByUserId(userId)
.orElseGet(() -> {
logger.info("⚠User {} is a CLIENT, promoting to OWNER", userId);
Owner newOwner = new Owner(user);
Owner savedOwner = ownerRepository.save(newOwner);
logger.info(" User promoted to OWNER with ID: {}", savedOwner.getUserId());
return savedOwner;
});
// Create new pet with all schema fields
Pet pet = new Pet(
request.getName(),
request.getSex(),
request.getDateOfBirth(),
request.getPhotoUrl(),
request.getType(),
request.getSpecies(),
request.getBreed(),
request.getLocatedName(),
owner
);
Pet savedPet = petRepository.save(pet);
logger.info("Pet ID: {}, Owner ID: {}, Name: {}",
savedPet.getAnimalId(), userId, savedPet.getName());
AnimalResponseDTO result = new AnimalResponseDTO(savedPet);
return result;
}
Creating a new listing
@Transactional
public ListingDTO createListing(Long userId, CreateListingRequest request) {
// Check if user is an owner
Owner owner = ownerRepository.findByUserId(userId)
.orElseThrow(() -> new RuntimeException("User is not an owner. Only owners can create listings."));
logger.info("Creating listing for owner ID: {}", userId);
// Create new listing with Owner object
Listing listing = new Listing(
owner,
request.getAnimalId(),
request.getPrice(),
request.getDescription()
);
Listing savedListing = listingRepository.save(listing);
logger.info("Listing created successfully - ID: {}, Owner ID: {}, Animal ID: {}",
savedListing.getListingId(), userId, request.getAnimalId());
return mapToDTO(savedListing);
}
Note:
See TracWiki
for help on using the wiki.
