Skip to content

Commit

Permalink
Merge pull request #132 from Team-Blitz-Steady/feat/#129
Browse files Browse the repository at this point in the history
[4차 스프린트 - Review] 내가 받은 리뷰 조회, 비공개 설정 기능 구현/Review 관련 Controller 테스트 및 문서화
  • Loading branch information
na-yk authored Nov 20, 2023
2 parents 91cc392 + f433455 commit 3ce3f03
Show file tree
Hide file tree
Showing 27 changed files with 394 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public ResponseEntity<ApplicationDetailResponse> getApplicationDetail(@PathVaria

@PatchMapping("/applications/{applicationId}/status")
public ResponseEntity<Void> updateApplicationStatus(@PathVariable Long applicationId,
@RequestBody ApplicationStatusUpdateRequest request,
@Auth UserInfo userInfo) {
@RequestBody ApplicationStatusUpdateRequest request,
@Auth UserInfo userInfo) {
applicationService.updateStatusOfApplication(applicationId, request, userInfo);
return ResponseEntity.noContent().build();
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/dev/steady/global/config/QueryDslConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.steady.global.config;

import com.querydsl.jpa.JPQLTemplates;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -14,7 +15,7 @@ public class QueryDslConfig {

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
return new JPAQueryFactory(JPQLTemplates.DEFAULT, entityManager);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import dev.steady.application.domain.Application;
import dev.steady.application.domain.ApplicationStatus;
import dev.steady.steady.domain.Steady;
import dev.steady.user.domain.User;

public class ApplicationResultNotificationStrategy extends NotificationStrategy {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dev.steady.notification.domain;

import dev.steady.steady.domain.Steady;
import dev.steady.user.domain.User;

public class FreshApplicationNotificationStrategy extends NotificationStrategy {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ public enum NotificationMessage {

FRESH_APPLICATION("[%s] 스테디에 새로운 신청서가 도착했어요."),
APPLICATION_ACCEPTED("[%s] 스터디에 제출한 신청서가 수락됐어요."),
APPLICATION_REJECTED("[%s] 스터디에 제출한 신청서가 거절됐어요."),;
APPLICATION_REJECTED("[%s] 스터디에 제출한 신청서가 거절됐어요."),
;

private final String message;

Expand Down
22 changes: 20 additions & 2 deletions src/main/java/dev/steady/review/controller/ReviewController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import dev.steady.global.auth.Auth;
import dev.steady.global.auth.UserInfo;
import dev.steady.review.dto.ReviewCreateRequest;
import dev.steady.review.dto.request.ReviewCreateRequest;
import dev.steady.review.dto.response.ReviewMyResponse;
import dev.steady.review.dto.response.ReviewSwitchResponse;
import dev.steady.review.service.ReviewService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -29,8 +33,22 @@ public ResponseEntity<Void> createReview(@PathVariable Long steadyId,
reviewService.createUserCards(request);

return ResponseEntity.created(
URI.create(String.format("/api/v1/steadies/%d/review/%d", steadyId, reviewId)))
URI.create(String.format("/api/v1/reviews/%d", reviewId)))
.build();
}

@PatchMapping("/reviews/{reviewId}")
public ResponseEntity<ReviewSwitchResponse> updateReviewIsPublic(@PathVariable Long reviewId,
@Auth UserInfo userInfo) {
ReviewSwitchResponse response = reviewService.switchReviewIsPublic(reviewId, userInfo);

return ResponseEntity.ok(response);
}

@GetMapping("/reviews/my")
public ResponseEntity<ReviewMyResponse> getMyCardsAndReviews(@Auth UserInfo userInfo) {
ReviewMyResponse response = reviewService.getMyCardsAndReviews(userInfo);
return ResponseEntity.ok(response);
}

}
4 changes: 4 additions & 0 deletions src/main/java/dev/steady/review/domain/Review.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ private Review(Participant reviewer,
this.isPublic = true;
}

public void switchIsPublic() {
this.isPublic = !isPublic;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import static dev.steady.review.exception.ReviewErrorCode.REVIEW_NOT_FOUND;

public interface ReviewRepository extends JpaRepository<Review, Long> {

default Review getById(Long reviewId) {
return findById(reviewId)
.orElseThrow(() -> new NotFoundException(REVIEW_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.steady.review.dto;
package dev.steady.review.dto.request;

import dev.steady.review.domain.Review;
import dev.steady.steady.domain.Participant;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.steady.review.dto.response;

import java.time.LocalDateTime;

public record ReviewDetailResponse(
Long reviewId,
String comment,
boolean isPublic,
LocalDateTime createdAt
) {
}
15 changes: 15 additions & 0 deletions src/main/java/dev/steady/review/dto/response/ReviewMyResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.steady.review.dto.response;

import java.util.List;

public record ReviewMyResponse(
List<UserCardResponse> userCards,
List<ReviewsBySteadyResponse> reviews
) {

public static ReviewMyResponse of(List<UserCardResponse> userCards,
List<ReviewsBySteadyResponse> reviews) {
return new ReviewMyResponse(userCards, reviews);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dev.steady.review.dto.response;

import dev.steady.review.domain.Review;

public record ReviewSwitchResponse(
boolean isPublic
) {

public static ReviewSwitchResponse from(Review review) {
return new ReviewSwitchResponse(review.isPublic());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package dev.steady.review.dto.response;

import java.util.List;

public record ReviewsBySteadyResponse(
Long steadyId,
String steadyName,
List<ReviewDetailResponse> reviews
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ public enum ReviewErrorCode implements ErrorCode {
CARD_NOT_FOUND("R002", "카드를 찾을 수 없습니다."),
REVIEW_NOT_ENABLED("R003", "리뷰할 수 있는 상태가 아닙니다"),
REVIEWEE_EQUALS_REVIEWER("R004", "리뷰이와 리뷰어가 동일합니다."),
REVIEW_DUPLICATE("R005", "리뷰를 중복 제출할 수 없습니다.");
REVIEW_DUPLICATE("R005", "리뷰를 중복 제출할 수 없습니다."),
REVIEW_AUTH_FAILURE("R006", "리뷰에 접근 권한이 없습니다.");

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package dev.steady.review.infrastructure;

import dev.steady.review.dto.response.ReviewsBySteadyResponse;
import dev.steady.user.domain.User;

import java.util.List;

public interface ReviewQueryRepository {

List<String> findPublicCommentsByRevieweeUser(User user);
List<String> getPublicCommentsByRevieweeUser(User user);

List<ReviewsBySteadyResponse> getAllReviewsByRevieweeUser(User user);

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
package dev.steady.review.infrastructure;

import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import dev.steady.review.dto.response.ReviewDetailResponse;
import dev.steady.review.dto.response.ReviewsBySteadyResponse;
import dev.steady.user.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.querydsl.core.group.GroupBy.groupBy;
import static com.querydsl.core.group.GroupBy.list;
import static dev.steady.review.domain.QReview.review;
import static dev.steady.steady.domain.QSteady.steady;

@Repository
@RequiredArgsConstructor
Expand All @@ -19,7 +25,7 @@ public class ReviewQueryRepositoryImpl implements ReviewQueryRepository {
private final JPAQueryFactory jpaQueryFactory;

@Override
public List<String> findPublicCommentsByRevieweeUser(User user) {
public List<String> getPublicCommentsByRevieweeUser(User user) {
return jpaQueryFactory.select(review.comment)
.from(review)
.where(revieweeEqualsUser(user),
Expand All @@ -28,6 +34,28 @@ public List<String> findPublicCommentsByRevieweeUser(User user) {
.fetch();
}

@Override
public List<ReviewsBySteadyResponse> getAllReviewsByRevieweeUser(User user) {
return jpaQueryFactory.selectFrom(steady)
.leftJoin(review)
.on(steady.id.eq(review.steady.id))
.where(revieweeEqualsUser(user))
.orderBy(steady.finishedAt.desc())
.transform(groupBy(steady.id)
.list(Projections.constructor(
ReviewsBySteadyResponse.class,
steady.id,
steady.name,
list(Projections.constructor(
ReviewDetailResponse.class,
review.id,
review.comment,
review.isPublic,
review.createdAt
))
)));
}

private BooleanExpression revieweeEqualsUser(User user) {
return review.reviewee.user.eq(user);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

public interface UserCardQueryRepository {

List<UserCardResponse> findCardCountByUser(User user);
List<UserCardResponse> getCardCountByUser(User user);

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class UserCardQueryRepositoryImpl implements UserCardQueryRepository {
private final JPAQueryFactory jpaQueryFactory;

@Override
public List<UserCardResponse> findCardCountByUser(User user) {
public List<UserCardResponse> getCardCountByUser(User user) {
return jpaQueryFactory.select(Projections.constructor(UserCardResponse.class,
card.id,
card.content,
Expand Down
38 changes: 37 additions & 1 deletion src/main/java/dev/steady/review/service/ReviewService.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package dev.steady.review.service;

import dev.steady.global.auth.UserInfo;
import dev.steady.global.exception.ForbiddenException;
import dev.steady.global.exception.InvalidStateException;
import dev.steady.review.domain.Card;
import dev.steady.review.domain.Review;
import dev.steady.review.domain.UserCard;
import dev.steady.review.domain.repository.CardRepository;
import dev.steady.review.domain.repository.ReviewRepository;
import dev.steady.review.domain.repository.UserCardRepository;
import dev.steady.review.dto.ReviewCreateRequest;
import dev.steady.review.dto.request.ReviewCreateRequest;
import dev.steady.review.dto.response.ReviewMyResponse;
import dev.steady.review.dto.response.ReviewSwitchResponse;
import dev.steady.review.dto.response.ReviewsBySteadyResponse;
import dev.steady.review.dto.response.UserCardResponse;
import dev.steady.review.infrastructure.ReviewQueryRepository;
import dev.steady.review.infrastructure.UserCardQueryRepository;
import dev.steady.steady.domain.Participant;
import dev.steady.steady.domain.Participants;
import dev.steady.steady.domain.Steady;
Expand All @@ -23,6 +30,7 @@
import java.util.Objects;

import static dev.steady.review.exception.ReviewErrorCode.REVIEWEE_EQUALS_REVIEWER;
import static dev.steady.review.exception.ReviewErrorCode.REVIEW_AUTH_FAILURE;
import static dev.steady.review.exception.ReviewErrorCode.REVIEW_DUPLICATE;
import static dev.steady.review.exception.ReviewErrorCode.REVIEW_NOT_ENABLED;

Expand All @@ -35,6 +43,8 @@ public class ReviewService {
private final UserRepository userRepository;
private final CardRepository cardRepository;
private final UserCardRepository userCardRepository;
private final UserCardQueryRepository userCardQueryRepository;
private final ReviewQueryRepository reviewQueryRepository;

@Transactional
public Long createReview(Long steadyId, ReviewCreateRequest request, UserInfo userInfo) {
Expand Down Expand Up @@ -75,6 +85,32 @@ public void createUserCards(ReviewCreateRequest request) {
userCardRepository.saveAll(userCards);
}

/**
* 리뷰의 공개 여부(isPublic)을 변경하고 그 결과를 반환한다.
*
* @param reviewId 리뷰 식별자
* @param userInfo 사용자 정보
* @return 리뷰 공개 여부 변경된 결과
*/
@Transactional
public ReviewSwitchResponse switchReviewIsPublic(Long reviewId, UserInfo userInfo) {
Review review = reviewRepository.getById(reviewId);
Participant reviewee = review.getReviewee();
if (!Objects.equals(reviewee.getUserId(), userInfo.userId())) {
throw new ForbiddenException(REVIEW_AUTH_FAILURE);
}
review.switchIsPublic();
return ReviewSwitchResponse.from(review);
}

@Transactional(readOnly = true)
public ReviewMyResponse getMyCardsAndReviews(UserInfo userInfo) {
User user = userRepository.getUserBy(userInfo.userId());
List<UserCardResponse> userCards = userCardQueryRepository.getCardCountByUser(user);
List<ReviewsBySteadyResponse> reviews = reviewQueryRepository.getAllReviewsByRevieweeUser(user);
return ReviewMyResponse.of(userCards, reviews);
}

private boolean isAlreadyReviewed(Participant reviewer, Participant reviewee, Steady steady) {
return reviewRepository.existsByReviewerAndRevieweeAndSteady(
reviewer,
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/dev/steady/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public UserOtherDetailResponse getOtherUserDetail(Long userId) {
User user = userRepository.getUserBy(userId);
List<UserStack> userStacks = userStackRepository.findAllByUser(user);
UserDetailResponse userDetailResponse = UserDetailResponse.of(user, userStacks);
List<UserCardResponse> userCardResponses = userCardQueryRepository.findCardCountByUser(user);
List<String> reviews = reviewQueryRepository.findPublicCommentsByRevieweeUser(user);
List<UserCardResponse> userCardResponses = userCardQueryRepository.getCardCountByUser(user);
List<String> reviews = reviewQueryRepository.getPublicCommentsByRevieweeUser(user);

return UserOtherDetailResponse.of(
userDetailResponse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import dev.steady.global.auth.AuthContext;
import dev.steady.notification.controller.NotificationController;
import dev.steady.notification.service.NotificationService;
import dev.steady.review.controller.ReviewController;
import dev.steady.review.service.ReviewService;
import dev.steady.steady.controller.SteadyController;
import dev.steady.steady.controller.SteadyLikeController;
import dev.steady.steady.service.SteadyLikeService;
Expand Down Expand Up @@ -48,6 +50,7 @@
StackController.class,
PositionController.class,
NotificationController.class,
ReviewController.class,
AuthContext.class,
JwtResolver.class,
JwtProperties.class,
Expand Down Expand Up @@ -83,6 +86,8 @@ public abstract class ControllerTestConfig {
@MockBean
protected NotificationService notificationService;
@MockBean
protected ReviewService reviewService;
@MockBean
protected JwtResolver jwtResolver;

@BeforeEach
Expand Down
Loading

0 comments on commit 3ce3f03

Please sign in to comment.