-
Notifications
You must be signed in to change notification settings - Fork 5
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
[BE] issue120: 스터디 리뷰 작성 #140
Changes from 21 commits
ef0e0ff
38dad80
7ea0057
c7fa3cc
1a42d6b
51fb4d8
b07fc33
1230c32
56f8bc3
54644f4
4d0b365
7cdfb2f
eea26ed
81b19ff
94dcdf4
68cac97
b07373d
196b3dc
dca3c70
643bfb0
2bb5f55
36d8a34
11fe2f1
6a61f2b
f41383e
9bab968
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.woowacourse.moamoa.common.exception; | ||
|
||
public class BadRequestException extends RuntimeException { | ||
|
||
public BadRequestException(final String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.woowacourse.moamoa.common.exception; | ||
|
||
public class NotFoundException extends RuntimeException { | ||
|
||
public NotFoundException(final String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,10 +23,20 @@ public MemberDao(final JdbcTemplate jdbcTemplate) { | |
this.jdbcTemplate = jdbcTemplate; | ||
} | ||
|
||
public List<MemberData> findMembersByStudyId(Long studyId) { | ||
String sql = "SELECT github_id, username, image_url, profile_url " | ||
public List<MemberData> findMembersByStudyId(final Long studyId) { | ||
final String sql = "SELECT github_id, username, image_url, profile_url " | ||
Comment on lines
-29
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 굿굿!!👍 |
||
+ "FROM member JOIN study_member ON member.id = study_member.member_id " | ||
+ "WHERE study_member.study_id = ?"; | ||
return jdbcTemplate.query(sql, ROW_MAPPER, studyId); | ||
} | ||
|
||
public boolean existsByStudyIdAndMemberId(final Long studyId, final Long memberId) { | ||
final String sql = "SELECT EXISTS " | ||
+ "( " | ||
+ "SELECT * " | ||
+ "FROM member JOIN study_member ON member.id = study_member.member_id " | ||
+ "WHERE study_member.study_id = ? AND study_member.member_id = ? " | ||
+ ")"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 서브쿼리를 사용하셨군요..!! inner 쿼리에 |
||
return Boolean.TRUE.equals(jdbcTemplate.queryForObject(sql, Boolean.class, studyId, memberId)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
import com.woowacourse.moamoa.member.domain.Member; | ||
import com.woowacourse.moamoa.member.domain.repository.MemberRepository; | ||
import com.woowacourse.moamoa.member.query.data.MemberData; | ||
import com.woowacourse.moamoa.member.service.exception.InvalidMemberException; | ||
import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
@@ -24,7 +24,7 @@ public void saveOrUpdate(final Member member) { | |
|
||
public MemberData searchBy(final Long githubId) { | ||
final Member member = memberRepository.findByGithubId(githubId) | ||
.orElseThrow(() -> new InvalidMemberException("사용자를 찾을 수 없습니다.")); | ||
.orElseThrow(MemberNotFoundException::new); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 명확해서 좋아요 👍 |
||
return new MemberData(member.getGithubId(), member.getUsername(), member.getImageUrl(), member.getProfileUrl()); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.woowacourse.moamoa.member.service.exception; | ||
|
||
import com.woowacourse.moamoa.common.exception.NotFoundException; | ||
|
||
public class MemberNotFoundException extends NotFoundException { | ||
|
||
public MemberNotFoundException() { | ||
super("회원을 찾을 수 없습니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.woowacourse.moamoa.member.service.exception; | ||
|
||
import com.woowacourse.moamoa.common.exception.UnauthorizedException; | ||
|
||
public class NotParticipatedMemberException extends UnauthorizedException { | ||
|
||
public NotParticipatedMemberException() { | ||
super("스터디에 참여한 회원만 후기를 작성할 수 있습니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,32 @@ | ||
package com.woowacourse.moamoa.review.controller; | ||
|
||
import com.woowacourse.moamoa.auth.config.AuthenticationPrincipal; | ||
import com.woowacourse.moamoa.review.service.ReviewService; | ||
import com.woowacourse.moamoa.review.service.response.ReviewsResponse; | ||
import com.woowacourse.moamoa.review.service.request.WriteReviewRequest; | ||
import java.net.URI; | ||
import javax.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/api/studies") | ||
@RequestMapping("/api/studies/{study-id}/reviews") | ||
@RequiredArgsConstructor | ||
public class ReviewController { | ||
|
||
private final ReviewService reviewService; | ||
|
||
@GetMapping("/{study-id}/reviews") | ||
public ResponseEntity<ReviewsResponse> getReviews( | ||
@PathVariable(name = "study-id") Long studyId, | ||
@RequestParam(required = false) Integer size | ||
@PostMapping | ||
public ResponseEntity<Void> writeReview( | ||
@AuthenticationPrincipal final Long githubId, | ||
@PathVariable(name = "study-id") final Long studyId, | ||
@Valid @RequestBody final WriteReviewRequest writeReviewRequest | ||
) { | ||
final ReviewsResponse reviewsResponse = reviewService.getReviewsByStudy(studyId, size); | ||
|
||
return ResponseEntity.ok(reviewsResponse); | ||
final Long id = reviewService.writeReview(githubId, studyId, writeReviewRequest); | ||
return ResponseEntity.created(URI.create("/api/studies/" + studyId + "/reviews/" + id)).build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.woowacourse.moamoa.review.controller; | ||
|
||
import com.woowacourse.moamoa.review.service.SearchingReviewService; | ||
import com.woowacourse.moamoa.review.service.response.ReviewsResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/api/studies/{study-id}/reviews") | ||
@RequiredArgsConstructor | ||
public class SearchingReviewController { | ||
|
||
private final SearchingReviewService searchingReviewService; | ||
|
||
@GetMapping | ||
public ResponseEntity<ReviewsResponse> getReviews( | ||
@PathVariable(name = "study-id") final Long studyId, | ||
@RequestParam(required = false) final Integer size | ||
) { | ||
final ReviewsResponse reviewsResponse = searchingReviewService.getReviewsByStudy(studyId, size); | ||
return ResponseEntity.ok(reviewsResponse); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,9 +19,9 @@ | |
import org.springframework.data.annotation.LastModifiedDate; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor(access = PROTECTED) | ||
@AllArgsConstructor | ||
@Getter | ||
public class Review { | ||
|
||
@Id | ||
|
@@ -39,10 +39,17 @@ public class Review { | |
private String content; | ||
|
||
@CreatedDate | ||
@Column(nullable = false) | ||
@Column(nullable = false, updatable = false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
private LocalDateTime createdDate; | ||
|
||
@LastModifiedDate | ||
@Column(nullable = false) | ||
private LocalDateTime lastModifiedDate; | ||
|
||
public Review( | ||
final AssociatedStudy associatedStudy, final Member member, final String content, | ||
final LocalDateTime createdDate, final LocalDateTime lastModifiedDate | ||
) { | ||
this(null, associatedStudy, member, content, createdDate, lastModifiedDate); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.woowacourse.moamoa.review.domain.exception; | ||
|
||
import com.woowacourse.moamoa.common.exception.BadRequestException; | ||
|
||
public class WritingReviewBadRequestException extends BadRequestException { | ||
|
||
public WritingReviewBadRequestException() { | ||
super("스터디 시작 전 후기를 작성할 수 없습니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,53 @@ | ||
package com.woowacourse.moamoa.review.service; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
|
||
import com.woowacourse.moamoa.member.domain.Member; | ||
import com.woowacourse.moamoa.member.domain.repository.MemberRepository; | ||
import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; | ||
import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; | ||
import com.woowacourse.moamoa.review.domain.AssociatedStudy; | ||
import com.woowacourse.moamoa.review.domain.Review; | ||
import com.woowacourse.moamoa.review.domain.exception.WritingReviewBadRequestException; | ||
import com.woowacourse.moamoa.review.domain.repository.ReviewRepository; | ||
import com.woowacourse.moamoa.review.service.response.ReviewResponse; | ||
import com.woowacourse.moamoa.review.service.response.ReviewsResponse; | ||
import java.util.List; | ||
import com.woowacourse.moamoa.review.service.request.WriteReviewRequest; | ||
import com.woowacourse.moamoa.study.domain.Participant; | ||
import com.woowacourse.moamoa.study.domain.Study; | ||
import com.woowacourse.moamoa.study.domain.repository.StudyRepository; | ||
import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; | ||
import java.time.LocalDateTime; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
@Transactional | ||
@RequiredArgsConstructor | ||
public class ReviewService { | ||
|
||
private final ReviewRepository reviewRepository; | ||
|
||
public ReviewsResponse getReviewsByStudy(Long studyId, Integer size) { | ||
final AssociatedStudy associatedStudy = new AssociatedStudy(studyId); | ||
|
||
final List<Review> reviews = reviewRepository.findAllByAssociatedStudy(associatedStudy); | ||
|
||
if (size != null) { | ||
return makeReviewsResponse(reviews.subList(0, size), reviews.size()); | ||
private final MemberRepository memberRepository; | ||
private final StudyRepository studyRepository; | ||
|
||
public Long writeReview(final Long githubId, final Long studyId, final WriteReviewRequest writeReviewRequest) { | ||
final Study study = studyRepository.findById(studyId) | ||
.orElseThrow(StudyNotFoundException::new); | ||
final Member member = memberRepository.findByGithubId(githubId) | ||
.orElseThrow(MemberNotFoundException::new); | ||
|
||
final Participant participant = new Participant(member.getId()); | ||
if (!study.isParticipated(participant)) { | ||
throw new NotParticipatedMemberException(); | ||
} | ||
|
||
return makeReviewsResponse(reviews, reviews.size()); | ||
} | ||
final LocalDateTime reviewCreatedDate = LocalDateTime.now(); | ||
if (study.isBeforeThanStudyStartDate(reviewCreatedDate.toLocalDate())) { | ||
throw new WritingReviewBadRequestException(); | ||
} | ||
|
||
private ReviewsResponse makeReviewsResponse(final List<Review> reviews, final int totalCount) { | ||
final List<ReviewResponse> reviewResponses = reviews.stream() | ||
.map(ReviewResponse::new) | ||
.collect(toList()); | ||
final AssociatedStudy associatedStudy = new AssociatedStudy(studyId); | ||
final Review review = new Review( | ||
associatedStudy, member, writeReviewRequest.getContent(), reviewCreatedDate, reviewCreatedDate | ||
); | ||
|
||
return new ReviewsResponse(reviewResponses, totalCount); | ||
return reviewRepository.save(review).getId(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.woowacourse.moamoa.review.service; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
|
||
import com.woowacourse.moamoa.review.domain.AssociatedStudy; | ||
import com.woowacourse.moamoa.review.domain.Review; | ||
import com.woowacourse.moamoa.review.domain.repository.ReviewRepository; | ||
import com.woowacourse.moamoa.review.service.response.ReviewResponse; | ||
import com.woowacourse.moamoa.review.service.response.ReviewsResponse; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
@RequiredArgsConstructor | ||
public class SearchingReviewService { | ||
|
||
private final ReviewRepository reviewRepository; | ||
|
||
public ReviewsResponse getReviewsByStudy(Long studyId, Integer size) { | ||
final AssociatedStudy associatedStudy = new AssociatedStudy(studyId); | ||
|
||
final List<Review> reviews = reviewRepository.findAllByAssociatedStudy(associatedStudy); | ||
|
||
if (size != null) { | ||
return makeReviewsResponse(reviews.subList(0, size), reviews.size()); | ||
} | ||
|
||
return makeReviewsResponse(reviews, reviews.size()); | ||
} | ||
|
||
private ReviewsResponse makeReviewsResponse(final List<Review> reviews, final int totalCount) { | ||
final List<ReviewResponse> reviewResponses = reviews.stream() | ||
.map(ReviewResponse::new) | ||
.collect(toList()); | ||
|
||
return new ReviewsResponse(reviewResponses, totalCount); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기도
스터디 생성
뿐 아니라리뷰 작성
에 대해서도 토큰이 필요해지면서 변경이 필요해졌군요..!!그린론 코드에서는
내 스터디 조회
시에도 토큰일 필요하게 되어 변경이 발생하더라구요!흠..🤔
이와 같이
토큰이 있는 경우
즉 토큰이 포함된 요청인 경우에 토큰의 유효성을 검사하는 방향으로 수정하면 어떨까요??기존의 코드는 새로운
토큰을 동반한 요청
의 경우 계속해서 case가 추가되어 코드가 변경되어야할 것 같아요 ㅠ.ㅠThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이것도 정말 좋은데 이렇게 되면 토큰이 필요없는 전체 목록 조회같은 기능에 유효하지 않은 토큰이 포함된다면 예외가 나지 않을까요? 원래같으면 토큰이 필요없는 비회원도 목록을 볼 수 있을텐데..!