From e0bd7afab8ba3d3d5e8bea2010fd448c3917e2a0 Mon Sep 17 00:00:00 2001 From: Donghun Won Date: Wed, 23 Oct 2024 17:20:57 +0900 Subject: [PATCH] =?UTF-8?q?Feat(#228)=20:=20=EC=A0=95=EB=B3=B4=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=83=9D=EC=84=B1,=20=EC=A1=B0=ED=9A=8C,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20(#238)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feat : 정보 댓글 생성, 수정, 삭제 * Feat : 댓글 조회 정보 조회 시 댓글도 같이 조회 댓글만 페이지 단위로 조회 * Style : 불필요한 import 삭제 * Fix : CreatedDate 삭제, validation 예외 처리 로직 추가 * Fix : validation 추가, modifiedDate 어노테이션 추가 --- .../error/GlobalControllerAdvice.java | 6 +- .../response/InformationDetailResponse.java | 5 ++ .../information/entity/Information.java | 2 +- .../repository/InformationRepository.java | 6 ++ .../service/InformationService.java | 14 +++- .../InformationCommentController.java | 82 +++++++++++++++++++ .../request/InformationCommentRequest.java | 14 ++++ .../InformationCommentListResponse.java | 20 +++++ .../respose/InformationCommentResponse.java | 12 +++ .../entity/InformationComment.java | 54 ++++++++++++ .../exception/CommentNotOwnerException.java | 8 ++ .../InformationCommentNotExistsException.java | 8 ++ .../InformationCommentRepository.java | 9 ++ .../InformationCommentRepositoryCustom.java | 12 +++ .../InformationCommentRepositoryImpl.java | 53 ++++++++++++ .../service/InformationCommentService.java | 80 ++++++++++++++++++ src/main/resources/schema.sql | 16 +++- 17 files changed, 396 insertions(+), 5 deletions(-) create mode 100644 src/main/java/solitour_backend/solitour/information_comment/controller/InformationCommentController.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/dto/request/InformationCommentRequest.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentListResponse.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentResponse.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/entity/InformationComment.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/exception/CommentNotOwnerException.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/exception/InformationCommentNotExistsException.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepository.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryCustom.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryImpl.java create mode 100644 src/main/java/solitour_backend/solitour/information_comment/service/InformationCommentService.java diff --git a/src/main/java/solitour_backend/solitour/error/GlobalControllerAdvice.java b/src/main/java/solitour_backend/solitour/error/GlobalControllerAdvice.java index a877ef34..9d86e406 100644 --- a/src/main/java/solitour_backend/solitour/error/GlobalControllerAdvice.java +++ b/src/main/java/solitour_backend/solitour/error/GlobalControllerAdvice.java @@ -28,6 +28,8 @@ import solitour_backend.solitour.image.exception.ImageRequestValidationFailedException; import solitour_backend.solitour.information.exception.InformationNotExistsException; import solitour_backend.solitour.information.exception.InformationNotManageException; +import solitour_backend.solitour.information_comment.exception.CommentNotOwnerException; +import solitour_backend.solitour.information_comment.exception.InformationCommentNotExistsException; import solitour_backend.solitour.user.exception.BlockedUserException; import solitour_backend.solitour.user.exception.DeletedUserException; import solitour_backend.solitour.user.exception.DormantUserException; @@ -79,6 +81,7 @@ public ResponseEntity conflictException(Exception exception) { GatheringBookMarkNotExistsException.class, InformationBookMarkNotExistsException.class, DiaryNotExistsException.class, + InformationCommentNotExistsException.class }) public ResponseEntity notFoundException(Exception exception) { return ResponseEntity @@ -89,7 +92,8 @@ public ResponseEntity notFoundException(Exception exception) { @ExceptionHandler({GatheringNotManagerException.class, ForbiddenAccessException.class, BlockedUserException.class, - DeletedUserException.class + DeletedUserException.class, + CommentNotOwnerException.class }) public ResponseEntity forbiddenException(Exception exception) { return ResponseEntity diff --git a/src/main/java/solitour_backend/solitour/information/dto/response/InformationDetailResponse.java b/src/main/java/solitour_backend/solitour/information/dto/response/InformationDetailResponse.java index ef5c47e6..404a223f 100644 --- a/src/main/java/solitour_backend/solitour/information/dto/response/InformationDetailResponse.java +++ b/src/main/java/solitour_backend/solitour/information/dto/response/InformationDetailResponse.java @@ -5,8 +5,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import solitour_backend.solitour.category.dto.response.CategoryResponse; import solitour_backend.solitour.image.dto.response.ImageResponse; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentListResponse; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentResponse; import solitour_backend.solitour.place.dto.response.PlaceResponse; import solitour_backend.solitour.tag.dto.response.TagResponse; import solitour_backend.solitour.user.dto.UserPostingResponse; @@ -34,4 +38,5 @@ public class InformationDetailResponse { private String userImage; private Boolean isLike; private List recommendInformation; + private Page informationCommentResponses; } diff --git a/src/main/java/solitour_backend/solitour/information/entity/Information.java b/src/main/java/solitour_backend/solitour/information/entity/Information.java index 23fc47c9..1d951855 100644 --- a/src/main/java/solitour_backend/solitour/information/entity/Information.java +++ b/src/main/java/solitour_backend/solitour/information/entity/Information.java @@ -10,6 +10,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import solitour_backend.solitour.category.entity.Category; +import solitour_backend.solitour.information_comment.entity.InformationComment; import solitour_backend.solitour.place.entity.Place; import solitour_backend.solitour.user.entity.User; import solitour_backend.solitour.zone_category.entity.ZoneCategory; @@ -43,7 +44,6 @@ public class Information { @JoinColumn(name = "place_id") private Place place; - @Column(name = "information_title") private String title; diff --git a/src/main/java/solitour_backend/solitour/information/repository/InformationRepository.java b/src/main/java/solitour_backend/solitour/information/repository/InformationRepository.java index 434f4100..0125580f 100644 --- a/src/main/java/solitour_backend/solitour/information/repository/InformationRepository.java +++ b/src/main/java/solitour_backend/solitour/information/repository/InformationRepository.java @@ -1,9 +1,15 @@ package solitour_backend.solitour.information.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import solitour_backend.solitour.information.entity.Information; +import solitour_backend.solitour.user.entity.User; + +import java.util.Optional; public interface InformationRepository extends JpaRepository, InformationRepositoryCustom { + @Query("SELECT i FROM Information i WHERE i.user.id = :userId") + Optional findByUserId(Long userId); } diff --git a/src/main/java/solitour_backend/solitour/information/service/InformationService.java b/src/main/java/solitour_backend/solitour/information/service/InformationService.java index f0b04eca..12197775 100644 --- a/src/main/java/solitour_backend/solitour/information/service/InformationService.java +++ b/src/main/java/solitour_backend/solitour/information/service/InformationService.java @@ -18,6 +18,8 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -53,6 +55,10 @@ import solitour_backend.solitour.information.exception.InformationNotExistsException; import solitour_backend.solitour.information.exception.InformationNotManageException; import solitour_backend.solitour.information.repository.InformationRepository; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentListResponse; +import solitour_backend.solitour.information_comment.entity.InformationComment; +import solitour_backend.solitour.information_comment.repository.InformationCommentRepository; +import solitour_backend.solitour.information_comment.service.InformationCommentService; import solitour_backend.solitour.place.dto.mapper.PlaceMapper; import solitour_backend.solitour.place.dto.request.PlaceModifyRequest; import solitour_backend.solitour.place.dto.response.PlaceResponse; @@ -101,7 +107,7 @@ public class InformationService { private final UserImageRepository userImageRepository; private final ImageRepository imageRepository; private final CategoryMapper categoryMapper; - + private final InformationCommentService informationCommentService; @Transactional public InformationResponse registerInformation(Long userId, InformationCreateRequest informationCreateRequest) { @@ -210,6 +216,8 @@ public InformationDetailResponse getDetailInformation(Long userId, Long informat .orElseGet( () -> userRepository.getProfileUrl(user.getSex())); + int INFORMATION_COMMENT_PAGE_SIZE = 5; + Page comments = informationCommentService.getPageInformationComment(PageRequest.of(0, INFORMATION_COMMENT_PAGE_SIZE), information.getId()); try { updateViewCount(information, request, response, userId); } catch (Exception e) { @@ -232,7 +240,9 @@ public InformationDetailResponse getDetailInformation(Long userId, Long informat likeCount, userImageUrl, isLike, - informationRecommend); + informationRecommend, + comments + ); } @Transactional diff --git a/src/main/java/solitour_backend/solitour/information_comment/controller/InformationCommentController.java b/src/main/java/solitour_backend/solitour/information_comment/controller/InformationCommentController.java new file mode 100644 index 00000000..cd108884 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/controller/InformationCommentController.java @@ -0,0 +1,82 @@ +package solitour_backend.solitour.information_comment.controller; + + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; +import solitour_backend.solitour.auth.config.Authenticated; +import solitour_backend.solitour.auth.config.AuthenticationPrincipal; +import solitour_backend.solitour.error.Utils; +import solitour_backend.solitour.information_comment.dto.request.InformationCommentRequest; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentListResponse; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentResponse; +import solitour_backend.solitour.information_comment.service.InformationCommentService; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/informations/comments") +public class InformationCommentController { + + private final InformationCommentService informationCommentService; + + + @Authenticated + @PostMapping("/{informationId}") + public ResponseEntity createInformationComment(@AuthenticationPrincipal Long userId, + @PathVariable Long informationId, + @Valid @RequestBody InformationCommentRequest informationCommentRequest, + BindingResult bindingResult) { + Utils.validationRequest(bindingResult); + + InformationCommentResponse informationCommentResponse = informationCommentService.createInformationComment( + userId, informationId, informationCommentRequest); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(informationCommentResponse); + } + + @GetMapping("/{informationId}") + public ResponseEntity> getPageInformationComment( + @RequestParam(defaultValue = "0") int page, + @PathVariable Long informationId) { + + final int PAGE_SIZE = 5; + Pageable pageable = PageRequest.of(page, PAGE_SIZE); + Page pageInformation = informationCommentService.getPageInformationComment( + pageable, informationId); + + return ResponseEntity + .status(HttpStatus.OK) + .body(pageInformation); + } + + @Authenticated + @PutMapping("/{informationCommentId}") + public ResponseEntity modifyInformationComment(@AuthenticationPrincipal Long userId, + @PathVariable Long informationCommentId, + @Valid @RequestBody InformationCommentRequest informationCommentRequest, + BindingResult bindingResult) { + Utils.validationRequest(bindingResult); + + informationCommentService.modifyInformationComment(userId, informationCommentId, informationCommentRequest); + + return ResponseEntity.noContent().build(); + } + + @Authenticated + @DeleteMapping("/{informationCommentId}") + public ResponseEntity deleteInformationComment(@AuthenticationPrincipal Long userId, + @PathVariable Long informationCommentId) { + informationCommentService.deleteInformationComment(userId, informationCommentId); + + return ResponseEntity.noContent().build(); + } +} + diff --git a/src/main/java/solitour_backend/solitour/information_comment/dto/request/InformationCommentRequest.java b/src/main/java/solitour_backend/solitour/information_comment/dto/request/InformationCommentRequest.java new file mode 100644 index 00000000..72d8f5a1 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/dto/request/InformationCommentRequest.java @@ -0,0 +1,14 @@ +package solitour_backend.solitour.information_comment.dto.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class InformationCommentRequest { + @NotBlank + private String comment; +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentListResponse.java b/src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentListResponse.java new file mode 100644 index 00000000..b7540b1c --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentListResponse.java @@ -0,0 +1,20 @@ +package solitour_backend.solitour.information_comment.dto.respose; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Getter +@AllArgsConstructor +@ToString +public class InformationCommentListResponse { + private Long commentId; + private Long userId; + private String userNickname; + private String userProfile; + private String content; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentResponse.java b/src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentResponse.java new file mode 100644 index 00000000..7bd3319a --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/dto/respose/InformationCommentResponse.java @@ -0,0 +1,12 @@ +package solitour_backend.solitour.information_comment.dto.respose; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class InformationCommentResponse { + @NotBlank + private Long commentId; +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/entity/InformationComment.java b/src/main/java/solitour_backend/solitour/information_comment/entity/InformationComment.java new file mode 100644 index 00000000..46f5484e --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/entity/InformationComment.java @@ -0,0 +1,54 @@ +package solitour_backend.solitour.information_comment.entity; + +import jakarta.persistence.*; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import solitour_backend.solitour.information.entity.Information; +import solitour_backend.solitour.information_comment.dto.request.InformationCommentRequest; +import solitour_backend.solitour.user.entity.User; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "information_comment") +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +@EntityListeners(AuditingEntityListener.class) +public class InformationComment { + + @Id + @Column(name = "information_comment_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "information_id") + private Information information; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "information_comment_content") + private String content; + + @CreatedDate + @Column(name = "information_comment_created_date") + private LocalDateTime createdDate; + + @LastModifiedDate + @Column(name = "information_comment_updated_date") + private LocalDateTime updatedDate; + + public void updateComment(@Valid InformationCommentRequest informationCommentRequest) { + this.content = informationCommentRequest.getComment(); + } +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/exception/CommentNotOwnerException.java b/src/main/java/solitour_backend/solitour/information_comment/exception/CommentNotOwnerException.java new file mode 100644 index 00000000..92e3924c --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/exception/CommentNotOwnerException.java @@ -0,0 +1,8 @@ +package solitour_backend.solitour.information_comment.exception; + +public class CommentNotOwnerException extends RuntimeException { + + public CommentNotOwnerException(String message) { + super(message); + } +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/exception/InformationCommentNotExistsException.java b/src/main/java/solitour_backend/solitour/information_comment/exception/InformationCommentNotExistsException.java new file mode 100644 index 00000000..7a047383 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/exception/InformationCommentNotExistsException.java @@ -0,0 +1,8 @@ +package solitour_backend.solitour.information_comment.exception; + +public class InformationCommentNotExistsException extends RuntimeException { + + public InformationCommentNotExistsException(String message) { + super(message); + } +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepository.java b/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepository.java new file mode 100644 index 00000000..348bb791 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepository.java @@ -0,0 +1,9 @@ +package solitour_backend.solitour.information_comment.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import solitour_backend.solitour.information_comment.entity.InformationComment; + + +public interface InformationCommentRepository extends JpaRepository, InformationCommentRepositoryCustom { +} + diff --git a/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryCustom.java b/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryCustom.java new file mode 100644 index 00000000..034a54a4 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryCustom.java @@ -0,0 +1,12 @@ +package solitour_backend.solitour.information_comment.repository; + +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.NoRepositoryBean; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentListResponse; + + +@NoRepositoryBean +public interface InformationCommentRepositoryCustom { + PageImpl getPageInformationComment(Pageable pageable, Long id); +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryImpl.java b/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryImpl.java new file mode 100644 index 00000000..2e26bd64 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/repository/InformationCommentRepositoryImpl.java @@ -0,0 +1,53 @@ +package solitour_backend.solitour.information_comment.repository; + +import com.querydsl.core.types.Projections; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; +import solitour_backend.solitour.information.entity.Information; +import solitour_backend.solitour.information.entity.QInformation; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentListResponse; +import solitour_backend.solitour.information_comment.entity.QInformationComment; + +import java.util.List; + +@Slf4j +public class InformationCommentRepositoryImpl extends QuerydslRepositorySupport implements InformationCommentRepositoryCustom { + + public InformationCommentRepositoryImpl() { + super(Information.class); + } + + QInformation information = QInformation.information; + QInformationComment informationComment = QInformationComment.informationComment; + + @Override + public PageImpl getPageInformationComment(Pageable pageable, Long informationId) { + + long total = from(informationComment) + .leftJoin(information).on(information.id.eq(informationComment.information.id)) + .where(informationComment.information.id.eq(informationId)) + .distinct() + .fetchCount(); + + List list = from(informationComment) + .leftJoin(information).on(information.id.eq(informationComment.information.id)) + .where(informationComment.information.id.eq(informationId)) + .groupBy(informationComment.id) + .select(Projections.constructor( + InformationCommentListResponse.class, + informationComment.id, + informationComment.user.id, + informationComment.user.nickname, + informationComment.user.userImage.address, + informationComment.content, + informationComment.createdDate, + informationComment.updatedDate + )).offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + return new PageImpl<>(list, pageable, total); + } +} diff --git a/src/main/java/solitour_backend/solitour/information_comment/service/InformationCommentService.java b/src/main/java/solitour_backend/solitour/information_comment/service/InformationCommentService.java new file mode 100644 index 00000000..492aac7e --- /dev/null +++ b/src/main/java/solitour_backend/solitour/information_comment/service/InformationCommentService.java @@ -0,0 +1,80 @@ +package solitour_backend.solitour.information_comment.service; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import solitour_backend.solitour.information.entity.Information; +import solitour_backend.solitour.information.exception.InformationNotExistsException; +import solitour_backend.solitour.information.repository.InformationRepository; +import solitour_backend.solitour.information_comment.dto.request.InformationCommentRequest; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentListResponse; +import solitour_backend.solitour.information_comment.dto.respose.InformationCommentResponse; +import solitour_backend.solitour.information_comment.entity.InformationComment; +import solitour_backend.solitour.information_comment.exception.CommentNotOwnerException; +import solitour_backend.solitour.information_comment.exception.InformationCommentNotExistsException; +import solitour_backend.solitour.information_comment.repository.InformationCommentRepository; +import solitour_backend.solitour.user.entity.User; +import solitour_backend.solitour.user.exception.UserNotExistsException; +import solitour_backend.solitour.user.repository.UserRepository; + +import java.time.LocalDateTime; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class InformationCommentService { + + private final InformationRepository informationRepository; + private final UserRepository userRepository; + private final InformationCommentRepository informationCommentRepository; + + @Transactional + public InformationCommentResponse createInformationComment(Long userId, Long informationId, @Valid InformationCommentRequest informationCommentRequest) { + Information information = informationRepository.findById(informationId) + .orElseThrow(() -> new InformationNotExistsException("해당하는 정보가 없습니다.")); + User user = userRepository.findById(userId) + .orElseThrow(() -> new UserNotExistsException("해당하는 사용자가 없습니다.")); + + InformationComment informationComment = InformationComment.builder() + .information(information) + .user(user) + .content(informationCommentRequest.getComment()) + .createdDate(LocalDateTime.now()) + .build(); + + InformationComment savedInformationComment = informationCommentRepository.save(informationComment); + + return new InformationCommentResponse(savedInformationComment.getId()); + } + + public Page getPageInformationComment(Pageable pageable, Long informationId) { + return informationCommentRepository.getPageInformationComment(pageable, informationId); + } + + @Transactional + public void modifyInformationComment(Long userId, Long informationCommentId, @Valid InformationCommentRequest informationCommentRequest) { + InformationComment informationComment = informationCommentRepository.findById(informationCommentId) + .orElseThrow(() -> new InformationCommentNotExistsException("정보에 해당하는 댓글이 없습니다.")); + + if (!informationComment.getUser().getId().equals(userId)) { + throw new CommentNotOwnerException("댓글을 작성한 사용자가 아닙니다."); + } + + informationComment.updateComment(informationCommentRequest); + } + + @Transactional + public void deleteInformationComment(Long userId, Long informationCommentId) { + InformationComment informationComment = informationCommentRepository.findById(informationCommentId) + .orElseThrow(() -> new InformationCommentNotExistsException("정보에 해당하는 댓글이 없습니다.")); + + if (!informationComment.getUser().getId().equals(userId)) { + throw new CommentNotOwnerException("댓글을 작성한 사용자가 아닙니다."); + } + + informationCommentRepository.delete(informationComment); + } +} diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index fddd9751..37c20a46 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -6,6 +6,7 @@ DROP TABLE IF EXISTS `info_tag`; DROP TABLE IF EXISTS `gathering_tag`; DROP TABLE IF EXISTS `comment`; DROP TABLE IF EXISTS `image`; +Drop TABLE IF EXISTS `information_comment`; DROP TABLE IF EXISTS `information`; DROP TABLE IF EXISTS `gathering_applicants`; DROP TABLE IF EXISTS `gathering`; @@ -314,7 +315,6 @@ CREATE TABLE `diary_day_content` CONSTRAINT `FK_diary_day_content_TO_diary` FOREIGN KEY (`diary_id`) REFERENCES `diary` (`diary_id`) ); - CREATE TABLE `term` ( `term_id` BIGINT NOT NULL AUTO_INCREMENT, @@ -325,3 +325,17 @@ CREATE TABLE `term` PRIMARY KEY (`term_id`), CONSTRAINT `FK_term_TO_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ); + +CREATE TABLE `information_comment` +( + `information_comment_id` BIGINT NOT NULL AUTO_INCREMENT, + `information_id` BIGINT NOT NULL, + `user_id` BIGINT NOT NULL, + `information_comment_content` TEXT NOT NULL, + `information_comment_created_date` DATETIME NOT NULL, + `information_comment_updated_date` DATETIME NULL, + + PRIMARY KEY (`information_comment_id`), + CONSTRAINT `FK_information_comment_TO_information` FOREIGN KEY (`information_id`) REFERENCES `information` (`information_id`), + CONSTRAINT `FK_information_comment_TO_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) +);