From 9e85479bb8cef786b75b26f1e55060f219a33ba2 Mon Sep 17 00:00:00 2001 From: jiwoo Date: Sun, 25 Aug 2024 15:02:11 +0900 Subject: [PATCH 1/2] =?UTF-8?q?test(UserAcceptanceTest):=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EC=9D=98=20=EC=A7=88=EB=AC=B8=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=20=ED=9A=9F=EC=88=98=EB=A5=BC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kuring/acceptance/UserAcceptanceTest.java | 18 ++++++++++++++++++ .../kustacks/kuring/acceptance/UserStep.java | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java b/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java index 8fecb7ee..ebc70cb2 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java +++ b/src/test/java/com/kustacks/kuring/acceptance/UserAcceptanceTest.java @@ -199,4 +199,22 @@ void lookup_bookmark() { // then 북마크_조회_응답_확인(북마크_조회_응답); } + + /** + * Given : 사용자가 AI 질문을 한적이 있다 + * When : 남은 질문 가능 횟수를 조회한다 + * Then : 성공적으로 질문 가능횟수와 가능한 최대 질문 횟수를 반환한다 + */ + @DisplayName("[v2] 사용자는 자신의 남은 질문 가능 횟수를 조회할 수 있다") + @Test + void lookup_ask_count() { + // given + doNothing().when(firebaseSubscribeService).validationToken(anyString()); + + // when + var 질문_횟수_조회_응답 = 남은_질문_횟수_조회(USER_FCM_TOKEN); + + // then + 질문_횟수_응답_검증(질문_횟수_조회_응답); + } } diff --git a/src/test/java/com/kustacks/kuring/acceptance/UserStep.java b/src/test/java/com/kustacks/kuring/acceptance/UserStep.java index fdc0b61e..ce47de21 100644 --- a/src/test/java/com/kustacks/kuring/acceptance/UserStep.java +++ b/src/test/java/com/kustacks/kuring/acceptance/UserStep.java @@ -167,4 +167,23 @@ public class UserStep { .then().log().all() .extract(); } + + public static ExtractableResponse 남은_질문_횟수_조회(String userToken) { + return RestAssured + .given().log().all() + .header("User-Token", userToken) + .when().get("/api/v2/users/ask-counts") + .then().log().all() + .extract(); + } + + public static void 질문_횟수_응답_검증(ExtractableResponse 질문_횟수_조회_응답) { + assertAll( + () -> assertThat(질문_횟수_조회_응답.statusCode()).isEqualTo(HttpStatus.OK.value()), + () -> assertThat(질문_횟수_조회_응답.jsonPath().getInt("code")).isEqualTo(200), + () -> assertThat(질문_횟수_조회_응답.jsonPath().getString("message")).isEqualTo("질문 가능 횟수 조회에 성공하였습니다"), + () -> assertThat(질문_횟수_조회_응답.jsonPath().getInt("data.leftAskCount")).isEqualTo(2), + () -> assertThat(질문_횟수_조회_응답.jsonPath().getInt("data.maxAskCount")).isEqualTo(2) + ); + } } From c21425ef9384f3b6a47b44584344167b05112a84 Mon Sep 17 00:00:00 2001 From: jiwoo Date: Sun, 25 Aug 2024 15:04:00 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat(UserQueryApiV2):=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EC=A7=88=EB=AC=B8=20=ED=9A=9F=EC=88=98=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kuring/common/dto/ResponseCodeAndMessages.java | 1 + .../kuring/user/adapter/in/web/UserQueryApiV2.java | 13 +++++++++++++ .../adapter/in/web/dto/UserAIAskCountResponse.java | 12 ++++++++++++ .../user/application/port/in/UserQueryUseCase.java | 3 +++ .../port/in/dto/UserAIAskCountResult.java | 7 +++++++ .../user/application/service/UserQueryService.java | 7 +++++++ .../java/com/kustacks/kuring/user/domain/User.java | 1 + 7 files changed, 44 insertions(+) create mode 100644 src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserAIAskCountResponse.java create mode 100644 src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserAIAskCountResult.java diff --git a/src/main/java/com/kustacks/kuring/common/dto/ResponseCodeAndMessages.java b/src/main/java/com/kustacks/kuring/common/dto/ResponseCodeAndMessages.java index 05af52b3..dbbc3094 100644 --- a/src/main/java/com/kustacks/kuring/common/dto/ResponseCodeAndMessages.java +++ b/src/main/java/com/kustacks/kuring/common/dto/ResponseCodeAndMessages.java @@ -31,6 +31,7 @@ public enum ResponseCodeAndMessages { BOOKMARK_LOOKUP_SUCCESS(HttpStatus.OK.value(), "북마크 조회에 성공하였습니다"), FEEDBACK_SAVE_SUCCESS(HttpStatus.OK.value(), "피드백 저장에 성공하였습니다"), FEEDBACK_SEARCH_SUCCESS(HttpStatus.OK.value(), "피드백 조회에 성공하였습니다"), + ASK_COUNT_LOOKUP_SUCCESS(HttpStatus.OK.value(), "질문 가능 횟수 조회에 성공하였습니다"), /* Alert */ ALERT_SEARCH_SUCCESS(HttpStatus.OK.value(), "예약 알림 조회에 성공하였습니다"), diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java index 0c1f7453..fbb5a6eb 100644 --- a/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java +++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java @@ -2,10 +2,12 @@ import com.kustacks.kuring.common.annotation.RestWebAdapter; import com.kustacks.kuring.common.dto.BaseResponse; +import com.kustacks.kuring.user.adapter.in.web.dto.UserAIAskCountResponse; import com.kustacks.kuring.user.adapter.in.web.dto.UserBookmarkResponse; import com.kustacks.kuring.user.adapter.in.web.dto.UserCategoryNameResponse; import com.kustacks.kuring.user.adapter.in.web.dto.UserDepartmentNameResponse; import com.kustacks.kuring.user.application.port.in.UserQueryUseCase; +import com.kustacks.kuring.user.application.port.in.dto.UserAIAskCountResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; @@ -72,4 +74,15 @@ public ResponseEntity>> lookupUserBookma return ResponseEntity.ok().body(new BaseResponse<>(BOOKMARK_LOOKUP_SUCCESS, responses)); } + + @Operation(summary = "사용자 질문 가능횟수 조회", description = "사용자의 남은 질문횟수와 가능한 질문 횟수를 조회합니다") + @SecurityRequirement(name = USER_TOKEN_HEADER_KEY) + @GetMapping("/ask-counts") + public ResponseEntity> lookupUserAIAskCount( + @RequestHeader(USER_TOKEN_HEADER_KEY) String userToken + ) { + UserAIAskCountResult result = userQueryUseCase.lookupUserAIAskCount(userToken); + UserAIAskCountResponse response = UserAIAskCountResponse.from(result); + return ResponseEntity.ok().body(new BaseResponse<>(ASK_COUNT_LOOKUP_SUCCESS, response)); + } } diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserAIAskCountResponse.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserAIAskCountResponse.java new file mode 100644 index 00000000..f86901bd --- /dev/null +++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserAIAskCountResponse.java @@ -0,0 +1,12 @@ +package com.kustacks.kuring.user.adapter.in.web.dto; + +import com.kustacks.kuring.user.application.port.in.dto.UserAIAskCountResult; + +public record UserAIAskCountResponse( + int leftAskCount, + int maxAskCount +) { + public static UserAIAskCountResponse from(UserAIAskCountResult result) { + return new UserAIAskCountResponse(result.leftAskCount(), result.maxAskCount()); + } +} diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java b/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java index 338e951e..efaf4bc0 100644 --- a/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java +++ b/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java @@ -1,5 +1,6 @@ package com.kustacks.kuring.user.application.port.in; +import com.kustacks.kuring.user.application.port.in.dto.UserAIAskCountResult; import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkResult; import com.kustacks.kuring.user.application.port.in.dto.UserCategoryNameResult; import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentNameResult; @@ -10,4 +11,6 @@ public interface UserQueryUseCase { List lookupSubscribeCategories(String userToken); List lookupSubscribeDepartments(String userToken); List lookupUserBookmarkedNotices(String userToken); + + UserAIAskCountResult lookupUserAIAskCount(String userToken); } diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserAIAskCountResult.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserAIAskCountResult.java new file mode 100644 index 00000000..5f7ae61b --- /dev/null +++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserAIAskCountResult.java @@ -0,0 +1,7 @@ +package com.kustacks.kuring.user.application.port.in.dto; + +public record UserAIAskCountResult( + int leftAskCount, + int maxAskCount +) { +} diff --git a/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java b/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java index ef7dc380..a4440566 100644 --- a/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java +++ b/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java @@ -8,6 +8,7 @@ import com.kustacks.kuring.notice.domain.CategoryName; import com.kustacks.kuring.notice.domain.DepartmentName; import com.kustacks.kuring.user.application.port.in.UserQueryUseCase; +import com.kustacks.kuring.user.application.port.in.dto.UserAIAskCountResult; import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkResult; import com.kustacks.kuring.user.application.port.in.dto.UserCategoryNameResult; import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentNameResult; @@ -55,6 +56,12 @@ public List lookupUserBookmarkedNotices(String userToken) { return lookupAllBookmarkByIds(bookmarkIds); } + @Override + public UserAIAskCountResult lookupUserAIAskCount(String userToken) { + User user = findUserByToken(userToken); + return new UserAIAskCountResult(user.getQuestionCount(), User.MONTHLY_QUESTION_COUNT); + } + private List lookupAllBookmarkByIds(List bookmarkIds) { return noticeQueryPort.findAllByBookmarkIds(bookmarkIds) .stream() diff --git a/src/main/java/com/kustacks/kuring/user/domain/User.java b/src/main/java/com/kustacks/kuring/user/domain/User.java index e704e2c0..ebbda78e 100644 --- a/src/main/java/com/kustacks/kuring/user/domain/User.java +++ b/src/main/java/com/kustacks/kuring/user/domain/User.java @@ -47,6 +47,7 @@ public class User implements Serializable { @Column(name = "deleted", nullable = false) private boolean deleted = Boolean.FALSE; + @Getter(AccessLevel.PUBLIC) @Column(columnDefinition = "integer default 0") private Integer questionCount;