diff --git a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/controller/PlaceReviewController.java b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/controller/PlaceReviewController.java index 7e46b2be..0a8d52f4 100644 --- a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/controller/PlaceReviewController.java +++ b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/controller/PlaceReviewController.java @@ -6,24 +6,18 @@ import com.haejwo.tripcometrue.domain.review.placereview.dto.response.PlaceReviewResponseDto; import com.haejwo.tripcometrue.domain.review.placereview.dto.response.RegisterPlaceReviewResponseDto; import com.haejwo.tripcometrue.domain.review.placereview.dto.response.delete.DeletePlaceReviewResponseDto; -import com.haejwo.tripcometrue.domain.review.placereview.dto.response.delete.DeleteSomeFailurePlaceReviewResponseDto; import com.haejwo.tripcometrue.domain.review.placereview.service.PlaceReviewService; import com.haejwo.tripcometrue.global.springsecurity.PrincipalDetails; import com.haejwo.tripcometrue.global.util.ResponseDTO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.List; - import static org.springframework.http.HttpStatus.CREATED; -import static org.springframework.http.HttpStatus.MULTI_STATUS; @Slf4j @RestController @@ -58,23 +52,12 @@ public ResponseEntity> getOnePlaceReview( return ResponseEntity.ok(ResponseDTO.okWithData(responseDto)); } - @GetMapping("/{placeId}/reviews") - public ResponseEntity>> getPlaceReviewList( - @AuthenticationPrincipal PrincipalDetails principalDetails, - @PathVariable Long placeId, - @RequestParam(defaultValue = "false") boolean onlyImage, - Pageable pageable - ) { - - Page responseDtos = placeReviewService.getPlaceReviews(principalDetails, placeId, onlyImage, pageable); - return ResponseEntity.ok(ResponseDTO.okWithData(responseDtos)); - } - @PutMapping("/reviews/{placeReviewId}") public ResponseEntity> modifyPlaceReview( @AuthenticationPrincipal PrincipalDetails principalDetails, @PathVariable Long placeReviewId, - @RequestBody @Validated PlaceReviewRequestDto requestDto) { + @RequestBody @Validated PlaceReviewRequestDto requestDto + ) { PlaceReviewResponseDto responseDto = placeReviewService .modifyPlaceReview(principalDetails, placeReviewId, requestDto); @@ -82,34 +65,37 @@ public ResponseEntity> modifyPlaceReview( } //todo : 로그인한 사람이 맞는지 확인 - //todo : 복수형 s 붙이기가 @DeleteMapping("/reviews") - public ResponseEntity> removePlaceReview( - @RequestBody DeletePlaceReviewRequestDto requestDto) { + public ResponseEntity> removePlaceReviews( + @RequestBody DeletePlaceReviewRequestDto requestDto + ) { - DeletePlaceReviewResponseDto responseDto = placeReviewService.deletePlaceReview(requestDto); + DeletePlaceReviewResponseDto responseDto = + placeReviewService.deletePlaceReviews(requestDto); + return ResponseEntity.ok(ResponseDTO.okWithData(responseDto)); + } - if (responseDto instanceof DeleteSomeFailurePlaceReviewResponseDto) { - return ResponseEntity - .status(MULTI_STATUS) - .body(ResponseDTO.errorWithData(MULTI_STATUS, responseDto)); - } + @GetMapping("/{placeId}/reviews") + public ResponseEntity> getPlaceReviewList( + @AuthenticationPrincipal PrincipalDetails principalDetails, + @PathVariable Long placeId, + @RequestParam(defaultValue = "false") boolean onlyImage, + Pageable pageable + ) { - return ResponseEntity.ok(ResponseDTO.okWithData(responseDto)); + PlaceReviewListResponseDto responseDtos = + placeReviewService.getPlaceReviewList(principalDetails, placeId, onlyImage, pageable); + return ResponseEntity.ok(ResponseDTO.okWithData(responseDtos)); } @GetMapping("/reviews/my") - public ResponseEntity>> getMyPlaceReviews( - @AuthenticationPrincipal PrincipalDetails principalDetails, - Pageable pageable + public ResponseEntity> getMyPlaceReviews( + @AuthenticationPrincipal PrincipalDetails principalDetails, + Pageable pageable ) { - List responseDtos - = placeReviewService.getMyPlaceReviewsList(principalDetails, pageable); - ResponseDTO> responseBody - = ResponseDTO.okWithData(responseDtos); - return ResponseEntity - .status(HttpStatus.OK) - .body(responseBody); + PlaceReviewListResponseDto responseDtos + = placeReviewService.getMyPlaceReviewList(principalDetails, pageable); + return ResponseEntity.ok((ResponseDTO.okWithData(responseDtos))); } } diff --git a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/dto/response/PlaceReviewListResponseDto.java b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/dto/response/PlaceReviewListResponseDto.java index 3e4f24b5..df42fdaa 100644 --- a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/dto/response/PlaceReviewListResponseDto.java +++ b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/dto/response/PlaceReviewListResponseDto.java @@ -1,29 +1,29 @@ package com.haejwo.tripcometrue.domain.review.placereview.dto.response; import com.haejwo.tripcometrue.domain.review.placereview.entity.PlaceReview; +import org.springframework.data.domain.Page; -import java.time.LocalDateTime; +import java.util.List; public record PlaceReviewListResponseDto( - Long id, - String content, - String imageUrl, - Integer likeCount, - Long memberId, - Long placeId, - LocalDateTime createdAt + Long totalCount, + int nowPageNumber, + boolean isFirst, + boolean isLast, + List placeReviews ) { - public static PlaceReviewListResponseDto fromEntity(PlaceReview placeReview) { - return new PlaceReviewListResponseDto( - placeReview.getId(), - placeReview.getContent(), - placeReview.getImageUrl(), - placeReview.getLikeCount(), - placeReview.getMember().getId(), - placeReview.getPlace().getId(), - placeReview.getCreatedAt() - ); - } + public static PlaceReviewListResponseDto fromResponseDtos( + Page reviews, + List placeReviews + ) { + return new PlaceReviewListResponseDto( + reviews.getTotalElements(), + reviews.getNumber(), + reviews.isFirst(), + reviews.isLast(), + placeReviews + ); + } } \ No newline at end of file diff --git a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/entity/PlaceReview.java b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/entity/PlaceReview.java index 373df44b..ed7069cf 100644 --- a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/entity/PlaceReview.java +++ b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/entity/PlaceReview.java @@ -14,6 +14,8 @@ import java.util.ArrayList; import java.util.List; +import static com.haejwo.tripcometrue.domain.review.global.PointType.ONLY_ONE_POINT; +import static com.haejwo.tripcometrue.domain.review.global.PointType.TWO_POINTS; import static jakarta.persistence.FetchType.LAZY; @Getter @@ -43,6 +45,7 @@ public class PlaceReview extends BaseTimeEntity { private String imageUrl; private Integer likeCount; private Integer commentCount; + private boolean hasAnyRegisteredPhotoUrl; @Builder public PlaceReview(Member member, Place place, String content, String imageUrl) { @@ -52,8 +55,23 @@ public PlaceReview(Member member, Place place, String content, String imageUrl) this.imageUrl = imageUrl; } - public void update(PlaceReviewRequestDto requestDto) { + public void save(PlaceReviewRequestDto requestDto, Member member) { + if (requestDto.imageUrl() != null) { + member.earnPoint(TWO_POINTS.getPoint()); + hasAnyRegisteredPhotoUrl = true; + return; + } + + member.earnPoint(ONLY_ONE_POINT.getPoint()); + } + + public void update(PlaceReviewRequestDto requestDto, Member member) { this.content = requestDto.content(); + + if (!hasAnyRegisteredPhotoUrl && requestDto.imageUrl() != null) { + member.earnPoint(ONLY_ONE_POINT.getPoint()); + hasAnyRegisteredPhotoUrl = true; + } this.imageUrl = requestDto.imageUrl(); } diff --git a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/repository/PlaceReviewRepository.java b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/repository/PlaceReviewRepository.java index 081d08ad..739d8776 100644 --- a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/repository/PlaceReviewRepository.java +++ b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/repository/PlaceReviewRepository.java @@ -3,16 +3,18 @@ import com.haejwo.tripcometrue.domain.member.entity.Member; import com.haejwo.tripcometrue.domain.place.entity.Place; import com.haejwo.tripcometrue.domain.review.placereview.entity.PlaceReview; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public interface PlaceReviewRepository extends JpaRepository, PlaceReviewRepositoryCustom { boolean existsByMemberAndPlace(Member member, Place place); - List findByMemberId(Long memberId, Pageable pageable); + @Query("select pr from PlaceReview pr join fetch pr.member m where pr.member = :member order by pr.createdAt desc") + Page findByMember(@Param("member") Member member, Pageable pageable); } diff --git a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/service/PlaceReviewService.java b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/service/PlaceReviewService.java index f775b95b..fb98e28a 100644 --- a/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/service/PlaceReviewService.java +++ b/src/main/java/com/haejwo/tripcometrue/domain/review/placereview/service/PlaceReviewService.java @@ -2,6 +2,9 @@ import com.haejwo.tripcometrue.domain.likes.entity.PlaceReviewLikes; import com.haejwo.tripcometrue.domain.member.entity.Member; +import com.haejwo.tripcometrue.domain.member.exception.UserInvalidAccessException; +import com.haejwo.tripcometrue.domain.member.exception.UserNotFoundException; +import com.haejwo.tripcometrue.domain.member.repository.MemberRepository; import com.haejwo.tripcometrue.domain.place.entity.Place; import com.haejwo.tripcometrue.domain.place.exception.PlaceNotFoundException; import com.haejwo.tripcometrue.domain.place.repositroy.PlaceRepository; @@ -19,7 +22,6 @@ import com.haejwo.tripcometrue.domain.review.placereview.exception.PlaceReviewNotFoundException; import com.haejwo.tripcometrue.domain.review.placereview.repository.PlaceReviewRepository; import com.haejwo.tripcometrue.global.springsecurity.PrincipalDetails; -import jakarta.persistence.EntityManager; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -29,7 +31,7 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; +import java.util.Objects; @Slf4j @Service @@ -39,29 +41,30 @@ public class PlaceReviewService { private final PlaceReviewRepository placeReviewRepository; private final PlaceRepository placeRepository; - private final EntityManager em; + private final MemberRepository memberRepository; @Transactional public RegisterPlaceReviewResponseDto savePlaceReview( PrincipalDetails principalDetails, Long placeId, - PlaceReviewRequestDto requestDto) { + PlaceReviewRequestDto requestDto + ) { - Member member = getPersistentMember(principalDetails); + Member loginMember = getMember(principalDetails); Place place = getPlaceById(placeId); - isPlaceReviewExists(member, place); + isAlreadyPlaceReviewExists(loginMember, place); - PlaceReview placeReview = PlaceReviewRequestDto.toEntity(member, place, requestDto); - -// calculateAndSavePoints(placeReview, member); + PlaceReview placeReview = PlaceReviewRequestDto.toEntity(loginMember, place, requestDto); + placeReview.save(requestDto, loginMember); return RegisterPlaceReviewResponseDto .fromEntity(placeReviewRepository.save(placeReview)); } - private Member getPersistentMember(PrincipalDetails principalDetails) { - return em.merge(principalDetails.getMember()); //준영속 상태를 영속 상태로 변경 + private Member getMember(PrincipalDetails principalDetails) { + return memberRepository.findById(principalDetails.getMember().getId()) + .orElseThrow(UserNotFoundException::new); } private Place getPlaceById(Long placeId) { @@ -69,21 +72,12 @@ private Place getPlaceById(Long placeId) { .orElseThrow(PlaceNotFoundException::new); } - private void isPlaceReviewExists(Member member, Place place) { + private void isAlreadyPlaceReviewExists(Member member, Place place) { if (placeReviewRepository.existsByMemberAndPlace(member, place)) { throw new PlaceReviewAlreadyExistsException(); } } -// private void calculateAndSavePoints(PlaceReview placeReview, Member member) { -// int point = isImageIncluded(placeReview) ? CONTENT_WITH_IMAGE_POINT.getPoint() : ONLY_CONTENT_POINT.getPoint(); -// member.earnPoint(point); -// } -// -// private boolean isImageIncluded(PlaceReview placeReview) { -// return placeReview.getImageUrl() != null; -// } - public PlaceReviewResponseDto getPlaceReview(PrincipalDetails principalDetails, Long placeReviewId) { PlaceReview placeReview = getPlaceReviewById(placeReviewId); @@ -113,31 +107,33 @@ private boolean hasLikedPlaceReview(PrincipalDetails principalDetails, PlaceRevi return memberIds.contains(principalDetails.getMember().getId()); } - public Page getPlaceReviews(PrincipalDetails principalDetails, Long placeId, boolean onlyImage, Pageable pageable) { - - Place place = getPlaceById(placeId); - Page placeReviews = placeReviewRepository.findByPlace(place, onlyImage, pageable); - - return placeReviews.map(placeReview -> - PlaceReviewResponseDto.fromEntity(placeReview, hasLikedPlaceReview(principalDetails, placeReview)) - ); - } - @Transactional public PlaceReviewResponseDto modifyPlaceReview( PrincipalDetails principalDetails, Long placeReviewId, - PlaceReviewRequestDto requestDto) { + PlaceReviewRequestDto requestDto + ) { + Member loginMember = getMember(principalDetails); PlaceReview placeReview = getPlaceReviewById(placeReviewId); - placeReview.update(requestDto); + + validateRightMemberAccess(loginMember, placeReview); + placeReview.update(requestDto, loginMember); return PlaceReviewResponseDto .fromEntity(placeReview, hasLikedPlaceReview(principalDetails, placeReview)); } + private void validateRightMemberAccess(Member member, PlaceReview placeReview) { + if (!Objects.equals(placeReview.getMember().getId(), member.getId())) { + throw new UserInvalidAccessException(); + } + } + @Transactional - public DeletePlaceReviewResponseDto deletePlaceReview(DeletePlaceReviewRequestDto requestDto) { + public DeletePlaceReviewResponseDto deletePlaceReviews( + DeletePlaceReviewRequestDto requestDto + ) { List placeReviewIds = requestDto.placeReviewIds(); List failedIds = new ArrayList<>(); @@ -164,14 +160,37 @@ private boolean isDeleteAllFail(List placeReviewIds, List failedIds) return placeReviewIds.size() == failedIds.size(); } - @Transactional(readOnly = true) - public List getMyPlaceReviewsList( - PrincipalDetails principalDetails, Pageable pageable) { - Long memberId = principalDetails.getMember().getId(); - List reviews = placeReviewRepository.findByMemberId(memberId, pageable); + public PlaceReviewListResponseDto getPlaceReviewList( + PrincipalDetails principalDetails, + Long placeId, + boolean onlyImage, + Pageable pageable + ) { + + Place place = getPlaceById(placeId); + Page reviews = placeReviewRepository.findByPlace(place, onlyImage, pageable); + + return PlaceReviewListResponseDto.fromResponseDtos( + reviews, + reviews.map(placeReview -> PlaceReviewResponseDto.fromEntity( + placeReview, + hasLikedPlaceReview(principalDetails, placeReview)) + ).toList()); + } - return reviews.stream() - .map(PlaceReviewListResponseDto::fromEntity) - .collect(Collectors.toList()); + public PlaceReviewListResponseDto getMyPlaceReviewList( + PrincipalDetails principalDetails, + Pageable pageable + ) { + + Member loginMember = getMember(principalDetails); + Page reviews = placeReviewRepository.findByMember(loginMember, pageable); + + return PlaceReviewListResponseDto.fromResponseDtos( + reviews, + reviews.map(placeReview -> PlaceReviewResponseDto.fromEntity( + placeReview, + hasLikedPlaceReview(principalDetails, placeReview)) + ).toList()); } } diff --git a/src/main/java/com/haejwo/tripcometrue/domain/review/triprecordreview/service/TripRecordReviewService.java b/src/main/java/com/haejwo/tripcometrue/domain/review/triprecordreview/service/TripRecordReviewService.java index e9a804e7..67bf3c63 100644 --- a/src/main/java/com/haejwo/tripcometrue/domain/review/triprecordreview/service/TripRecordReviewService.java +++ b/src/main/java/com/haejwo/tripcometrue/domain/review/triprecordreview/service/TripRecordReviewService.java @@ -143,22 +143,6 @@ private void isReviewAlreadyRegister(TripRecordReview tripRecordReview) { } } - public TripRecordReviewListResponseDto getMyTripRecordReviewList( - PrincipalDetails principalDetails, - Pageable pageable - ) { - - Page reviews = tripRecordReviewRepository.findByMember(getMember(principalDetails), pageable); - - List responseDtos = - reviews.map(tripRecordReview -> TripRecordReviewResponseDto.fromEntity( - tripRecordReview, - hasLikedTripRecordReview(principalDetails, tripRecordReview)) - ).toList(); - - return TripRecordReviewListResponseDto.fromResponseDtos(reviews, responseDtos); - } - @Transactional public DeleteTripRecordReviewResponseDto deleteTripRecordReviews( DeleteTripRecordReviewRequestDto requestDto @@ -236,4 +220,20 @@ public TripRecordReviewListResponseDto getTripRecordReviewList( hasLikedTripRecordReview(principalDetails, tripRecordReview)) ).toList()); } + + public TripRecordReviewListResponseDto getMyTripRecordReviewList( + PrincipalDetails principalDetails, + Pageable pageable + ) { + + Member loginMember = getMember(principalDetails); + Page reviews = tripRecordReviewRepository.findByMember(loginMember, pageable); + + return TripRecordReviewListResponseDto.fromResponseDtos( + reviews, + reviews.map(tripRecordReview -> TripRecordReviewResponseDto.fromEntity( + tripRecordReview, + hasLikedTripRecordReview(principalDetails, tripRecordReview)) + ).toList()); + } }