Skip to content

Commit 3db5e2f

Browse files
Merge pull request #127 from prgrms-aibe-devcourse/feat/126-my-feedback
[feat] 멘토링 후기 페이지에 '나의 후기' 탭 추가
2 parents 7d1a814 + 424cb2b commit 3db5e2f

13 files changed

Lines changed: 313 additions & 14 deletions

File tree

src/main/java/com/knoc/global/exception/ErrorCode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public enum ErrorCode {
4040
INVALID_IDEMPOTENCY_KEY(400, "유효하지 않은 멱등성 키입니다."),
4141
ORDER_INVALID_AMOUNT(400, "유효하지 않은 결제 금액입니다."),
4242
ORDER_INVALID_ORDER_NUMBER(400, "유효하지 않은 주문번호입니다."),
43+
ORDER_CANNOT_BE_SETTLED(400, "현재 주문 상태에서는 정산을 진행할 수 없습니다."),
4344

4445
// 리뷰 요청서 관련 (Review Request)
4546
REVIEW_REQUEST_ALREADY_EXISTS(409, "이미 해당 주문에 대한 리뷰 요청서가 존재합니다."),
@@ -53,6 +54,8 @@ public enum ErrorCode {
5354
// 리뷰 관련 (Review)
5455
REVIEW_ALREADY_EXISTS(409, "이미 해당 주문에 대한 후기가 존재합니다."),
5556
REVIEW_NOT_ALLOWED(403, "결제 완료된 주문만 후기를 작성할 수 있습니다."),
57+
REVIEW_NOT_FOUND(404, "해당 주문에 대한 후기가 존재하지 않습니다."),
58+
REVIEW_UPDATE_NOT_ALLOWED(403, "후기를 수정할 권한이 없습니다."),
5659

5760
// GitHub 관련 (Github)
5861
GITHUB_PR_NOT_FOUND(404, "존재하지 않는 PR이거나 접근 권한이 없습니다."),

src/main/java/com/knoc/order/service/OrderService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ public void settleOrder(Long orderId, Long juniorId) {
280280
throw new BusinessException(ErrorCode.NOT_JUNIOR_FOR_ORDER);
281281
}
282282
if (order.getStatus() != OrderStatus.PAID) {
283-
throw new BusinessException(ErrorCode.ORDER_CANNOT_BE_PAID);
283+
throw new BusinessException(ErrorCode.ORDER_CANNOT_BE_SETTLED);
284284
}
285285

286286
order.updateStatus(OrderStatus.SETTLED);
@@ -296,7 +296,7 @@ public void settleOrder(Long orderId, Long juniorId) {
296296
eventPublisher.publishEvent(new ChatSystemEvent(
297297
order.getChatRoom().getId(),
298298
MessageType.ROOM_CLOSE,
299-
MessageType.ROOM_CLOSE.getTemplate(),
299+
null,
300300
null
301301
));
302302
}

src/main/java/com/knoc/reviewFeedback/controller/ReviewFeedbackController.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.knoc.reviewFeedback.controller;
22

3+
import com.knoc.reviewFeedback.dto.MyReviewPageResponse;
34
import com.knoc.reviewFeedback.dto.ReviewPageDto;
45
import com.knoc.reviewFeedback.service.ReviewFeedbackService;
56
import io.swagger.v3.oas.annotations.Operation;
@@ -9,6 +10,9 @@
910
import org.springframework.ui.Model;
1011
import org.springframework.web.bind.annotation.GetMapping;
1112
import org.springframework.web.bind.annotation.RequestMapping;
13+
import org.springframework.web.bind.annotation.ResponseBody;
14+
15+
import java.security.Principal;
1216

1317
@Tag(name = "Review-Page-Controller", description = "멘토링 후기 공개 페이지")
1418
@Controller
@@ -27,4 +31,11 @@ public String reviews(Model model) {
2731
model.addAttribute("topSeniors", page.getTopSeniors());
2832
return "review/posts";
2933
}
34+
35+
@Operation(summary = "나의 멘토링 후기 목록 카드", description = "내가 작성한 후기 카드를 최신순으로 조회합니다.")
36+
@GetMapping("/posts/me")
37+
@ResponseBody
38+
public MyReviewPageResponse myReviews(Principal principal) {
39+
return reviewFeedbackService.getMyReviewCards(principal.getName());
40+
}
3041
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.knoc.reviewFeedback.dto;
2+
3+
import lombok.Builder;
4+
5+
import java.util.List;
6+
7+
public record MyReviewPageResponse(List<ReviewPageDto.ReviewCardDto> myReviews, int totalCount) {
8+
@Builder
9+
public MyReviewPageResponse {
10+
}
11+
}

src/main/java/com/knoc/reviewFeedback/dto/ReviewPageDto.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public static class ReviewCardDto {
2323
private final String timeAgo;
2424
private final byte rating;
2525
private final String content;
26+
private final Long orderId;
2627
}
2728

2829
@Getter

src/main/java/com/knoc/reviewFeedback/entity/ReviewFeedback.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,9 @@ public ReviewFeedback(Order order, Member junior, SeniorProfile seniorProfile,
5757
this.rating = rating;
5858
this.comment = comment;
5959
}
60+
61+
public void update(byte rating, String comment) {
62+
this.rating = rating;
63+
this.comment = comment;
64+
}
6065
}

src/main/java/com/knoc/reviewFeedback/repository/ReviewFeedbackRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ public interface ReviewFeedbackRepository extends JpaRepository<ReviewFeedback,L
2626

2727
@Query("SELECT r.seniorProfile FROM ReviewFeedback r WHERE r.createdAt >= :startOfMonth GROUP BY r.seniorProfile ORDER BY COUNT(r) DESC")
2828
List<SeniorProfile> findTop3ActiveSeniorsThisMonth(@Param("startOfMonth") LocalDateTime startOfMonth, org.springframework.data.domain.Pageable pageable);
29+
30+
List<ReviewFeedback> findByJunior_IdOrderByCreatedAtDesc(Long juniorId);
2931
}

src/main/java/com/knoc/reviewFeedback/service/ReviewFeedbackService.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import com.knoc.global.exception.BusinessException;
44
import com.knoc.global.exception.ErrorCode;
5+
import com.knoc.member.Member;
6+
import com.knoc.member.MemberRepository;
57
import com.knoc.order.entity.Order;
68
import com.knoc.order.entity.OrderStatus;
79
import com.knoc.order.repository.OrderRepository;
10+
import com.knoc.reviewFeedback.dto.MyReviewPageResponse;
811
import com.knoc.reviewFeedback.dto.ReviewPageDto;
912
import com.knoc.senior.entity.SeniorProfile;
1013
import com.knoc.senior.repository.SeniorProfileRepository;
@@ -29,6 +32,7 @@ public class ReviewFeedbackService {
2932
private final ReviewFeedbackRepository reviewFeedbackRepository;
3033
private final OrderRepository orderRepository;
3134
private final SeniorProfileRepository seniorProfileRepository;
35+
private final MemberRepository memberRepository;
3236

3337
@Transactional
3438
public void createReview(ReviewFeedbackRequestDto dto, Long juniorId) {
@@ -66,6 +70,19 @@ public void createReview(ReviewFeedbackRequestDto dto, Long juniorId) {
6670

6771
}
6872

73+
@Transactional
74+
public void updateReview(Long orderId, ReviewFeedbackRequestDto dto, Long juniorId) {
75+
ReviewFeedback feedback = reviewFeedbackRepository.findByOrderId(orderId)
76+
.orElseThrow(() -> new BusinessException(ErrorCode.REVIEW_NOT_FOUND));
77+
78+
if (!feedback.getJunior().getId().equals(juniorId)) {
79+
throw new BusinessException(ErrorCode.REVIEW_UPDATE_NOT_ALLOWED);
80+
}
81+
82+
// rating/comment validation은 DTO(@Min/@Max) + 컨트롤러 @Valid에서 처리된다는 전제
83+
feedback.update(dto.getRating(), dto.getComment());
84+
}
85+
6986
public ReviewPageDto getReviewPage() {
7087
List<ReviewFeedback> feedbacks = reviewFeedbackRepository.findAllByOrderByCreatedAtDesc();
7188

@@ -90,6 +107,7 @@ private List<ReviewPageDto.ReviewCardDto> mapToCards(List<ReviewFeedback> feedba
90107
.timeAgo(timeAgo(r.getCreatedAt()))
91108
.rating(r.getRating())
92109
.content(r.getComment())
110+
.orderId(r.getOrder().getId())
93111
.build()
94112
).toList();
95113
}
@@ -112,4 +130,12 @@ private String timeAgo(LocalDateTime createdAt) {
112130
return (days / 30) + "개월 전";
113131
}
114132

133+
public MyReviewPageResponse getMyReviewCards(String email) {
134+
Long juniorId = memberRepository.findByEmail(email)
135+
.map(Member::getId)
136+
.orElseThrow(() -> new BusinessException(ErrorCode.MEMBER_NOT_FOUND));
137+
138+
List<ReviewFeedback> myFeedbacks = reviewFeedbackRepository.findByJunior_IdOrderByCreatedAtDesc(juniorId);
139+
return new MyReviewPageResponse(mapToCards(myFeedbacks), myFeedbacks.size());
140+
}
115141
}

src/main/java/com/knoc/workspace/WorkspaceController.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ public class WorkspaceController {
2525

2626
@Operation(summary = "워크스페이스 페이지 조회", description = "해당 주문(orderId)에 대한 워크스페이스 화면을 렌더링합니다.")
2727
@GetMapping("/orders/{orderId}")
28-
public String workspace(@PathVariable Long orderId, Principal principal, Model model) {
28+
public String workspace(@PathVariable Long orderId,
29+
@RequestParam(value = "reviewOnly", required = false) String reviewOnly,
30+
Principal principal,
31+
Model model) {
2932
WorkspaceDto dto = workspaceFacadeService.getWorkspaceData(orderId, principal.getName());
3033
model.addAttribute("workspace", dto);
34+
model.addAttribute("openReviewOnlyModal", "1".equals(reviewOnly) || "true".equalsIgnoreCase(reviewOnly));
3135
return "workspace/workspace";
3236
}
3337

@@ -74,6 +78,17 @@ public ResponseEntity<Void> submitFeedback(@PathVariable Long orderId,
7478
return ResponseEntity.ok().build();
7579
}
7680

81+
@Operation(summary = "후기 수정", description = "주니어가 이미 작성한 후기를 수정합니다.")
82+
@PatchMapping("/orders/{orderId}/feedback")
83+
@ResponseBody
84+
@PreAuthorize("hasRole('USER')")
85+
public ResponseEntity<Void> updateFeedback(@PathVariable Long orderId,
86+
@RequestBody ReviewFeedbackRequestDto dto,
87+
Principal principal) {
88+
workspaceFacadeService.updateFeedback(orderId, principal.getName(), dto);
89+
return ResponseEntity.ok().build();
90+
}
91+
7792
@Operation(summary = "후기 조회", description = "제출된 후기(평점/코멘트) 정보를 조회합니다.")
7893
@GetMapping("/orders/{orderId}/feedback")
7994
@ResponseBody

src/main/java/com/knoc/workspace/WorkspaceFacadeService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,13 @@ public void submitFeedback(Long orderId, String email, ReviewFeedbackRequestDto
222222
));
223223
}
224224

225+
@Transactional
226+
public void updateFeedback(Long orderId, String email, ReviewFeedbackRequestDto dto) {
227+
Member member = memberRepository.findByEmail(email)
228+
.orElseThrow(() -> new BusinessException(ErrorCode.MEMBER_NOT_FOUND));
229+
reviewFeedbackService.updateReview(orderId, dto, member.getId());
230+
}
231+
225232
@Transactional(readOnly = true)
226233
public ReviewFeedbackResponse getReviewFeedback(Long orderId, String email) {
227234
Order order = orderRepository.findById(orderId)

0 commit comments

Comments
 (0)