Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(#228) : 정보 댓글 생성, 조회, 수정, 삭제 #238

Merged
merged 5 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -79,6 +81,7 @@ public ResponseEntity<String> conflictException(Exception exception) {
GatheringBookMarkNotExistsException.class,
InformationBookMarkNotExistsException.class,
DiaryNotExistsException.class,
InformationCommentNotExistsException.class
})
public ResponseEntity<String> notFoundException(Exception exception) {
return ResponseEntity
Expand All @@ -89,7 +92,8 @@ public ResponseEntity<String> notFoundException(Exception exception) {
@ExceptionHandler({GatheringNotManagerException.class,
ForbiddenAccessException.class,
BlockedUserException.class,
DeletedUserException.class
DeletedUserException.class,
CommentNotOwnerException.class
})
public ResponseEntity<String> forbiddenException(Exception exception) {
return ResponseEntity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -34,4 +38,5 @@ public class InformationDetailResponse {
private String userImage;
private Boolean isLike;
private List<InformationBriefResponse> recommendInformation;
private Page<InformationCommentListResponse> informationCommentResponses;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -43,7 +44,6 @@ public class Information {
@JoinColumn(name = "place_id")
private Place place;


@Column(name = "information_title")
private String title;

Expand Down
Original file line number Diff line number Diff line change
@@ -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<Information, Long>, InformationRepositoryCustom {

@Query("SELECT i FROM Information i WHERE i.user.id = :userId")
Optional<Information> findByUserId(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -210,6 +216,8 @@ public InformationDetailResponse getDetailInformation(Long userId, Long informat
.orElseGet(
() -> userRepository.getProfileUrl(user.getSex()));

int INFORMATION_COMMENT_PAGE_SIZE = 5;
Page<InformationCommentListResponse> comments = informationCommentService.getPageInformationComment(PageRequest.of(0, INFORMATION_COMMENT_PAGE_SIZE), information.getId());
try {
updateViewCount(information, request, response, userId);
} catch (Exception e) {
Expand All @@ -232,7 +240,9 @@ public InformationDetailResponse getDetailInformation(Long userId, Long informat
likeCount,
userImageUrl,
isLike,
informationRecommend);
informationRecommend,
comments
);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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.web.bind.annotation.*;
import solitour_backend.solitour.auth.config.Authenticated;
import solitour_backend.solitour.auth.config.AuthenticationPrincipal;
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<InformationCommentResponse> createInformationComment(@AuthenticationPrincipal Long userId,
@PathVariable Long informationId,
@Valid @RequestBody InformationCommentRequest informationCommentRequest) {

Astin01 marked this conversation as resolved.
Show resolved Hide resolved
InformationCommentResponse informationCommentResponse = informationCommentService.createInformationComment(userId, informationId, informationCommentRequest);

return ResponseEntity
.status(HttpStatus.CREATED)
.body(informationCommentResponse);
}

@GetMapping("/{informationId}")
public ResponseEntity<Page<InformationCommentListResponse>> getPageInformationComment(@RequestParam(defaultValue = "0") int page,
@PathVariable Long informationId) {

final int PAGE_SIZE = 5;
Pageable pageable = PageRequest.of(page, PAGE_SIZE);
Page<InformationCommentListResponse> pageInformation = informationCommentService.getPageInformationComment(pageable, informationId);

return ResponseEntity
.status(HttpStatus.OK)
.body(pageInformation);
}

@Authenticated
@PutMapping("/{informationCommentId}")
public ResponseEntity<Void> modifyInformationComment(@AuthenticationPrincipal Long userId,
@PathVariable Long informationCommentId,
@Valid @RequestBody InformationCommentRequest informationCommentRequest) {

informationCommentService.modifyInformationComment(userId, informationCommentId, informationCommentRequest);

return ResponseEntity.noContent().build();
}

@Authenticated
@DeleteMapping("/{informationCommentId}")
public ResponseEntity<Void> deleteInformationComment(@AuthenticationPrincipal Long userId,
@PathVariable Long informationCommentId) {
informationCommentService.deleteInformationComment(userId, informationCommentId);

return ResponseEntity.noContent().build();
}
}

Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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.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;

@CreatedDate
Astin01 marked this conversation as resolved.
Show resolved Hide resolved
@Column(name = "information_comment_updated_date")
private LocalDateTime updatedDate;
hyeonjaez marked this conversation as resolved.
Show resolved Hide resolved

public void updateComment(@Valid InformationCommentRequest informationCommentRequest) {
this.content = informationCommentRequest.getComment();
this.updatedDate = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package solitour_backend.solitour.information_comment.exception;

public class CommentNotOwnerException extends RuntimeException {

public CommentNotOwnerException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package solitour_backend.solitour.information_comment.exception;

public class InformationCommentNotExistsException extends RuntimeException {

public InformationCommentNotExistsException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -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<InformationComment, Long>, InformationCommentRepositoryCustom {
}

Original file line number Diff line number Diff line change
@@ -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<InformationCommentListResponse> getPageInformationComment(Pageable pageable, Long id);
}
Original file line number Diff line number Diff line change
@@ -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<InformationCommentListResponse> 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<InformationCommentListResponse> 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);
}
}
Loading
Loading