Skip to content

Commit b4cb908

Browse files
authored
Merge pull request #27 from What-s-Your-Plan/feat/#23
Review Controller 마이그레이션을 진행
2 parents 52a65e0 + b23936b commit b4cb908

36 files changed

+899
-27
lines changed

application/wypl-core/build.gradle

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ java {
99

1010
dependencies {
1111
implementation project(':application:application-common')
12-
implementation project(':common')
1312
implementation project(':domain:jpa-common')
14-
implementation project(':domain:jpa-member-domain')
13+
implementation project(':domain:mongo-common')
14+
implementation project(':domain:jpamongo-review-domain')
1515
implementation project(':domain:jpa-calendar-domain')
16+
implementation project(':domain:jpa-member-domain')
17+
implementation project(':common')
1618
}

application/wypl-core/src/main/java/com/wypl/WyplCoreApplication.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
55
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
6+
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
67

78
@SpringBootApplication
89
@EnableJpaRepositories(basePackages = {"com.wypl"})
10+
@EnableMongoRepositories(basePackages = {"com.wypl"})
911
public class WyplCoreApplication {
1012

11-
public static void main(String[] args) {
12-
SpringApplication.run(WyplCoreApplication.class, args);
13-
}
14-
13+
public static void main(String[] args) {
14+
SpringApplication.run(WyplCoreApplication.class, args);
15+
}
1516
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.wypl.wyplcore.auth.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target(ElementType.PARAMETER)
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface Authenticated {
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.wypl.wyplcore.auth.domain;
2+
3+
public record AuthMember(
4+
long id
5+
) {
6+
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.wypl.wyplcore.auth.utils;
2+
3+
import org.springframework.core.MethodParameter;
4+
import org.springframework.stereotype.Component;
5+
import org.springframework.web.bind.support.WebDataBinderFactory;
6+
import org.springframework.web.context.request.NativeWebRequest;
7+
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
8+
import org.springframework.web.method.support.ModelAndViewContainer;
9+
10+
import com.wypl.wyplcore.auth.annotation.Authenticated;
11+
import com.wypl.wyplcore.auth.domain.AuthMember;
12+
13+
@Component
14+
public class AuthenticatedArgumentResolver implements HandlerMethodArgumentResolver {
15+
16+
@Override
17+
public boolean supportsParameter(MethodParameter parameter) {
18+
boolean hasParameterAnnotation = parameter.hasParameterAnnotation(Authenticated.class);
19+
boolean assignableFrom = AuthMember.class.isAssignableFrom(parameter.getParameterType());
20+
return hasParameterAnnotation && assignableFrom;
21+
}
22+
23+
@Override
24+
public AuthMember resolveArgument(
25+
MethodParameter parameter,
26+
ModelAndViewContainer mavContainer,
27+
NativeWebRequest webRequest,
28+
WebDataBinderFactory binderFactory
29+
) {
30+
return null;
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.wypl.wyplcore.global.config;
2+
3+
import java.util.List;
4+
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
7+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8+
9+
import com.wypl.wyplcore.auth.utils.AuthenticatedArgumentResolver;
10+
11+
@Configuration
12+
public class WebConfig implements WebMvcConfigurer {
13+
14+
@Override
15+
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
16+
resolvers.add(new AuthenticatedArgumentResolver());
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.wypl.wyplcore.review.controller;
2+
3+
import java.time.LocalDate;
4+
5+
import org.springframework.format.annotation.DateTimeFormat;
6+
import org.springframework.web.bind.annotation.DeleteMapping;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
import org.springframework.web.bind.annotation.PatchMapping;
9+
import org.springframework.web.bind.annotation.PathVariable;
10+
import org.springframework.web.bind.annotation.PostMapping;
11+
import org.springframework.web.bind.annotation.RequestBody;
12+
import org.springframework.web.bind.annotation.RequestMapping;
13+
import org.springframework.web.bind.annotation.RequestParam;
14+
import org.springframework.web.bind.annotation.RestController;
15+
16+
import com.wypl.applicationcommon.WyplResponseEntity;
17+
import com.wypl.wyplcore.auth.annotation.Authenticated;
18+
import com.wypl.wyplcore.auth.domain.AuthMember;
19+
import com.wypl.wyplcore.review.data.request.ReviewCreateRequest;
20+
import com.wypl.wyplcore.review.data.request.ReviewType;
21+
import com.wypl.wyplcore.review.data.request.ReviewUpdateRequest;
22+
import com.wypl.wyplcore.review.data.response.ReviewDetailResponse;
23+
import com.wypl.wyplcore.review.data.response.ReviewIdResponse;
24+
import com.wypl.wyplcore.review.data.response.ReviewListResponse;
25+
import com.wypl.wyplcore.review.service.ReviewModifyService;
26+
import com.wypl.wyplcore.review.service.ReviewReadService;
27+
28+
import lombok.RequiredArgsConstructor;
29+
30+
@RestController
31+
@RequiredArgsConstructor
32+
@RequestMapping("/review")
33+
public class ReviewController {
34+
35+
private final ReviewModifyService reviewModifyService;
36+
private final ReviewReadService reviewReadService;
37+
38+
@PostMapping
39+
public WyplResponseEntity<ReviewIdResponse> createReview(
40+
@Authenticated AuthMember authMember,
41+
@RequestBody ReviewCreateRequest reviewCreateRequest
42+
) {
43+
ReviewIdResponse response = reviewModifyService.createReview(authMember.id(), reviewCreateRequest);
44+
return WyplResponseEntity.created(response, "리뷰 등록에 성공했습니다.");
45+
}
46+
47+
@PatchMapping("/{reviewId}")
48+
public WyplResponseEntity<ReviewIdResponse> updateReview(
49+
@Authenticated AuthMember authMember,
50+
@PathVariable int reviewId,
51+
@RequestBody ReviewUpdateRequest reviewUpdateRequest
52+
) {
53+
ReviewIdResponse response = reviewModifyService.updateReview(authMember.id(), reviewId, reviewUpdateRequest);
54+
return WyplResponseEntity.ok(response, "리뷰 수정에 성공했습니다.");
55+
}
56+
57+
@DeleteMapping("/{reviewId}")
58+
public WyplResponseEntity<ReviewIdResponse> deleteReview(
59+
@Authenticated AuthMember authMember,
60+
@PathVariable("reviewId") int reviewId
61+
) {
62+
ReviewIdResponse response = reviewModifyService.deleteReview(authMember.id(), reviewId);
63+
return WyplResponseEntity.ok(response, "리뷰 삭제에 성공 했습니다.");
64+
}
65+
66+
@GetMapping("/detail/{reviewId}")
67+
public WyplResponseEntity<ReviewDetailResponse> getDetailReview(
68+
@Authenticated AuthMember authMember,
69+
@PathVariable int reviewId
70+
) {
71+
ReviewDetailResponse response = reviewReadService.getDetailReview(authMember.id(), reviewId);
72+
return WyplResponseEntity.ok(response, "리뷰 상세 조회에 성공했습니다.");
73+
}
74+
75+
@GetMapping("/{type}")
76+
public WyplResponseEntity<ReviewListResponse> getReviewsByMemberId(
77+
@Authenticated AuthMember authMember,
78+
@PathVariable("type") ReviewType reviewType,
79+
@RequestParam(value = "lastReviewId", required = false) Long lastReviewId,
80+
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
81+
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate
82+
) {
83+
ReviewListResponse response = reviewReadService.getReviews(authMember.id(), lastReviewId, reviewType, startDate,
84+
endDate);
85+
return WyplResponseEntity.ok(response, "리뷰 목록 조회에 성공했습니다.");
86+
}
87+
88+
@GetMapping("/{type}/{scheduleId}")
89+
public WyplResponseEntity<ReviewListResponse> getReviewsBySchedule(
90+
@Authenticated AuthMember authMember,
91+
@PathVariable("type") ReviewType reviewType,
92+
@PathVariable("scheduleId") long scheduleId
93+
) {
94+
ReviewListResponse response = reviewReadService.getReviewsByScheduleId(authMember.id(), scheduleId,
95+
reviewType);
96+
return WyplResponseEntity.ok(response, "일정 별 리뷰 조회에 성공했습니다.");
97+
}
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.wypl.wyplcore.review.data.request;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
import com.wypl.jpamongoreviewdomain.reviewcontents.domain.ReviewContent;
8+
9+
import lombok.Builder;
10+
11+
@Builder
12+
public record ReviewCreateRequest(
13+
14+
String title,
15+
16+
@JsonProperty("schedule_id")
17+
int scheduleId,
18+
19+
List<Map<String, ReviewContent>> contents
20+
21+
) {
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.wypl.wyplcore.review.data.request;
2+
3+
public enum ReviewType {
4+
NEWEST,
5+
6+
OLDEST
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.wypl.wyplcore.review.data.request;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
import com.wypl.jpamongoreviewdomain.reviewcontents.domain.ReviewContent;
8+
9+
public record ReviewUpdateRequest(
10+
String title,
11+
12+
@JsonProperty("schedule_id")
13+
int scheduleId,
14+
15+
List<Map<String, ReviewContent>> contents
16+
) {
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.wypl.wyplcore.review.data.response;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
import com.wypl.jpacalendardomain.schedule.domain.Schedule;
8+
import com.wypl.jpamongoreviewdomain.review.domain.Review;
9+
import com.wypl.jpamongoreviewdomain.reviewcontents.domain.ReviewContent;
10+
11+
import lombok.Builder;
12+
13+
@Builder
14+
public record ReviewDetailResponse(
15+
@JsonProperty("review_id")
16+
long reviewId,
17+
18+
String title,
19+
20+
// Todo : import 후 주석 해제
21+
// ScheduleResponse schedule,
22+
23+
List<Map<String, ReviewContent>> contents
24+
) {
25+
public static ReviewDetailResponse of(Review review, Schedule schedule,
26+
List<Map<String, ReviewContent>> reviewContents) {
27+
return ReviewDetailResponse.builder()
28+
.reviewId(review.getReviewId())
29+
.title(review.getTitle())
30+
// Todo : import 후 주석 해제
31+
// .schedule(ScheduleResponse.from(schedule))
32+
.contents(reviewContents)
33+
.build();
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.wypl.wyplcore.review.data.response;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
5+
public record ReviewIdResponse(
6+
@JsonProperty("review_id")
7+
long reviewId
8+
) {
9+
public static ReviewIdResponse from(long reviewId) {
10+
return new ReviewIdResponse(reviewId);
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.wypl.wyplcore.review.data.response;
2+
3+
import java.util.List;
4+
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
7+
public record ReviewListResponse(
8+
9+
@JsonProperty("review_count")
10+
int reviewCount,
11+
12+
List<ReviewResponse> reviews
13+
) {
14+
public static ReviewListResponse from(List<ReviewResponse> reviews) {
15+
return new ReviewListResponse(reviews.size(), reviews);
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.wypl.wyplcore.review.data.response;
2+
3+
import java.time.LocalDateTime;
4+
import java.util.Map;
5+
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
import com.wypl.jpamongoreviewdomain.review.domain.Review;
8+
import com.wypl.jpamongoreviewdomain.reviewcontents.domain.ReviewContent;
9+
10+
import lombok.Builder;
11+
12+
@Builder
13+
public record ReviewResponse(
14+
@JsonProperty("review_id")
15+
long reviewId,
16+
17+
@JsonProperty("created_at")
18+
LocalDateTime createdAt,
19+
20+
String title,
21+
22+
@JsonProperty("thumbnail_content")
23+
Map<String, ReviewContent> thumbnailContent
24+
) {
25+
public static ReviewResponse from(Review review, Map<String, ReviewContent> thumbnailContent) {
26+
return ReviewResponse.builder()
27+
.createdAt(LocalDateTime.now())
28+
.reviewId(review.getReviewId())
29+
.title(review.getTitle())
30+
.thumbnailContent(thumbnailContent)
31+
.build();
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.wypl.wyplcore.review.exception;
2+
3+
import com.wypl.common.exception.ServerErrorCode;
4+
5+
import lombok.Getter;
6+
7+
@Getter
8+
public enum ReviewErrorCode implements ServerErrorCode {
9+
EMPTY_CONTENTS(500, "REVIEW_001", "작성된 내용이 없습니다."),
10+
INVALID_TITLE(500, "REVIEW_002", "제목의 길이가 올바르지 않습니다."),
11+
NO_SUCH_REVIEW(500, "REVIEW_003", "존재하지 않는 회고입니다.")
12+
;
13+
14+
private final int statusCode;
15+
private final String errorCode;
16+
private final String message;
17+
18+
ReviewErrorCode(int statusCode, String errorCode, String message) {
19+
this.statusCode = statusCode;
20+
this.errorCode = errorCode;
21+
this.message = message;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.wypl.wyplcore.review.exception;
2+
3+
import com.wypl.common.exception.ServerErrorCode;
4+
import com.wypl.common.exception.WyplException;
5+
6+
public class ReviewException extends WyplException {
7+
public ReviewException(ServerErrorCode serverErrorCode) {
8+
super(serverErrorCode);
9+
}
10+
}

0 commit comments

Comments
 (0)