diff --git a/src/main/java/depth/jeonsilog/domain/alarm/application/AlarmService.java b/src/main/java/depth/jeonsilog/domain/alarm/application/AlarmService.java index fb806e7..10f346f 100644 --- a/src/main/java/depth/jeonsilog/domain/alarm/application/AlarmService.java +++ b/src/main/java/depth/jeonsilog/domain/alarm/application/AlarmService.java @@ -162,9 +162,11 @@ public void makeReviewAlarm(Review review) throws IOException { List follows = followRepository.findAllByFollow(review.getUser()); for (Follow follow : follows) { User receiver = follow.getUser(); + User sender = follow.getFollow(); + Alarm alarm = Alarm.builder() .user(receiver) - .senderId(follow.getFollow().getId()) + .senderId(sender.getId()) .alarmType(AlarmType.REVIEW) .targetId(review.getId()) .clickId(review.getId()) @@ -173,7 +175,7 @@ public void makeReviewAlarm(Review review) throws IOException { alarmRepository.save(alarm); if (!receiver.getIsRecvActive() || receiver.getFcmToken() == null) return; - fcmService.makeActiveAlarm(receiver.getFcmToken(), follow.getFollow().getNickname() + " 님이 감상평을 남겼어요"); + fcmService.makeActiveAlarm(receiver.getFcmToken(), sender.getNickname() + " 님이 감상평을 남겼어요"); } } @@ -183,9 +185,11 @@ public void makeRatingAlarm(Rating rating) throws IOException { List follows = followRepository.findAllByFollow(rating.getUser()); for (Follow follow : follows) { User receiver = follow.getUser(); + User sender = follow.getFollow(); + Alarm alarm = Alarm.builder() .user(receiver) - .senderId(follow.getFollow().getId()) + .senderId(sender.getId()) .alarmType(AlarmType.RATING) .targetId(rating.getId()) .clickId(rating.getExhibition().getId()) @@ -194,7 +198,7 @@ public void makeRatingAlarm(Rating rating) throws IOException { alarmRepository.save(alarm); if (!receiver.getIsRecvActive() || receiver.getFcmToken() == null) return; - fcmService.makeActiveAlarm(receiver.getFcmToken(), follow.getFollow().getNickname() + " 님이 별점을 남겼어요"); + fcmService.makeActiveAlarm(receiver.getFcmToken(), sender.getNickname() + " 님이 별점을 남겼어요"); } } @@ -202,9 +206,15 @@ public void makeRatingAlarm(Rating rating) throws IOException { @Transactional public void makeReplyAlarm(Reply reply) throws IOException { User receiver = reply.getReview().getUser(); + User sender = reply.getUser(); + if (receiver.equals(sender)) { + log.info("알림의 sender와 receiver가 동일 인물입니다."); + return; + } + Alarm alarm = Alarm.builder() .user(receiver) - .senderId(reply.getUser().getId()) + .senderId(sender.getId()) .alarmType(AlarmType.REPLY) .targetId(reply.getId()) .clickId(reply.getReview().getId()) @@ -213,16 +223,18 @@ public void makeReplyAlarm(Reply reply) throws IOException { alarmRepository.save(alarm); if (!receiver.getIsRecvActive() || receiver.getFcmToken() == null) return; - fcmService.makeActiveAlarm(receiver.getFcmToken(), reply.getUser().getNickname() + " 님이 댓글을 남겼어요"); + fcmService.makeActiveAlarm(receiver.getFcmToken(), sender.getNickname() + " 님이 댓글을 남겼어요"); } // TODO: 나를 팔로우 -> 알림 생성 @Transactional public void makeFollowAlarm(Follow follow) throws IOException { User receiver = follow.getFollow(); + User sender = follow.getUser(); + Alarm alarm = Alarm.builder() .user(receiver) - .senderId(follow.getUser().getId()) + .senderId(sender.getId()) .alarmType(AlarmType.FOLLOW) .targetId(follow.getId()) .clickId(follow.getUser().getId()) @@ -231,7 +243,7 @@ public void makeFollowAlarm(Follow follow) throws IOException { alarmRepository.save(alarm); if (!receiver.getIsRecvActive() || receiver.getFcmToken() == null) return; - fcmService.makeActiveAlarm(receiver.getFcmToken(), follow.getUser().getNickname() + " 님이 나를 팔로우해요"); + fcmService.makeActiveAlarm(receiver.getFcmToken(), sender.getNickname() + " 님이 나를 팔로우해요"); } // TODO: 관심 전시회 시작 전 -> 알림 생성 diff --git a/src/main/java/depth/jeonsilog/domain/openApi/application/AddService.java b/src/main/java/depth/jeonsilog/domain/openApi/application/AddService.java index ebb397c..0920f1b 100644 --- a/src/main/java/depth/jeonsilog/domain/openApi/application/AddService.java +++ b/src/main/java/depth/jeonsilog/domain/openApi/application/AddService.java @@ -153,9 +153,14 @@ public ResponseEntity addExhibitionAndPlace() { // Description : place 있는 지 확인 String placeName = placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulName(); String placeAddr = placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulAddr(); - - Optional placeByName = placeRepository.findByName(placeName); - Optional placeByAddr = placeRepository.findByAddress(placeAddr); + Optional placeByName = Optional.empty(); + Optional placeByAddr = Optional.empty(); + if (placeName != null) { + placeByName = placeRepository.findByName(placeName); + } + if (placeAddr != null) { + placeByAddr = placeRepository.findByAddress(placeAddr); + } Place place = null; @@ -167,15 +172,26 @@ public ResponseEntity addExhibitionAndPlace() { place = placeByAddr.get(); } else { - // Description : Place 최초 저장 - place = Place.builder() - .name(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulName()) - .address(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulAddr()) - .homePage(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulHomeUrl()) - .tel(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulTel()) - .build(); - - placeRepository.save(place); + if (placeName == null || placeAddr == null) { + place = Place.builder() + .name(null) + .address(null) + .homePage(null) + .tel(null) + .build(); + + placeRepository.save(place); + }else { + // Description : Place 최초 저장 + place = Place.builder() + .name(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulName()) + .address(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulAddr()) + .homePage(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulHomeUrl()) + .tel(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulTel()) + .build(); + + placeRepository.save(place); + } } PriceKeyword priceKeyword = null; diff --git a/src/main/java/depth/jeonsilog/domain/openApi/application/SaveService.java b/src/main/java/depth/jeonsilog/domain/openApi/application/SaveService.java index 275fdca..6c1e35c 100644 --- a/src/main/java/depth/jeonsilog/domain/openApi/application/SaveService.java +++ b/src/main/java/depth/jeonsilog/domain/openApi/application/SaveService.java @@ -77,24 +77,17 @@ public ResponseEntity saveExhibitionAndPlace() { } catch (IOException e) { e.printStackTrace(); } - // XML To JSON JSONObject jsonObject = XML.toJSONObject(listXml); - // JSON To String String listJsonStr = jsonObject.toString(); - - // Jackson Objectmapper 객체 생성 ObjectMapper objectMapper = new ObjectMapper(); - // JSON의 모든 데이터를 파싱하는 것이 아닌 내가 필요로 하는 데이터만, 즉, 내가 필드로 선언한 데이터들만 파싱할 수 있다 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - ExhibitionListDTO exhibitionList = null; try { // Description : JSON String -> ExhibitionListDTO (Object) exhibitionList = objectMapper.readValue(listJsonStr, ExhibitionListDTO.class); - } catch (JsonProcessingException e) { e.printStackTrace(); @@ -169,9 +162,14 @@ public ResponseEntity saveExhibitionAndPlace() { // Description : place 있는 지 확인 String placeName = placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulName(); String placeAddr = placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulAddr(); - - Optional placeByName = placeRepository.findByName(placeName); - Optional placeByAddr = placeRepository.findByAddress(placeAddr); + Optional placeByName = Optional.empty(); + Optional placeByAddr = Optional.empty(); + if (placeName != null) { + placeByName = placeRepository.findByName(placeName); + } + if (placeAddr != null) { + placeByAddr = placeRepository.findByAddress(placeAddr); + } Place place = null; @@ -183,15 +181,26 @@ public ResponseEntity saveExhibitionAndPlace() { place = placeByAddr.get(); } else { - // Description : Place 최초 저장 - place = Place.builder() - .name(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulName()) - .address(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulAddr()) - .homePage(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulHomeUrl()) - .tel(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulTel()) - .build(); - - placeRepository.save(place); + if (placeName == null || placeAddr == null) { + place = Place.builder() + .name(null) + .address(null) + .homePage(null) + .tel(null) + .build(); + + placeRepository.save(place); + } else { + // Description : Place 최초 저장 + place = Place.builder() + .name(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulName()) + .address(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulAddr()) + .homePage(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulHomeUrl()) + .tel(placeDetail.getResponse().getMsgBody().getPlaceInfo().getCulTel()) + .build(); + + placeRepository.save(place); + } } PriceKeyword priceKeyword = null; @@ -210,7 +219,7 @@ public ResponseEntity saveExhibitionAndPlace() { * - 시작 전 : startDate가 now보다 더 미래 * - 전시 중 : now가 startDate보다 더 미래 && endDate가 now보다 더 미래 */ - + LocalDate now = LocalDate.now(); LocalDate startDate = LocalDate.parse(exhibitionDetail.getResponse().getMsgBody().getPerforInfo().getStartDate(), formatter); LocalDate endDate = LocalDate.parse(exhibitionDetail.getResponse().getMsgBody().getPerforInfo().getEndDate(), formatter); diff --git a/src/main/java/depth/jeonsilog/domain/reply/application/ReplyService.java b/src/main/java/depth/jeonsilog/domain/reply/application/ReplyService.java index 4bedf83..5b325c5 100644 --- a/src/main/java/depth/jeonsilog/domain/reply/application/ReplyService.java +++ b/src/main/java/depth/jeonsilog/domain/reply/application/ReplyService.java @@ -93,9 +93,21 @@ public ResponseEntity deleteReply(UserPrincipal userPrincipal, Long replyId) return ResponseEntity.ok(apiResponse); } + // Description : 댓글 존재 여부 조회 + public ResponseEntity existReply(Long replyId) { + + Boolean isExist = replyRepository.existsById(replyId); + + ReplyResponseDto.ExistReplyRes existReplyRes = ReplyConverter.toExistReplyRes(replyId, isExist); + ApiResponse apiResponse = ApiResponse.toApiResponse(existReplyRes); + + return ResponseEntity.ok(apiResponse); + } + public Reply validateReplyById(Long replyId) { Optional reply = replyRepository.findById(replyId); DefaultAssert.isTrue(reply.isPresent(), "댓글 정보가 올바르지 않습니다."); return reply.get(); } + } diff --git a/src/main/java/depth/jeonsilog/domain/reply/converter/ReplyConverter.java b/src/main/java/depth/jeonsilog/domain/reply/converter/ReplyConverter.java index d1007ff..6c841f8 100644 --- a/src/main/java/depth/jeonsilog/domain/reply/converter/ReplyConverter.java +++ b/src/main/java/depth/jeonsilog/domain/reply/converter/ReplyConverter.java @@ -55,4 +55,11 @@ public static Reply toReply(Review review, User user, ReplyRequestDto.CreateRepl .contents(createReplyReq.getContents()) .build(); } + + public static ReplyResponseDto.ExistReplyRes toExistReplyRes(Long replyId, Boolean isExist) { + return ReplyResponseDto.ExistReplyRes.builder() + .replyId(replyId) + .isExist(isExist) + .build(); + } } diff --git a/src/main/java/depth/jeonsilog/domain/reply/domain/repository/ReplyRepository.java b/src/main/java/depth/jeonsilog/domain/reply/domain/repository/ReplyRepository.java index bfadd92..3db88a0 100644 --- a/src/main/java/depth/jeonsilog/domain/reply/domain/repository/ReplyRepository.java +++ b/src/main/java/depth/jeonsilog/domain/reply/domain/repository/ReplyRepository.java @@ -25,4 +25,8 @@ public interface ReplyRepository extends JpaRepository { @Query(value = "SELECT * FROM reply WHERE user_id = :userId", nativeQuery = true) List findAllRepliesByUserId(@Param("userId") Long userId); + @Query(value = "SELECT * FROM reply WHERE id = :replyId", nativeQuery = true) + Reply findReplyByReplyId(@Param("replyId") Long replyId); + + } diff --git a/src/main/java/depth/jeonsilog/domain/reply/dto/ReplyResponseDto.java b/src/main/java/depth/jeonsilog/domain/reply/dto/ReplyResponseDto.java index 7417aea..da6aacd 100644 --- a/src/main/java/depth/jeonsilog/domain/reply/dto/ReplyResponseDto.java +++ b/src/main/java/depth/jeonsilog/domain/reply/dto/ReplyResponseDto.java @@ -15,8 +15,10 @@ public class ReplyResponseDto { @Builder public static class ReplyRes { + @Schema(type = "long", example = "1", description = "댓글 ID를 출력합니다.") private Long replyId; + @Schema(type = "string", example = "앵무는 앵무의 말을 하고", description = "댓글 내용을 출력합니다.") private String contents; // 수정 없으므로 생성 시간 @@ -36,4 +38,15 @@ public static class ReplyResListWithPaging { private List data; } + @Data + @Builder + public static class ExistReplyRes { + + @Schema(type = "long", example = "1", description = "댓글 ID를 출력합니다.") + private Long replyId; + + @Schema(type = "boolean", example = "true", description = "댓글이 존재하는지 출력합니다. 삭제되었으면 false.") + private Boolean isExist; + } + } diff --git a/src/main/java/depth/jeonsilog/domain/reply/presentation/ReplyController.java b/src/main/java/depth/jeonsilog/domain/reply/presentation/ReplyController.java index a285394..b718731 100644 --- a/src/main/java/depth/jeonsilog/domain/reply/presentation/ReplyController.java +++ b/src/main/java/depth/jeonsilog/domain/reply/presentation/ReplyController.java @@ -34,7 +34,7 @@ public class ReplyController { @ApiResponse(responseCode = "200", description = "댓글 목록 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ReplyResponseDto.ReplyResListWithPaging.class))}), @ApiResponse(responseCode = "400", description = "댓글 목록 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) - @GetMapping("/{reviewId}") + @GetMapping("/reviews/{reviewId}") public ResponseEntity findReplyList( @Parameter(description = "댓글 목록을 페이지별로 조회합니다. **Page는 0부터 시작합니다!**", required = true) @RequestParam(value = "page") Integer page, @Parameter(description = "감상평 Id를 입력해주세요.", required = true) @PathVariable(value = "reviewId") Long reviewId @@ -69,4 +69,17 @@ public ResponseEntity deleteReply( ) { return replyService.deleteReply(userPrincipal, replyId); } + + // Description : 댓글 존재 여부 조회 + @Operation(summary = "댓글 존재 여부 조회", description = "댓글 존재 여부를 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ReplyResponseDto.ExistReplyRes.class))}), + @ApiResponse(responseCode = "400", description = "조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), + }) + @GetMapping("/{replyId}") + public ResponseEntity existReply( + @Parameter(description = "댓글 Id를 입력해주세요.", required = true) @PathVariable(value = "replyId") Long replyId + ) { + return replyService.existReply(replyId); + } } diff --git a/src/main/java/depth/jeonsilog/domain/report/application/ReportService.java b/src/main/java/depth/jeonsilog/domain/report/application/ReportService.java index 9a4bdf1..a0fe594 100644 --- a/src/main/java/depth/jeonsilog/domain/report/application/ReportService.java +++ b/src/main/java/depth/jeonsilog/domain/report/application/ReportService.java @@ -122,8 +122,8 @@ private List createTargetList(List reports) { Object target = new Object(); switch (report.getReportType()) { - case REVIEW -> target = reviewService.validateReviewById(report.getReportedId()); - case REPLY -> target = replyService.validateReplyById(report.getReportedId()); + case REVIEW -> target = reviewRepository.findReviewByReviewId(report.getReportedId()); + case REPLY -> target = replyRepository.findReplyByReplyId(report.getReportedId()); case EXHIBITION -> target = exhibitionService.validateExhibitionById(report.getReportedId()); } targetList.add(target); diff --git a/src/main/java/depth/jeonsilog/domain/report/converter/ReportConverter.java b/src/main/java/depth/jeonsilog/domain/report/converter/ReportConverter.java index bd8eefd..499d1b5 100644 --- a/src/main/java/depth/jeonsilog/domain/report/converter/ReportConverter.java +++ b/src/main/java/depth/jeonsilog/domain/report/converter/ReportConverter.java @@ -1,5 +1,6 @@ package depth.jeonsilog.domain.report.converter; +import depth.jeonsilog.domain.common.Status; import depth.jeonsilog.domain.exhibition.domain.Exhibition; import depth.jeonsilog.domain.reply.domain.Reply; import depth.jeonsilog.domain.reply.dto.ReplyResponseDto; @@ -33,28 +34,35 @@ public static List toReportResList(List rep String name = ""; Report report = reports.get(i); Object target = targetList.get(i); + Long clickId = null; if (target instanceof Review) { Review review = (Review) target; + if (review.getStatus().equals(Status.DELETE)) + continue; User user = review.getUser(); name = user.getNickname(); + clickId = review.getId(); } else if (target instanceof Reply) { Reply reply = (Reply) target; + if (reply.getStatus().equals(Status.DELETE)) + continue; User user = reply.getUser(); name = user.getNickname(); - + clickId = reply.getReview().getId(); } else if (target instanceof Exhibition) { Exhibition exhibition = (Exhibition) target; name = exhibition.getName(); - + clickId = exhibition.getId(); } ReportResponseDto.ReportRes reportRes = ReportResponseDto.ReportRes.builder() .reportId(report.getId()) .name(name) // 신고된 유저 혹은 전시회 이름 .reportType(report.getReportType()) .reportedId(report.getReportedId()) + .clickId(clickId) .isChecked(report.getIsChecked()) .build(); diff --git a/src/main/java/depth/jeonsilog/domain/report/dto/ReportResponseDto.java b/src/main/java/depth/jeonsilog/domain/report/dto/ReportResponseDto.java index 6ea9193..468554a 100644 --- a/src/main/java/depth/jeonsilog/domain/report/dto/ReportResponseDto.java +++ b/src/main/java/depth/jeonsilog/domain/report/dto/ReportResponseDto.java @@ -26,6 +26,9 @@ public static class ReportRes { @Schema(type = "Long", example = "1", description = "신고된 감상평, 댓글 혹은 전시회 ID를 출력합니다.") private Long reportedId; + @Schema(type = "Long", example = "1", description = "클릭 시 이동할 페이지를 위한 ID입니다. Exhibition, Review는 Exhibition, Review ID와 같으며, Reply의 경우 clickId는 작성된 Review의 ID입니다.") + private Long clickId; + @Schema(type = "boolean", example = "true", description = "신고를 확인했는지 출력합니다.") private Boolean isChecked; } diff --git a/src/main/java/depth/jeonsilog/domain/report/presentation/ReportController.java b/src/main/java/depth/jeonsilog/domain/report/presentation/ReportController.java index 53a6ceb..10f25c7 100644 --- a/src/main/java/depth/jeonsilog/domain/report/presentation/ReportController.java +++ b/src/main/java/depth/jeonsilog/domain/report/presentation/ReportController.java @@ -61,7 +61,7 @@ public ResponseEntity findReportList( @ApiResponse(responseCode = "200", description = "확인 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = Message.class))}), @ApiResponse(responseCode = "400", description = "확인 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}), }) - @PostMapping("/check/{reportId}") + @PatchMapping("/check/{reportId}") public ResponseEntity checkReport( @Parameter(description = "Access Token을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal, @Parameter(description = "신고 Id를 입력해주세요.", required = true) @PathVariable(value = "reportId") Long reportId diff --git a/src/main/java/depth/jeonsilog/domain/review/domain/repository/ReviewRepository.java b/src/main/java/depth/jeonsilog/domain/review/domain/repository/ReviewRepository.java index ebae039..8641b02 100644 --- a/src/main/java/depth/jeonsilog/domain/review/domain/repository/ReviewRepository.java +++ b/src/main/java/depth/jeonsilog/domain/review/domain/repository/ReviewRepository.java @@ -19,6 +19,9 @@ public interface ReviewRepository extends JpaRepository { @Query(value = "SELECT * FROM review WHERE user_id = :userId", nativeQuery = true) List findAllReviewsByUserId(@Param("userId") Long userId); + @Query(value = "SELECT * FROM review WHERE id = :reviewId", nativeQuery = true) + Review findReviewByReviewId(@Param("reviewId") Long reviewId); + Optional findByUserIdAndExhibitionId(Long userId, Long exhibitionId); Page findByUserId(PageRequest pageRequest, Long userId);