From cd11407d7981b690634845326371d2bf8a1320f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:09:29 +0900 Subject: [PATCH 01/30] Create stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/stag-client-api-deploy.yml diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml new file mode 100644 index 00000000..32ad8c17 --- /dev/null +++ b/.github/workflows/stag-client-api-deploy.yml @@ -0,0 +1,42 @@ +name: stag-client-api-deploy + +on: + push: + branches: [ "stag/client" ] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: 'corretto' + java-version: '17' + + - name: app clean + run: ./gradlew build + + - name: client api build + run: ./gradlew :likelion-client:build + + - name: Docker Hub 로그인 # (3) + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_EMAIL }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: docker image push + run: docker buildx build -f ./likelion-client/Dockerfile --build-arg PROFILE=stag --platform linux/amd64 -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKER_CLIENT_API_STAG_IMAGE }} --push . + + - name: client-api-deploy + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.HOST }} + username: ubuntu + key: ${{ secrets.KEY }} + script: | + sudo docker rm -f ${{ secrets.DOCKER_CLIENT_API_STAG_CONTAINER }} + sudo docker rmi ${{ secrets.DOCKER_CLIENT_API_STAG_IMAGE }} + docker-compose -f ${{ secrets.DOCKER_COMPOSE_DIRECTORY }} up -d + docker image prune -f From 9813597a53a19f0670ddbfbef9ada218af3b9df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:13:29 +0900 Subject: [PATCH 02/30] Update stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml index 32ad8c17..15278e2e 100644 --- a/.github/workflows/stag-client-api-deploy.yml +++ b/.github/workflows/stag-client-api-deploy.yml @@ -1,8 +1,6 @@ name: stag-client-api-deploy -on: - push: - branches: [ "stag/client" ] +on: workflow_dispatch jobs: deploy: @@ -20,7 +18,7 @@ jobs: - name: client api build run: ./gradlew :likelion-client:build - - name: Docker Hub 로그인 # (3) + - name: Docker login uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_EMAIL }} From 52ea9683573e804e9705b7dce4546dbe8de31dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:20:33 +0900 Subject: [PATCH 03/30] Update stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml index 15278e2e..39a66585 100644 --- a/.github/workflows/stag-client-api-deploy.yml +++ b/.github/workflows/stag-client-api-deploy.yml @@ -25,7 +25,7 @@ jobs: password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: docker image push - run: docker buildx build -f ./likelion-client/Dockerfile --build-arg PROFILE=stag --platform linux/amd64 -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKER_CLIENT_API_STAG_IMAGE }} --push . + run: docker buildx build -f ./likelion-client/Dockerfile --build-arg PROFILE=stag --platform linux/amd64 -t ${{ secrets.DOCKER_CLIENT_API_STAG_IMAGE }} --push . - name: client-api-deploy uses: appleboy/ssh-action@master From e1fa50dfdbe15a11e1b7160533e459190631c9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:22:08 +0900 Subject: [PATCH 04/30] Update stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml index 39a66585..0bde279a 100644 --- a/.github/workflows/stag-client-api-deploy.yml +++ b/.github/workflows/stag-client-api-deploy.yml @@ -13,7 +13,7 @@ jobs: java-version: '17' - name: app clean - run: ./gradlew build + run: ./gradlew clean - name: client api build run: ./gradlew :likelion-client:build From fbaba888c354e76d3b243b173d78c423970a7ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:42:32 +0900 Subject: [PATCH 05/30] Update stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml index 0bde279a..b6040466 100644 --- a/.github/workflows/stag-client-api-deploy.yml +++ b/.github/workflows/stag-client-api-deploy.yml @@ -16,7 +16,7 @@ jobs: run: ./gradlew clean - name: client api build - run: ./gradlew :likelion-client:build + run: ./gradlew :likelion-client:bootJar - name: Docker login uses: docker/login-action@v2 From de88e04cad57c40d5868ba9b50db29697e5016f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:47:00 +0900 Subject: [PATCH 06/30] =?UTF-8?q?chore=20:=20client=20Docker=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- likelion-client/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/likelion-client/Dockerfile b/likelion-client/Dockerfile index 3c790882..92de7192 100644 --- a/likelion-client/Dockerfile +++ b/likelion-client/Dockerfile @@ -1,5 +1,5 @@ FROM openjdk:17 -ARG JAR_FILE=build/libs/*.jar +ARG JAR_FILE=./build/libs/*.jar COPY ${JAR_FILE} app.jar -ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=${PROFILE}","/app.jar"] \ No newline at end of file +ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=${PROFILE}","/app.jar"] From f6336c566fb4b8e807d8f948112768a4e9b43578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:47:40 +0900 Subject: [PATCH 07/30] =?UTF-8?q?chore=20:=20admin=20Docker=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- likelion-admin/Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/likelion-admin/Dockerfile b/likelion-admin/Dockerfile index 4de98a9b..92de7192 100644 --- a/likelion-admin/Dockerfile +++ b/likelion-admin/Dockerfile @@ -1,6 +1,5 @@ FROM openjdk:17 -ARG JAR_FILE=build/libs/*.jar +ARG JAR_FILE=./build/libs/*.jar COPY ${JAR_FILE} app.jar -EXPOSE 8090 -ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=${PROFILE}","/app.jar"] \ No newline at end of file +ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=${PROFILE}","/app.jar"] From 94d0878991478974989179da8fd230bec1c5c0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:52:39 +0900 Subject: [PATCH 08/30] =?UTF-8?q?chore=20:=20client=20Dockerfile=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- likelion-client/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/likelion-client/Dockerfile b/likelion-client/Dockerfile index 92de7192..28c361b4 100644 --- a/likelion-client/Dockerfile +++ b/likelion-client/Dockerfile @@ -1,5 +1,4 @@ FROM openjdk:17 -ARG JAR_FILE=./build/libs/*.jar -COPY ${JAR_FILE} app.jar +COPY ./build/libs/*.jar app.jar ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=${PROFILE}","/app.jar"] From a893d358b927df3cb035174156f849e7a6b59994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:27:37 +0900 Subject: [PATCH 09/30] Update stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml index b6040466..aa784181 100644 --- a/.github/workflows/stag-client-api-deploy.yml +++ b/.github/workflows/stag-client-api-deploy.yml @@ -1,6 +1,9 @@ name: stag-client-api-deploy -on: workflow_dispatch +on: + push: + branches: [ "stag/client" ] + workflow_dispatch: jobs: deploy: @@ -16,7 +19,7 @@ jobs: run: ./gradlew clean - name: client api build - run: ./gradlew :likelion-client:bootJar + run: ./gradlew :likelion-client:build - name: Docker login uses: docker/login-action@v2 @@ -24,8 +27,13 @@ jobs: username: ${{ secrets.DOCKERHUB_EMAIL }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - - name: docker image push - run: docker buildx build -f ./likelion-client/Dockerfile --build-arg PROFILE=stag --platform linux/amd64 -t ${{ secrets.DOCKER_CLIENT_API_STAG_IMAGE }} --push . + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: ./likelion-client + push: true + tags: ${{ secrets.DOCKER_CLIENT_API_STAG_IMAGE }} + build-args: PROFILE=stag - name: client-api-deploy uses: appleboy/ssh-action@master From 55d5053841e6b7cb18380bfe9c848808348a8714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:30:20 +0900 Subject: [PATCH 10/30] Update stag-client-api-deploy.yml --- .github/workflows/stag-client-api-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stag-client-api-deploy.yml b/.github/workflows/stag-client-api-deploy.yml index aa784181..f6f98d9e 100644 --- a/.github/workflows/stag-client-api-deploy.yml +++ b/.github/workflows/stag-client-api-deploy.yml @@ -19,7 +19,7 @@ jobs: run: ./gradlew clean - name: client api build - run: ./gradlew :likelion-client:build + run: ./gradlew :likelion-client:build -x test - name: Docker login uses: docker/login-action@v2 From f65ae7a4594655b7b9773da668a3bb78127b8397 Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:02:48 +0900 Subject: [PATCH 11/30] fix : post category --- .../univ/post/dto/PostCreateRequestDto.java | 4 +-- .../post/entity/enums/MainCategory.java | 7 ++--- .../domain/post/entity/enums/SubCategory.java | 30 ++++++++++++------- .../post/service/PostDomainService.java | 7 +++-- .../univ/domain/user/entity/Part.java | 2 -- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/likelion-client/src/main/java/likelion/univ/post/dto/PostCreateRequestDto.java b/likelion-client/src/main/java/likelion/univ/post/dto/PostCreateRequestDto.java index a8974660..3bdf5d8a 100644 --- a/likelion-client/src/main/java/likelion/univ/post/dto/PostCreateRequestDto.java +++ b/likelion-client/src/main/java/likelion/univ/post/dto/PostCreateRequestDto.java @@ -21,9 +21,9 @@ public class PostCreateRequestDto { @Schema(description = "썸네일 이미지", example = "string") private String thumbnail; @NotNull - @Schema(description = "메인 카테고리", example = "자유게시판", required = true) + @Schema(description = "메인 카테고리", example = "FREE_BOARD", required = true) private String mainCategory; @NotNull - @Schema(description = "서브 카테고리", example = "백엔드", required = true) + @Schema(description = "서브 카테고리", example = "FREE_INFO", required = true) private String subCategory; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/MainCategory.java b/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/MainCategory.java index b12d8dc7..bdad3f81 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/MainCategory.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/MainCategory.java @@ -6,10 +6,9 @@ @Getter @RequiredArgsConstructor public enum MainCategory { - HQ("HQ"), - BOARD("BOARD"), - OVERFLOW("OVERFLOW"); - + HQ_BOARD("멋대 중앙"), + FREE_BOARD("자유게시판"), + OVERFLOW("멋사 오버플로우"); private final String value; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/SubCategory.java b/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/SubCategory.java index 4b70fc51..c70c2faa 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/SubCategory.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/entity/enums/SubCategory.java @@ -8,17 +8,25 @@ @Getter @RequiredArgsConstructor public enum SubCategory { - NOTICE("SUBCATEGORY_NOTICE", "공지"), - QNA("SUBCATEGORY_QNA", "질의응답"), - FREEBOARD("SUBCATEGORY_INFO", "정보공유"), - FRONTEND("SUBCATEGORY_FRONTEND", "프론트"), - BACKEND("SUBCATEGORY_BACKEND", "백엔드"), - DESIGN("SUBCATEGORY_DESIGN", "디자인"), - PROJECT("SUBCATEGORY_PROJECT", "프로젝트"); - - - private final String key; - private final String title; + // HQ + NOTICE("공지사항"), + QNA("질문건의"), + HQ_INFO("중앙정보공유"), + + // board + FREE_INFO("멋대정보공유"), + GET_MEMBER("팀원 모집"), + GET_PROJECT("프로젝트 모집"), + SHOWOFF("프로젝트 자랑"), + + // overflow + FRONTEND("프론트"), + BACKEND("백엔드"), + PM("기획"), + UXUI("디자인"), + ETC("기타"); + + private final String value; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/service/PostDomainService.java b/likelion-core/src/main/java/likelion/univ/domain/post/service/PostDomainService.java index 6a587e78..d91a6787 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/service/PostDomainService.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/service/PostDomainService.java @@ -6,6 +6,8 @@ import likelion.univ.domain.post.dto.request.PostUpdateServiceDto; import likelion.univ.domain.post.dto.response.PostCommandResponseDto; import likelion.univ.domain.post.entity.Post; +import likelion.univ.domain.post.entity.enums.MainCategory; +import likelion.univ.domain.post.entity.enums.SubCategory; import likelion.univ.domain.post.exception.PostNoAuthorizationException; import likelion.univ.domain.user.adaptor.UserAdaptor; import lombok.RequiredArgsConstructor; @@ -54,9 +56,8 @@ private Post createEntity(PostCreateServiceDto request) { .title(request.getTitle()) .body(request.getBody()) .thumbnail(request.getThumbnail()) - // TODO : category 입력되도록 수정 -// .mainCategory(MainCategory.valueOf(request.getMainCategory())) -// .subCategory(SubCategory.valueOf(request.getSubCategory())) + .mainCategory(MainCategory.valueOf(request.getMainCategory())) + .subCategory(SubCategory.valueOf(request.getSubCategory())) .build(); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java index fca30d1d..a945338f 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java @@ -11,7 +11,5 @@ public enum Part { PM("기획"), DESIGNER("디자인"), PM_DESIGNER("기획/디자인"); - private String value; - } From a312844625a8fa5215e0a0c4bf586913627628d5 Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:23:12 +0900 Subject: [PATCH 12/30] fix : swagger controller description --- .../likelion/univ/comment/controller/CommentController.java | 2 +- .../like/commentlike/controller/CommentLikeController.java | 2 +- .../univ/like/postlike/controller/PostLikeController.java | 2 ++ .../java/likelion/univ/post/controller/PostController.java | 4 +++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/likelion-client/src/main/java/likelion/univ/comment/controller/CommentController.java b/likelion-client/src/main/java/likelion/univ/comment/controller/CommentController.java index d2498f3b..2d410d28 100644 --- a/likelion-client/src/main/java/likelion/univ/comment/controller/CommentController.java +++ b/likelion-client/src/main/java/likelion/univ/comment/controller/CommentController.java @@ -20,7 +20,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/v1/community/comments") -@Tag(name = "댓글", description = "댓글 API") +@Tag(name = "댓글", description = "커뮤니티 APIs") public class CommentController { private final CreateParentCommentUseCase createParentCommentUseCase; private final CreateChildCommentUseCase createChildCommentUseCase; diff --git a/likelion-client/src/main/java/likelion/univ/like/commentlike/controller/CommentLikeController.java b/likelion-client/src/main/java/likelion/univ/like/commentlike/controller/CommentLikeController.java index 85c638ba..42e4a2dd 100644 --- a/likelion-client/src/main/java/likelion/univ/like/commentlike/controller/CommentLikeController.java +++ b/likelion-client/src/main/java/likelion/univ/like/commentlike/controller/CommentLikeController.java @@ -15,7 +15,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/v1/community/commentlike") -@Tag(name = "댓글 좋아요", description = "댓글 좋아요 API") +@Tag(name = "댓글 좋아요", description = "커뮤니티 APIs") public class CommentLikeController { private final CreateCommentLikeUseCase createCommentLikeUseCase; private final SwitchCommentLikeUseCase switchCommentLikeUseCase; diff --git a/likelion-client/src/main/java/likelion/univ/like/postlike/controller/PostLikeController.java b/likelion-client/src/main/java/likelion/univ/like/postlike/controller/PostLikeController.java index 9d9086c4..d491716b 100644 --- a/likelion-client/src/main/java/likelion/univ/like/postlike/controller/PostLikeController.java +++ b/likelion-client/src/main/java/likelion/univ/like/postlike/controller/PostLikeController.java @@ -2,6 +2,7 @@ import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import likelion.univ.domain.like.postlike.dto.PostLikeResponseDto; import likelion.univ.like.postlike.dto.PostLikeRequestDto; import likelion.univ.like.postlike.usecase.CreatePostLikeUseCase; @@ -13,6 +14,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/v1/community/likepost") +@Tag(name = "게시글 좋아요", description = "커뮤니티 APIs") public class PostLikeController { private final CreatePostLikeUseCase createPostLikeUseCase; private final DeletePostLikeUseCase deletePostLikeUseCase; diff --git a/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java b/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java index 6f18ff17..1cd750c3 100644 --- a/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java +++ b/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java @@ -2,6 +2,7 @@ import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import likelion.univ.domain.post.dto.response.PostDetailResponseDto; import likelion.univ.domain.post.dto.response.PostCommandResponseDto; import likelion.univ.domain.post.entity.enums.MainCategory; @@ -22,6 +23,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/v1/community/posts") +@Tag(name = "게시글", description = "커뮤니티, 마이페이지 APIs") public class PostController { private final PostCreateUseCase postCreateUseCase; @@ -62,7 +64,7 @@ public SuccessResponse findLikedPosts(@RequestParam Integer page, @RequestPar } /* command */ - @Operation(summary = "게시글을 생성", description = "(작업중 - 카테고리 반영 필요)") + @Operation(summary = "게시글을 생성", description = "Main Category\n- HQ_BOARD(멋대 중앙)\n- FREE_BOARD(자유게시판)\n- OVERFLOW(멋사 오버플로우) \n\nSub Category\n- HQ_BOARD : NOTICE(공지사항), QNA(질문건의), HQ_INFO(정보공유)\n- FREE_BOARD : FREE_INFO(정보공유), GET_MEMBER(팀원구함), GET_PROJECT(프로젝트 구함), SHOWOFF(프로젝트 자랑)\n- OVERFLOW : FRONTEND(프론트엔드), BACKEND(백엔드), PM(기획), UXUI(디자인), ETC(기타)") @PostMapping("/new") public SuccessResponse createPost(@RequestBody @Valid PostCreateRequestDto request/*, BindingResult bindingResult*/) { PostCommandResponseDto response = postCreateUseCase.execute(request); From 476b35e92541aee93d782f5292664e1700f84ebd Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:47:17 +0900 Subject: [PATCH 13/30] =?UTF-8?q?fix=20:=20swagger=20description=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../likelion/univ/post/controller/PostController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java b/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java index 1cd750c3..ceaa9a5d 100644 --- a/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java +++ b/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java @@ -32,14 +32,14 @@ public class PostController { private final PostReadRepository postReadRepository; /* read */ - @Operation(summary = "(커뮤니티) 카테고리별 posts 최신순 조회", description = "카테고리가 일치하는 게시글 최신순으로 조회") + @Operation(summary = "(커뮤니티) 카테고리별 posts 최신순 조회", description = "- page : 0 이상의 정수 \n- size : 양수") @GetMapping("") public SuccessResponse findCategorizedPosts(@RequestParam MainCategory mainCategory, @RequestParam SubCategory subCategory, @RequestParam Integer page, @RequestParam Integer size) { PageRequest pageRequest = PageRequest.of(page, size); List response = postReadRepository.findAll(mainCategory, subCategory, pageRequest); return SuccessResponse.of(response); } - @Operation(summary = "(마이페이지) 유저별 posts 최신순 조회", description = "유저Id를 param으로 넣어서, 유저별로 작성한 게시글을 최신순으로 조회") + @Operation(summary = "(마이페이지) 유저별 posts 최신순 조회", description = "유저Id를 param으로 넣어서, 유저별로 작성한 게시글을 최신순으로 조회 \n- page : 0 이상의 정수 \n- size : 양수") @GetMapping("/author/{userId}") public SuccessResponse findAuthorPosts(@PathVariable Long userId, @RequestParam Integer page, @RequestParam Integer size) { PageRequest pageRequest = PageRequest.of(page, size); @@ -47,7 +47,7 @@ public SuccessResponse findAuthorPosts(@PathVariable Long userId, @RequestPar return SuccessResponse.of(response); } - @Operation(summary = "(마이페이지) 유저가 댓글을 단 posts 최신순 조회", description = "(로그인된 유저 기준 only) 댓글 단 posts 최신순 조회") + @Operation(summary = "(마이페이지) 유저가 댓글을 단 posts 최신순 조회", description = "(로그인된 유저 기준 only) 댓글 단 posts 최신순 조회 \n- page : 0 이상의 정수 \n- size : 양수") @GetMapping("/commented") public SuccessResponse findCommentedPosts(@RequestParam Integer page, @RequestParam Integer size) { PageRequest pageRequest = PageRequest.of(page, size); @@ -55,7 +55,7 @@ public SuccessResponse findCommentedPosts(@RequestParam Integer page, @Reques return SuccessResponse.of(response); } - @Operation(summary = "(마이페이지) 유저가 좋아요한 posts 최신순 조회", description = "(로그인된 유저 기준 only) 좋아요를 누른 posts 최신순 조회") + @Operation(summary = "(마이페이지) 유저가 좋아요한 posts 최신순 조회", description = "(로그인된 유저 기준 only) 좋아요를 누른 posts 최신순 조회 \n- page : 0 이상의 정수 \n- size : 양수") @GetMapping("/liked") public SuccessResponse findLikedPosts(@RequestParam Integer page, @RequestParam Integer size) { PageRequest pageRequest = PageRequest.of(page, size); From f70a23201658bf94a1a0bc3c0aec0e527b779198 Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:06:53 +0900 Subject: [PATCH 14/30] fix : post/findall api category params modified --- .../java/likelion/univ/post/controller/PostController.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java b/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java index ceaa9a5d..d9517629 100644 --- a/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java +++ b/likelion-client/src/main/java/likelion/univ/post/controller/PostController.java @@ -32,10 +32,13 @@ public class PostController { private final PostReadRepository postReadRepository; /* read */ - @Operation(summary = "(커뮤니티) 카테고리별 posts 최신순 조회", description = "- page : 0 이상의 정수 \n- size : 양수") + @Operation(summary = "(커뮤니티) 카테고리별 posts 최신순 조회", description = "카테고리 params\n- maincatstr : 메인 카테고리 문자열(HQ_BOARD, FREE_BOARD, OVERFLOW)\n- subcatstr : 서브 카테고리 문자열(post 생성 참고)\n\n페이지네이션 params\n- page : 0 이상의 정수 \n- size : 양수") @GetMapping("") - public SuccessResponse findCategorizedPosts(@RequestParam MainCategory mainCategory, @RequestParam SubCategory subCategory, @RequestParam Integer page, @RequestParam Integer size) { + public SuccessResponse findCategorizedPosts(@RequestParam String maincatstr, @RequestParam String subcatstr, @RequestParam Integer page, @RequestParam Integer size) { PageRequest pageRequest = PageRequest.of(page, size); + MainCategory mainCategory = MainCategory.valueOf(maincatstr); + SubCategory subCategory = SubCategory.valueOf(subcatstr); + List response = postReadRepository.findAll(mainCategory, subCategory, pageRequest); return SuccessResponse.of(response); } From ff6a821e3c4079fae88d2da9bfee828f08e8d97d Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Mon, 9 Oct 2023 17:01:33 +0900 Subject: [PATCH 15/30] =?UTF-8?q?fix=20:=20QueryDslConfig=20=ED=95=98?= =?UTF-8?q?=EB=82=98=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/likelion/univ/config/QueryDslConfig.java | 7 +------ .../java/likelion/univ/config/QuerydslConfig.java | 15 --------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java diff --git a/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java b/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java index ab3b334d..65a6c6e3 100644 --- a/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java +++ b/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java @@ -5,16 +5,11 @@ import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; @Configuration public class QueryDslConfig { - - @PersistenceContext - private EntityManager entityManager; - @Bean - public JPAQueryFactory jpaQueryFactory () { + public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { return new JPAQueryFactory(entityManager); } } diff --git a/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java b/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java deleted file mode 100644 index 56502ebd..00000000 --- a/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package likelion.univ.config; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManager; - -@Configuration -public class QuerydslConfig { - @Bean - public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { - return new JPAQueryFactory(entityManager); - } -} From 0c7473c9f47c380d214affdd51368b4146a66fe0 Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:46:54 +0900 Subject: [PATCH 16/30] =?UTF-8?q?feature=20:=20post=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=8B=9C=20likecount=20=C3=A3=EC=A0=9C=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/post/repository/PostReadRepositoryCustomImpl.java | 1 + .../java/likelion/univ/domain/comment/entity/Comment.java | 4 ++-- .../domain/post/dto/response/PostDetailResponseDto.java | 5 ++++- .../main/java/likelion/univ/domain/post/entity/Post.java | 7 +++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java b/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java index 3d6551c3..ddec26d7 100644 --- a/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java +++ b/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java @@ -120,6 +120,7 @@ private static QPostDetailResponseDto postDetailResponseDto() { post.title, post.body, post.thumbnail, + post.postLikes.size(), post.mainCategory, post.subCategory, post.createdDate, diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java index 018bc699..415bfbad 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java @@ -36,12 +36,12 @@ public class Comment extends BaseTimeEntity { private Comment parentComment; @OneToMany(mappedBy = "comment", - cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true) // 안정성 체크해봐야됨 + cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true) private List commentLikes = new ArrayList<>(); @OneToMany(mappedBy = "parentComment", - cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true) // 안정성 체크해봐야됨 + cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true) private List childComments = new ArrayList<>(); @Column(nullable = false, columnDefinition = "TEXT") diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/dto/response/PostDetailResponseDto.java b/likelion-core/src/main/java/likelion/univ/domain/post/dto/response/PostDetailResponseDto.java index 6e1c3e0d..db1781c4 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/dto/response/PostDetailResponseDto.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/dto/response/PostDetailResponseDto.java @@ -23,6 +23,8 @@ public class PostDetailResponseDto { private String thumbnail; + private Integer likeCount; + private MainCategory mainCategory; private SubCategory subCategory; @@ -32,13 +34,14 @@ public class PostDetailResponseDto { private LocalDateTime modifiedDate; @QueryProjection - public PostDetailResponseDto(Long postId, Long authorId, String authorName, String title, String body, String thumbnail, MainCategory mainCategory, SubCategory subCategory, LocalDateTime createdDate, LocalDateTime modifiedDate) { + public PostDetailResponseDto(Long postId, Long authorId, String authorName, String title, String body, String thumbnail, Integer likeCount, MainCategory mainCategory, SubCategory subCategory, LocalDateTime createdDate, LocalDateTime modifiedDate) { this.postId = postId; this.authorId = authorId; this.authorName = authorName; this.title = title; this.body = body; this.thumbnail = thumbnail; + this.likeCount = likeCount; this.mainCategory = mainCategory; this.subCategory = subCategory; this.createdDate = createdDate; diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java b/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java index 480f6bad..946c48f9 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java @@ -1,6 +1,7 @@ package likelion.univ.domain.post.entity; import likelion.univ.common.entity.BaseTimeEntity; +import likelion.univ.domain.like.postlike.entity.PostLike; import likelion.univ.domain.post.dto.request.PostUpdateServiceDto; import likelion.univ.domain.post.entity.enums.MainCategory; import likelion.univ.domain.post.entity.enums.SubCategory; @@ -8,6 +9,8 @@ import lombok.*; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -32,6 +35,10 @@ public class Post extends BaseTimeEntity { private String thumbnail; + @OneToMany(mappedBy = "post", + cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true) + private List postLikes = new ArrayList(); + @Enumerated(EnumType.STRING) private MainCategory mainCategory; From 83fb645490260926ee2c1017763b7b4bf822e281 Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:51:17 +0900 Subject: [PATCH 17/30] fix: dealing conflict --- .../java/likelion/univ/config/QueryDslConfig.java | 8 ++------ .../java/likelion/univ/config/QuerydslConfig.java | 15 --------------- 2 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java diff --git a/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java b/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java index ab3b334d..3f7d8d3e 100644 --- a/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java +++ b/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java @@ -5,16 +5,12 @@ import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; @Configuration public class QueryDslConfig { - - @PersistenceContext - private EntityManager entityManager; - @Bean - public JPAQueryFactory jpaQueryFactory () { + public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { return new JPAQueryFactory(entityManager); } } + diff --git a/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java b/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java deleted file mode 100644 index 56502ebd..00000000 --- a/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package likelion.univ.config; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManager; - -@Configuration -public class QuerydslConfig { - @Bean - public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { - return new JPAQueryFactory(entityManager); - } -} From c73e5f7d343fdcfe4d0d6da50f353f6f3a3deb63 Mon Sep 17 00:00:00 2001 From: ghkdwp018 <99382672+ghkdwp018@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:52:59 +0900 Subject: [PATCH 18/30] fix : dealing conflict --- .../java/likelion/univ/config/QueryDslConfig.java | 7 +------ .../java/likelion/univ/config/QuerydslConfig.java | 15 --------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java diff --git a/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java b/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java index ab3b334d..65a6c6e3 100644 --- a/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java +++ b/likelion-core/src/main/java/likelion/univ/config/QueryDslConfig.java @@ -5,16 +5,11 @@ import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; @Configuration public class QueryDslConfig { - - @PersistenceContext - private EntityManager entityManager; - @Bean - public JPAQueryFactory jpaQueryFactory () { + public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { return new JPAQueryFactory(entityManager); } } diff --git a/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java b/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java deleted file mode 100644 index 56502ebd..00000000 --- a/likelion-core/src/main/java/likelion/univ/config/QuerydslConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package likelion.univ.config; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManager; - -@Configuration -public class QuerydslConfig { - @Bean - public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { - return new JPAQueryFactory(entityManager); - } -} From 75d5b907585ebb491473034b986b4968d8e41e8d Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Tue, 10 Oct 2023 11:16:09 +0900 Subject: [PATCH 19/30] =?UTF-8?q?feat=20:=20=EC=9C=A0=EC=A0=80=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EA=B0=84=EB=8B=A8=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/auth/controller/AuthController.java | 14 +++++++---- .../auth/dto/response/AccountUserInfoDto.java | 20 ++++++++++++++++ .../univ/auth/usecase/GetUserInfoUsecase.java | 23 +++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java diff --git a/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java b/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java index ccf949a8..1a56497b 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java +++ b/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java @@ -3,11 +3,9 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import likelion.univ.auth.dto.response.AccountTokenDto; +import likelion.univ.auth.dto.response.AccountUserInfoDto; import likelion.univ.auth.dto.response.IdTokenDto; -import likelion.univ.auth.usecase.LoginUseCase; -import likelion.univ.auth.usecase.RefreshTokenUseCase; -import likelion.univ.auth.usecase.RequestIdTokenUseCase; -import likelion.univ.auth.usecase.SignUpUseCase; +import likelion.univ.auth.usecase.*; import likelion.univ.auth.dto.request.SignUpRequestDto; import likelion.univ.response.SuccessResponse; import lombok.RequiredArgsConstructor; @@ -23,6 +21,7 @@ public class AuthController { private final RequestIdTokenUseCase requestIdTokenUseCase; private final SignUpUseCase signUpUseCase; private final RefreshTokenUseCase refreshTokenUseCase; + private final GetUserInfoUsecase getUserInfoUsecase; @Operation(summary = "id token 발급", description = "인가 코드로 id token을 발급받습니다.") @GetMapping("/{logintype}/idtoken") @@ -53,6 +52,13 @@ public SuccessResponse signUp( return SuccessResponse.of(accountTokenDto); } + @Operation(summary = "유저 정보 조회", description = "간단한 유저정보를 조회합니다.") + @GetMapping("/userinfo") + public SuccessResponse getUserInfo(){ + AccountUserInfoDto accountUserInfoDto = getUserInfoUsecase.execute(); + return SuccessResponse.of(accountUserInfoDto); + } + @Operation(summary = "토큰 재발급", description = "refresh token으로 access token을 재발급합니다.") @PostMapping("/refresh") public SuccessResponse refreshToken( diff --git a/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java b/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java new file mode 100644 index 00000000..a7ec8fc7 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java @@ -0,0 +1,20 @@ +package likelion.univ.auth.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class AccountUserInfoDto { + private String profileImage; + private String name; + + public static AccountUserInfoDto of(User user){ + return AccountUserInfoDto.builder() + .profileImage(user.getProfile().getProfileImage()) + .name(user.getProfile().getName()) + .build(); + } + +} diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java b/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java new file mode 100644 index 00000000..d8b026e9 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java @@ -0,0 +1,23 @@ +package likelion.univ.auth.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.auth.dto.response.AccountTokenDto; +import likelion.univ.auth.dto.response.AccountUserInfoDto; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.LoginType; +import likelion.univ.domain.user.entity.User; +import likelion.univ.jwt.dto.UserInfoFromIdToken; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class GetUserInfoUsecase { + + private final AuthentiatedUserUtils authentiatedUserUtils; + + public AccountUserInfoDto execute(){ + User user = authentiatedUserUtils.getCurrentUser(); + return AccountUserInfoDto.of(user); + } +} From e127a530508a0842cca161d46e9fbda5c018ecc0 Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Wed, 11 Oct 2023 10:31:45 +0900 Subject: [PATCH 20/30] =?UTF-8?q?feat=20:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/auth/controller/AuthController.java | 2 +- ...foUsecase.java => GetUserInfoUseCase.java} | 6 +- .../mypage/controller/MypageController.java | 70 +++++++++++++++++++ .../mypage/dto/response/MyPagePostsDto.java | 29 ++++++++ .../dto/response/ProfileDetailsDto.java | 35 ++++++++++ .../mypage/usecase/GetProfileUseCase.java | 27 +++++++ .../univ/domain/comment/entity/Comment.java | 1 - .../domain/comment/entity/LikeComment.java | 1 - .../univ/domain/example/entity/Example.java | 1 - .../domain/follow/adaptor/FolllowAdaptor.java | 20 ++++++ .../univ/domain/follow/entity/Follow.java | 1 - .../follow/repository/FollowRepository.java | 9 +++ .../univ/domain/post/adaptor/PostAdaptor.java | 7 +- .../univ/domain/post/entity/LikePost.java | 3 +- .../univ/domain/post/entity/Post.java | 4 +- .../post/repository/PostRepository.java | 4 ++ .../univ/domain/project/entity/Image.java | 1 - .../univ/domain/project/entity/Project.java | 1 - .../domain/project/entity/ProjectMember.java | 1 - .../univ/domain/recruit/entity/Recruit.java | 1 - .../domain/university/entity/University.java | 1 - .../univ/domain/user/adaptor/UserAdaptor.java | 4 ++ .../univ/domain/user/entity/AuthInfo.java | 2 + .../univ/domain/user/entity/Profile.java | 2 - .../univ/domain/user/entity/User.java | 1 - .../user/repository/UserRepository.java | 4 ++ .../src/main/resources/application-core.yml | 35 ++++++++-- 27 files changed, 244 insertions(+), 29 deletions(-) rename likelion-client/src/main/java/likelion/univ/auth/usecase/{GetUserInfoUsecase.java => GetUserInfoUseCase.java} (68%) create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java diff --git a/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java b/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java index 1a56497b..f30a5f47 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java +++ b/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java @@ -21,7 +21,7 @@ public class AuthController { private final RequestIdTokenUseCase requestIdTokenUseCase; private final SignUpUseCase signUpUseCase; private final RefreshTokenUseCase refreshTokenUseCase; - private final GetUserInfoUsecase getUserInfoUsecase; + private final GetUserInfoUseCase getUserInfoUsecase; @Operation(summary = "id token 발급", description = "인가 코드로 id token을 발급받습니다.") @GetMapping("/{logintype}/idtoken") diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java b/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java similarity index 68% rename from likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java rename to likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java index d8b026e9..a9b5dadd 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUsecase.java +++ b/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java @@ -1,18 +1,14 @@ package likelion.univ.auth.usecase; import likelion.univ.annotation.UseCase; -import likelion.univ.auth.dto.response.AccountTokenDto; import likelion.univ.auth.dto.response.AccountUserInfoDto; -import likelion.univ.domain.user.adaptor.UserAdaptor; -import likelion.univ.domain.user.entity.LoginType; import likelion.univ.domain.user.entity.User; -import likelion.univ.jwt.dto.UserInfoFromIdToken; import likelion.univ.utils.AuthentiatedUserUtils; import lombok.RequiredArgsConstructor; @UseCase @RequiredArgsConstructor -public class GetUserInfoUsecase { +public class GetUserInfoUseCase { private final AuthentiatedUserUtils authentiatedUserUtils; diff --git a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java b/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java new file mode 100644 index 00000000..518e2f84 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java @@ -0,0 +1,70 @@ +package likelion.univ.mypage.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import likelion.univ.auth.dto.request.SignUpRequestDto; +import likelion.univ.auth.dto.response.AccountTokenDto; +import likelion.univ.auth.dto.response.IdTokenDto; +import likelion.univ.auth.usecase.LoginUseCase; +import likelion.univ.auth.usecase.RefreshTokenUseCase; +import likelion.univ.auth.usecase.RequestIdTokenUseCase; +import likelion.univ.auth.usecase.SignUpUseCase; +import likelion.univ.mypage.dto.response.ProfileDetailsDto; +import likelion.univ.mypage.usecase.GetProfileUseCase; +import likelion.univ.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springdoc.api.annotations.ParameterObject; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/v1/mypage") +@Tag(name = "마이페이지", description = "마이페이지관련 API입니다.") +public class MypageController { + private final GetProfileUseCase getProfileUseCase; + + @Operation(summary = "마이페이지 프로필 조회", description = "본인의 프로필 정보를 조회합니다.") + @GetMapping("/profile") + public SuccessResponse getProfile(){ + ProfileDetailsDto profileDetailsDto = getProfileUseCase.execute(); + return SuccessResponse.of(profileDetailsDto); + } + + @Operation(summary = "내가쓴 게시글 조회", description = "작성한 게시글을 조회합니다.") + @GetMapping("/posts") + public SuccessResponse getMyPosts(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + + return SuccessResponse.of(); + } + +// @Operation(summary = "내가 참여한 프로젝트 조회", description = "참여한 프로젝트를 조회합니다.") +// @GetMapping("/projects") +// public SuccessResponse getMyProjects(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ +// +// return SuccessResponse.of(); +// } +// +// @Operation(summary = "내가쓴 댓글 조회", description = "작성한 댓글을 조회합니다.") +// @GetMapping("/comments") +// public SuccessResponse getMyComments(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ +// +// return SuccessResponse.of(); +// } + +// @Operation(summary = "휴대폰 인증 요청", description = "휴대폰 번호 인증을 위해 서버 내부에 인증번호를 생성합니다.") +// @PostMapping("/phone/certify") +// public SuccessResponse login(@RequestParam("phonenum") String phoneNum){ +// return SuccessResponse.of(); +// } +// +// @Operation(summary = "휴대폰 인증번호 확인", description = "휴대폰 인증번호 확인 후 인증 토큰을 발급합니다.") +// @PostMapping("/phone/certify/check") +// public SuccessResponse getIdToken(@RequestParam("certifynum") Long certifyNum){ +// +// return SuccessResponse.of(); +// } + +} + diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java new file mode 100644 index 00000000..70b8f71e --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java @@ -0,0 +1,29 @@ +package likelion.univ.mypage.dto.response; + +import likelion.univ.domain.post.entity.Post; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDate; + + +@Getter +@Builder +public class MyPagePostsDto { + private Long id; + private String title; + private String body; + private String thumbnail; + private Boolean isAuthor = true; + private LocalDate createdDate; + + public static MyPagePostsDto of(Post post){ + return MyPagePostsDto.builder() + .id(post.getId()) + .title(post.getTitle()) + .body(post.getBody()) + .thumbnail(post.getThumbnail()) + .createdDate(post.getCreatedDate().toLocalDate()) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java new file mode 100644 index 00000000..f7c4c35e --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java @@ -0,0 +1,35 @@ +package likelion.univ.mypage.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ProfileDetailsDto { + private String profileImage; + private String name; + private String role; + private String phoneNum; + private String universityName; + private String major; + private Long ordinal; + private Long followerNum; + private Long followingNum; + private String introduction; + + public static ProfileDetailsDto of(User user, Long followerNum, Long followingNum){ + return ProfileDetailsDto.builder() + .profileImage(user.getProfile().getProfileImage()) + .name(user.getProfile().getName()) + .role(user.getAuthInfo().getRole().getValue()) + .phoneNum(user.getAuthInfo().getPhoneNumber()) + .universityName(user.getUniversityInfo().getUniversity().getName()) + .major(user.getUniversityInfo().getMajor()) + .ordinal(user.getUniversityInfo().getOrdinal()) + .followerNum(followerNum) + .followingNum(followingNum) + .introduction(user.getProfile().getIntroduction()) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java new file mode 100644 index 00000000..8a8c6251 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java @@ -0,0 +1,27 @@ +package likelion.univ.mypage.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.follow.adaptor.FolllowAdaptor; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.User; +import likelion.univ.mypage.dto.response.ProfileDetailsDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class GetProfileUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final UserAdaptor userAdaptor; + private final FolllowAdaptor folllowAdaptor; + + public ProfileDetailsDto execute(){ + Long userId = authentiatedUserUtils.getCurrentUserId(); + User user = userAdaptor.findByIdWithUniversity(userId); + /*임시로 카운트쿼리로.. */ + Long followerNum = folllowAdaptor.countByFolloweeId(userId); + Long followingNum = folllowAdaptor.countByFollowerId(userId); + + return ProfileDetailsDto.of(user, followerNum, followingNum); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java index e4f629eb..a89f757d 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java @@ -19,7 +19,6 @@ public class Comment extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "comment_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/LikeComment.java b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/LikeComment.java index d405657d..c6ba1467 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/LikeComment.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/LikeComment.java @@ -14,7 +14,6 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class LikeComment extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "like_comment_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java b/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java index 3368c700..6f671abe 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java +++ b/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java @@ -15,7 +15,6 @@ public class Example extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "example_id") private Long id; @Column(nullable = false) diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java new file mode 100644 index 00000000..bd6288d4 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java @@ -0,0 +1,20 @@ +package likelion.univ.domain.follow.adaptor; + +import likelion.univ.annotation.Adaptor; +import likelion.univ.domain.follow.repository.FollowRepository; +import lombok.RequiredArgsConstructor; + +@Adaptor +@RequiredArgsConstructor +public class FolllowAdaptor { + private final FollowRepository followRepository; + + public Long countByFollowerId(Long followerId){ + return followRepository.countByFollowerId(followerId); + } + + public Long countByFolloweeId(Long followeeId){ + return followRepository.countByFolloweeId(followeeId); + } + +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java index 38b98a5a..72c81376 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java @@ -15,7 +15,6 @@ public class Follow extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "follow_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java new file mode 100644 index 00000000..cee82e2d --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.follow.repository; + +import likelion.univ.domain.follow.entity.Follow; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FollowRepository extends JpaRepository { + Long countByFollowerId(Long followerId); + Long countByFolloweeId(Long followeeId); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java index 54fbac7a..be2e3d00 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java @@ -2,10 +2,11 @@ import likelion.univ.annotation.Adaptor; import likelion.univ.domain.post.entity.Post; -//import likelion.univ.domain.community.post.repository.PostCustomRepository; import likelion.univ.domain.post.repository.PostRepository; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; @Adaptor @RequiredArgsConstructor @@ -29,6 +30,10 @@ public void delete(Post post) { postRepository.delete(post); //예외처리 } + public Page findAllByAuthor_Id(Long userId, Pageable pageable){ + return postRepository.findAllByAuthor_Id(userId,pageable); + } + // public List retrievePostPaging(Integer page, Integer limit) { // return postCustomRepository.pagingWithCoveringIndex(page, limit); // } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/entity/LikePost.java b/likelion-core/src/main/java/likelion/univ/domain/post/entity/LikePost.java index 1cb7a76c..e9ed1a3a 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/entity/LikePost.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/entity/LikePost.java @@ -15,8 +15,7 @@ public class LikePost extends BaseTimeEntity { @Id @GeneratedValue - @Column(name = "like_post_id") - private Long likeId; + private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java b/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java index 7d601fdd..3a94cbae 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java @@ -17,8 +17,8 @@ @Setter @Table(name = "post") public class Post extends BaseTimeEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "post_id") + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java index 6927a8cc..909c8e83 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java @@ -1,8 +1,12 @@ package likelion.univ.domain.post.repository; import likelion.univ.domain.post.entity.Post; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface PostRepository extends JpaRepository { + Page findAllByAuthor_Id(Long userId, Pageable pageable); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java index fec1b505..1fe8492d 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java +++ b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java @@ -15,7 +15,6 @@ public class Image { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="image_id") private long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java index b9b43b1e..ad3e6388 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java +++ b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java @@ -18,7 +18,6 @@ public class Project extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="project_id") private long id; private String thon; diff --git a/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java b/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java index 46257aec..ae540c4f 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java +++ b/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java @@ -15,7 +15,6 @@ public class ProjectMember { @Id @GeneratedValue - @Column(name = "projectMember_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java b/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java index 1b90cba0..4b62e561 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java +++ b/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java @@ -19,7 +19,6 @@ public class Recruit extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "recruit_id") private Long id; private String name; diff --git a/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java b/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java index 23fe663b..f693d51c 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java +++ b/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java @@ -14,7 +14,6 @@ public class University extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "university_id") private Long id; @Column(unique = true) private String name; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java index 69896568..07919901 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java @@ -19,6 +19,10 @@ public User findById(Long id){ return userRepository.findById(id) .orElseThrow(()-> new UserNotFoundException()); } + public User findByIdWithUniversity(Long id){ + return userRepository.findByIdWithUniversity(id) + .orElseThrow(()-> new UserNotFoundException()); + } public User findByEmail(String email){ return userRepository.findByAuthInfoEmail(email) .orElseThrow(()-> new UserNotFoundException()); diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java index 118f9a20..00b2b3a2 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java @@ -20,6 +20,8 @@ public class AuthInfo { private String email; @Enumerated(EnumType.STRING) private AccountStatus accountStatus; + // 01000000000 형태로 + private String phoneNumber; @Enumerated(EnumType.STRING) private Role role; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java index 517f7f31..64610b20 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java @@ -15,8 +15,6 @@ public class Profile { private String name; - // 010-0000-0000 형태로 - private String phoneNumber; private String profileImage; @Column(columnDefinition = "TEXT") diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java index 7aa5d3dc..25746000 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java @@ -16,7 +16,6 @@ public class User extends BaseTimeEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "user_id") private Long id; @Embedded diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java index a642764d..953ac076 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java @@ -2,10 +2,14 @@ import likelion.univ.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.Optional; public interface UserRepository extends JpaRepository { Optional findByAuthInfoEmail(String email); Boolean existsByAuthInfoEmail(String email); + + @Query("SELECT u FROM User u join fetch u.universityInfo.university") + Optional findByIdWithUniversity(Long id); } diff --git a/likelion-core/src/main/resources/application-core.yml b/likelion-core/src/main/resources/application-core.yml index 3f2a1565..b68c9948 100644 --- a/likelion-core/src/main/resources/application-core.yml +++ b/likelion-core/src/main/resources/application-core.yml @@ -16,12 +16,6 @@ spring: hibernate: default_batch_fetch_size: 1000 -logging: - level: - org.springframework.orm.jpa: DEBUG - org.springframework.transaction: DEBUG - pattern: - console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" --- ## dev 환경 설정 spring: @@ -29,12 +23,41 @@ spring: activate: on-profile: dev + jpa: + properties: + hibernate: + show_sql: true + format_sql: true + +logging: + level: + org.springframework.orm.jpa: DEBUG + org.springframework.transaction: DEBUG + org: + hibernate: + type: + descriptor: + sql: trace + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" + --- ## staging환경 설정 spring: config: activate: on-profile: staging + jpa: + properties: + hibernate: + show_sql: false + format_sql: false + +logging: + level: + root: INFO + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" --- ## prod 환경 설정 spring: config: From 705eb5f0b7d73ccc43006f68bb162a36c451d17f Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Thu, 12 Oct 2023 19:33:55 +0900 Subject: [PATCH 21/30] =?UTF-8?q?feat=20:=20=EB=82=B4=EA=B0=80=EC=93=B4=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mypage/controller/MypageController.java | 9 +++- .../mypage/dto/response/MyPagePostsDto.java | 9 +++- .../mypage/usecase/GetMypagePostsUseCase.java | 51 +++++++++++++++++++ .../src/main/resources/application.yml | 5 -- likelion-core/build.gradle | 1 - .../univ/common/page/PageResponse.java | 34 +++++++++++++ .../comment/adaptor/CommentAdaptor.java | 3 ++ .../comment/repository/CommentRepository.java | 2 + .../domain/post/adaptor/LikePostAdaptor.java | 15 ++++++ .../post/repository/LikePostRepository.java | 8 +++ .../post/repository/PostRepository.java | 1 - .../univ/domain/user/adaptor/UserAdaptor.java | 4 +- .../src/main/resources/application-core.yml | 5 ++ .../univ/common/base/BaseRedisRepository.java | 14 +++-- .../config/RedisCacheManagerConfig.java | 1 - .../univ/common/constant/RedisKey.java | 4 +- .../univ/post/dao/PostCountInfoRedisDao.java | 19 +++++++ .../univ/post/entity/PostCountInfo.java | 15 ++++++ .../service/PostCountInfoRedisService.java | 21 ++++++++ .../adaptor/RefreshTokenRedisAdaptor.java | 21 -------- .../dao/RefreshTokenRedisDao.java | 6 +-- .../refreshtoken/entity/RefreshToken.java | 1 - .../service/RefreshTokenRedisService.java | 13 +++-- 23 files changed, 211 insertions(+), 51 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java create mode 100644 likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/post/adaptor/LikePostAdaptor.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/post/repository/LikePostRepository.java create mode 100644 likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java create mode 100644 likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java create mode 100644 likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java delete mode 100644 likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java diff --git a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java b/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java index 518e2f84..e106c120 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java @@ -9,11 +9,15 @@ import likelion.univ.auth.usecase.RefreshTokenUseCase; import likelion.univ.auth.usecase.RequestIdTokenUseCase; import likelion.univ.auth.usecase.SignUpUseCase; +import likelion.univ.common.page.PageResponse; +import likelion.univ.mypage.dto.response.MyPagePostsDto; import likelion.univ.mypage.dto.response.ProfileDetailsDto; +import likelion.univ.mypage.usecase.GetMypagePostsUseCase; import likelion.univ.mypage.usecase.GetProfileUseCase; import likelion.univ.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springdoc.api.annotations.ParameterObject; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.*; @@ -24,6 +28,7 @@ @Tag(name = "마이페이지", description = "마이페이지관련 API입니다.") public class MypageController { private final GetProfileUseCase getProfileUseCase; + private final GetMypagePostsUseCase getMypagePostsUseCase; @Operation(summary = "마이페이지 프로필 조회", description = "본인의 프로필 정보를 조회합니다.") @GetMapping("/profile") @@ -35,8 +40,8 @@ public SuccessResponse getProfile(){ @Operation(summary = "내가쓴 게시글 조회", description = "작성한 게시글을 조회합니다.") @GetMapping("/posts") public SuccessResponse getMyPosts(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ - - return SuccessResponse.of(); + PageResponse myPagePostsPage = getMypagePostsUseCase.execute(pageable); + return SuccessResponse.of(myPagePostsPage); } // @Operation(summary = "내가 참여한 프로젝트 조회", description = "참여한 프로젝트를 조회합니다.") diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java index 70b8f71e..6b8979c1 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java @@ -14,16 +14,21 @@ public class MyPagePostsDto { private String title; private String body; private String thumbnail; - private Boolean isAuthor = true; + private Boolean isAuthor; private LocalDate createdDate; + private Long likeCount; + private Long commentCount; - public static MyPagePostsDto of(Post post){ + public static MyPagePostsDto of(Post post, Long likeCount, Long commentCount){ return MyPagePostsDto.builder() .id(post.getId()) .title(post.getTitle()) .body(post.getBody()) .thumbnail(post.getThumbnail()) + .isAuthor(true) .createdDate(post.getCreatedDate().toLocalDate()) + .likeCount(likeCount) + .commentCount(commentCount) .build(); } } diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java new file mode 100644 index 00000000..12f1ea69 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java @@ -0,0 +1,51 @@ +package likelion.univ.mypage.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.page.PageResponse; +import likelion.univ.domain.comment.adaptor.CommentAdaptor; +import likelion.univ.domain.post.adaptor.LikePostAdaptor; +import likelion.univ.domain.post.adaptor.PostAdaptor; +import likelion.univ.domain.post.entity.Post; +import likelion.univ.mypage.dto.response.MyPagePostsDto; +import likelion.univ.post.dao.PostCountInfoRedisDao; +import likelion.univ.post.entity.PostCountInfo; +import likelion.univ.post.service.PostCountInfoRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class GetMypagePostsUseCase { + + private final AuthentiatedUserUtils authentiatedUserUtils; + private final PostAdaptor postAdaptor; + private final PostCountInfoRedisDao postCountInfoRedisDao; + private final PostCountInfoRedisService postCountInfoRedisService; + private final CommentAdaptor commentAdaptor; + private final LikePostAdaptor likePostAdaptor; + + public PageResponse execute(Pageable pageable){ + Long userId = authentiatedUserUtils.getCurrentUserId(); + Page posts = postAdaptor.findAllByAuthor_Id(userId, pageable); + + return PageResponse.of(posts.map(p-> createDto(p))); + } + + private MyPagePostsDto createDto(Post post){ + PostCountInfo postCountInfo = getPostCountInfo(post.getId()); + return MyPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount()); + } + + private PostCountInfo getPostCountInfo(Long postId){ + Optional postCountInfo = postCountInfoRedisDao.findById(postId); + if(postCountInfo.isEmpty()){ + Long commentCount = commentAdaptor.countByPostId(postId); + Long likeCount = likePostAdaptor.countByPostId(postId); + return postCountInfoRedisService.save(postId, commentCount, likeCount); + }else return postCountInfo.get(); + } +} diff --git a/likelion-client/src/main/resources/application.yml b/likelion-client/src/main/resources/application.yml index 58a7e573..a9d0162b 100644 --- a/likelion-client/src/main/resources/application.yml +++ b/likelion-client/src/main/resources/application.yml @@ -7,10 +7,6 @@ spring: - infrastructure - security - redis - data: - web: - pageable: ##페이징 - one-indexed-parameters: true #1페이지부터 시작, default:0페이지 server: servlet: @@ -18,7 +14,6 @@ server: springdoc: default-consumes-media-type: application/json;charset=UTF-8 - default-produces-media-type: application/json;charset=UTF-8 api-docs: enabled: ${SWAGGER_ENABLED} path: '/swagger' diff --git a/likelion-core/build.gradle b/likelion-core/build.gradle index 3ab57b92..322916de 100644 --- a/likelion-core/build.gradle +++ b/likelion-core/build.gradle @@ -9,7 +9,6 @@ dependencies { implementation 'com.querydsl:querydsl-jpa' implementation 'com.querydsl:querydsl-core' implementation project(path: ':likelion-common') - // Querydsl JPAAnnotationProcessor 사용 지정 annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" annotationProcessor("jakarta.persistence:jakarta.persistence-api") // java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 대응 diff --git a/likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java b/likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java new file mode 100644 index 00000000..f9ebedb7 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java @@ -0,0 +1,34 @@ +package likelion.univ.common.page; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.domain.Page; + +import java.util.List; + +@Getter +@Builder +public class PageResponse { + private int totalPage; + private Long totalElements; + private int pagingSize; + private int currentPage; + private Boolean isFirst; + private Boolean isLast; + private Boolean isEmpty; + private List data; + + + public static PageResponse of(Page page) { + return PageResponse.builder() + .totalPage(page.getTotalPages()) + .totalElements(page.getTotalElements()) + .pagingSize(page.getSize()) + .currentPage(page.getNumber()+1) + .isFirst(page.isFirst()) + .isLast(page.isLast()) + .isEmpty(page.isEmpty()) + .data(page.getContent()) + .build(); + } +} \ No newline at end of file diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java index 0288da9a..7bd2f83a 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java @@ -31,4 +31,7 @@ public List findAllByPost(Post post) { return commentRepository.findByPost(post); } + public Long countByPostId(Long postId){ + return commentRepository.countByPostId(postId); + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java b/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java index 4b522ddf..69d71652 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java @@ -10,4 +10,6 @@ public interface CommentRepository extends JpaRepository { @Query("SELECT c from Comment c JOIN FETCH c.author u JOIN FETCH c.post p JOIN FETCH c.parentComment pc") List findByPost(Post post); + + Long countByPostId(Long postId); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/LikePostAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/LikePostAdaptor.java new file mode 100644 index 00000000..0f53a0df --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/LikePostAdaptor.java @@ -0,0 +1,15 @@ +package likelion.univ.domain.post.adaptor; + +import likelion.univ.annotation.Adaptor; +import likelion.univ.domain.post.repository.LikePostRepository; +import lombok.RequiredArgsConstructor; + +@Adaptor +@RequiredArgsConstructor +public class LikePostAdaptor { + private final LikePostRepository likePostRepository; + + public Long countByPostId(Long postId){ + return likePostRepository.countByPostId(postId); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/LikePostRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/LikePostRepository.java new file mode 100644 index 00000000..fed16e41 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/LikePostRepository.java @@ -0,0 +1,8 @@ +package likelion.univ.domain.post.repository; + +import likelion.univ.domain.post.entity.LikePost; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LikePostRepository extends JpaRepository { + Long countByPostId(Long postId); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java index 909c8e83..dd16da2e 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java @@ -4,7 +4,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; public interface PostRepository extends JpaRepository { diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java index 07919901..0f102f61 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java @@ -21,11 +21,11 @@ public User findById(Long id){ } public User findByIdWithUniversity(Long id){ return userRepository.findByIdWithUniversity(id) - .orElseThrow(()-> new UserNotFoundException()); + .orElseThrow(() -> new UserNotFoundException()); } public User findByEmail(String email){ return userRepository.findByAuthInfoEmail(email) - .orElseThrow(()-> new UserNotFoundException()); + .orElseThrow(() -> new UserNotFoundException()); } public Boolean checkEmail(String email){ return userRepository.existsByAuthInfoEmail(email); diff --git a/likelion-core/src/main/resources/application-core.yml b/likelion-core/src/main/resources/application-core.yml index b68c9948..d212ccb8 100644 --- a/likelion-core/src/main/resources/application-core.yml +++ b/likelion-core/src/main/resources/application-core.yml @@ -5,6 +5,11 @@ spring: url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_NAME} username: ${MYSQL_USERNAME} password: ${MYSQL_PASSWORD} + + data: + web: + pageable: + one-indexed-parameters: true jpa: show-sql: true database: mysql diff --git a/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java b/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java index 1d40b4db..e1cd4590 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java +++ b/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java @@ -4,18 +4,24 @@ import org.springframework.data.redis.core.RedisTemplate; import java.util.Optional; +import java.util.concurrent.TimeUnit; + -@Slf4j public abstract class BaseRedisRepository { protected RedisTemplate redisTemplate; protected String prefix; + protected Long ttl; - public void save(Long id, T t) { - redisTemplate.opsForValue().set(generateKeyfromId(id), t); + public void save(Long id, T data) { + redisTemplate.opsForValue().set(generateKeyfromId(id), data, ttl, TimeUnit.SECONDS); } public Optional findById(Long id) { - return Optional.of(redisTemplate.opsForValue().get(generateKeyfromId(id))); + try{ + return Optional.of(redisTemplate.opsForValue().get(generateKeyfromId(id))); + }catch (NullPointerException e){ + return Optional.empty(); + } } public Boolean delete(Long id) { return redisTemplate.delete(generateKeyfromId(id)); diff --git a/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java b/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java index 98540ae3..1ab852f4 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java +++ b/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java @@ -46,7 +46,6 @@ private Map customConfigurationMap(RedisCacheCo Map customConfigurationMap = new HashMap<>(); customConfigurationMap.put(KAKAO_PUBLIC_KEYS, redisCacheConfiguration.entryTtl(Duration.ofDays(1L))); customConfigurationMap.put(GOOGLE_PUBLIC_KEYS, redisCacheConfiguration.entryTtl(Duration.ofDays(1L))); - customConfigurationMap.put(REFRESH_TOKEN, redisCacheConfiguration.entryTtl(Duration.ofDays(14L))); return customConfigurationMap; } } diff --git a/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java b/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java index 65d5c34e..c1d652fa 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java +++ b/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java @@ -7,5 +7,7 @@ public class RedisKey { public static final String GOOGLE_PUBLIC_KEYS = "googlePublicKeys"; public static final String REFRESH_TOKEN = "refreshToken"; - public static final int REFRESH_TOKEN_EXPIRE_SEC = 1209600; + public static final String POST_COUNT_INFO = "postCount"; + public static final Long REFRESH_TOKEN_EXPIRE_SEC = 1209600L; + public static final Long POST_COUNT_INFO_EXPIRE_SEC = 86400L; } diff --git a/likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java b/likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java new file mode 100644 index 00000000..b9e9b6e5 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java @@ -0,0 +1,19 @@ +package likelion.univ.post.dao; + +import likelion.univ.annotation.RedisRepository; +import likelion.univ.common.base.BaseRedisRepository; +import likelion.univ.post.entity.PostCountInfo; +import org.springframework.data.redis.core.RedisTemplate; + +import static likelion.univ.common.constant.RedisKey.POST_COUNT_INFO; +import static likelion.univ.common.constant.RedisKey.POST_COUNT_INFO_EXPIRE_SEC; + +@RedisRepository +public class PostCountInfoRedisDao extends BaseRedisRepository { + + public PostCountInfoRedisDao(RedisTemplate redisTemplate) { + this.prefix = POST_COUNT_INFO + ":"; + this.ttl = POST_COUNT_INFO_EXPIRE_SEC; + this.redisTemplate = redisTemplate; + } +} diff --git a/likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java b/likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java new file mode 100644 index 00000000..a7f2158f --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java @@ -0,0 +1,15 @@ +package likelion.univ.post.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PostCountInfo { + private Long commentCount; + private Long likeCount; +} diff --git a/likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java b/likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java new file mode 100644 index 00000000..7c3f23a4 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java @@ -0,0 +1,21 @@ +package likelion.univ.post.service; + +import likelion.univ.post.dao.PostCountInfoRedisDao; +import likelion.univ.post.entity.PostCountInfo; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PostCountInfoRedisService { + private final PostCountInfoRedisDao postCountInfoRedisDao; + + public PostCountInfo save(Long postId, Long commentCount, Long likeCount){ + PostCountInfo postCountInfo = PostCountInfo.builder() + .commentCount(commentCount) + .likeCount(likeCount) + .build(); + postCountInfoRedisDao.save(postId, postCountInfo); + return postCountInfo; + } +} diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java deleted file mode 100644 index 9cf0212c..00000000 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java +++ /dev/null @@ -1,21 +0,0 @@ -package likelion.univ.refreshtoken.adaptor; - -import likelion.univ.annotation.Adaptor; -import likelion.univ.refreshtoken.dao.RefreshTokenRedisDao; -import likelion.univ.refreshtoken.entity.RefreshToken; -import likelion.univ.refreshtoken.exception.ExpiredRefreshTokenException; -import lombok.RequiredArgsConstructor; - -@Adaptor -@RequiredArgsConstructor -public class RefreshTokenRedisAdaptor { - private final RefreshTokenRedisDao refreshTokenRedisDao; - - public void save(Long id, RefreshToken refreshToken){ - refreshTokenRedisDao.save(id, refreshToken); - } - public RefreshToken findById(Long id){ - return refreshTokenRedisDao.findById(id) - .orElseThrow(() -> new ExpiredRefreshTokenException()); - } -} diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java index a3d2da2e..836be70f 100644 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java +++ b/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java @@ -3,17 +3,17 @@ import likelion.univ.annotation.RedisRepository; import likelion.univ.common.base.BaseRedisRepository; import likelion.univ.refreshtoken.entity.RefreshToken; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; import static likelion.univ.common.constant.RedisKey.REFRESH_TOKEN; +import static likelion.univ.common.constant.RedisKey.REFRESH_TOKEN_EXPIRE_SEC; @RedisRepository public class RefreshTokenRedisDao extends BaseRedisRepository { - @Autowired + public RefreshTokenRedisDao(RedisTemplate redisTemplate) { this.prefix = REFRESH_TOKEN + ":"; + this.ttl = REFRESH_TOKEN_EXPIRE_SEC; this.redisTemplate = redisTemplate; } } diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java index f4faccb3..a00e2d38 100644 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java +++ b/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java @@ -13,7 +13,6 @@ @Builder public class RefreshToken { - private Long userId; private String token; } diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java index b44d6809..4545a42d 100644 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java +++ b/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java @@ -1,28 +1,27 @@ package likelion.univ.refreshtoken.service; -import likelion.univ.refreshtoken.adaptor.RefreshTokenRedisAdaptor; +import likelion.univ.refreshtoken.dao.RefreshTokenRedisDao; import likelion.univ.refreshtoken.entity.RefreshToken; +import likelion.univ.refreshtoken.exception.ExpiredRefreshTokenException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -@Slf4j public class RefreshTokenRedisService { - private final RefreshTokenRedisAdaptor refreshTokenRedisAdaptor; - + private final RefreshTokenRedisDao refreshTokenRedisDao; public void save(Long id, String token){ RefreshToken refreshToken = RefreshToken.builder() .userId(id) .token(token) .build(); - refreshTokenRedisAdaptor.save(id, refreshToken); + refreshTokenRedisDao.save(id, refreshToken); } public Boolean checkToken(Long id, String token){ - RefreshToken refreshToken = refreshTokenRedisAdaptor.findById(id); + RefreshToken refreshToken = refreshTokenRedisDao.findById(id) + .orElseThrow(() -> new ExpiredRefreshTokenException()); if(token.equals(refreshToken.getToken())) return true; else return false; } From 7ab4d76534b85f44af7d157b1c5008634b840e4f Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Mon, 30 Oct 2023 15:47:10 +0900 Subject: [PATCH 22/30] =?UTF-8?q?feat=20:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=8C=93=EA=B8=80=EC=93=B4=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/LikelionClientApplication.java | 4 + .../mypage/controller/MypageController.java | 29 +++--- .../mypage/dto/response/MyPagePostsDto.java | 12 +++ .../mypage/scheduler/MyPageScheduler.java | 4 + ...stsUseCase.java => GetMyPostsUseCase.java} | 2 +- .../usecase/GetPostsCommentedByMeUseCase.java | 52 +++++++++++ .../univ/domain/post/adaptor/PostAdaptor.java | 8 +- .../post/repository/PostCustomRepository.java | 21 ++--- .../repository/PostCustomRepositoryImpl.java | 89 +++++++++++++------ .../post/repository/PostRepository.java | 2 +- 10 files changed, 161 insertions(+), 62 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/scheduler/MyPageScheduler.java rename likelion-client/src/main/java/likelion/univ/mypage/usecase/{GetMypagePostsUseCase.java => GetMyPostsUseCase.java} (98%) create mode 100644 likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java diff --git a/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java b/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java index f4beb2af..e6ed9749 100644 --- a/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java +++ b/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java @@ -4,9 +4,13 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; @EnableCaching @EnableJpaAuditing +@EnableScheduling +@EnableAsync @SpringBootApplication public class LikelionClientApplication { diff --git a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java b/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java index e106c120..aa21e403 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java @@ -2,22 +2,15 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import likelion.univ.auth.dto.request.SignUpRequestDto; -import likelion.univ.auth.dto.response.AccountTokenDto; -import likelion.univ.auth.dto.response.IdTokenDto; -import likelion.univ.auth.usecase.LoginUseCase; -import likelion.univ.auth.usecase.RefreshTokenUseCase; -import likelion.univ.auth.usecase.RequestIdTokenUseCase; -import likelion.univ.auth.usecase.SignUpUseCase; import likelion.univ.common.page.PageResponse; import likelion.univ.mypage.dto.response.MyPagePostsDto; import likelion.univ.mypage.dto.response.ProfileDetailsDto; -import likelion.univ.mypage.usecase.GetMypagePostsUseCase; +import likelion.univ.mypage.usecase.GetMyPostsUseCase; +import likelion.univ.mypage.usecase.GetPostsCommentedByMeUseCase; import likelion.univ.mypage.usecase.GetProfileUseCase; import likelion.univ.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springdoc.api.annotations.ParameterObject; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.web.bind.annotation.*; @@ -28,7 +21,8 @@ @Tag(name = "마이페이지", description = "마이페이지관련 API입니다.") public class MypageController { private final GetProfileUseCase getProfileUseCase; - private final GetMypagePostsUseCase getMypagePostsUseCase; + private final GetMyPostsUseCase getMyPostsUseCase; + private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; @Operation(summary = "마이페이지 프로필 조회", description = "본인의 프로필 정보를 조회합니다.") @GetMapping("/profile") @@ -40,9 +34,15 @@ public SuccessResponse getProfile(){ @Operation(summary = "내가쓴 게시글 조회", description = "작성한 게시글을 조회합니다.") @GetMapping("/posts") public SuccessResponse getMyPosts(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ - PageResponse myPagePostsPage = getMypagePostsUseCase.execute(pageable); + PageResponse myPagePostsPage = getMyPostsUseCase.execute(pageable); return SuccessResponse.of(myPagePostsPage); } + @Operation(summary = "내가 댓글 쓴 게시글 조회", description = "댓글을 작성한 게시글을 조회합니다.") + @GetMapping("/comments") + public SuccessResponse getPostsCommentedByMe(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + PageResponse myPagePostsPageCommentedByMe = getPostsCommentedByMeUseCase.execute(pageable); + return SuccessResponse.of(myPagePostsPageCommentedByMe); + } // @Operation(summary = "내가 참여한 프로젝트 조회", description = "참여한 프로젝트를 조회합니다.") // @GetMapping("/projects") @@ -51,13 +51,6 @@ public SuccessResponse getMyPosts(@ParameterObject @PageableDefault(size // return SuccessResponse.of(); // } // -// @Operation(summary = "내가쓴 댓글 조회", description = "작성한 댓글을 조회합니다.") -// @GetMapping("/comments") -// public SuccessResponse getMyComments(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ -// -// return SuccessResponse.of(); -// } - // @Operation(summary = "휴대폰 인증 요청", description = "휴대폰 번호 인증을 위해 서버 내부에 인증번호를 생성합니다.") // @PostMapping("/phone/certify") // public SuccessResponse login(@RequestParam("phonenum") String phoneNum){ diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java index 6b8979c1..0112c2a9 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java @@ -31,4 +31,16 @@ public static MyPagePostsDto of(Post post, Long likeCount, Long commentCount){ .commentCount(commentCount) .build(); } + public static MyPagePostsDto withAuthorOf(Post post, Long likeCount, Long commentCount, Boolean isAuthor){ + return MyPagePostsDto.builder() + .id(post.getId()) + .title(post.getTitle()) + .body(post.getBody()) + .thumbnail(post.getThumbnail()) + .isAuthor(isAuthor) + .createdDate(post.getCreatedDate().toLocalDate()) + .likeCount(likeCount) + .commentCount(commentCount) + .build(); + } } diff --git a/likelion-client/src/main/java/likelion/univ/mypage/scheduler/MyPageScheduler.java b/likelion-client/src/main/java/likelion/univ/mypage/scheduler/MyPageScheduler.java new file mode 100644 index 00000000..bf8c6631 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/scheduler/MyPageScheduler.java @@ -0,0 +1,4 @@ +package likelion.univ.mypage.scheduler; + +//public class MyPageScheduler { +//} diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMyPostsUseCase.java similarity index 98% rename from likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java rename to likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMyPostsUseCase.java index 12f1ea69..5b903e52 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMypagePostsUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMyPostsUseCase.java @@ -19,7 +19,7 @@ @UseCase @RequiredArgsConstructor -public class GetMypagePostsUseCase { +public class GetMyPostsUseCase { private final AuthentiatedUserUtils authentiatedUserUtils; private final PostAdaptor postAdaptor; diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java new file mode 100644 index 00000000..9a59c5da --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java @@ -0,0 +1,52 @@ +package likelion.univ.mypage.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.page.PageResponse; +import likelion.univ.domain.comment.adaptor.CommentAdaptor; +import likelion.univ.domain.post.adaptor.LikePostAdaptor; +import likelion.univ.domain.post.adaptor.PostAdaptor; +import likelion.univ.domain.post.entity.Post; +import likelion.univ.mypage.dto.response.MyPagePostsDto; +import likelion.univ.post.dao.PostCountInfoRedisDao; +import likelion.univ.post.entity.PostCountInfo; +import likelion.univ.post.service.PostCountInfoRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class GetPostsCommentedByMeUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final PostAdaptor postAdaptor; + private final PostCountInfoRedisDao postCountInfoRedisDao; + private final PostCountInfoRedisService postCountInfoRedisService; + private final CommentAdaptor commentAdaptor; + private final LikePostAdaptor likePostAdaptor; + + public PageResponse execute(Pageable pageable){ + Long userId = authentiatedUserUtils.getCurrentUserId(); + Page posts = postAdaptor.findByCommentAuthorId(userId, pageable); + + return PageResponse.of(posts.map(p-> createDto(p, userId))); + } + + private MyPagePostsDto createDto(Post post, Long userId){ + PostCountInfo postCountInfo = getPostCountInfo(post.getId()); + if(post.getAuthor().getId().equals(userId)) + return MyPagePostsDto.withAuthorOf(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),true); + else return MyPagePostsDto.withAuthorOf(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),false); + } + + private PostCountInfo getPostCountInfo(Long postId){ + Optional postCountInfo = postCountInfoRedisDao.findById(postId); + if(postCountInfo.isEmpty()){ + Long commentCount = commentAdaptor.countByPostId(postId); + Long likeCount = likePostAdaptor.countByPostId(postId); + return postCountInfoRedisService.save(postId, commentCount, likeCount); + }else return postCountInfo.get(); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java index be2e3d00..d7d033d8 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java @@ -12,10 +12,7 @@ @RequiredArgsConstructor public class PostAdaptor { - @Autowired - private PostRepository postRepository; -// @Autowired -// private PostCustomRepository postCustomRepository; + private final PostRepository postRepository; public void save(Post post) { @@ -34,6 +31,9 @@ public Page findAllByAuthor_Id(Long userId, Pageable pageable){ return postRepository.findAllByAuthor_Id(userId,pageable); } + public Page findByCommentAuthorId(Long userId, Pageable pageable){ + return postRepository.findByCommentAuthorId(userId,pageable); + } // public List retrievePostPaging(Integer page, Integer limit) { // return postCustomRepository.pagingWithCoveringIndex(page, limit); // } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java index bb8e6bb8..df89f942 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java @@ -1,10 +1,11 @@ -//package likelion.univ.domain.community.post.repository; -// -//import likelion.univ.domain.community.post.entity.Post; -// -//import java.util.List; -// -//public interface PostCustomRepository { -// -// public List pagingWithCoveringIndex(Integer page, Integer limit); -//} +package likelion.univ.domain.post.repository; + +import likelion.univ.domain.post.entity.Post; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface PostCustomRepository { + +// public List pagingWithCoveringIndex(Integer page, Integer limit);\ + public Page findByCommentAuthorId(Long userId, Pageable pageable); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java index 07560d90..c8f6d84b 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java @@ -1,33 +1,66 @@ -//package likelion.univ.domain.community.post.repository; -// -//import com.querydsl.jpa.impl.JPAQueryFactory; -//import likelion.univ.domain.community.post.entity.Post; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.stereotype.Repository; -// -//import java.util.List; -// -//@Repository -//public class PostCustomRepositoryImpl implements PostCustomRepository{ -// @Autowired -// private JPAQueryFactory jpaQueryFactory; -// +package likelion.univ.domain.post.repository; + +import com.querydsl.core.types.Predicate; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import likelion.univ.domain.post.entity.Post; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +import java.util.List; + +import static likelion.univ.domain.comment.entity.QComment.comment; +import static likelion.univ.domain.post.entity.QPost.post; +import static likelion.univ.domain.user.entity.QUser.user; + +@RequiredArgsConstructor +@Repository +public class PostCustomRepositoryImpl implements PostCustomRepository { + + private final JPAQueryFactory queryFactory; + + private List getCoveringIndexByComment(Predicate predicate) { + return queryFactory.select(comment.post.id).from(comment).where(predicate).fetch(); + } + @Override + public Page findByCommentAuthorId(Long userId, Pageable pageable){ + List ids = getCoveringIndexByComment(comment.author.id.eq(userId)); + List posts = + queryFactory + .select(post) + .from(post) + .innerJoin(user) + .on(post.author.id.eq(user.id)) + .where(post.id.in(ids)) + .offset(pageable.getOffset()) + .orderBy(post.createdDate.desc()) + .limit(pageable.getPageSize()) + .fetch(); + + return new PageImpl<>(posts, pageable, ids.size()); + } + + + // @Override // public List pagingWithCoveringIndex(Integer page, Integer limit) { // // return null; -//// List ids = jpaQueryFactory -//// .select(post.id) -//// .from(post) -//// .limit(limit) -//// .offset(page * limit) -//// .fetch(); -//// -//// return jpaQueryFactory -//// .selectFrom(post) -//// .innerJoin(post.author, user) -//// .fetchJoin() -//// .where(post.id.in(ids)) -//// .fetch(); +// List ids = jpaQueryFactory +// .select(post.id) +// .from(post) +// .limit(limit) +// .offset(page * limit) +// .fetch(); +// +// return jpaQueryFactory +// .selectFrom(post) +// .innerJoin(post.author, user) +// .fetchJoin() +// .where(post.id.in(ids)) +// .fetch(); // } -//} +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java index dd16da2e..7a90a579 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java @@ -5,7 +5,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -public interface PostRepository extends JpaRepository { +public interface PostRepository extends JpaRepository, PostCustomRepository { Page findAllByAuthor_Id(Long userId, Pageable pageable); } From ed122a1ca3bdae3162be47a1cbe6c89844044b96 Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Tue, 31 Oct 2023 13:05:56 +0900 Subject: [PATCH 23/30] =?UTF-8?q?fix=20:=20=EB=8C=93=EA=B8=80=EB=A1=9C=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=B0=BE=EA=B8=B0=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/domain/post/repository/PostCustomRepositoryImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java index c8f6d84b..8d26acfc 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java @@ -32,8 +32,7 @@ public Page findByCommentAuthorId(Long userId, Pageable pageable){ queryFactory .select(post) .from(post) - .innerJoin(user) - .on(post.author.id.eq(user.id)) + .innerJoin(post.author, user).fetchJoin() .where(post.id.in(ids)) .offset(pageable.getOffset()) .orderBy(post.createdDate.desc()) From e45f98e9e3e32fdc70beacd0ba17687f13c1267a Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Tue, 31 Oct 2023 15:00:02 +0900 Subject: [PATCH 24/30] =?UTF-8?q?refactor=20:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9C=A0=EC=A0=80=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20api=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/dto/response/AccountUserInfoDto.java | 2 + ...ageController.java => UserController.java} | 38 ++++++++++--------- .../dto/response/ProfileDetailsDto.java | 4 +- ...agePostsDto.java => UserPagePostsDto.java} | 18 ++------- ...eScheduler.java => UserPageScheduler.java} | 0 .../usecase/GetPostsCommentedByMeUseCase.java | 14 +++---- .../mypage/usecase/GetProfileUseCase.java | 10 +++-- ...sUseCase.java => GetUserPostsUseCase.java} | 16 ++++---- 8 files changed, 50 insertions(+), 52 deletions(-) rename likelion-client/src/main/java/likelion/univ/mypage/controller/{MypageController.java => UserController.java} (60%) rename likelion-client/src/main/java/likelion/univ/mypage/dto/response/{MyPagePostsDto.java => UserPagePostsDto.java} (53%) rename likelion-client/src/main/java/likelion/univ/mypage/scheduler/{MyPageScheduler.java => UserPageScheduler.java} (100%) rename likelion-client/src/main/java/likelion/univ/mypage/usecase/{GetMyPostsUseCase.java => GetUserPostsUseCase.java} (71%) diff --git a/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java b/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java index a7ec8fc7..5553f3f9 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java +++ b/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java @@ -7,11 +7,13 @@ @Getter @Builder public class AccountUserInfoDto { + private Long userId; private String profileImage; private String name; public static AccountUserInfoDto of(User user){ return AccountUserInfoDto.builder() + .userId(user.getId()) .profileImage(user.getProfile().getProfileImage()) .name(user.getProfile().getName()) .build(); diff --git a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java b/likelion-client/src/main/java/likelion/univ/mypage/controller/UserController.java similarity index 60% rename from likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java rename to likelion-client/src/main/java/likelion/univ/mypage/controller/UserController.java index aa21e403..4b7fe4fe 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/controller/MypageController.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/controller/UserController.java @@ -3,9 +3,9 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import likelion.univ.common.page.PageResponse; -import likelion.univ.mypage.dto.response.MyPagePostsDto; +import likelion.univ.mypage.dto.response.UserPagePostsDto; import likelion.univ.mypage.dto.response.ProfileDetailsDto; -import likelion.univ.mypage.usecase.GetMyPostsUseCase; +import likelion.univ.mypage.usecase.GetUserPostsUseCase; import likelion.univ.mypage.usecase.GetPostsCommentedByMeUseCase; import likelion.univ.mypage.usecase.GetProfileUseCase; import likelion.univ.response.SuccessResponse; @@ -17,30 +17,32 @@ @RestController @RequiredArgsConstructor -@RequestMapping(value = "/v1/mypage") -@Tag(name = "마이페이지", description = "마이페이지관련 API입니다.") -public class MypageController { +@RequestMapping(value = "/v1/user") +@Tag(name = "유저페이지", description = "유저페이지관련 API입니다.") +public class UserController { private final GetProfileUseCase getProfileUseCase; - private final GetMyPostsUseCase getMyPostsUseCase; + private final GetUserPostsUseCase getMyPostsUseCase; private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; - @Operation(summary = "마이페이지 프로필 조회", description = "본인의 프로필 정보를 조회합니다.") - @GetMapping("/profile") - public SuccessResponse getProfile(){ - ProfileDetailsDto profileDetailsDto = getProfileUseCase.execute(); + @Operation(summary = "유저페이지 프로필 조회", description = "해당 유저의 프로필 정보를 조회합니다.") + @GetMapping("/{userId}/profile") + public SuccessResponse getProfile(@PathVariable Long userId){ + ProfileDetailsDto profileDetailsDto = getProfileUseCase.execute(userId); return SuccessResponse.of(profileDetailsDto); } - @Operation(summary = "내가쓴 게시글 조회", description = "작성한 게시글을 조회합니다.") - @GetMapping("/posts") - public SuccessResponse getMyPosts(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ - PageResponse myPagePostsPage = getMyPostsUseCase.execute(pageable); + @Operation(summary = "해당 유저가 쓴 게시글 조회", description = "해당 유저가 작성한 게시글을 조회합니다.") + @GetMapping("/{userId}/posts") + public SuccessResponse getMyPosts(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + PageResponse myPagePostsPage = getMyPostsUseCase.execute(userId, pageable); return SuccessResponse.of(myPagePostsPage); } - @Operation(summary = "내가 댓글 쓴 게시글 조회", description = "댓글을 작성한 게시글을 조회합니다.") - @GetMapping("/comments") - public SuccessResponse getPostsCommentedByMe(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ - PageResponse myPagePostsPageCommentedByMe = getPostsCommentedByMeUseCase.execute(pageable); + @Operation(summary = "해당 유저가 댓글 쓴 게시글 조회", description = "해당 유저가 댓글을 작성한 게시글을 조회합니다.") + @GetMapping("/{userId}/comments") + public SuccessResponse getPostsCommentedByMe(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + PageResponse myPagePostsPageCommentedByMe = getPostsCommentedByMeUseCase.execute(userId, pageable); return SuccessResponse.of(myPagePostsPageCommentedByMe); } diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java index f7c4c35e..ca72cbd9 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java @@ -17,8 +17,9 @@ public class ProfileDetailsDto { private Long followerNum; private Long followingNum; private String introduction; + private Boolean isMine; - public static ProfileDetailsDto of(User user, Long followerNum, Long followingNum){ + public static ProfileDetailsDto of(User user, Boolean isMine,Long followerNum, Long followingNum){ return ProfileDetailsDto.builder() .profileImage(user.getProfile().getProfileImage()) .name(user.getProfile().getName()) @@ -30,6 +31,7 @@ public static ProfileDetailsDto of(User user, Long followerNum, Long followingNu .followerNum(followerNum) .followingNum(followingNum) .introduction(user.getProfile().getIntroduction()) + .isMine(isMine) .build(); } } diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/UserPagePostsDto.java similarity index 53% rename from likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java rename to likelion-client/src/main/java/likelion/univ/mypage/dto/response/UserPagePostsDto.java index 0112c2a9..fbafa824 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/MyPagePostsDto.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/dto/response/UserPagePostsDto.java @@ -9,7 +9,7 @@ @Getter @Builder -public class MyPagePostsDto { +public class UserPagePostsDto { private Long id; private String title; private String body; @@ -19,20 +19,8 @@ public class MyPagePostsDto { private Long likeCount; private Long commentCount; - public static MyPagePostsDto of(Post post, Long likeCount, Long commentCount){ - return MyPagePostsDto.builder() - .id(post.getId()) - .title(post.getTitle()) - .body(post.getBody()) - .thumbnail(post.getThumbnail()) - .isAuthor(true) - .createdDate(post.getCreatedDate().toLocalDate()) - .likeCount(likeCount) - .commentCount(commentCount) - .build(); - } - public static MyPagePostsDto withAuthorOf(Post post, Long likeCount, Long commentCount, Boolean isAuthor){ - return MyPagePostsDto.builder() + public static UserPagePostsDto of(Post post, Long likeCount, Long commentCount, Boolean isAuthor){ + return UserPagePostsDto.builder() .id(post.getId()) .title(post.getTitle()) .body(post.getBody()) diff --git a/likelion-client/src/main/java/likelion/univ/mypage/scheduler/MyPageScheduler.java b/likelion-client/src/main/java/likelion/univ/mypage/scheduler/UserPageScheduler.java similarity index 100% rename from likelion-client/src/main/java/likelion/univ/mypage/scheduler/MyPageScheduler.java rename to likelion-client/src/main/java/likelion/univ/mypage/scheduler/UserPageScheduler.java diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java index 9a59c5da..72e9730b 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java @@ -6,7 +6,7 @@ import likelion.univ.domain.post.adaptor.LikePostAdaptor; import likelion.univ.domain.post.adaptor.PostAdaptor; import likelion.univ.domain.post.entity.Post; -import likelion.univ.mypage.dto.response.MyPagePostsDto; +import likelion.univ.mypage.dto.response.UserPagePostsDto; import likelion.univ.post.dao.PostCountInfoRedisDao; import likelion.univ.post.entity.PostCountInfo; import likelion.univ.post.service.PostCountInfoRedisService; @@ -27,18 +27,18 @@ public class GetPostsCommentedByMeUseCase { private final CommentAdaptor commentAdaptor; private final LikePostAdaptor likePostAdaptor; - public PageResponse execute(Pageable pageable){ - Long userId = authentiatedUserUtils.getCurrentUserId(); + public PageResponse execute(Long userId, Pageable pageable){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); Page posts = postAdaptor.findByCommentAuthorId(userId, pageable); - return PageResponse.of(posts.map(p-> createDto(p, userId))); + return PageResponse.of(posts.map(p-> createDto(p, currentUserId))); } - private MyPagePostsDto createDto(Post post, Long userId){ + private UserPagePostsDto createDto(Post post, Long userId){ PostCountInfo postCountInfo = getPostCountInfo(post.getId()); if(post.getAuthor().getId().equals(userId)) - return MyPagePostsDto.withAuthorOf(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),true); - else return MyPagePostsDto.withAuthorOf(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),false); + return UserPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),true); + else return UserPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),false); } private PostCountInfo getPostCountInfo(Long postId){ diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java index 8a8c6251..38917535 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java @@ -15,13 +15,15 @@ public class GetProfileUseCase { private final UserAdaptor userAdaptor; private final FolllowAdaptor folllowAdaptor; - public ProfileDetailsDto execute(){ - Long userId = authentiatedUserUtils.getCurrentUserId(); + public ProfileDetailsDto execute(Long userId){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); User user = userAdaptor.findByIdWithUniversity(userId); - /*임시로 카운트쿼리로.. */ + /* 임시로 카운트쿼리로.. */ Long followerNum = folllowAdaptor.countByFolloweeId(userId); Long followingNum = folllowAdaptor.countByFollowerId(userId); - return ProfileDetailsDto.of(user, followerNum, followingNum); + if (userId.equals(currentUserId)) + return ProfileDetailsDto.of(user, true, followerNum, followingNum); + else return ProfileDetailsDto.of(user, false, followerNum, followingNum); } } diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMyPostsUseCase.java b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetUserPostsUseCase.java similarity index 71% rename from likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMyPostsUseCase.java rename to likelion-client/src/main/java/likelion/univ/mypage/usecase/GetUserPostsUseCase.java index 5b903e52..64eb6986 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetMyPostsUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetUserPostsUseCase.java @@ -6,7 +6,7 @@ import likelion.univ.domain.post.adaptor.LikePostAdaptor; import likelion.univ.domain.post.adaptor.PostAdaptor; import likelion.univ.domain.post.entity.Post; -import likelion.univ.mypage.dto.response.MyPagePostsDto; +import likelion.univ.mypage.dto.response.UserPagePostsDto; import likelion.univ.post.dao.PostCountInfoRedisDao; import likelion.univ.post.entity.PostCountInfo; import likelion.univ.post.service.PostCountInfoRedisService; @@ -19,7 +19,7 @@ @UseCase @RequiredArgsConstructor -public class GetMyPostsUseCase { +public class GetUserPostsUseCase { private final AuthentiatedUserUtils authentiatedUserUtils; private final PostAdaptor postAdaptor; @@ -28,16 +28,18 @@ public class GetMyPostsUseCase { private final CommentAdaptor commentAdaptor; private final LikePostAdaptor likePostAdaptor; - public PageResponse execute(Pageable pageable){ - Long userId = authentiatedUserUtils.getCurrentUserId(); + public PageResponse execute(Long userId, Pageable pageable){ + Long currentUserIdId = authentiatedUserUtils.getCurrentUserId(); Page posts = postAdaptor.findAllByAuthor_Id(userId, pageable); - return PageResponse.of(posts.map(p-> createDto(p))); + return PageResponse.of(posts.map(p-> createDto(p, currentUserIdId))); } - private MyPagePostsDto createDto(Post post){ + private UserPagePostsDto createDto(Post post, Long userId){ PostCountInfo postCountInfo = getPostCountInfo(post.getId()); - return MyPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount()); + if(post.getAuthor().getId().equals(userId)) + return UserPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),true); + else return UserPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),false); } private PostCountInfo getPostCountInfo(Long postId){ From cecff73bdf01aa7126c91d7b8756d7680098ebe2 Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Mon, 6 Nov 2023 15:40:33 +0900 Subject: [PATCH 25/30] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mypage/scheduler/UserPageScheduler.java | 4 --- .../controller/UserController.java | 24 +++++++++---- .../dto/request/ProfileEditRequestDto.java | 36 +++++++++++++++++++ .../dto/response/ProfileDetailsDto.java | 6 +++- .../dto/response/UserPagePostsDto.java | 2 +- .../user/scheduler/UserPageScheduler.java | 4 +++ .../univ/user/usecase/EditProfileUseCase.java | 24 +++++++++++++ .../usecase/GetPostsCommentedByMeUseCase.java | 6 ++-- .../usecase/GetProfileUseCase.java | 4 +-- .../usecase/GetUserPostsUseCase.java | 6 ++-- .../univ/utils/AuthentiatedUserUtils.java | 6 ++++ .../{page => response}/PageResponse.java | 2 +- .../domain/user/entity/UniversityInfo.java | 1 - .../univ/domain/user/entity/User.java | 3 ++ .../domain/user/exception/UserErrorCode.java | 4 +-- .../user/exception/UserNotMatchException.java | 10 ++++++ .../user/service/UserDomainService.java | 6 ++++ 17 files changed, 123 insertions(+), 25 deletions(-) delete mode 100644 likelion-client/src/main/java/likelion/univ/mypage/scheduler/UserPageScheduler.java rename likelion-client/src/main/java/likelion/univ/{mypage => user}/controller/UserController.java (76%) create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java rename likelion-client/src/main/java/likelion/univ/{mypage => user}/dto/response/ProfileDetailsDto.java (87%) rename likelion-client/src/main/java/likelion/univ/{mypage => user}/dto/response/UserPagePostsDto.java (95%) create mode 100644 likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java rename likelion-client/src/main/java/likelion/univ/{mypage => user}/usecase/GetPostsCommentedByMeUseCase.java (93%) rename likelion-client/src/main/java/likelion/univ/{mypage => user}/usecase/GetProfileUseCase.java (91%) rename likelion-client/src/main/java/likelion/univ/{mypage => user}/usecase/GetUserPostsUseCase.java (93%) rename likelion-core/src/main/java/likelion/univ/common/{page => response}/PageResponse.java (95%) create mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java diff --git a/likelion-client/src/main/java/likelion/univ/mypage/scheduler/UserPageScheduler.java b/likelion-client/src/main/java/likelion/univ/mypage/scheduler/UserPageScheduler.java deleted file mode 100644 index bf8c6631..00000000 --- a/likelion-client/src/main/java/likelion/univ/mypage/scheduler/UserPageScheduler.java +++ /dev/null @@ -1,4 +0,0 @@ -package likelion.univ.mypage.scheduler; - -//public class MyPageScheduler { -//} diff --git a/likelion-client/src/main/java/likelion/univ/mypage/controller/UserController.java b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java similarity index 76% rename from likelion-client/src/main/java/likelion/univ/mypage/controller/UserController.java rename to likelion-client/src/main/java/likelion/univ/user/controller/UserController.java index 4b7fe4fe..f85b6299 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/controller/UserController.java +++ b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java @@ -1,13 +1,15 @@ -package likelion.univ.mypage.controller; +package likelion.univ.user.controller; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import likelion.univ.common.page.PageResponse; -import likelion.univ.mypage.dto.response.UserPagePostsDto; -import likelion.univ.mypage.dto.response.ProfileDetailsDto; -import likelion.univ.mypage.usecase.GetUserPostsUseCase; -import likelion.univ.mypage.usecase.GetPostsCommentedByMeUseCase; -import likelion.univ.mypage.usecase.GetProfileUseCase; +import likelion.univ.common.response.PageResponse; +import likelion.univ.user.dto.request.ProfileEditRequestDto; +import likelion.univ.user.dto.response.UserPagePostsDto; +import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.user.usecase.EditProfileUseCase; +import likelion.univ.user.usecase.GetUserPostsUseCase; +import likelion.univ.user.usecase.GetPostsCommentedByMeUseCase; +import likelion.univ.user.usecase.GetProfileUseCase; import likelion.univ.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springdoc.api.annotations.ParameterObject; @@ -21,6 +23,7 @@ @Tag(name = "유저페이지", description = "유저페이지관련 API입니다.") public class UserController { private final GetProfileUseCase getProfileUseCase; + private final EditProfileUseCase editProfileUseCase; private final GetUserPostsUseCase getMyPostsUseCase; private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; @@ -30,6 +33,13 @@ public SuccessResponse getProfile(@PathVariable Long userId){ ProfileDetailsDto profileDetailsDto = getProfileUseCase.execute(userId); return SuccessResponse.of(profileDetailsDto); } + @Operation(summary = "유저페이지 프로필 수정", description = "해당 유저의 프로필 정보를 수정합니다.") + @PatchMapping("/{userId}/profile") + public SuccessResponse editProfile(@PathVariable Long userId, + @RequestBody ProfileEditRequestDto profileEditRequestDto){ + editProfileUseCase.execute(userId,profileEditRequestDto); + return SuccessResponse.empty(); + } @Operation(summary = "해당 유저가 쓴 게시글 조회", description = "해당 유저가 작성한 게시글을 조회합니다.") @GetMapping("/{userId}/posts") diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java new file mode 100644 index 00000000..58eeab0d --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java @@ -0,0 +1,36 @@ +package likelion.univ.user.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import likelion.univ.domain.user.entity.Part; +import likelion.univ.domain.user.entity.Profile; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + + +@Getter +@NoArgsConstructor +public class ProfileEditRequestDto { + @NotNull + @Schema(description = "이름", example = "김슬기", required = true) + private String name; + + @Schema(description = "한줄 소개", example = "안녕하세요. 김슬기입니다.", required = false) + private String introduction; + + @Schema(description = "프로필 이미지", example = "", required = false) + private String profileImage; + + @NotNull + @Schema(description = "트랙(파트)", example = "BACKEND", required = true) + private Part part; + + public Profile toProfile(){ + return Profile.builder() + .name(name) + .profileImage(profileImage) + .introduction(introduction) + .part(part) + .build(); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java similarity index 87% rename from likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java rename to likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java index ca72cbd9..de0b2128 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/ProfileDetailsDto.java +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java @@ -1,4 +1,4 @@ -package likelion.univ.mypage.dto.response; +package likelion.univ.user.dto.response; import likelion.univ.domain.user.entity.User; import lombok.Builder; @@ -7,6 +7,7 @@ @Getter @Builder public class ProfileDetailsDto { + private Long id; private String profileImage; private String name; private String role; @@ -14,6 +15,7 @@ public class ProfileDetailsDto { private String universityName; private String major; private Long ordinal; + private String part; private Long followerNum; private Long followingNum; private String introduction; @@ -21,6 +23,7 @@ public class ProfileDetailsDto { public static ProfileDetailsDto of(User user, Boolean isMine,Long followerNum, Long followingNum){ return ProfileDetailsDto.builder() + .id(user.getId()) .profileImage(user.getProfile().getProfileImage()) .name(user.getProfile().getName()) .role(user.getAuthInfo().getRole().getValue()) @@ -28,6 +31,7 @@ public static ProfileDetailsDto of(User user, Boolean isMine,Long followerNum, L .universityName(user.getUniversityInfo().getUniversity().getName()) .major(user.getUniversityInfo().getMajor()) .ordinal(user.getUniversityInfo().getOrdinal()) + .part(user.getProfile().getPart().toString()) .followerNum(followerNum) .followingNum(followingNum) .introduction(user.getProfile().getIntroduction()) diff --git a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/UserPagePostsDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java similarity index 95% rename from likelion-client/src/main/java/likelion/univ/mypage/dto/response/UserPagePostsDto.java rename to likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java index fbafa824..a1d29035 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/dto/response/UserPagePostsDto.java +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java @@ -1,4 +1,4 @@ -package likelion.univ.mypage.dto.response; +package likelion.univ.user.dto.response; import likelion.univ.domain.post.entity.Post; import lombok.Builder; diff --git a/likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java b/likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java new file mode 100644 index 00000000..45bb7cd9 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java @@ -0,0 +1,4 @@ +package likelion.univ.user.scheduler; + +//public class MyPageScheduler { +//} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java new file mode 100644 index 00000000..0b9df489 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java @@ -0,0 +1,24 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.user.entity.Profile; +import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.service.UserDomainService; +import likelion.univ.user.dto.request.ProfileEditRequestDto; +import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class EditProfileUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final UserDomainService userDomainService; + + public void execute(Long userId, ProfileEditRequestDto profileEditRequestDto){ + authentiatedUserUtils.checkidentification(userId); + + Profile profile = profileEditRequestDto.toProfile(); + User user = userDomainService.editProfile(userId, profile); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java similarity index 93% rename from likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java rename to likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java index 72e9730b..f012e4c5 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetPostsCommentedByMeUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java @@ -1,12 +1,12 @@ -package likelion.univ.mypage.usecase; +package likelion.univ.user.usecase; import likelion.univ.annotation.UseCase; -import likelion.univ.common.page.PageResponse; +import likelion.univ.common.response.PageResponse; import likelion.univ.domain.comment.adaptor.CommentAdaptor; import likelion.univ.domain.post.adaptor.LikePostAdaptor; import likelion.univ.domain.post.adaptor.PostAdaptor; import likelion.univ.domain.post.entity.Post; -import likelion.univ.mypage.dto.response.UserPagePostsDto; +import likelion.univ.user.dto.response.UserPagePostsDto; import likelion.univ.post.dao.PostCountInfoRedisDao; import likelion.univ.post.entity.PostCountInfo; import likelion.univ.post.service.PostCountInfoRedisService; diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java similarity index 91% rename from likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java rename to likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java index 38917535..8aa0b326 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetProfileUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java @@ -1,10 +1,10 @@ -package likelion.univ.mypage.usecase; +package likelion.univ.user.usecase; import likelion.univ.annotation.UseCase; import likelion.univ.domain.follow.adaptor.FolllowAdaptor; import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.User; -import likelion.univ.mypage.dto.response.ProfileDetailsDto; +import likelion.univ.user.dto.response.ProfileDetailsDto; import likelion.univ.utils.AuthentiatedUserUtils; import lombok.RequiredArgsConstructor; diff --git a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetUserPostsUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java similarity index 93% rename from likelion-client/src/main/java/likelion/univ/mypage/usecase/GetUserPostsUseCase.java rename to likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java index 64eb6986..3efeccdc 100644 --- a/likelion-client/src/main/java/likelion/univ/mypage/usecase/GetUserPostsUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java @@ -1,12 +1,12 @@ -package likelion.univ.mypage.usecase; +package likelion.univ.user.usecase; import likelion.univ.annotation.UseCase; -import likelion.univ.common.page.PageResponse; +import likelion.univ.common.response.PageResponse; import likelion.univ.domain.comment.adaptor.CommentAdaptor; import likelion.univ.domain.post.adaptor.LikePostAdaptor; import likelion.univ.domain.post.adaptor.PostAdaptor; import likelion.univ.domain.post.entity.Post; -import likelion.univ.mypage.dto.response.UserPagePostsDto; +import likelion.univ.user.dto.response.UserPagePostsDto; import likelion.univ.post.dao.PostCountInfoRedisDao; import likelion.univ.post.entity.PostCountInfo; import likelion.univ.post.service.PostCountInfoRedisService; diff --git a/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java b/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java index 489dc643..0bfc856f 100644 --- a/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java +++ b/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java @@ -2,6 +2,7 @@ import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.exception.UserNotMatchException; import likelion.univ.security.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -18,4 +19,9 @@ public Long getCurrentUserId() { public User getCurrentUser() { return userAdaptor.findById(getCurrentUserId()); } + + public void checkidentification(Long userId){ + if(!SecurityUtils.getCurrentUserId().equals(userId)) + throw new UserNotMatchException(); + } } diff --git a/likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java b/likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java similarity index 95% rename from likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java rename to likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java index f9ebedb7..07e35a10 100644 --- a/likelion-core/src/main/java/likelion/univ/common/page/PageResponse.java +++ b/likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java @@ -1,4 +1,4 @@ -package likelion.univ.common.page; +package likelion.univ.common.response; import lombok.Builder; import lombok.Getter; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java index 617d9871..aa526c61 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java @@ -14,7 +14,6 @@ @AllArgsConstructor @Builder public class UniversityInfo { - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "university_id") private University university; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java index 25746000..0cb05815 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java @@ -27,4 +27,7 @@ public class User extends BaseTimeEntity{ @Embedded private AuthInfo authInfo; + public void editProfile(Profile profile){ + this.profile = profile; + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java index afd959fc..4bd6e166 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java @@ -4,13 +4,13 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import static likelion.univ.constant.StaticValue.BAD_REQUEST; -import static likelion.univ.constant.StaticValue.NOT_FOUND; +import static likelion.univ.constant.StaticValue.*; @Getter @AllArgsConstructor public enum UserErrorCode implements BaseErrorCode{ NOT_SUPPORTED_LOGIN_TYPE(BAD_REQUEST, "LOGIN_TYPE_400", "해당 방식은 지원하지않는 로그인 방식입니다."), + USER_NOT_MATCH(FORBIDDEN, "USER_403", "사용자가 일치하지 않습니다."), USER_NOT_FOUND(NOT_FOUND, "USER_404", "유저를 찾을 수 없습니다."), EMAIL_ALREADY_REGISTERED(NOT_FOUND, "USER_409", "같은 이메일로 회원가입된 계정이 있습니다."); diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java new file mode 100644 index 00000000..64525922 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java @@ -0,0 +1,10 @@ +package likelion.univ.domain.user.exception; + +import likelion.univ.exception.base.BaseErrorCode; +import likelion.univ.exception.base.BaseException; + +public class UserNotMatchException extends BaseException { + public UserNotMatchException() { + super(UserErrorCode.USER_NOT_MATCH); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java b/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java index 504f4550..e99aabb8 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java @@ -34,6 +34,12 @@ public User signUp(Profile profile, AuthInfo authInfo, UniversityInfo university .build(); return userAdaptor.save(user); } + @Transactional + public User editProfile(Long userId, Profile profile){ + User user = userAdaptor.findById(userId); + user.editProfile(profile); + return user; + } public User findByEmail(String email) { return userAdaptor.findByEmail(email); From df95efee4820e0d7637bb9f580a458ae7e151f4d Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Thu, 9 Nov 2023 16:19:24 +0900 Subject: [PATCH 26/30] =?UTF-8?q?fix=20:=20follow=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=84=B1=EB=8A=A5=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/user/controller/UserController.java | 25 ++++- .../user/dto/response/FollowUserInfoDto.java | 27 ++++++ .../user/usecase/GetFollowInfoUseCase.java | 45 +++++++++ .../univ/user/usecase/GetProfileUseCase.java | 35 +++++-- .../processor/ConvertSliceProcessor.java | 25 +++++ .../univ/common/response/SliceResponse.java | 26 ++++++ ...FolllowAdaptor.java => FollowAdaptor.java} | 12 ++- .../univ/domain/follow/entity/Follow.java | 4 +- .../follow/repository/FollowRepository.java | 6 +- .../repository/PostCustomRepositoryImpl.java | 1 - .../univ/domain/user/adaptor/UserAdaptor.java | 15 ++- .../user/repository/UserCustomRepository.java | 15 +++ .../user/repository/UserQueryRepository.java | 47 ---------- .../user/repository/UserRepository.java | 2 +- .../impl/UserCustomRepositoryImpl.java | 93 +++++++++++++++++++ .../univ/common/constant/RedisKey.java | 2 + .../univ/user/dao/UserFollowNumRedisDao.java | 19 ++++ .../univ/user/entity/UserFollowNum.java | 15 +++ .../service/UserFollowNumRedisService.java | 21 +++++ 19 files changed, 363 insertions(+), 72 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java create mode 100644 likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java create mode 100644 likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java rename likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/{FolllowAdaptor.java => FollowAdaptor.java} (60%) create mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java delete mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java create mode 100644 likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java create mode 100644 likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java create mode 100644 likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java diff --git a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java index f85b6299..7cebbda8 100644 --- a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java +++ b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java @@ -3,13 +3,12 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import likelion.univ.common.response.PageResponse; +import likelion.univ.common.response.SliceResponse; import likelion.univ.user.dto.request.ProfileEditRequestDto; +import likelion.univ.user.dto.response.FollowUserInfoDto; import likelion.univ.user.dto.response.UserPagePostsDto; import likelion.univ.user.dto.response.ProfileDetailsDto; -import likelion.univ.user.usecase.EditProfileUseCase; -import likelion.univ.user.usecase.GetUserPostsUseCase; -import likelion.univ.user.usecase.GetPostsCommentedByMeUseCase; -import likelion.univ.user.usecase.GetProfileUseCase; +import likelion.univ.user.usecase.*; import likelion.univ.response.SuccessResponse; import lombok.RequiredArgsConstructor; import org.springdoc.api.annotations.ParameterObject; @@ -26,6 +25,7 @@ public class UserController { private final EditProfileUseCase editProfileUseCase; private final GetUserPostsUseCase getMyPostsUseCase; private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; + private final GetFollowInfoUseCase getFollowingListUseCase; @Operation(summary = "유저페이지 프로필 조회", description = "해당 유저의 프로필 정보를 조회합니다.") @GetMapping("/{userId}/profile") @@ -33,6 +33,7 @@ public SuccessResponse getProfile(@PathVariable Long userId){ ProfileDetailsDto profileDetailsDto = getProfileUseCase.execute(userId); return SuccessResponse.of(profileDetailsDto); } + @Operation(summary = "유저페이지 프로필 수정", description = "해당 유저의 프로필 정보를 수정합니다.") @PatchMapping("/{userId}/profile") public SuccessResponse editProfile(@PathVariable Long userId, @@ -41,6 +42,21 @@ public SuccessResponse editProfile(@PathVariable Long userId, return SuccessResponse.empty(); } + @Operation(summary = "팔로잉 목록 조회", description = "해당 유저의 팔로잉 목록을 조회합니다.") + @GetMapping("/{userId}/following") + public SuccessResponse getFollowingList(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 4, page = 1) Pageable pageable){ + SliceResponse followingUsers = getFollowingListUseCase.executeForFollowing(userId,pageable); + return SuccessResponse.of(followingUsers); + } + + @Operation(summary = "팔로워 목록 조회", description = "해당 유저의 팔로워 목록을 조회합니다.") + @GetMapping("/{userId}/follower") + public SuccessResponse getFollowerList(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 4, page = 1) Pageable pageable){ + SliceResponse followerUsers = getFollowingListUseCase.executeForFollower(userId,pageable); + return SuccessResponse.of(followerUsers); + } @Operation(summary = "해당 유저가 쓴 게시글 조회", description = "해당 유저가 작성한 게시글을 조회합니다.") @GetMapping("/{userId}/posts") public SuccessResponse getMyPosts(@PathVariable Long userId, @@ -48,6 +64,7 @@ public SuccessResponse getMyPosts(@PathVariable Long userId, PageResponse myPagePostsPage = getMyPostsUseCase.execute(userId, pageable); return SuccessResponse.of(myPagePostsPage); } + @Operation(summary = "해당 유저가 댓글 쓴 게시글 조회", description = "해당 유저가 댓글을 작성한 게시글을 조회합니다.") @GetMapping("/{userId}/comments") public SuccessResponse getPostsCommentedByMe(@PathVariable Long userId, diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java new file mode 100644 index 00000000..7259d21a --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java @@ -0,0 +1,27 @@ +package likelion.univ.user.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class FollowUserInfoDto { + private Long userId; + private String name; + private String profileImage; + private Long ordinal; + private String part; + private Boolean isFollowed; + + public static FollowUserInfoDto of(User user, Boolean isFollowed){ + return FollowUserInfoDto.builder() + .userId(user.getId()) + .name(user.getProfile().getName()) + .profileImage(user.getProfile().getProfileImage()) + .ordinal(user.getUniversityInfo().getOrdinal()) + .part(user.getProfile().getPart().toString()) + .isFollowed(isFollowed) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java new file mode 100644 index 00000000..8a963a36 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java @@ -0,0 +1,45 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.SliceResponse; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.User; +import likelion.univ.user.dto.response.FollowUserInfoDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +import java.util.List; + +@UseCase +@RequiredArgsConstructor +public class GetFollowInfoUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final UserAdaptor userAdaptor; + + public SliceResponse executeForFollowing(Long userId, Pageable pageable){ + Slice userSlice = userAdaptor.findFollowingUsersByFollowerID(userId, pageable); + List myFollowingUsers = getMyFollowingUsers(userSlice); + + return SliceResponse.of(userSlice.map(u -> + FollowUserInfoDto.of(u, checkIFollowingTarget(u, myFollowingUsers)))); + } + + public SliceResponse executeForFollower(Long userId, Pageable pageable){ + Slice userSlice = userAdaptor.findFollowerUsersByFollowingID(userId, pageable); + List myFollowingUsers = getMyFollowingUsers(userSlice); + + return SliceResponse.of(userSlice.map(u -> + FollowUserInfoDto.of(u, checkIFollowingTarget(u, myFollowingUsers)))); + } + private List getMyFollowingUsers(Slice userSlice){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + List followingUserIds = userSlice.getContent().stream().map(user -> user.getId()).toList(); + return userAdaptor.findMyFollowingUsersByFollowingIdIn(currentUserId, followingUserIds); + } + + private Boolean checkIFollowingTarget(User target, List myFollowingUsers){ + return myFollowingUsers.stream().anyMatch(u -> u.getId().equals(target.getId())); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java index 8aa0b326..7a97f39e 100644 --- a/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java @@ -1,29 +1,48 @@ package likelion.univ.user.usecase; import likelion.univ.annotation.UseCase; -import likelion.univ.domain.follow.adaptor.FolllowAdaptor; +import likelion.univ.domain.follow.adaptor.FollowAdaptor; import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.User; +import likelion.univ.user.dao.UserFollowNumRedisDao; import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.user.entity.UserFollowNum; +import likelion.univ.user.service.UserFollowNumRedisService; import likelion.univ.utils.AuthentiatedUserUtils; import lombok.RequiredArgsConstructor; +import java.util.Optional; + @UseCase @RequiredArgsConstructor public class GetProfileUseCase { private final AuthentiatedUserUtils authentiatedUserUtils; private final UserAdaptor userAdaptor; - private final FolllowAdaptor folllowAdaptor; + private final UserFollowNumRedisDao userFollowNumRedisDao; + private final UserFollowNumRedisService userFollowNumRedisService; + private final FollowAdaptor followAdaptor; public ProfileDetailsDto execute(Long userId){ Long currentUserId = authentiatedUserUtils.getCurrentUserId(); User user = userAdaptor.findByIdWithUniversity(userId); - /* 임시로 카운트쿼리로.. */ - Long followerNum = folllowAdaptor.countByFolloweeId(userId); - Long followingNum = folllowAdaptor.countByFollowerId(userId); - if (userId.equals(currentUserId)) - return ProfileDetailsDto.of(user, true, followerNum, followingNum); - else return ProfileDetailsDto.of(user, false, followerNum, followingNum); + return createDto(user, currentUserId); + } + + private ProfileDetailsDto createDto(User user, Long currentUserId){ + UserFollowNum userFollowNum = getUserFollowNum(user.getId()); + + if (user.getId().equals(currentUserId)) + return ProfileDetailsDto.of(user, true, userFollowNum.getFollowerNum(), userFollowNum.getFollowingNum()); + else return ProfileDetailsDto.of(user, false, userFollowNum.getFollowerNum(), userFollowNum.getFollowingNum()); + } + + private UserFollowNum getUserFollowNum(Long userId){ + Optional userFollowNum = userFollowNumRedisDao.findById(userId); + if(userFollowNum.isEmpty()){ + Long followerNum = followAdaptor.countByFollowingId(userId); + Long followingNum = followAdaptor.countByFollowerId(userId); + return userFollowNumRedisService.save(userId, followerNum, followingNum); + }else return userFollowNum.get(); } } diff --git a/likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java b/likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java new file mode 100644 index 00000000..8e273610 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java @@ -0,0 +1,25 @@ +package likelion.univ.common.processor; + +import likelion.univ.annotation.Processor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; + +import java.util.List; + +@Processor +public class ConvertSliceProcessor { + + public Slice execute(List contents, Pageable pageable) { + if (hasNext(contents, pageable)) + return new SliceImpl<>(subContentOne(contents, pageable), pageable, true); + else return new SliceImpl<>(contents, pageable, false); + } + + private Boolean hasNext(List content, Pageable pageable) { + return pageable.isPaged() && content.size() > pageable.getPageSize(); + } + private List subContentOne(List content, Pageable pageable) { + return content.subList(0, pageable.getPageSize()); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java b/likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java new file mode 100644 index 00000000..3869e0b3 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java @@ -0,0 +1,26 @@ +package likelion.univ.common.response; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.domain.Slice; + +import java.util.List; + +@Getter +@Builder +public class SliceResponse { + + private int currentPage; + private int size; + private Boolean hasNext; + private List data; + + public static SliceResponse of(Slice slice) { + return SliceResponse.builder() + .currentPage(slice.getNumber()+1) + .size(slice.getNumberOfElements()) + .hasNext(slice.hasNext()) + .data(slice.getContent()) + .build(); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java similarity index 60% rename from likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java rename to likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java index bd6288d4..bd870e72 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FolllowAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java @@ -1,20 +1,22 @@ package likelion.univ.domain.follow.adaptor; import likelion.univ.annotation.Adaptor; +import likelion.univ.domain.follow.entity.Follow; import likelion.univ.domain.follow.repository.FollowRepository; +import likelion.univ.domain.user.entity.User; import lombok.RequiredArgsConstructor; +import java.util.List; + @Adaptor @RequiredArgsConstructor -public class FolllowAdaptor { +public class FollowAdaptor { private final FollowRepository followRepository; public Long countByFollowerId(Long followerId){ return followRepository.countByFollowerId(followerId); } - - public Long countByFolloweeId(Long followeeId){ - return followRepository.countByFolloweeId(followeeId); + public Long countByFollowingId(Long followingId){ + return followRepository.countByFollowingId(followingId); } - } diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java index 72c81376..cd31847f 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java @@ -22,8 +22,8 @@ public class Follow extends BaseTimeEntity { private User follower; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "followee_id") - private User followee; + @JoinColumn(name = "following_id") + private User following; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java index cee82e2d..8d2a9cfb 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java @@ -1,9 +1,13 @@ package likelion.univ.domain.follow.repository; import likelion.univ.domain.follow.entity.Follow; +import likelion.univ.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; public interface FollowRepository extends JpaRepository { Long countByFollowerId(Long followerId); - Long countByFolloweeId(Long followeeId); + Long countByFollowingId(Long followingId); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java index 8d26acfc..02bfac04 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepositoryImpl.java @@ -17,7 +17,6 @@ import static likelion.univ.domain.user.entity.QUser.user; @RequiredArgsConstructor -@Repository public class PostCustomRepositoryImpl implements PostCustomRepository { private final JPAQueryFactory queryFactory; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java index 0f102f61..4e722ceb 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java @@ -3,10 +3,11 @@ import likelion.univ.annotation.Adaptor; import likelion.univ.domain.user.entity.User; import likelion.univ.domain.user.exception.UserNotFoundException; -import likelion.univ.domain.user.repository.UserQueryRepository; import likelion.univ.domain.user.repository.UserRepository; import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import java.util.List; @@ -14,7 +15,6 @@ @RequiredArgsConstructor public class UserAdaptor { private final UserRepository userRepository; - private final UserQueryRepository userQueryRepository; public User findById(Long id){ return userRepository.findById(id) .orElseThrow(()-> new UserNotFoundException()); @@ -37,6 +37,15 @@ public List findAll() { return userRepository.findAll(); } public List findDynamicUsers(UserSearchCondition condition) { - return userQueryRepository.findDynamicUsers(condition); + return userRepository.findDynamicUsers(condition); + } + public Slice findFollowingUsersByFollowerID(Long userId, Pageable pageable){ + return userRepository.findFollowingUsersByFollowerID(userId, pageable); + } + public Slice findFollowerUsersByFollowingID(Long userId, Pageable pageable){ + return userRepository.findFollowerUsersByFollowingID(userId, pageable); + } + public List findMyFollowingUsersByFollowingIdIn(Long follwerId, List followingIdList){ + return userRepository.findMyFollowingUsersByFollowingIdIn(follwerId, followingIdList); } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java new file mode 100644 index 00000000..5f010ca4 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java @@ -0,0 +1,15 @@ +package likelion.univ.domain.user.repository; + +import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +import java.util.List; + +public interface UserCustomRepository { + List findDynamicUsers(UserSearchCondition condition); + Slice findFollowingUsersByFollowerID(Long userId, Pageable pageable); + Slice findFollowerUsersByFollowingID(Long userId, Pageable pageable); + List findMyFollowingUsersByFollowingIdIn(Long followerId, List followingIdList); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java deleted file mode 100644 index c14f8f1a..00000000 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java +++ /dev/null @@ -1,47 +0,0 @@ -package likelion.univ.domain.user.repository; - -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; -import likelion.univ.domain.university.entity.University; -import likelion.univ.domain.user.entity.Part; -import likelion.univ.domain.user.entity.User; -import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; -import org.springframework.util.StringUtils; - -import java.util.List; - -import static likelion.univ.domain.user.entity.QUser.user; - -@Repository -@RequiredArgsConstructor -public class UserQueryRepository { - - private final JPAQueryFactory jpaQueryFactory; - - public List findDynamicUsers(UserSearchCondition condition) { - return jpaQueryFactory - .selectFrom(user) - .where( - containsName(condition.getName()), - eqUniversity(condition.getUniversity()), - eqPart(condition.getPart()) - ) - .fetch(); - } - - private BooleanExpression containsName(String searchName) { - return StringUtils.hasText(searchName) ? user.profile.name.contains(searchName) : null; - } - - private BooleanExpression eqUniversity(String searchUniversity) { - return searchUniversity != null ? user.universityInfo.university.name.eq(searchUniversity) : null; - } - - private BooleanExpression eqPart(String searchPart) { - return searchPart != null ? user.profile.part.eq(Part.valueOf(searchPart)) : null; - } - - -} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java index 953ac076..223cc2bd 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java @@ -6,7 +6,7 @@ import java.util.Optional; -public interface UserRepository extends JpaRepository { +public interface UserRepository extends JpaRepository, UserCustomRepository { Optional findByAuthInfoEmail(String email); Boolean existsByAuthInfoEmail(String email); diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java new file mode 100644 index 00000000..09875a0c --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java @@ -0,0 +1,93 @@ +package likelion.univ.domain.user.repository.impl; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import likelion.univ.common.processor.ConvertSliceProcessor; +import likelion.univ.domain.user.entity.Part; +import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.repository.UserCustomRepository; +import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.util.StringUtils; + +import java.util.List; + +import static likelion.univ.domain.follow.entity.QFollow.follow; +import static likelion.univ.domain.user.entity.QUser.user; + +@RequiredArgsConstructor +public class UserCustomRepositoryImpl implements UserCustomRepository { + private final JPAQueryFactory queryFactory; + private final ConvertSliceProcessor convertSliceProcessor; + + @Override + public List findDynamicUsers(UserSearchCondition condition) { + return queryFactory + .selectFrom(user) + .where( + containsName(condition.getName()), + eqUniversity(condition.getUniversity()), + eqPart(condition.getPart()) + ) + .fetch(); + } + + private BooleanExpression containsName(String searchName) { + return StringUtils.hasText(searchName) ? user.profile.name.contains(searchName) : null; + } + + private BooleanExpression eqUniversity(String searchUniversity) { + return searchUniversity != null ? user.universityInfo.university.name.eq(searchUniversity) : null; + } + + private BooleanExpression eqPart(String searchPart) { + return searchPart != null ? user.profile.part.eq(Part.valueOf(searchPart)) : null; + } + + + @Override + public Slice findFollowingUsersByFollowerID(Long followerId, Pageable pageable){ + List users = + queryFactory + .select(follow.following) + .from(follow) + .innerJoin(follow.following, user) + .where(follow.follower.id.eq(followerId)) + .offset(pageable.getOffset()) + .orderBy(user.createdDate.desc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return convertSliceProcessor.execute(users, pageable); + } + @Override + public Slice findFollowerUsersByFollowingID(Long followingId, Pageable pageable){ + List users = + queryFactory + .select(user) + .from(follow) + .innerJoin(follow.follower, user) + .where(follow.following.id.eq(followingId)) + .offset(pageable.getOffset()) + .orderBy(user.createdDate.desc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return convertSliceProcessor.execute(users, pageable); + } + + @Override + public List findMyFollowingUsersByFollowingIdIn(Long followerId, List followingIdList){ + List users = + queryFactory + .select(user) + .from(follow) + .innerJoin(follow.following, user) + .where(follow.follower.id.eq(followerId) + .and(follow.following.id.in(followingIdList))) + .fetch(); + return users; + } +} diff --git a/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java b/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java index c1d652fa..3f4f8298 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java +++ b/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java @@ -8,6 +8,8 @@ public class RedisKey { public static final String REFRESH_TOKEN = "refreshToken"; public static final String POST_COUNT_INFO = "postCount"; + public static final String USER_FOLLOW_NUM = "userFollowNum"; public static final Long REFRESH_TOKEN_EXPIRE_SEC = 1209600L; public static final Long POST_COUNT_INFO_EXPIRE_SEC = 86400L; + public static final Long USER_FOLLOW_NUM_EXPIRE_SEC = 86400L; } diff --git a/likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java b/likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java new file mode 100644 index 00000000..0a558f2c --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java @@ -0,0 +1,19 @@ +package likelion.univ.user.dao; + +import likelion.univ.annotation.RedisRepository; +import likelion.univ.common.base.BaseRedisRepository; +import likelion.univ.user.entity.UserFollowNum; +import org.springframework.data.redis.core.RedisTemplate; + +import static likelion.univ.common.constant.RedisKey.USER_FOLLOW_NUM; +import static likelion.univ.common.constant.RedisKey.USER_FOLLOW_NUM_EXPIRE_SEC; + +@RedisRepository +public class UserFollowNumRedisDao extends BaseRedisRepository { + + public UserFollowNumRedisDao(RedisTemplate redisTemplate) { + this.prefix = USER_FOLLOW_NUM + ":"; + this.ttl = USER_FOLLOW_NUM_EXPIRE_SEC; + this.redisTemplate = redisTemplate; + } +} \ No newline at end of file diff --git a/likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java b/likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java new file mode 100644 index 00000000..576a309a --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java @@ -0,0 +1,15 @@ +package likelion.univ.user.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class UserFollowNum { + private Long followerNum; + private Long followingNum; +} diff --git a/likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java b/likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java new file mode 100644 index 00000000..84074c0f --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java @@ -0,0 +1,21 @@ +package likelion.univ.user.service; + +import likelion.univ.user.dao.UserFollowNumRedisDao; +import likelion.univ.user.entity.UserFollowNum; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UserFollowNumRedisService { + private final UserFollowNumRedisDao userFollowNumRedisDao; + + public UserFollowNum save(Long userId, Long followerNum, Long followingNum){ + UserFollowNum userFollowNum = UserFollowNum.builder() + .followerNum(followerNum) + .followingNum(followingNum) + .build(); + userFollowNumRedisDao.save(userId, userFollowNum); + return userFollowNum; + } +} \ No newline at end of file From 6c294fd3c4953a91b36623841dad74845125988e Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Fri, 10 Nov 2023 13:30:03 +0900 Subject: [PATCH 27/30] =?UTF-8?q?feat=20:=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../follow/controller/FollowController.java | 33 +++++++++++++ .../follow/usecase/CancelFollowUseCase.java | 33 +++++++++++++ .../follow/usecase/FollowUserUseCase.java | 33 +++++++++++++ .../univ/user/usecase/GetProfileUseCase.java | 22 ++++----- .../domain/follow/adaptor/FollowAdaptor.java | 10 ++-- .../univ/domain/follow/entity/Follow.java | 1 + .../AlreadyFollowingUserException.java | 9 ++++ .../follow/exception/FollowErrorCode.java | 18 +++++++ .../follow/repository/FollowRepository.java | 14 +++++- .../user/repository/UserRepository.java | 2 +- .../dao/FollowNumRedisDao.java} | 8 +-- .../entity/FollowNum.java} | 4 +- .../follow/service/FollowNumRedisService.java | 49 +++++++++++++++++++ .../service/UserFollowNumRedisService.java | 21 -------- 14 files changed, 212 insertions(+), 45 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java create mode 100644 likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java rename likelion-redis/src/main/java/likelion/univ/{user/dao/UserFollowNumRedisDao.java => follow/dao/FollowNumRedisDao.java} (68%) rename likelion-redis/src/main/java/likelion/univ/{user/entity/UserFollowNum.java => follow/entity/FollowNum.java} (78%) create mode 100644 likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java delete mode 100644 likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java diff --git a/likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java b/likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java new file mode 100644 index 00000000..33a7cbc9 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java @@ -0,0 +1,33 @@ +package likelion.univ.follow.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import likelion.univ.follow.usecase.CancelFollowUseCase; +import likelion.univ.follow.usecase.FollowUserUseCase; +import likelion.univ.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/v1/follow") +@Tag(name = "팔로우", description = "팔로우 관련 API입니다.") +public class FollowController { + private final FollowUserUseCase followUserUseCase; + private final CancelFollowUseCase cancelFollowUseCase; + + @Operation(summary = "팔로우 ", description = "해당 유저를 팔로우 합니다.") + @PostMapping("/{userId}") + public SuccessResponse follow(@PathVariable("userId") Long userId){ + followUserUseCase.execute(userId); + return SuccessResponse.empty(); + } + + @Operation(summary = "팔로우 취소", description = "해당 유저를 팔로우 취소 합니다.") + @DeleteMapping("/{userId}") + public SuccessResponse deleteFollow(@PathVariable("userId") Long userId) { + cancelFollowUseCase.execute(userId); + return SuccessResponse.empty(); + } +} + diff --git a/likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java b/likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java new file mode 100644 index 00000000..31b38569 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java @@ -0,0 +1,33 @@ +package likelion.univ.follow.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.follow.adaptor.FollowAdaptor; +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.follow.entity.FollowNum; +import likelion.univ.follow.service.FollowNumRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class CancelFollowUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final FollowAdaptor followAdaptor; + private final FollowNumRedisDao followNumRedisDao; + private final FollowNumRedisService followNumRedisService; + + public void execute(Long userId){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + followAdaptor.delete(currentUserId, userId); + updateFollowNumRedis(currentUserId, userId); + } + + private void updateFollowNumRedis(Long currentUserId, Long userId){ + Optional myFollowNum = followNumRedisDao.findById(currentUserId); + if(myFollowNum.isPresent()) followNumRedisService.followingDown(currentUserId, myFollowNum.get()); + Optional targetFollowNum = followNumRedisDao.findById(userId); + if(targetFollowNum.isPresent()) followNumRedisService.followerDown(userId, targetFollowNum.get()); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java b/likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java new file mode 100644 index 00000000..3726330c --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java @@ -0,0 +1,33 @@ +package likelion.univ.follow.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.follow.adaptor.FollowAdaptor; +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.follow.entity.FollowNum; +import likelion.univ.follow.service.FollowNumRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class FollowUserUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final FollowAdaptor followAdaptor; + private final FollowNumRedisDao followNumRedisDao; + private final FollowNumRedisService followNumRedisService; + + public void execute(Long userId){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + followAdaptor.save(currentUserId, userId); + updateFollowNumRedis(currentUserId, userId); + } + + private void updateFollowNumRedis(Long currentUserId, Long userId){ + Optional myFollowNum = followNumRedisDao.findById(currentUserId); + if(myFollowNum.isPresent()) followNumRedisService.followingUp(currentUserId, myFollowNum.get()); + Optional targetFollowNum = followNumRedisDao.findById(userId); + if(targetFollowNum.isPresent()) followNumRedisService.followerUp(userId, targetFollowNum.get()); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java index 7a97f39e..325bc2ac 100644 --- a/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java @@ -4,10 +4,10 @@ import likelion.univ.domain.follow.adaptor.FollowAdaptor; import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.User; -import likelion.univ.user.dao.UserFollowNumRedisDao; +import likelion.univ.follow.dao.FollowNumRedisDao; import likelion.univ.user.dto.response.ProfileDetailsDto; -import likelion.univ.user.entity.UserFollowNum; -import likelion.univ.user.service.UserFollowNumRedisService; +import likelion.univ.follow.entity.FollowNum; +import likelion.univ.follow.service.FollowNumRedisService; import likelion.univ.utils.AuthentiatedUserUtils; import lombok.RequiredArgsConstructor; @@ -18,8 +18,8 @@ public class GetProfileUseCase { private final AuthentiatedUserUtils authentiatedUserUtils; private final UserAdaptor userAdaptor; - private final UserFollowNumRedisDao userFollowNumRedisDao; - private final UserFollowNumRedisService userFollowNumRedisService; + private final FollowNumRedisDao followNumRedisDao; + private final FollowNumRedisService followNumRedisService; private final FollowAdaptor followAdaptor; public ProfileDetailsDto execute(Long userId){ @@ -30,19 +30,19 @@ public ProfileDetailsDto execute(Long userId){ } private ProfileDetailsDto createDto(User user, Long currentUserId){ - UserFollowNum userFollowNum = getUserFollowNum(user.getId()); + FollowNum followNum = getUserFollowNum(user.getId()); if (user.getId().equals(currentUserId)) - return ProfileDetailsDto.of(user, true, userFollowNum.getFollowerNum(), userFollowNum.getFollowingNum()); - else return ProfileDetailsDto.of(user, false, userFollowNum.getFollowerNum(), userFollowNum.getFollowingNum()); + return ProfileDetailsDto.of(user, true, followNum.getFollowerNum(), followNum.getFollowingNum()); + else return ProfileDetailsDto.of(user, false, followNum.getFollowerNum(), followNum.getFollowingNum()); } - private UserFollowNum getUserFollowNum(Long userId){ - Optional userFollowNum = userFollowNumRedisDao.findById(userId); + private FollowNum getUserFollowNum(Long userId){ + Optional userFollowNum = followNumRedisDao.findById(userId); if(userFollowNum.isEmpty()){ Long followerNum = followAdaptor.countByFollowingId(userId); Long followingNum = followAdaptor.countByFollowerId(userId); - return userFollowNumRedisService.save(userId, followerNum, followingNum); + return followNumRedisService.save(userId, followerNum, followingNum); }else return userFollowNum.get(); } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java index bd870e72..416feedb 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java @@ -1,13 +1,10 @@ package likelion.univ.domain.follow.adaptor; import likelion.univ.annotation.Adaptor; -import likelion.univ.domain.follow.entity.Follow; +import likelion.univ.domain.follow.exception.AlreadyFollowingUserException; import likelion.univ.domain.follow.repository.FollowRepository; -import likelion.univ.domain.user.entity.User; import lombok.RequiredArgsConstructor; -import java.util.List; - @Adaptor @RequiredArgsConstructor public class FollowAdaptor { @@ -19,4 +16,9 @@ public Long countByFollowerId(Long followerId){ public Long countByFollowingId(Long followingId){ return followRepository.countByFollowingId(followingId); } + public void save(Long currentUserId, Long userId) { + try { followRepository.save(currentUserId,userId);} + catch(Exception e) { throw new AlreadyFollowingUserException(); } + } + public void delete(Long currentUserId, Long userId) { followRepository.delete(currentUserId,userId);} } diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java index cd31847f..f1b6f5b4 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java @@ -11,6 +11,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity +@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"follower_id", "following_id"})}) public class Follow extends BaseTimeEntity { @Id diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java new file mode 100644 index 00000000..aa42d0c0 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.follow.exception; + +import likelion.univ.exception.base.BaseException; + +public class AlreadyFollowingUserException extends BaseException { + public AlreadyFollowingUserException() { + super(FollowErrorCode.ALREADY_FOLLOWING_USER); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java new file mode 100644 index 00000000..5cbfce87 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java @@ -0,0 +1,18 @@ +package likelion.univ.domain.follow.exception; + +import likelion.univ.exception.base.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static likelion.univ.constant.StaticValue.*; + +@Getter +@AllArgsConstructor +public enum FollowErrorCode implements BaseErrorCode { + ALREADY_FOLLOWING_USER(BAD_REQUEST, "FOLLOW_400_1", "이미 팔로우하고 있습니다."); + + + private final int httpStatus; + private final String code; + private final String message; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java index 8d2a9cfb..93f864e2 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java @@ -1,13 +1,23 @@ package likelion.univ.domain.follow.repository; import likelion.univ.domain.follow.entity.Follow; -import likelion.univ.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; -import java.util.List; public interface FollowRepository extends JpaRepository { Long countByFollowerId(Long followerId); Long countByFollowingId(Long followingId); + @Modifying + @Transactional + @Query(value = "insert into follow(created_date, modified_date, follower_id, following_id)" + + "values (now(), now(), :currentId , :userId)", nativeQuery = true) + void save(Long currentId, Long userId); + + @Modifying + @Transactional + @Query("delete from Follow f where f.follower.id = :currentId and f.following.id = :userId") + void delete(Long currentId, Long userId); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java index 223cc2bd..f5962274 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java @@ -10,6 +10,6 @@ public interface UserRepository extends JpaRepository, UserCustomRepo Optional findByAuthInfoEmail(String email); Boolean existsByAuthInfoEmail(String email); - @Query("SELECT u FROM User u join fetch u.universityInfo.university") + @Query("SELECT u FROM User u join fetch u.universityInfo.university where u.id = :id ") Optional findByIdWithUniversity(Long id); } diff --git a/likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java b/likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java similarity index 68% rename from likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java rename to likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java index 0a558f2c..a8297c35 100644 --- a/likelion-redis/src/main/java/likelion/univ/user/dao/UserFollowNumRedisDao.java +++ b/likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java @@ -1,17 +1,17 @@ -package likelion.univ.user.dao; +package likelion.univ.follow.dao; import likelion.univ.annotation.RedisRepository; import likelion.univ.common.base.BaseRedisRepository; -import likelion.univ.user.entity.UserFollowNum; +import likelion.univ.follow.entity.FollowNum; import org.springframework.data.redis.core.RedisTemplate; import static likelion.univ.common.constant.RedisKey.USER_FOLLOW_NUM; import static likelion.univ.common.constant.RedisKey.USER_FOLLOW_NUM_EXPIRE_SEC; @RedisRepository -public class UserFollowNumRedisDao extends BaseRedisRepository { +public class FollowNumRedisDao extends BaseRedisRepository { - public UserFollowNumRedisDao(RedisTemplate redisTemplate) { + public FollowNumRedisDao(RedisTemplate redisTemplate) { this.prefix = USER_FOLLOW_NUM + ":"; this.ttl = USER_FOLLOW_NUM_EXPIRE_SEC; this.redisTemplate = redisTemplate; diff --git a/likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java b/likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java similarity index 78% rename from likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java rename to likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java index 576a309a..7c88387a 100644 --- a/likelion-redis/src/main/java/likelion/univ/user/entity/UserFollowNum.java +++ b/likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java @@ -1,4 +1,4 @@ -package likelion.univ.user.entity; +package likelion.univ.follow.entity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -9,7 +9,7 @@ @AllArgsConstructor @NoArgsConstructor @Builder -public class UserFollowNum { +public class FollowNum { private Long followerNum; private Long followingNum; } diff --git a/likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java b/likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java new file mode 100644 index 00000000..b0cb6d41 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java @@ -0,0 +1,49 @@ +package likelion.univ.follow.service; + +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.follow.entity.FollowNum; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class FollowNumRedisService { + private final FollowNumRedisDao followNumRedisDao; + + public FollowNum save(Long userId, Long followerNum, Long followingNum){ + FollowNum followNum = FollowNum.builder() + .followerNum(followerNum) + .followingNum(followingNum) + .build(); + followNumRedisDao.save(userId, followNum); + return followNum; + } + public void followerUp(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum() + 1) + .followingNum(followNum.getFollowingNum()) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } + public void followerDown(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum() - 1) + .followingNum(followNum.getFollowingNum()) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } + public void followingUp(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum()) + .followingNum(followNum.getFollowingNum() + 1) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } + public void followingDown(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum()) + .followingNum(followNum.getFollowingNum() - 1) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } +} \ No newline at end of file diff --git a/likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java b/likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java deleted file mode 100644 index 84074c0f..00000000 --- a/likelion-redis/src/main/java/likelion/univ/user/service/UserFollowNumRedisService.java +++ /dev/null @@ -1,21 +0,0 @@ -package likelion.univ.user.service; - -import likelion.univ.user.dao.UserFollowNumRedisDao; -import likelion.univ.user.entity.UserFollowNum; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class UserFollowNumRedisService { - private final UserFollowNumRedisDao userFollowNumRedisDao; - - public UserFollowNum save(Long userId, Long followerNum, Long followingNum){ - UserFollowNum userFollowNum = UserFollowNum.builder() - .followerNum(followerNum) - .followingNum(followingNum) - .build(); - userFollowNumRedisDao.save(userId, userFollowNum); - return userFollowNum; - } -} \ No newline at end of file From a041be35d3cc39bce45cb016b3389c13b8501cc6 Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Mon, 13 Nov 2023 22:13:19 +0900 Subject: [PATCH 28/30] =?UTF-8?q?feat=20:=20=EC=8B=A0=EA=B7=9C=20=EB=8C=80?= =?UTF-8?q?=ED=95=99=20=EB=AA=A8=EC=A7=91=20=EC=95=8C=EB=9E=8C=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=20=EB=93=B1=EB=A1=9D=20api=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alarm/controller/AlarmController.java | 25 +++++++++++++++ .../dto/request/AlarmRegisterRequestDto.java | 32 +++++++++++++++++++ .../alarm/usecase/RegisterAlarmUseCase.java | 22 +++++++++++++ .../univ/user/controller/UserController.java | 11 +++++++ .../dto/request/ProfileEditRequestDto.java | 2 +- .../dto/response/UserSearchResultDto.java | 28 ++++++++++++++++ .../user/usecase/SearchUserByNameUseCase.java | 22 +++++++++++++ .../domain/alarm/adaptor/AlarmAdaptor.java | 21 ++++++++++++ .../univ/domain/alarm/entity/Alarm.java | 28 ++++++++++++++++ .../univ/domain/alarm/entity/AlarmType.java | 13 ++++++++ .../univ/domain/alarm/entity/SendStatus.java | 14 ++++++++ .../alarm/exception/AlarmErrorCode.java | 18 +++++++++++ ...mailAlreadyRegisteredAsAlarmException.java | 9 ++++++ .../alarm/repository/AlarmRepository.java | 9 ++++++ .../alarm/service/AlarmDomainService.java | 23 +++++++++++++ .../univ/domain/user/adaptor/UserAdaptor.java | 3 ++ .../domain/user/entity/AccountStatus.java | 2 +- .../univ/domain/user/entity/AuthInfo.java | 4 +-- .../univ/domain/user/entity/Part.java | 6 ++-- .../univ/domain/user/entity/Role.java | 9 +++--- .../user/repository/UserCustomRepository.java | 1 + .../impl/UserCustomRepositoryImpl.java | 28 +++++++++++++++- 22 files changed, 317 insertions(+), 13 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java create mode 100644 likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java diff --git a/likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java b/likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java new file mode 100644 index 00000000..847cb5cc --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java @@ -0,0 +1,25 @@ +package likelion.univ.alarm.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import likelion.univ.alarm.dto.request.AlarmRegisterRequestDto; +import likelion.univ.alarm.usecase.RegisterAlarmUseCase; +import likelion.univ.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/v1/alarm") +@Tag(name = "알람", description = "알람 API") +public class AlarmController { + private final RegisterAlarmUseCase registerAlarmUseCase; + + @Operation(summary = "알람 등록", description = "이메일과 알람 타입을 입력받아 해당 기수의 알람을 등록합니다.") + @PostMapping("/{ordinal}/register") + public SuccessResponse registerAlarm(@PathVariable Long ordinal, + @RequestBody AlarmRegisterRequestDto alarmRegisterRequestDto){ + registerAlarmUseCase.execute(ordinal, alarmRegisterRequestDto); + return SuccessResponse.empty(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java b/likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java new file mode 100644 index 00000000..d7454965 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java @@ -0,0 +1,32 @@ +package likelion.univ.alarm.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import likelion.univ.domain.alarm.entity.SendStatus; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + +import static likelion.univ.domain.alarm.entity.SendStatus.NOT_SENT; + +@Getter +@NoArgsConstructor +public class AlarmRegisterRequestDto { + @NotNull + @Schema(description = "이메일", example = "tmfrk0426@gmail.com", required = true) + private String email; + + @NotNull + @Schema(description = "알람 타입", example = "NEW_UNIVERSITY_RECRUITING", required = true, enumAsRef = true) + private AlarmType alarmType; + + public static Alarm toEntity(Long ordinal, AlarmRegisterRequestDto alarmRegisterRequestDto){ + return Alarm.builder() + .ordinal(ordinal) + .email(alarmRegisterRequestDto.getEmail()) + .alarmType(alarmRegisterRequestDto.getAlarmType()) + .sendStatus(NOT_SENT) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java b/likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java new file mode 100644 index 00000000..0c7e9e7c --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java @@ -0,0 +1,22 @@ +package likelion.univ.alarm.usecase; + +import likelion.univ.alarm.dto.request.AlarmRegisterRequestDto; +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.alarm.adaptor.AlarmAdaptor; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.service.AlarmDomainService; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class RegisterAlarmUseCase { + private final AlarmAdaptor alarmAdaptor; + private final AlarmDomainService alarmDomainService; + + public void execute(Long ordinal, AlarmRegisterRequestDto alarmRegisterRequestDto){ + alarmAdaptor.existsByOrdinalAndEmailAndAlarmType(ordinal, + alarmRegisterRequestDto.getEmail(), alarmRegisterRequestDto.getAlarmType()); + Alarm newAlarm = AlarmRegisterRequestDto.toEntity(ordinal, alarmRegisterRequestDto); + alarmDomainService.createAlarm(newAlarm); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java index 7cebbda8..f8efaaec 100644 --- a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java +++ b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java @@ -8,6 +8,7 @@ import likelion.univ.user.dto.response.FollowUserInfoDto; import likelion.univ.user.dto.response.UserPagePostsDto; import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.user.dto.response.UserSearchResultDto; import likelion.univ.user.usecase.*; import likelion.univ.response.SuccessResponse; import lombok.RequiredArgsConstructor; @@ -26,6 +27,7 @@ public class UserController { private final GetUserPostsUseCase getMyPostsUseCase; private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; private final GetFollowInfoUseCase getFollowingListUseCase; + private final SearchUserByNameUseCase searchUserByNameUseCase; @Operation(summary = "유저페이지 프로필 조회", description = "해당 유저의 프로필 정보를 조회합니다.") @GetMapping("/{userId}/profile") @@ -73,6 +75,15 @@ public SuccessResponse getPostsCommentedByMe(@PathVariable Long userId, return SuccessResponse.of(myPagePostsPageCommentedByMe); } + @Operation(summary = "유저 검색 (Simple Data) (project page)", description = "이름으로 유저를 검색합니다. (프로젝트 페이지 모달)") + @GetMapping("/search") + public SuccessResponse searchUser(@RequestParam(required = false) String name, + @ParameterObject @PageableDefault(size = 4, page = 1) Pageable pageable){ + SliceResponse searchedUsers = searchUserByNameUseCase.execute(name, pageable); + return SuccessResponse.of(searchedUsers); + } + + // @Operation(summary = "내가 참여한 프로젝트 조회", description = "참여한 프로젝트를 조회합니다.") // @GetMapping("/projects") // public SuccessResponse getMyProjects(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java index 58eeab0d..3cff2535 100644 --- a/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java +++ b/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java @@ -22,7 +22,7 @@ public class ProfileEditRequestDto { private String profileImage; @NotNull - @Schema(description = "트랙(파트)", example = "BACKEND", required = true) + @Schema(description = "트랙(파트)", example = "BACKEND", required = true, enumAsRef = true) private Part part; public Profile toProfile(){ diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java new file mode 100644 index 00000000..052e767d --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java @@ -0,0 +1,28 @@ +package likelion.univ.user.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserSearchResultDto { + private Long userId; + private String name; + private String profileImage; + private String universityName; + private Long ordinal; + private String part; + + public static UserSearchResultDto of(User user){ + return UserSearchResultDto.builder() + .userId(user.getId()) + .name(user.getProfile().getName()) + .profileImage(user.getProfile().getProfileImage()) + .universityName(user.getUniversityInfo().getUniversity().getName()) + .ordinal(user.getUniversityInfo().getOrdinal()) + .part(user.getProfile().getPart().getValue()) + .build(); + } + +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java new file mode 100644 index 00000000..9a803181 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java @@ -0,0 +1,22 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.SliceResponse; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.User; +import likelion.univ.user.dto.response.UserSearchResultDto; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +@UseCase +@RequiredArgsConstructor +public class SearchUserByNameUseCase { + private final UserAdaptor userAdaptor; + + public SliceResponse execute(String name, Pageable pageable){ + System.out.println(name); + Slice userSlice = userAdaptor.searchByName(name, pageable); + return SliceResponse.of(userSlice.map(u -> UserSearchResultDto.of(u))); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java new file mode 100644 index 00000000..8e76a1a1 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java @@ -0,0 +1,21 @@ +package likelion.univ.domain.alarm.adaptor; + +import likelion.univ.annotation.Adaptor; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import likelion.univ.domain.alarm.exception.EmailAlreadyRegisteredAsAlarmException; +import likelion.univ.domain.alarm.repository.AlarmRepository; +import lombok.RequiredArgsConstructor; + +@Adaptor +@RequiredArgsConstructor +public class AlarmAdaptor { + private final AlarmRepository alarmRepository; + + public Alarm save(Alarm alarm){ return alarmRepository.save(alarm);} + + public void existsByOrdinalAndEmailAndAlarmType(Long ordinal, String email, AlarmType alarmType) { + if (alarmRepository.existsByOrdinalAndEmailAndAlarmType(ordinal, email, alarmType)) + throw new EmailAlreadyRegisteredAsAlarmException(); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java new file mode 100644 index 00000000..4ba12003 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java @@ -0,0 +1,28 @@ +package likelion.univ.domain.alarm.entity; +import likelion.univ.common.entity.BaseTimeEntity; +import lombok.*; + +import javax.persistence.*; + +import static likelion.univ.domain.alarm.entity.SendStatus.NOT_SENT; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +@AllArgsConstructor +@Entity +public class Alarm extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Long ordinal; + + private String email; + + @Enumerated(EnumType.STRING) + private AlarmType alarmType; + + @Enumerated(EnumType.STRING) + private SendStatus sendStatus; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java new file mode 100644 index 00000000..4602f7f4 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java @@ -0,0 +1,13 @@ +package likelion.univ.domain.alarm.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum AlarmType { + NEW_UNIVERSITY_RECRUITING("신규 대학 모집 알람"), + EXISTING_UNIVERSITY_RECRUITING("기존 대학 재신청 알람"); + + private String value; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java new file mode 100644 index 00000000..889b5e8c --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java @@ -0,0 +1,14 @@ +package likelion.univ.domain.alarm.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum SendStatus { + NOT_SENT("NOT_SENT"), + RESERVED("RESERVED"), + SENT("SENT"); + + private String value; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java new file mode 100644 index 00000000..beaabada --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java @@ -0,0 +1,18 @@ +package likelion.univ.domain.alarm.exception; + +import likelion.univ.exception.base.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static likelion.univ.constant.StaticValue.*; + +@Getter +@AllArgsConstructor +public enum AlarmErrorCode implements BaseErrorCode { + EMAIL_ALREADY_REGISTERED_AS_ALARM(BAD_REQUEST, "ALARM_409", "해당 이메일은 이미 신청되어 있습니다."); + + + private final int httpStatus; + private final String code; + private final String message; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java new file mode 100644 index 00000000..5478c7a1 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.alarm.exception; + +import likelion.univ.exception.base.BaseException; + +public class EmailAlreadyRegisteredAsAlarmException extends BaseException { + public EmailAlreadyRegisteredAsAlarmException() { + super(AlarmErrorCode.EMAIL_ALREADY_REGISTERED_AS_ALARM); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java new file mode 100644 index 00000000..12ae20bf --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.alarm.repository; + +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AlarmRepository extends JpaRepository { + boolean existsByOrdinalAndEmailAndAlarmType(Long ordinal, String email, AlarmType alarmType); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java new file mode 100644 index 00000000..63b4a5a5 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java @@ -0,0 +1,23 @@ +package likelion.univ.domain.alarm.service; + +import likelion.univ.domain.alarm.adaptor.AlarmAdaptor; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import likelion.univ.domain.alarm.entity.SendStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static likelion.univ.domain.alarm.entity.SendStatus.NOT_SENT; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class AlarmDomainService { + private final AlarmAdaptor alarmAdaptor; + + @Transactional + public Alarm createAlarm(Alarm alarm){ + return alarmAdaptor.save(alarm); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java index 4e722ceb..41e4858c 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java @@ -48,4 +48,7 @@ public Slice findFollowerUsersByFollowingID(Long userId, Pageable pageable public List findMyFollowingUsersByFollowingIdIn(Long follwerId, List followingIdList){ return userRepository.findMyFollowingUsersByFollowingIdIn(follwerId, followingIdList); } + public Slice searchByName(String name, Pageable pageable){ + return userRepository.searchByName(name, pageable); + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java index 64062178..6471a4e9 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java @@ -6,7 +6,7 @@ @AllArgsConstructor @Getter public enum AccountStatus { - MEMBER("MEMBER"), + ACTIVE("ACTIVE"), Deleted("DELETED"); private String value; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java index 00b2b3a2..65ca700e 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java @@ -4,7 +4,7 @@ import javax.persistence.*; -import static likelion.univ.domain.user.entity.AccountStatus.MEMBER; +import static likelion.univ.domain.user.entity.AccountStatus.ACTIVE; import static likelion.univ.domain.user.entity.Role.GUEST; @Embeddable @@ -30,7 +30,7 @@ public static AuthInfo authInfoForSignUp(LoginType loginType, String email) { return AuthInfo.builder() .loginType(loginType) .email(email) - .accountStatus(MEMBER) + .accountStatus(ACTIVE) .role(GUEST) .build(); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java index fca30d1d..53513784 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java @@ -6,11 +6,11 @@ @AllArgsConstructor @Getter public enum Part { - BACKEND("백엔드"), - FRONTEND("프론트엔드"), PM("기획"), DESIGNER("디자인"), - PM_DESIGNER("기획/디자인"); + PM_DESIGNER("기획/디자인"), + FRONTEND("프론트엔드"), + BACKEND("백엔드"); private String value; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java index 9dc91893..6f97f5db 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java @@ -8,11 +8,10 @@ public enum Role { GUEST("GUEST"), - USER("USER"), - MANAGER("MANAGER"), - ADMIN("ADMIN"), - CODEIT_ADMIN("CODEIT_ADMIN"), - SUPER_ADMIN("SUPER_ADMIN"); + USER("USER"), /* 아기사자 */ + MANAGER("MANAGER"), /* 운영진 */ + UNIVERSITY_ADMIN("UNIVERSITY_ADMIN"), /* 대학대표 (대학관리자) */ + SUPER_ADMIN("SUPER_ADMIN"); /* 총관리자 */ private String value; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java index 5f010ca4..476a70de 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java @@ -11,5 +11,6 @@ public interface UserCustomRepository { List findDynamicUsers(UserSearchCondition condition); Slice findFollowingUsersByFollowerID(Long userId, Pageable pageable); Slice findFollowerUsersByFollowingID(Long userId, Pageable pageable); + Slice searchByName(String name, Pageable pageable); List findMyFollowingUsersByFollowingIdIn(Long followerId, List followingIdList); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java index 09875a0c..062c394f 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java @@ -1,6 +1,8 @@ package likelion.univ.domain.user.repository.impl; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.CaseBuilder; +import com.querydsl.core.types.dsl.NumberExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import likelion.univ.common.processor.ConvertSliceProcessor; import likelion.univ.domain.user.entity.Part; @@ -15,6 +17,7 @@ import java.util.List; import static likelion.univ.domain.follow.entity.QFollow.follow; +import static likelion.univ.domain.university.entity.QUniversity.university; import static likelion.univ.domain.user.entity.QUser.user; @RequiredArgsConstructor @@ -90,4 +93,27 @@ public List findMyFollowingUsersByFollowingIdIn(Long followerId, List searchByName(String name, Pageable pageable){ + NumberExpression partOrder = new CaseBuilder() + .when(user.profile.part.eq(Part.PM)).then(1) + .when(user.profile.part.eq(Part.DESIGNER)).then(2) + .when(user.profile.part.eq(Part.PM_DESIGNER)).then(3) + .when(user.profile.part.eq(Part.FRONTEND)).then(4) + .when(user.profile.part.eq(Part.BACKEND)).then(5) + .otherwise(6); + + List users = + queryFactory + .select(user) + .from(user) + .innerJoin(user.universityInfo.university, university).fetchJoin() + .where(containsName(name)) + .offset(pageable.getOffset()) + .orderBy(partOrder.asc(), user.profile.name.asc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return convertSliceProcessor.execute(users, pageable); + } +} \ No newline at end of file From dccb91c6a5018f22e1719ee33bb4e670d65a001f Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Tue, 14 Nov 2023 10:35:40 +0900 Subject: [PATCH 29/30] =?UTF-8?q?refoctor=20:=20redis=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EB=B0=8F=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20processor=EB=A1=9C=20=EB=A7=8C=EB=93=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/LikelionClientApplication.java | 4 + .../alarm/controller/AlarmController.java | 25 ++++ .../dto/request/AlarmRegisterRequestDto.java | 32 +++++ .../alarm/usecase/RegisterAlarmUseCase.java | 22 ++++ .../univ/auth/controller/AuthController.java | 21 ++-- .../auth/dto/response/AccountUserInfoDto.java | 22 ++++ .../GenerateAccountTokenProcessor.java | 2 +- .../processor/LoginByIdTokenProcessor.java | 2 +- .../processor/PublicKeyProcessor.java | 2 +- .../univ/auth/usecase/GetUserInfoUseCase.java | 19 +++ .../univ/auth/usecase/LoginUseCase.java | 4 +- .../auth/usecase/RefreshTokenUseCase.java | 2 +- .../univ/auth/usecase/SignUpUseCase.java | 4 +- .../follow/controller/FollowController.java | 33 +++++ .../follow/usecase/CancelFollowUseCase.java | 33 +++++ .../follow/usecase/FollowUserUseCase.java | 33 +++++ .../GetOrCreatePostCountInfoProcessor.java | 30 +++++ .../PostReadRepositoryCustomImpl.java | 3 +- .../univ/user/controller/UserController.java | 108 ++++++++++++++++ .../dto/request/ProfileEditRequestDto.java | 36 ++++++ .../user/dto/response/FollowUserInfoDto.java | 27 ++++ .../user/dto/response/ProfileDetailsDto.java | 41 ++++++ .../user/dto/response/UserPagePostsDto.java | 41 ++++++ .../dto/response/UserSearchResultDto.java | 28 +++++ .../user/scheduler/UserPageScheduler.java | 4 + .../univ/user/usecase/EditProfileUseCase.java | 24 ++++ .../user/usecase/GetFollowInfoUseCase.java | 45 +++++++ .../usecase/GetPostsCommentedByMeUseCase.java | 28 +++++ .../univ/user/usecase/GetProfileUseCase.java | 48 +++++++ .../user/usecase/GetUserPostsUseCase.java | 32 +++++ .../user/usecase/SearchUserByNameUseCase.java | 22 ++++ .../univ/utils/AuthentiatedUserUtils.java | 6 + .../src/main/resources/application.yml | 6 - likelion-core/build.gradle | 6 +- .../processor/ConvertSliceProcessor.java | 25 ++++ .../univ/common/response/PageResponse.java | 34 +++++ .../univ/common/response/SliceResponse.java | 26 ++++ .../domain/alarm/adaptor/AlarmAdaptor.java | 21 ++++ .../univ/domain/alarm/entity/Alarm.java | 28 +++++ .../univ/domain/alarm/entity/AlarmType.java | 13 ++ .../univ/domain/alarm/entity/SendStatus.java | 14 +++ .../alarm/exception/AlarmErrorCode.java | 18 +++ ...mailAlreadyRegisteredAsAlarmException.java | 9 ++ .../alarm/repository/AlarmRepository.java | 9 ++ .../alarm/service/AlarmDomainService.java | 23 ++++ .../comment/adaptor/CommentAdaptor.java | 3 + .../univ/domain/comment/entity/Comment.java | 3 +- .../comment/repository/CommentRepository.java | 2 + .../univ/domain/example/entity/Example.java | 1 - .../domain/follow/adaptor/FollowAdaptor.java | 24 ++++ .../univ/domain/follow/entity/Follow.java | 6 +- .../AlreadyFollowingUserException.java | 9 ++ .../follow/exception/FollowErrorCode.java | 18 +++ .../follow/repository/FollowRepository.java | 23 ++++ .../like/commentlike/entity/CommentLike.java | 1 - .../postlike/adaptor/PostLikeAdaptor.java | 3 + .../domain/like/postlike/entity/PostLike.java | 1 - .../repository/PostLikeRepository.java | 1 + .../univ/domain/post/adaptor/PostAdaptor.java | 22 ++-- .../univ/domain/post/entity/Post.java | 1 - .../PostCommandCustomRepositoryImpl.java | 18 --- .../repository/PostCommandRepository.java | 9 -- ...ository.java => PostCustomRepository.java} | 10 +- .../post/repository/PostRepository.java | 9 ++ .../impl/PostCustomRepositoryImpl.java | 80 ++++++++++++ .../univ/domain/project/entity/Image.java | 1 - .../univ/domain/project/entity/Project.java | 1 - .../domain/project/entity/ProjectMember.java | 1 - .../univ/domain/recruit/entity/Recruit.java | 1 - .../domain/university/entity/University.java | 1 - .../univ/domain/user/adaptor/UserAdaptor.java | 24 +++- .../domain/user/entity/AccountStatus.java | 2 +- .../univ/domain/user/entity/AuthInfo.java | 6 +- .../univ/domain/user/entity/Part.java | 6 +- .../univ/domain/user/entity/Profile.java | 2 - .../univ/domain/user/entity/Role.java | 9 +- .../domain/user/entity/UniversityInfo.java | 1 - .../univ/domain/user/entity/User.java | 6 +- .../domain/user/exception/UserErrorCode.java | 4 +- .../user/exception/UserNotMatchException.java | 10 ++ .../user/repository/UserCustomRepository.java | 16 +++ .../user/repository/UserQueryRepository.java | 47 ------- .../user/repository/UserRepository.java | 6 +- .../impl/UserCustomRepositoryImpl.java | 119 ++++++++++++++++++ .../user/service/UserDomainService.java | 6 + .../src/main/resources/application-core.yml | 40 +++++- .../univ/common/base/BaseRedisRepository.java | 14 ++- .../config/RedisCacheManagerConfig.java | 1 - .../univ/common/constant/RedisKey.java | 6 +- .../univ/follow/dao/FollowNumRedisDao.java | 19 +++ .../univ/follow/entity/FollowNum.java | 15 +++ .../follow/service/FollowNumRedisService.java | 49 ++++++++ .../univ/post/dao/PostCountInfoRedisDao.java | 19 +++ .../univ/post/entity/PostCountInfo.java | 15 +++ .../service/PostCountInfoRedisService.java | 21 ++++ .../adaptor/RefreshTokenRedisAdaptor.java | 21 ---- .../dao/RefreshTokenRedisDao.java | 6 +- .../refreshtoken/entity/RefreshToken.java | 1 - .../service/RefreshTokenRedisService.java | 13 +- 99 files changed, 1568 insertions(+), 200 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java create mode 100644 likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java rename likelion-client/src/main/java/likelion/univ/auth/{usecase => }/processor/GenerateAccountTokenProcessor.java (96%) rename likelion-client/src/main/java/likelion/univ/auth/{usecase => }/processor/LoginByIdTokenProcessor.java (97%) rename likelion-client/src/main/java/likelion/univ/auth/{usecase => }/processor/PublicKeyProcessor.java (96%) create mode 100644 likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java create mode 100644 likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/post/processor/GetOrCreatePostCountInfoProcessor.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/controller/UserController.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java create mode 100644 likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java create mode 100644 likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java create mode 100644 likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java delete mode 100644 likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepositoryImpl.java delete mode 100644 likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandRepository.java rename likelion-core/src/main/java/likelion/univ/domain/post/repository/{PostCommandCustomRepository.java => PostCustomRepository.java} (50%) create mode 100644 likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java delete mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java create mode 100644 likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java create mode 100644 likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java create mode 100644 likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java create mode 100644 likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java create mode 100644 likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java create mode 100644 likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java create mode 100644 likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java delete mode 100644 likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java diff --git a/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java b/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java index f4beb2af..e6ed9749 100644 --- a/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java +++ b/likelion-client/src/main/java/likelion/univ/LikelionClientApplication.java @@ -4,9 +4,13 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; @EnableCaching @EnableJpaAuditing +@EnableScheduling +@EnableAsync @SpringBootApplication public class LikelionClientApplication { diff --git a/likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java b/likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java new file mode 100644 index 00000000..847cb5cc --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/alarm/controller/AlarmController.java @@ -0,0 +1,25 @@ +package likelion.univ.alarm.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import likelion.univ.alarm.dto.request.AlarmRegisterRequestDto; +import likelion.univ.alarm.usecase.RegisterAlarmUseCase; +import likelion.univ.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/v1/alarm") +@Tag(name = "알람", description = "알람 API") +public class AlarmController { + private final RegisterAlarmUseCase registerAlarmUseCase; + + @Operation(summary = "알람 등록", description = "이메일과 알람 타입을 입력받아 해당 기수의 알람을 등록합니다.") + @PostMapping("/{ordinal}/register") + public SuccessResponse registerAlarm(@PathVariable Long ordinal, + @RequestBody AlarmRegisterRequestDto alarmRegisterRequestDto){ + registerAlarmUseCase.execute(ordinal, alarmRegisterRequestDto); + return SuccessResponse.empty(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java b/likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java new file mode 100644 index 00000000..d7454965 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/alarm/dto/request/AlarmRegisterRequestDto.java @@ -0,0 +1,32 @@ +package likelion.univ.alarm.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import likelion.univ.domain.alarm.entity.SendStatus; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + +import static likelion.univ.domain.alarm.entity.SendStatus.NOT_SENT; + +@Getter +@NoArgsConstructor +public class AlarmRegisterRequestDto { + @NotNull + @Schema(description = "이메일", example = "tmfrk0426@gmail.com", required = true) + private String email; + + @NotNull + @Schema(description = "알람 타입", example = "NEW_UNIVERSITY_RECRUITING", required = true, enumAsRef = true) + private AlarmType alarmType; + + public static Alarm toEntity(Long ordinal, AlarmRegisterRequestDto alarmRegisterRequestDto){ + return Alarm.builder() + .ordinal(ordinal) + .email(alarmRegisterRequestDto.getEmail()) + .alarmType(alarmRegisterRequestDto.getAlarmType()) + .sendStatus(NOT_SENT) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java b/likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java new file mode 100644 index 00000000..0c7e9e7c --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/alarm/usecase/RegisterAlarmUseCase.java @@ -0,0 +1,22 @@ +package likelion.univ.alarm.usecase; + +import likelion.univ.alarm.dto.request.AlarmRegisterRequestDto; +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.alarm.adaptor.AlarmAdaptor; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.service.AlarmDomainService; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class RegisterAlarmUseCase { + private final AlarmAdaptor alarmAdaptor; + private final AlarmDomainService alarmDomainService; + + public void execute(Long ordinal, AlarmRegisterRequestDto alarmRegisterRequestDto){ + alarmAdaptor.existsByOrdinalAndEmailAndAlarmType(ordinal, + alarmRegisterRequestDto.getEmail(), alarmRegisterRequestDto.getAlarmType()); + Alarm newAlarm = AlarmRegisterRequestDto.toEntity(ordinal, alarmRegisterRequestDto); + alarmDomainService.createAlarm(newAlarm); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java b/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java index 25f4283c..5a171bf3 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java +++ b/likelion-client/src/main/java/likelion/univ/auth/controller/AuthController.java @@ -3,11 +3,9 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import likelion.univ.auth.dto.response.AccountTokenDto; +import likelion.univ.auth.dto.response.AccountUserInfoDto; import likelion.univ.auth.dto.response.IdTokenDto; -import likelion.univ.auth.usecase.LoginUseCase; -import likelion.univ.auth.usecase.RefreshTokenUseCase; -import likelion.univ.auth.usecase.RequestIdTokenUseCase; -import likelion.univ.auth.usecase.SignUpUseCase; +import likelion.univ.auth.usecase.*; import likelion.univ.auth.dto.request.SignUpRequestDto; import likelion.univ.response.SuccessResponse; import likelion.univ.utils.AuthentiatedUserUtils; @@ -24,7 +22,7 @@ public class AuthController { private final RequestIdTokenUseCase requestIdTokenUseCase; private final SignUpUseCase signUpUseCase; private final RefreshTokenUseCase refreshTokenUseCase; - private final AuthentiatedUserUtils userUtils; + private final GetUserInfoUseCase getUserInfoUsecase; @Operation(summary = "id token 발급", description = "인가 코드로 id token을 발급받습니다.") @GetMapping("/{logintype}/idtoken") @@ -55,6 +53,13 @@ public SuccessResponse signUp( return SuccessResponse.of(accountTokenDto); } + @Operation(summary = "유저 정보 조회", description = "간단한 유저정보를 조회합니다.") + @GetMapping("/userinfo") + public SuccessResponse getUserInfo(){ + AccountUserInfoDto accountUserInfoDto = getUserInfoUsecase.execute(); + return SuccessResponse.of(accountUserInfoDto); + } + @Operation(summary = "토큰 재발급", description = "refresh token으로 access token을 재발급합니다.") @PostMapping("/refresh") public SuccessResponse refreshToken( @@ -62,10 +67,4 @@ public SuccessResponse refreshToken( AccountTokenDto accountTokenDto = refreshTokenUseCase.execute(refreshToken); return SuccessResponse.of(accountTokenDto); } - - @Operation(summary = "로그인 유저 Id 반환", description = "(for client only) 로그인 중인 유저의 Id를 얻습니다.") - @GetMapping("/loginuserid") - public SuccessResponse getLoginUserId() { - return SuccessResponse.of(userUtils.getCurrentUserId()); - } } diff --git a/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java b/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java new file mode 100644 index 00000000..5553f3f9 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/auth/dto/response/AccountUserInfoDto.java @@ -0,0 +1,22 @@ +package likelion.univ.auth.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class AccountUserInfoDto { + private Long userId; + private String profileImage; + private String name; + + public static AccountUserInfoDto of(User user){ + return AccountUserInfoDto.builder() + .userId(user.getId()) + .profileImage(user.getProfile().getProfileImage()) + .name(user.getProfile().getName()) + .build(); + } + +} diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/processor/GenerateAccountTokenProcessor.java b/likelion-client/src/main/java/likelion/univ/auth/processor/GenerateAccountTokenProcessor.java similarity index 96% rename from likelion-client/src/main/java/likelion/univ/auth/usecase/processor/GenerateAccountTokenProcessor.java rename to likelion-client/src/main/java/likelion/univ/auth/processor/GenerateAccountTokenProcessor.java index f870f8a7..3e8e2345 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/processor/GenerateAccountTokenProcessor.java +++ b/likelion-client/src/main/java/likelion/univ/auth/processor/GenerateAccountTokenProcessor.java @@ -1,4 +1,4 @@ -package likelion.univ.auth.usecase.processor; +package likelion.univ.auth.processor; import likelion.univ.annotation.Processor; import likelion.univ.auth.dto.response.AccountTokenDto; diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/processor/LoginByIdTokenProcessor.java b/likelion-client/src/main/java/likelion/univ/auth/processor/LoginByIdTokenProcessor.java similarity index 97% rename from likelion-client/src/main/java/likelion/univ/auth/usecase/processor/LoginByIdTokenProcessor.java rename to likelion-client/src/main/java/likelion/univ/auth/processor/LoginByIdTokenProcessor.java index f80cbe0d..3c5e3633 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/processor/LoginByIdTokenProcessor.java +++ b/likelion-client/src/main/java/likelion/univ/auth/processor/LoginByIdTokenProcessor.java @@ -1,4 +1,4 @@ -package likelion.univ.auth.usecase.processor; +package likelion.univ.auth.processor; import likelion.univ.annotation.Processor; import likelion.univ.feign.oauth.oidc.PublicKeyDto; diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/processor/PublicKeyProcessor.java b/likelion-client/src/main/java/likelion/univ/auth/processor/PublicKeyProcessor.java similarity index 96% rename from likelion-client/src/main/java/likelion/univ/auth/usecase/processor/PublicKeyProcessor.java rename to likelion-client/src/main/java/likelion/univ/auth/processor/PublicKeyProcessor.java index c3a00403..d4e4b49b 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/processor/PublicKeyProcessor.java +++ b/likelion-client/src/main/java/likelion/univ/auth/processor/PublicKeyProcessor.java @@ -1,4 +1,4 @@ -package likelion.univ.auth.usecase.processor; +package likelion.univ.auth.processor; import likelion.univ.annotation.Processor; import likelion.univ.feign.oauth.google.RequestGooglePublicKeysClient; diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java b/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java new file mode 100644 index 00000000..a9b5dadd --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/auth/usecase/GetUserInfoUseCase.java @@ -0,0 +1,19 @@ +package likelion.univ.auth.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.auth.dto.response.AccountUserInfoDto; +import likelion.univ.domain.user.entity.User; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class GetUserInfoUseCase { + + private final AuthentiatedUserUtils authentiatedUserUtils; + + public AccountUserInfoDto execute(){ + User user = authentiatedUserUtils.getCurrentUser(); + return AccountUserInfoDto.of(user); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/LoginUseCase.java b/likelion-client/src/main/java/likelion/univ/auth/usecase/LoginUseCase.java index 1e0c5554..2f0d1e9b 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/LoginUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/auth/usecase/LoginUseCase.java @@ -2,8 +2,8 @@ import likelion.univ.annotation.UseCase; import likelion.univ.auth.dto.response.AccountTokenDto; -import likelion.univ.auth.usecase.processor.GenerateAccountTokenProcessor; -import likelion.univ.auth.usecase.processor.LoginByIdTokenProcessor; +import likelion.univ.auth.processor.GenerateAccountTokenProcessor; +import likelion.univ.auth.processor.LoginByIdTokenProcessor; import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.LoginType; import likelion.univ.domain.user.entity.User; diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/RefreshTokenUseCase.java b/likelion-client/src/main/java/likelion/univ/auth/usecase/RefreshTokenUseCase.java index 9fa48afc..9f1dcc33 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/RefreshTokenUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/auth/usecase/RefreshTokenUseCase.java @@ -2,7 +2,7 @@ import likelion.univ.annotation.UseCase; import likelion.univ.auth.dto.response.AccountTokenDto; -import likelion.univ.auth.usecase.processor.GenerateAccountTokenProcessor; +import likelion.univ.auth.processor.GenerateAccountTokenProcessor; import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.User; import likelion.univ.exception.InvalidTokenException; diff --git a/likelion-client/src/main/java/likelion/univ/auth/usecase/SignUpUseCase.java b/likelion-client/src/main/java/likelion/univ/auth/usecase/SignUpUseCase.java index e77d320e..f22d634c 100644 --- a/likelion-client/src/main/java/likelion/univ/auth/usecase/SignUpUseCase.java +++ b/likelion-client/src/main/java/likelion/univ/auth/usecase/SignUpUseCase.java @@ -3,8 +3,8 @@ import likelion.univ.annotation.UseCase; import likelion.univ.auth.dto.request.SignUpRequestDto; import likelion.univ.auth.dto.response.AccountTokenDto; -import likelion.univ.auth.usecase.processor.GenerateAccountTokenProcessor; -import likelion.univ.auth.usecase.processor.LoginByIdTokenProcessor; +import likelion.univ.auth.processor.GenerateAccountTokenProcessor; +import likelion.univ.auth.processor.LoginByIdTokenProcessor; import likelion.univ.domain.university.adaptor.UniversityAdaptor; import likelion.univ.domain.university.entity.University; import likelion.univ.domain.user.adaptor.UserAdaptor; diff --git a/likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java b/likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java new file mode 100644 index 00000000..33a7cbc9 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/follow/controller/FollowController.java @@ -0,0 +1,33 @@ +package likelion.univ.follow.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import likelion.univ.follow.usecase.CancelFollowUseCase; +import likelion.univ.follow.usecase.FollowUserUseCase; +import likelion.univ.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/v1/follow") +@Tag(name = "팔로우", description = "팔로우 관련 API입니다.") +public class FollowController { + private final FollowUserUseCase followUserUseCase; + private final CancelFollowUseCase cancelFollowUseCase; + + @Operation(summary = "팔로우 ", description = "해당 유저를 팔로우 합니다.") + @PostMapping("/{userId}") + public SuccessResponse follow(@PathVariable("userId") Long userId){ + followUserUseCase.execute(userId); + return SuccessResponse.empty(); + } + + @Operation(summary = "팔로우 취소", description = "해당 유저를 팔로우 취소 합니다.") + @DeleteMapping("/{userId}") + public SuccessResponse deleteFollow(@PathVariable("userId") Long userId) { + cancelFollowUseCase.execute(userId); + return SuccessResponse.empty(); + } +} + diff --git a/likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java b/likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java new file mode 100644 index 00000000..31b38569 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/follow/usecase/CancelFollowUseCase.java @@ -0,0 +1,33 @@ +package likelion.univ.follow.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.follow.adaptor.FollowAdaptor; +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.follow.entity.FollowNum; +import likelion.univ.follow.service.FollowNumRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class CancelFollowUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final FollowAdaptor followAdaptor; + private final FollowNumRedisDao followNumRedisDao; + private final FollowNumRedisService followNumRedisService; + + public void execute(Long userId){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + followAdaptor.delete(currentUserId, userId); + updateFollowNumRedis(currentUserId, userId); + } + + private void updateFollowNumRedis(Long currentUserId, Long userId){ + Optional myFollowNum = followNumRedisDao.findById(currentUserId); + if(myFollowNum.isPresent()) followNumRedisService.followingDown(currentUserId, myFollowNum.get()); + Optional targetFollowNum = followNumRedisDao.findById(userId); + if(targetFollowNum.isPresent()) followNumRedisService.followerDown(userId, targetFollowNum.get()); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java b/likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java new file mode 100644 index 00000000..3726330c --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/follow/usecase/FollowUserUseCase.java @@ -0,0 +1,33 @@ +package likelion.univ.follow.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.follow.adaptor.FollowAdaptor; +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.follow.entity.FollowNum; +import likelion.univ.follow.service.FollowNumRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class FollowUserUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final FollowAdaptor followAdaptor; + private final FollowNumRedisDao followNumRedisDao; + private final FollowNumRedisService followNumRedisService; + + public void execute(Long userId){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + followAdaptor.save(currentUserId, userId); + updateFollowNumRedis(currentUserId, userId); + } + + private void updateFollowNumRedis(Long currentUserId, Long userId){ + Optional myFollowNum = followNumRedisDao.findById(currentUserId); + if(myFollowNum.isPresent()) followNumRedisService.followingUp(currentUserId, myFollowNum.get()); + Optional targetFollowNum = followNumRedisDao.findById(userId); + if(targetFollowNum.isPresent()) followNumRedisService.followerUp(userId, targetFollowNum.get()); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/post/processor/GetOrCreatePostCountInfoProcessor.java b/likelion-client/src/main/java/likelion/univ/post/processor/GetOrCreatePostCountInfoProcessor.java new file mode 100644 index 00000000..c244c84d --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/post/processor/GetOrCreatePostCountInfoProcessor.java @@ -0,0 +1,30 @@ +package likelion.univ.post.processor; + +import likelion.univ.annotation.Processor; +import likelion.univ.domain.comment.adaptor.CommentAdaptor; +import likelion.univ.domain.like.postlike.adaptor.PostLikeAdaptor; +import likelion.univ.post.dao.PostCountInfoRedisDao; +import likelion.univ.post.entity.PostCountInfo; +import likelion.univ.post.service.PostCountInfoRedisService; +import lombok.RequiredArgsConstructor; + +import java.util.Optional; + +@Processor +@RequiredArgsConstructor +public class GetOrCreatePostCountInfoProcessor { + + private final PostCountInfoRedisDao postCountInfoRedisDao; + private final PostCountInfoRedisService postCountInfoRedisService; + private final CommentAdaptor commentAdaptor; + private final PostLikeAdaptor postLikeAdaptor; + + public PostCountInfo execute(Long postId){ + Optional postCountInfo = postCountInfoRedisDao.findById(postId); + if(postCountInfo.isEmpty()){ + Long commentCount = commentAdaptor.countByPostId(postId); + Long likeCount = postLikeAdaptor.countByPostId(postId); + return postCountInfoRedisService.save(postId, commentCount, likeCount); + }else return postCountInfo.get(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java b/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java index ddec26d7..e925bab4 100644 --- a/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java +++ b/likelion-client/src/main/java/likelion/univ/post/repository/PostReadRepositoryCustomImpl.java @@ -1,6 +1,6 @@ package likelion.univ.post.repository; -import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; import likelion.univ.domain.post.dto.response.PostDetailResponseDto; import likelion.univ.domain.post.dto.response.QPostDetailResponseDto; import likelion.univ.domain.post.entity.enums.MainCategory; @@ -9,7 +9,6 @@ import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.springframework.data.domain.Pageable; -import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.stereotype.Repository; import java.util.List; diff --git a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java new file mode 100644 index 00000000..f8efaaec --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java @@ -0,0 +1,108 @@ +package likelion.univ.user.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import likelion.univ.common.response.PageResponse; +import likelion.univ.common.response.SliceResponse; +import likelion.univ.user.dto.request.ProfileEditRequestDto; +import likelion.univ.user.dto.response.FollowUserInfoDto; +import likelion.univ.user.dto.response.UserPagePostsDto; +import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.user.dto.response.UserSearchResultDto; +import likelion.univ.user.usecase.*; +import likelion.univ.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springdoc.api.annotations.ParameterObject; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/v1/user") +@Tag(name = "유저페이지", description = "유저페이지관련 API입니다.") +public class UserController { + private final GetProfileUseCase getProfileUseCase; + private final EditProfileUseCase editProfileUseCase; + private final GetUserPostsUseCase getMyPostsUseCase; + private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; + private final GetFollowInfoUseCase getFollowingListUseCase; + private final SearchUserByNameUseCase searchUserByNameUseCase; + + @Operation(summary = "유저페이지 프로필 조회", description = "해당 유저의 프로필 정보를 조회합니다.") + @GetMapping("/{userId}/profile") + public SuccessResponse getProfile(@PathVariable Long userId){ + ProfileDetailsDto profileDetailsDto = getProfileUseCase.execute(userId); + return SuccessResponse.of(profileDetailsDto); + } + + @Operation(summary = "유저페이지 프로필 수정", description = "해당 유저의 프로필 정보를 수정합니다.") + @PatchMapping("/{userId}/profile") + public SuccessResponse editProfile(@PathVariable Long userId, + @RequestBody ProfileEditRequestDto profileEditRequestDto){ + editProfileUseCase.execute(userId,profileEditRequestDto); + return SuccessResponse.empty(); + } + + @Operation(summary = "팔로잉 목록 조회", description = "해당 유저의 팔로잉 목록을 조회합니다.") + @GetMapping("/{userId}/following") + public SuccessResponse getFollowingList(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 4, page = 1) Pageable pageable){ + SliceResponse followingUsers = getFollowingListUseCase.executeForFollowing(userId,pageable); + return SuccessResponse.of(followingUsers); + } + + @Operation(summary = "팔로워 목록 조회", description = "해당 유저의 팔로워 목록을 조회합니다.") + @GetMapping("/{userId}/follower") + public SuccessResponse getFollowerList(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 4, page = 1) Pageable pageable){ + SliceResponse followerUsers = getFollowingListUseCase.executeForFollower(userId,pageable); + return SuccessResponse.of(followerUsers); + } + @Operation(summary = "해당 유저가 쓴 게시글 조회", description = "해당 유저가 작성한 게시글을 조회합니다.") + @GetMapping("/{userId}/posts") + public SuccessResponse getMyPosts(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + PageResponse myPagePostsPage = getMyPostsUseCase.execute(userId, pageable); + return SuccessResponse.of(myPagePostsPage); + } + + @Operation(summary = "해당 유저가 댓글 쓴 게시글 조회", description = "해당 유저가 댓글을 작성한 게시글을 조회합니다.") + @GetMapping("/{userId}/comments") + public SuccessResponse getPostsCommentedByMe(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + PageResponse myPagePostsPageCommentedByMe = getPostsCommentedByMeUseCase.execute(userId, pageable); + return SuccessResponse.of(myPagePostsPageCommentedByMe); + } + + @Operation(summary = "유저 검색 (Simple Data) (project page)", description = "이름으로 유저를 검색합니다. (프로젝트 페이지 모달)") + @GetMapping("/search") + public SuccessResponse searchUser(@RequestParam(required = false) String name, + @ParameterObject @PageableDefault(size = 4, page = 1) Pageable pageable){ + SliceResponse searchedUsers = searchUserByNameUseCase.execute(name, pageable); + return SuccessResponse.of(searchedUsers); + } + + +// @Operation(summary = "내가 참여한 프로젝트 조회", description = "참여한 프로젝트를 조회합니다.") +// @GetMapping("/projects") +// public SuccessResponse getMyProjects(@ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ +// +// return SuccessResponse.of(); +// } +// +// @Operation(summary = "휴대폰 인증 요청", description = "휴대폰 번호 인증을 위해 서버 내부에 인증번호를 생성합니다.") +// @PostMapping("/phone/certify") +// public SuccessResponse login(@RequestParam("phonenum") String phoneNum){ +// return SuccessResponse.of(); +// } +// +// @Operation(summary = "휴대폰 인증번호 확인", description = "휴대폰 인증번호 확인 후 인증 토큰을 발급합니다.") +// @PostMapping("/phone/certify/check") +// public SuccessResponse getIdToken(@RequestParam("certifynum") Long certifyNum){ +// +// return SuccessResponse.of(); +// } + +} + diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java new file mode 100644 index 00000000..3cff2535 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/request/ProfileEditRequestDto.java @@ -0,0 +1,36 @@ +package likelion.univ.user.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import likelion.univ.domain.user.entity.Part; +import likelion.univ.domain.user.entity.Profile; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + + +@Getter +@NoArgsConstructor +public class ProfileEditRequestDto { + @NotNull + @Schema(description = "이름", example = "김슬기", required = true) + private String name; + + @Schema(description = "한줄 소개", example = "안녕하세요. 김슬기입니다.", required = false) + private String introduction; + + @Schema(description = "프로필 이미지", example = "", required = false) + private String profileImage; + + @NotNull + @Schema(description = "트랙(파트)", example = "BACKEND", required = true, enumAsRef = true) + private Part part; + + public Profile toProfile(){ + return Profile.builder() + .name(name) + .profileImage(profileImage) + .introduction(introduction) + .part(part) + .build(); + } +} \ No newline at end of file diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java new file mode 100644 index 00000000..7259d21a --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/FollowUserInfoDto.java @@ -0,0 +1,27 @@ +package likelion.univ.user.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class FollowUserInfoDto { + private Long userId; + private String name; + private String profileImage; + private Long ordinal; + private String part; + private Boolean isFollowed; + + public static FollowUserInfoDto of(User user, Boolean isFollowed){ + return FollowUserInfoDto.builder() + .userId(user.getId()) + .name(user.getProfile().getName()) + .profileImage(user.getProfile().getProfileImage()) + .ordinal(user.getUniversityInfo().getOrdinal()) + .part(user.getProfile().getPart().toString()) + .isFollowed(isFollowed) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java new file mode 100644 index 00000000..de0b2128 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/ProfileDetailsDto.java @@ -0,0 +1,41 @@ +package likelion.univ.user.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ProfileDetailsDto { + private Long id; + private String profileImage; + private String name; + private String role; + private String phoneNum; + private String universityName; + private String major; + private Long ordinal; + private String part; + private Long followerNum; + private Long followingNum; + private String introduction; + private Boolean isMine; + + public static ProfileDetailsDto of(User user, Boolean isMine,Long followerNum, Long followingNum){ + return ProfileDetailsDto.builder() + .id(user.getId()) + .profileImage(user.getProfile().getProfileImage()) + .name(user.getProfile().getName()) + .role(user.getAuthInfo().getRole().getValue()) + .phoneNum(user.getAuthInfo().getPhoneNumber()) + .universityName(user.getUniversityInfo().getUniversity().getName()) + .major(user.getUniversityInfo().getMajor()) + .ordinal(user.getUniversityInfo().getOrdinal()) + .part(user.getProfile().getPart().toString()) + .followerNum(followerNum) + .followingNum(followingNum) + .introduction(user.getProfile().getIntroduction()) + .isMine(isMine) + .build(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java new file mode 100644 index 00000000..d519ff6e --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserPagePostsDto.java @@ -0,0 +1,41 @@ +package likelion.univ.user.dto.response; + +import likelion.univ.domain.post.entity.Post; +import likelion.univ.post.entity.PostCountInfo; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDate; + + +@Getter +@Builder +public class UserPagePostsDto { + private Long id; + private String title; + private String body; + private String thumbnail; + private Boolean isAuthor; + private LocalDate createdDate; + private Long likeCount; + private Long commentCount; + + public static UserPagePostsDto of(Post post, Long likeCount, Long commentCount, Boolean isAuthor){ + return UserPagePostsDto.builder() + .id(post.getId()) + .title(post.getTitle()) + .body(post.getBody()) + .thumbnail(post.getThumbnail()) + .isAuthor(isAuthor) + .createdDate(post.getCreatedDate().toLocalDate()) + .likeCount(likeCount) + .commentCount(commentCount) + .build(); + } + + public static UserPagePostsDto of(Post post, Long userId, PostCountInfo postCountInfo){ + if(post.getAuthor().getId().equals(userId)) + return UserPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),true); + else return UserPagePostsDto.of(post, postCountInfo.getLikeCount(), postCountInfo.getCommentCount(),false); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java new file mode 100644 index 00000000..052e767d --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/dto/response/UserSearchResultDto.java @@ -0,0 +1,28 @@ +package likelion.univ.user.dto.response; + +import likelion.univ.domain.user.entity.User; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserSearchResultDto { + private Long userId; + private String name; + private String profileImage; + private String universityName; + private Long ordinal; + private String part; + + public static UserSearchResultDto of(User user){ + return UserSearchResultDto.builder() + .userId(user.getId()) + .name(user.getProfile().getName()) + .profileImage(user.getProfile().getProfileImage()) + .universityName(user.getUniversityInfo().getUniversity().getName()) + .ordinal(user.getUniversityInfo().getOrdinal()) + .part(user.getProfile().getPart().getValue()) + .build(); + } + +} diff --git a/likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java b/likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java new file mode 100644 index 00000000..45bb7cd9 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/scheduler/UserPageScheduler.java @@ -0,0 +1,4 @@ +package likelion.univ.user.scheduler; + +//public class MyPageScheduler { +//} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java new file mode 100644 index 00000000..0b9df489 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/EditProfileUseCase.java @@ -0,0 +1,24 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.user.entity.Profile; +import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.service.UserDomainService; +import likelion.univ.user.dto.request.ProfileEditRequestDto; +import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +@UseCase +@RequiredArgsConstructor +public class EditProfileUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final UserDomainService userDomainService; + + public void execute(Long userId, ProfileEditRequestDto profileEditRequestDto){ + authentiatedUserUtils.checkidentification(userId); + + Profile profile = profileEditRequestDto.toProfile(); + User user = userDomainService.editProfile(userId, profile); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java new file mode 100644 index 00000000..8a963a36 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetFollowInfoUseCase.java @@ -0,0 +1,45 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.SliceResponse; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.User; +import likelion.univ.user.dto.response.FollowUserInfoDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +import java.util.List; + +@UseCase +@RequiredArgsConstructor +public class GetFollowInfoUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final UserAdaptor userAdaptor; + + public SliceResponse executeForFollowing(Long userId, Pageable pageable){ + Slice userSlice = userAdaptor.findFollowingUsersByFollowerID(userId, pageable); + List myFollowingUsers = getMyFollowingUsers(userSlice); + + return SliceResponse.of(userSlice.map(u -> + FollowUserInfoDto.of(u, checkIFollowingTarget(u, myFollowingUsers)))); + } + + public SliceResponse executeForFollower(Long userId, Pageable pageable){ + Slice userSlice = userAdaptor.findFollowerUsersByFollowingID(userId, pageable); + List myFollowingUsers = getMyFollowingUsers(userSlice); + + return SliceResponse.of(userSlice.map(u -> + FollowUserInfoDto.of(u, checkIFollowingTarget(u, myFollowingUsers)))); + } + private List getMyFollowingUsers(Slice userSlice){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + List followingUserIds = userSlice.getContent().stream().map(user -> user.getId()).toList(); + return userAdaptor.findMyFollowingUsersByFollowingIdIn(currentUserId, followingUserIds); + } + + private Boolean checkIFollowingTarget(User target, List myFollowingUsers){ + return myFollowingUsers.stream().anyMatch(u -> u.getId().equals(target.getId())); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java new file mode 100644 index 00000000..5143575b --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetPostsCommentedByMeUseCase.java @@ -0,0 +1,28 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.PageResponse; +import likelion.univ.domain.post.adaptor.PostAdaptor; +import likelion.univ.domain.post.entity.Post; +import likelion.univ.post.processor.GetOrCreatePostCountInfoProcessor; +import likelion.univ.user.dto.response.UserPagePostsDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +@UseCase +@RequiredArgsConstructor +public class GetPostsCommentedByMeUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final PostAdaptor postAdaptor; + private final GetOrCreatePostCountInfoProcessor getOrCreatePostCountInfoProcessor; + + public PageResponse execute(Long userId, Pageable pageable){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + Page posts = postAdaptor.findByCommentAuthorId(userId, pageable); + + return PageResponse.of(posts.map(p-> UserPagePostsDto.of(p, currentUserId, getOrCreatePostCountInfoProcessor.execute(p.getId())))); + } + +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java new file mode 100644 index 00000000..325bc2ac --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetProfileUseCase.java @@ -0,0 +1,48 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.domain.follow.adaptor.FollowAdaptor; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.User; +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.user.dto.response.ProfileDetailsDto; +import likelion.univ.follow.entity.FollowNum; +import likelion.univ.follow.service.FollowNumRedisService; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class GetProfileUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final UserAdaptor userAdaptor; + private final FollowNumRedisDao followNumRedisDao; + private final FollowNumRedisService followNumRedisService; + private final FollowAdaptor followAdaptor; + + public ProfileDetailsDto execute(Long userId){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + User user = userAdaptor.findByIdWithUniversity(userId); + + return createDto(user, currentUserId); + } + + private ProfileDetailsDto createDto(User user, Long currentUserId){ + FollowNum followNum = getUserFollowNum(user.getId()); + + if (user.getId().equals(currentUserId)) + return ProfileDetailsDto.of(user, true, followNum.getFollowerNum(), followNum.getFollowingNum()); + else return ProfileDetailsDto.of(user, false, followNum.getFollowerNum(), followNum.getFollowingNum()); + } + + private FollowNum getUserFollowNum(Long userId){ + Optional userFollowNum = followNumRedisDao.findById(userId); + if(userFollowNum.isEmpty()){ + Long followerNum = followAdaptor.countByFollowingId(userId); + Long followingNum = followAdaptor.countByFollowerId(userId); + return followNumRedisService.save(userId, followerNum, followingNum); + }else return userFollowNum.get(); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java new file mode 100644 index 00000000..683f838a --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserPostsUseCase.java @@ -0,0 +1,32 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.PageResponse; +import likelion.univ.domain.post.adaptor.PostAdaptor; +import likelion.univ.domain.post.entity.Post; +import likelion.univ.post.processor.GetOrCreatePostCountInfoProcessor; +import likelion.univ.user.dto.response.UserPagePostsDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.Optional; + +@UseCase +@RequiredArgsConstructor +public class GetUserPostsUseCase { + + private final AuthentiatedUserUtils authentiatedUserUtils; + private final PostAdaptor postAdaptor; + private final GetOrCreatePostCountInfoProcessor getOrCreatePostCountInfoProcessor; + + public PageResponse execute(Long userId, Pageable pageable){ + Long currentUserIdId = authentiatedUserUtils.getCurrentUserId(); + Page posts = postAdaptor.findAllByAuthor_Id(userId, pageable); + + + return PageResponse.of(posts.map(p-> UserPagePostsDto.of(p, currentUserIdId, + getOrCreatePostCountInfoProcessor.execute(p.getId())))); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java new file mode 100644 index 00000000..9a803181 --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/SearchUserByNameUseCase.java @@ -0,0 +1,22 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.SliceResponse; +import likelion.univ.domain.user.adaptor.UserAdaptor; +import likelion.univ.domain.user.entity.User; +import likelion.univ.user.dto.response.UserSearchResultDto; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +@UseCase +@RequiredArgsConstructor +public class SearchUserByNameUseCase { + private final UserAdaptor userAdaptor; + + public SliceResponse execute(String name, Pageable pageable){ + System.out.println(name); + Slice userSlice = userAdaptor.searchByName(name, pageable); + return SliceResponse.of(userSlice.map(u -> UserSearchResultDto.of(u))); + } +} diff --git a/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java b/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java index 489dc643..0bfc856f 100644 --- a/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java +++ b/likelion-client/src/main/java/likelion/univ/utils/AuthentiatedUserUtils.java @@ -2,6 +2,7 @@ import likelion.univ.domain.user.adaptor.UserAdaptor; import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.exception.UserNotMatchException; import likelion.univ.security.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -18,4 +19,9 @@ public Long getCurrentUserId() { public User getCurrentUser() { return userAdaptor.findById(getCurrentUserId()); } + + public void checkidentification(Long userId){ + if(!SecurityUtils.getCurrentUserId().equals(userId)) + throw new UserNotMatchException(); + } } diff --git a/likelion-client/src/main/resources/application.yml b/likelion-client/src/main/resources/application.yml index 5fb5850e..066b827b 100644 --- a/likelion-client/src/main/resources/application.yml +++ b/likelion-client/src/main/resources/application.yml @@ -7,11 +7,6 @@ spring: - infrastructure - security - redis -# data: -# web: -# pageable: ##페이징 -# default-page-size: 5 #기획에 따라 5페이지가 기본 -# one-indexed-parameters: true #1페이지부터 시작, default:0페이지 # 황제철의견 : 동작원리가 안보이는데 이게 원하는대로 동작하고 있지 않는 것 같아요. 원하는 효과가 간단해서 일단 그냥 로직에 포함하겠습니다. server: servlet: @@ -19,7 +14,6 @@ server: springdoc: default-consumes-media-type: application/json;charset=UTF-8 - default-produces-media-type: application/json;charset=UTF-8 api-docs: enabled: ${SWAGGER_ENABLED} path: '/swagger' diff --git a/likelion-core/build.gradle b/likelion-core/build.gradle index ad09a576..47634f29 100644 --- a/likelion-core/build.gradle +++ b/likelion-core/build.gradle @@ -12,11 +12,11 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' runtimeOnly 'com.h2database:h2' implementation group: 'com.mysql', name: 'mysql-connector-j' - - // Querydsl + // Querydsl api 'com.querydsl:querydsl-jpa' api 'com.querydsl:querydsl-core' - // Querydsl JPAAnnotationProcessor 사용 지정 + implementation project(path: ':likelion-common') + // Querydsl JPAAnnotationProcessor 사용 지정 annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" annotationProcessor("jakarta.persistence:jakarta.persistence-api") // java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 대응 annotationProcessor("jakarta.annotation:jakarta.annotation-api") // java.lang.NoClassDefFoundError (javax.annotation.Generated) 발생 대응 diff --git a/likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java b/likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java new file mode 100644 index 00000000..8e273610 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/common/processor/ConvertSliceProcessor.java @@ -0,0 +1,25 @@ +package likelion.univ.common.processor; + +import likelion.univ.annotation.Processor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; + +import java.util.List; + +@Processor +public class ConvertSliceProcessor { + + public Slice execute(List contents, Pageable pageable) { + if (hasNext(contents, pageable)) + return new SliceImpl<>(subContentOne(contents, pageable), pageable, true); + else return new SliceImpl<>(contents, pageable, false); + } + + private Boolean hasNext(List content, Pageable pageable) { + return pageable.isPaged() && content.size() > pageable.getPageSize(); + } + private List subContentOne(List content, Pageable pageable) { + return content.subList(0, pageable.getPageSize()); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java b/likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java new file mode 100644 index 00000000..07e35a10 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/common/response/PageResponse.java @@ -0,0 +1,34 @@ +package likelion.univ.common.response; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.domain.Page; + +import java.util.List; + +@Getter +@Builder +public class PageResponse { + private int totalPage; + private Long totalElements; + private int pagingSize; + private int currentPage; + private Boolean isFirst; + private Boolean isLast; + private Boolean isEmpty; + private List data; + + + public static PageResponse of(Page page) { + return PageResponse.builder() + .totalPage(page.getTotalPages()) + .totalElements(page.getTotalElements()) + .pagingSize(page.getSize()) + .currentPage(page.getNumber()+1) + .isFirst(page.isFirst()) + .isLast(page.isLast()) + .isEmpty(page.isEmpty()) + .data(page.getContent()) + .build(); + } +} \ No newline at end of file diff --git a/likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java b/likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java new file mode 100644 index 00000000..3869e0b3 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/common/response/SliceResponse.java @@ -0,0 +1,26 @@ +package likelion.univ.common.response; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.data.domain.Slice; + +import java.util.List; + +@Getter +@Builder +public class SliceResponse { + + private int currentPage; + private int size; + private Boolean hasNext; + private List data; + + public static SliceResponse of(Slice slice) { + return SliceResponse.builder() + .currentPage(slice.getNumber()+1) + .size(slice.getNumberOfElements()) + .hasNext(slice.hasNext()) + .data(slice.getContent()) + .build(); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java new file mode 100644 index 00000000..8e76a1a1 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/adaptor/AlarmAdaptor.java @@ -0,0 +1,21 @@ +package likelion.univ.domain.alarm.adaptor; + +import likelion.univ.annotation.Adaptor; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import likelion.univ.domain.alarm.exception.EmailAlreadyRegisteredAsAlarmException; +import likelion.univ.domain.alarm.repository.AlarmRepository; +import lombok.RequiredArgsConstructor; + +@Adaptor +@RequiredArgsConstructor +public class AlarmAdaptor { + private final AlarmRepository alarmRepository; + + public Alarm save(Alarm alarm){ return alarmRepository.save(alarm);} + + public void existsByOrdinalAndEmailAndAlarmType(Long ordinal, String email, AlarmType alarmType) { + if (alarmRepository.existsByOrdinalAndEmailAndAlarmType(ordinal, email, alarmType)) + throw new EmailAlreadyRegisteredAsAlarmException(); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java new file mode 100644 index 00000000..4ba12003 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/Alarm.java @@ -0,0 +1,28 @@ +package likelion.univ.domain.alarm.entity; +import likelion.univ.common.entity.BaseTimeEntity; +import lombok.*; + +import javax.persistence.*; + +import static likelion.univ.domain.alarm.entity.SendStatus.NOT_SENT; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +@AllArgsConstructor +@Entity +public class Alarm extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Long ordinal; + + private String email; + + @Enumerated(EnumType.STRING) + private AlarmType alarmType; + + @Enumerated(EnumType.STRING) + private SendStatus sendStatus; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java new file mode 100644 index 00000000..4602f7f4 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/AlarmType.java @@ -0,0 +1,13 @@ +package likelion.univ.domain.alarm.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum AlarmType { + NEW_UNIVERSITY_RECRUITING("신규 대학 모집 알람"), + EXISTING_UNIVERSITY_RECRUITING("기존 대학 재신청 알람"); + + private String value; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java new file mode 100644 index 00000000..889b5e8c --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/entity/SendStatus.java @@ -0,0 +1,14 @@ +package likelion.univ.domain.alarm.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum SendStatus { + NOT_SENT("NOT_SENT"), + RESERVED("RESERVED"), + SENT("SENT"); + + private String value; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java new file mode 100644 index 00000000..beaabada --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/AlarmErrorCode.java @@ -0,0 +1,18 @@ +package likelion.univ.domain.alarm.exception; + +import likelion.univ.exception.base.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static likelion.univ.constant.StaticValue.*; + +@Getter +@AllArgsConstructor +public enum AlarmErrorCode implements BaseErrorCode { + EMAIL_ALREADY_REGISTERED_AS_ALARM(BAD_REQUEST, "ALARM_409", "해당 이메일은 이미 신청되어 있습니다."); + + + private final int httpStatus; + private final String code; + private final String message; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java new file mode 100644 index 00000000..5478c7a1 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/exception/EmailAlreadyRegisteredAsAlarmException.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.alarm.exception; + +import likelion.univ.exception.base.BaseException; + +public class EmailAlreadyRegisteredAsAlarmException extends BaseException { + public EmailAlreadyRegisteredAsAlarmException() { + super(AlarmErrorCode.EMAIL_ALREADY_REGISTERED_AS_ALARM); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java new file mode 100644 index 00000000..12ae20bf --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/repository/AlarmRepository.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.alarm.repository; + +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AlarmRepository extends JpaRepository { + boolean existsByOrdinalAndEmailAndAlarmType(Long ordinal, String email, AlarmType alarmType); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java b/likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java new file mode 100644 index 00000000..63b4a5a5 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/alarm/service/AlarmDomainService.java @@ -0,0 +1,23 @@ +package likelion.univ.domain.alarm.service; + +import likelion.univ.domain.alarm.adaptor.AlarmAdaptor; +import likelion.univ.domain.alarm.entity.Alarm; +import likelion.univ.domain.alarm.entity.AlarmType; +import likelion.univ.domain.alarm.entity.SendStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static likelion.univ.domain.alarm.entity.SendStatus.NOT_SENT; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class AlarmDomainService { + private final AlarmAdaptor alarmAdaptor; + + @Transactional + public Alarm createAlarm(Alarm alarm){ + return alarmAdaptor.save(alarm); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java index 9ba6cdb9..89fa64a8 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/adaptor/CommentAdaptor.java @@ -31,4 +31,7 @@ public List findAllByPost(Post post) { return commentRepository.findByPost(post); } + public Long countByPostId(Long postId){ + return commentRepository.countByPostId(postId); + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java index 415bfbad..a1d39e2b 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/entity/Comment.java @@ -16,11 +16,10 @@ @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "comments") +@Table(name = "comment") public class Comment extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "comment_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java b/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java index 4b522ddf..69d71652 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/comment/repository/CommentRepository.java @@ -10,4 +10,6 @@ public interface CommentRepository extends JpaRepository { @Query("SELECT c from Comment c JOIN FETCH c.author u JOIN FETCH c.post p JOIN FETCH c.parentComment pc") List findByPost(Post post); + + Long countByPostId(Long postId); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java b/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java index 3368c700..6f671abe 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java +++ b/likelion-core/src/main/java/likelion/univ/domain/example/entity/Example.java @@ -15,7 +15,6 @@ public class Example extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "example_id") private Long id; @Column(nullable = false) diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java new file mode 100644 index 00000000..416feedb --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/adaptor/FollowAdaptor.java @@ -0,0 +1,24 @@ +package likelion.univ.domain.follow.adaptor; + +import likelion.univ.annotation.Adaptor; +import likelion.univ.domain.follow.exception.AlreadyFollowingUserException; +import likelion.univ.domain.follow.repository.FollowRepository; +import lombok.RequiredArgsConstructor; + +@Adaptor +@RequiredArgsConstructor +public class FollowAdaptor { + private final FollowRepository followRepository; + + public Long countByFollowerId(Long followerId){ + return followRepository.countByFollowerId(followerId); + } + public Long countByFollowingId(Long followingId){ + return followRepository.countByFollowingId(followingId); + } + public void save(Long currentUserId, Long userId) { + try { followRepository.save(currentUserId,userId);} + catch(Exception e) { throw new AlreadyFollowingUserException(); } + } + public void delete(Long currentUserId, Long userId) { followRepository.delete(currentUserId,userId);} +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java index 38b98a5a..f1b6f5b4 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/entity/Follow.java @@ -11,11 +11,11 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity +@Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"follower_id", "following_id"})}) public class Follow extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "follow_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @@ -23,8 +23,8 @@ public class Follow extends BaseTimeEntity { private User follower; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "followee_id") - private User followee; + @JoinColumn(name = "following_id") + private User following; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java new file mode 100644 index 00000000..aa42d0c0 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/AlreadyFollowingUserException.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.follow.exception; + +import likelion.univ.exception.base.BaseException; + +public class AlreadyFollowingUserException extends BaseException { + public AlreadyFollowingUserException() { + super(FollowErrorCode.ALREADY_FOLLOWING_USER); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java new file mode 100644 index 00000000..5cbfce87 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/exception/FollowErrorCode.java @@ -0,0 +1,18 @@ +package likelion.univ.domain.follow.exception; + +import likelion.univ.exception.base.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static likelion.univ.constant.StaticValue.*; + +@Getter +@AllArgsConstructor +public enum FollowErrorCode implements BaseErrorCode { + ALREADY_FOLLOWING_USER(BAD_REQUEST, "FOLLOW_400_1", "이미 팔로우하고 있습니다."); + + + private final int httpStatus; + private final String code; + private final String message; +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java new file mode 100644 index 00000000..93f864e2 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/follow/repository/FollowRepository.java @@ -0,0 +1,23 @@ +package likelion.univ.domain.follow.repository; + +import likelion.univ.domain.follow.entity.Follow; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; + + +public interface FollowRepository extends JpaRepository { + Long countByFollowerId(Long followerId); + Long countByFollowingId(Long followingId); + @Modifying + @Transactional + @Query(value = "insert into follow(created_date, modified_date, follower_id, following_id)" + + "values (now(), now(), :currentId , :userId)", nativeQuery = true) + void save(Long currentId, Long userId); + + @Modifying + @Transactional + @Query("delete from Follow f where f.follower.id = :currentId and f.following.id = :userId") + void delete(Long currentId, Long userId); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/like/commentlike/entity/CommentLike.java b/likelion-core/src/main/java/likelion/univ/domain/like/commentlike/entity/CommentLike.java index 63404d9a..5b59995d 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/like/commentlike/entity/CommentLike.java +++ b/likelion-core/src/main/java/likelion/univ/domain/like/commentlike/entity/CommentLike.java @@ -15,7 +15,6 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CommentLike extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "like_comment_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/like/postlike/adaptor/PostLikeAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/like/postlike/adaptor/PostLikeAdaptor.java index 07ceeefe..ecc8c911 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/like/postlike/adaptor/PostLikeAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/like/postlike/adaptor/PostLikeAdaptor.java @@ -28,4 +28,7 @@ public PostLike find(Post post, User author) { public PostLike findById(Long postLikeId) { return postLikeRepository.findById(postLikeId).orElseThrow(() -> new PostLikeNotFoundException()); } + public Long countByPostId(Long postId){ + return postLikeRepository.countByPostId(postId); + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/like/postlike/entity/PostLike.java b/likelion-core/src/main/java/likelion/univ/domain/like/postlike/entity/PostLike.java index 31787729..f9ef7c8c 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/like/postlike/entity/PostLike.java +++ b/likelion-core/src/main/java/likelion/univ/domain/like/postlike/entity/PostLike.java @@ -16,7 +16,6 @@ @Builder public class PostLike { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "like_post_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/like/postlike/repository/PostLikeRepository.java b/likelion-core/src/main/java/likelion/univ/domain/like/postlike/repository/PostLikeRepository.java index e1fac128..e5f17658 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/like/postlike/repository/PostLikeRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/like/postlike/repository/PostLikeRepository.java @@ -9,4 +9,5 @@ public interface PostLikeRepository extends JpaRepository { Optional findByPostAndAuthor(Post post, User author); + Long countByPostId(Long postId); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java index ff7137c8..24e2132c 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/adaptor/PostAdaptor.java @@ -2,21 +2,16 @@ import likelion.univ.annotation.Adaptor; import likelion.univ.domain.post.entity.Post; -import likelion.univ.domain.post.exception.PostNotFoudException; -import likelion.univ.domain.post.repository.PostCommandRepository; -import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.post.repository.PostRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; - -import java.util.List; +import likelion.univ.domain.post.exception.PostNotFoudException; @Adaptor @RequiredArgsConstructor public class PostAdaptor { - - private final PostCommandRepository postRepository; - + private final PostRepository postRepository; public Long save(Post post) { Post savedPost = postRepository.save(post); @@ -31,4 +26,15 @@ public void delete(Post post) { postRepository.delete(post); //예외처리 } + public Page findAllByAuthor_Id(Long userId, Pageable pageable){ + return postRepository.findAllByAuthor_Id(userId,pageable); + } + + public Page findByCommentAuthorId(Long userId, Pageable pageable){ + return postRepository.findByCommentAuthorId(userId,pageable); + } + + public Page findByPostLikeAuthorId(Long userId, Pageable pageable){ + return postRepository.findByPostLikeAuthorId(userId,pageable); + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java b/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java index 946c48f9..f3a3f234 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/entity/Post.java @@ -20,7 +20,6 @@ public class Post extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "post_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepositoryImpl.java deleted file mode 100644 index e6a32b85..00000000 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepositoryImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package likelion.univ.domain.post.repository; - -import likelion.univ.domain.post.entity.Post; -import likelion.univ.domain.user.entity.User; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Repository; - -import java.util.List; - -import static likelion.univ.domain.post.entity.QPost.post; -import static likelion.univ.domain.user.entity.QUser.user; - -@Repository -public class PostCommandCustomRepositoryImpl implements PostCommandCustomRepository { - -} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandRepository.java deleted file mode 100644 index 8e1f2eb7..00000000 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package likelion.univ.domain.post.repository; - -import likelion.univ.domain.post.entity.Post; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PostCommandRepository extends JpaRepository, PostCommandCustomRepository { - - -} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java similarity index 50% rename from likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepository.java rename to likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java index c370bccf..7cb681ba 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCommandCustomRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostCustomRepository.java @@ -1,14 +1,10 @@ package likelion.univ.domain.post.repository; import likelion.univ.domain.post.entity.Post; -import likelion.univ.domain.user.entity.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import java.util.List; - -public interface PostCommandCustomRepository { - - - +public interface PostCustomRepository { + public Page findByCommentAuthorId(Long userId, Pageable pageable); + Page findByPostLikeAuthorId(Long userId, Pageable pageable); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java new file mode 100644 index 00000000..68a16ae6 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/PostRepository.java @@ -0,0 +1,9 @@ +package likelion.univ.domain.post.repository; + +import likelion.univ.domain.post.entity.Post; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +public interface PostRepository extends JpaRepository, PostCustomRepository { + Page findAllByAuthor_Id(Long userId, Pageable pageable); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java new file mode 100644 index 00000000..1aef9152 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java @@ -0,0 +1,80 @@ +package likelion.univ.domain.post.repository.impl; + +import com.querydsl.core.types.Predicate; +import com.querydsl.jpa.impl.JPAQueryFactory; +import likelion.univ.domain.post.entity.Post; +import likelion.univ.domain.post.repository.PostCustomRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +import static likelion.univ.domain.comment.entity.QComment.comment; +import static likelion.univ.domain.like.postlike.entity.QPostLike.postLike; +import static likelion.univ.domain.post.entity.QPost.post; +import static likelion.univ.domain.user.entity.QUser.user; + +@RequiredArgsConstructor +public class PostCustomRepositoryImpl implements PostCustomRepository { + + private final JPAQueryFactory queryFactory; + + @Override + public Page findByCommentAuthorId(Long userId, Pageable pageable){ + List ids = getCoveringIndexByComment(comment.author.id.eq(userId) + .and(comment.isDeleted.isFalse())); + return findByCoveringIndex(ids, pageable); + } + + @Override + public Page findByPostLikeAuthorId(Long userId, Pageable pageable){ + List ids = getCoveringIndexByComment(postLike.author.id.eq(userId)); + return findByCoveringIndex(ids, pageable); + } + + private List getCoveringIndexByComment(Predicate predicate) { + return queryFactory.select(comment.post.id).from(comment).where(predicate).fetch(); + } + private List getCoveringIndexByPostLike(Predicate predicate) { + return queryFactory.select(postLike.post.id).from(postLike).where(predicate).fetch(); + } + private Page findByCoveringIndex(List ids, Pageable pageable){ + List posts = + queryFactory + .select(post) + .from(post) + .innerJoin(post.author, user).fetchJoin() + .where(post.id.in(ids)) + .offset(pageable.getOffset()) + .orderBy(post.createdDate.desc()) + .limit(pageable.getPageSize()) + .fetch(); + + return new PageImpl<>(posts, pageable, ids.size()); + } + + + + + +// @Override +// public List pagingWithCoveringIndex(Integer page, Integer limit) { +// +// return null; +// List ids = jpaQueryFactory +// .select(post.id) +// .from(post) +// .limit(limit) +// .offset(page * limit) +// .fetch(); +// +// return jpaQueryFactory +// .selectFrom(post) +// .innerJoin(post.author, user) +// .fetchJoin() +// .where(post.id.in(ids)) +// .fetch(); +// } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java index fec1b505..1fe8492d 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java +++ b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Image.java @@ -15,7 +15,6 @@ public class Image { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="image_id") private long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java index b9b43b1e..ad3e6388 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java +++ b/likelion-core/src/main/java/likelion/univ/domain/project/entity/Project.java @@ -18,7 +18,6 @@ public class Project extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="project_id") private long id; private String thon; diff --git a/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java b/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java index 46257aec..ae540c4f 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java +++ b/likelion-core/src/main/java/likelion/univ/domain/project/entity/ProjectMember.java @@ -15,7 +15,6 @@ public class ProjectMember { @Id @GeneratedValue - @Column(name = "projectMember_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java b/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java index 1b90cba0..4b62e561 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java +++ b/likelion-core/src/main/java/likelion/univ/domain/recruit/entity/Recruit.java @@ -19,7 +19,6 @@ public class Recruit extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "recruit_id") private Long id; private String name; diff --git a/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java b/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java index 23fe663b..f693d51c 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java +++ b/likelion-core/src/main/java/likelion/univ/domain/university/entity/University.java @@ -14,7 +14,6 @@ public class University extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "university_id") private Long id; @Column(unique = true) private String name; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java index 69896568..41e4858c 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/adaptor/UserAdaptor.java @@ -3,10 +3,11 @@ import likelion.univ.annotation.Adaptor; import likelion.univ.domain.user.entity.User; import likelion.univ.domain.user.exception.UserNotFoundException; -import likelion.univ.domain.user.repository.UserQueryRepository; import likelion.univ.domain.user.repository.UserRepository; import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import java.util.List; @@ -14,14 +15,17 @@ @RequiredArgsConstructor public class UserAdaptor { private final UserRepository userRepository; - private final UserQueryRepository userQueryRepository; public User findById(Long id){ return userRepository.findById(id) .orElseThrow(()-> new UserNotFoundException()); } + public User findByIdWithUniversity(Long id){ + return userRepository.findByIdWithUniversity(id) + .orElseThrow(() -> new UserNotFoundException()); + } public User findByEmail(String email){ return userRepository.findByAuthInfoEmail(email) - .orElseThrow(()-> new UserNotFoundException()); + .orElseThrow(() -> new UserNotFoundException()); } public Boolean checkEmail(String email){ return userRepository.existsByAuthInfoEmail(email); @@ -33,6 +37,18 @@ public List findAll() { return userRepository.findAll(); } public List findDynamicUsers(UserSearchCondition condition) { - return userQueryRepository.findDynamicUsers(condition); + return userRepository.findDynamicUsers(condition); + } + public Slice findFollowingUsersByFollowerID(Long userId, Pageable pageable){ + return userRepository.findFollowingUsersByFollowerID(userId, pageable); + } + public Slice findFollowerUsersByFollowingID(Long userId, Pageable pageable){ + return userRepository.findFollowerUsersByFollowingID(userId, pageable); + } + public List findMyFollowingUsersByFollowingIdIn(Long follwerId, List followingIdList){ + return userRepository.findMyFollowingUsersByFollowingIdIn(follwerId, followingIdList); + } + public Slice searchByName(String name, Pageable pageable){ + return userRepository.searchByName(name, pageable); } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java index 64062178..6471a4e9 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AccountStatus.java @@ -6,7 +6,7 @@ @AllArgsConstructor @Getter public enum AccountStatus { - MEMBER("MEMBER"), + ACTIVE("ACTIVE"), Deleted("DELETED"); private String value; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java index 118f9a20..65ca700e 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/AuthInfo.java @@ -4,7 +4,7 @@ import javax.persistence.*; -import static likelion.univ.domain.user.entity.AccountStatus.MEMBER; +import static likelion.univ.domain.user.entity.AccountStatus.ACTIVE; import static likelion.univ.domain.user.entity.Role.GUEST; @Embeddable @@ -20,6 +20,8 @@ public class AuthInfo { private String email; @Enumerated(EnumType.STRING) private AccountStatus accountStatus; + // 01000000000 형태로 + private String phoneNumber; @Enumerated(EnumType.STRING) private Role role; @@ -28,7 +30,7 @@ public static AuthInfo authInfoForSignUp(LoginType loginType, String email) { return AuthInfo.builder() .loginType(loginType) .email(email) - .accountStatus(MEMBER) + .accountStatus(ACTIVE) .role(GUEST) .build(); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java index a945338f..e61323f7 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Part.java @@ -6,10 +6,10 @@ @AllArgsConstructor @Getter public enum Part { - BACKEND("백엔드"), - FRONTEND("프론트엔드"), PM("기획"), DESIGNER("디자인"), - PM_DESIGNER("기획/디자인"); + PM_DESIGNER("기획/디자인"), + FRONTEND("프론트엔드"), + BACKEND("백엔드"); private String value; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java index 517f7f31..64610b20 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Profile.java @@ -15,8 +15,6 @@ public class Profile { private String name; - // 010-0000-0000 형태로 - private String phoneNumber; private String profileImage; @Column(columnDefinition = "TEXT") diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java index 9dc91893..6f97f5db 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/Role.java @@ -8,11 +8,10 @@ public enum Role { GUEST("GUEST"), - USER("USER"), - MANAGER("MANAGER"), - ADMIN("ADMIN"), - CODEIT_ADMIN("CODEIT_ADMIN"), - SUPER_ADMIN("SUPER_ADMIN"); + USER("USER"), /* 아기사자 */ + MANAGER("MANAGER"), /* 운영진 */ + UNIVERSITY_ADMIN("UNIVERSITY_ADMIN"), /* 대학대표 (대학관리자) */ + SUPER_ADMIN("SUPER_ADMIN"); /* 총관리자 */ private String value; } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java index 617d9871..aa526c61 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/UniversityInfo.java @@ -14,7 +14,6 @@ @AllArgsConstructor @Builder public class UniversityInfo { - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "university_id") private University university; diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java b/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java index b78ed1e0..951b6c43 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/entity/User.java @@ -9,12 +9,11 @@ @Builder @AllArgsConstructor @Entity -@Table(name="users", uniqueConstraints = {@UniqueConstraint(columnNames = {"email", "loginType"})}) +@Table(name="user", uniqueConstraints = {@UniqueConstraint(columnNames = {"email", "loginType"})}) public class User extends BaseTimeEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "user_id") private Long id; @Embedded @@ -26,4 +25,7 @@ public class User extends BaseTimeEntity{ @Embedded private AuthInfo authInfo; + public void editProfile(Profile profile){ + this.profile = profile; + } } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java index afd959fc..4bd6e166 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserErrorCode.java @@ -4,13 +4,13 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import static likelion.univ.constant.StaticValue.BAD_REQUEST; -import static likelion.univ.constant.StaticValue.NOT_FOUND; +import static likelion.univ.constant.StaticValue.*; @Getter @AllArgsConstructor public enum UserErrorCode implements BaseErrorCode{ NOT_SUPPORTED_LOGIN_TYPE(BAD_REQUEST, "LOGIN_TYPE_400", "해당 방식은 지원하지않는 로그인 방식입니다."), + USER_NOT_MATCH(FORBIDDEN, "USER_403", "사용자가 일치하지 않습니다."), USER_NOT_FOUND(NOT_FOUND, "USER_404", "유저를 찾을 수 없습니다."), EMAIL_ALREADY_REGISTERED(NOT_FOUND, "USER_409", "같은 이메일로 회원가입된 계정이 있습니다."); diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java new file mode 100644 index 00000000..64525922 --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/user/exception/UserNotMatchException.java @@ -0,0 +1,10 @@ +package likelion.univ.domain.user.exception; + +import likelion.univ.exception.base.BaseErrorCode; +import likelion.univ.exception.base.BaseException; + +public class UserNotMatchException extends BaseException { + public UserNotMatchException() { + super(UserErrorCode.USER_NOT_MATCH); + } +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java new file mode 100644 index 00000000..476a70de --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserCustomRepository.java @@ -0,0 +1,16 @@ +package likelion.univ.domain.user.repository; + +import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +import java.util.List; + +public interface UserCustomRepository { + List findDynamicUsers(UserSearchCondition condition); + Slice findFollowingUsersByFollowerID(Long userId, Pageable pageable); + Slice findFollowerUsersByFollowingID(Long userId, Pageable pageable); + Slice searchByName(String name, Pageable pageable); + List findMyFollowingUsersByFollowingIdIn(Long followerId, List followingIdList); +} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java deleted file mode 100644 index c14f8f1a..00000000 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserQueryRepository.java +++ /dev/null @@ -1,47 +0,0 @@ -package likelion.univ.domain.user.repository; - -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; -import likelion.univ.domain.university.entity.University; -import likelion.univ.domain.user.entity.Part; -import likelion.univ.domain.user.entity.User; -import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; -import org.springframework.util.StringUtils; - -import java.util.List; - -import static likelion.univ.domain.user.entity.QUser.user; - -@Repository -@RequiredArgsConstructor -public class UserQueryRepository { - - private final JPAQueryFactory jpaQueryFactory; - - public List findDynamicUsers(UserSearchCondition condition) { - return jpaQueryFactory - .selectFrom(user) - .where( - containsName(condition.getName()), - eqUniversity(condition.getUniversity()), - eqPart(condition.getPart()) - ) - .fetch(); - } - - private BooleanExpression containsName(String searchName) { - return StringUtils.hasText(searchName) ? user.profile.name.contains(searchName) : null; - } - - private BooleanExpression eqUniversity(String searchUniversity) { - return searchUniversity != null ? user.universityInfo.university.name.eq(searchUniversity) : null; - } - - private BooleanExpression eqPart(String searchPart) { - return searchPart != null ? user.profile.part.eq(Part.valueOf(searchPart)) : null; - } - - -} diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java index a642764d..f5962274 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/UserRepository.java @@ -2,10 +2,14 @@ import likelion.univ.domain.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.Optional; -public interface UserRepository extends JpaRepository { +public interface UserRepository extends JpaRepository, UserCustomRepository { Optional findByAuthInfoEmail(String email); Boolean existsByAuthInfoEmail(String email); + + @Query("SELECT u FROM User u join fetch u.universityInfo.university where u.id = :id ") + Optional findByIdWithUniversity(Long id); } diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java new file mode 100644 index 00000000..062c394f --- /dev/null +++ b/likelion-core/src/main/java/likelion/univ/domain/user/repository/impl/UserCustomRepositoryImpl.java @@ -0,0 +1,119 @@ +package likelion.univ.domain.user.repository.impl; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.CaseBuilder; +import com.querydsl.core.types.dsl.NumberExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import likelion.univ.common.processor.ConvertSliceProcessor; +import likelion.univ.domain.user.entity.Part; +import likelion.univ.domain.user.entity.User; +import likelion.univ.domain.user.repository.UserCustomRepository; +import likelion.univ.domain.user.repository.searchcondition.UserSearchCondition; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.util.StringUtils; + +import java.util.List; + +import static likelion.univ.domain.follow.entity.QFollow.follow; +import static likelion.univ.domain.university.entity.QUniversity.university; +import static likelion.univ.domain.user.entity.QUser.user; + +@RequiredArgsConstructor +public class UserCustomRepositoryImpl implements UserCustomRepository { + private final JPAQueryFactory queryFactory; + private final ConvertSliceProcessor convertSliceProcessor; + + @Override + public List findDynamicUsers(UserSearchCondition condition) { + return queryFactory + .selectFrom(user) + .where( + containsName(condition.getName()), + eqUniversity(condition.getUniversity()), + eqPart(condition.getPart()) + ) + .fetch(); + } + + private BooleanExpression containsName(String searchName) { + return StringUtils.hasText(searchName) ? user.profile.name.contains(searchName) : null; + } + + private BooleanExpression eqUniversity(String searchUniversity) { + return searchUniversity != null ? user.universityInfo.university.name.eq(searchUniversity) : null; + } + + private BooleanExpression eqPart(String searchPart) { + return searchPart != null ? user.profile.part.eq(Part.valueOf(searchPart)) : null; + } + + + @Override + public Slice findFollowingUsersByFollowerID(Long followerId, Pageable pageable){ + List users = + queryFactory + .select(follow.following) + .from(follow) + .innerJoin(follow.following, user) + .where(follow.follower.id.eq(followerId)) + .offset(pageable.getOffset()) + .orderBy(user.createdDate.desc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return convertSliceProcessor.execute(users, pageable); + } + @Override + public Slice findFollowerUsersByFollowingID(Long followingId, Pageable pageable){ + List users = + queryFactory + .select(user) + .from(follow) + .innerJoin(follow.follower, user) + .where(follow.following.id.eq(followingId)) + .offset(pageable.getOffset()) + .orderBy(user.createdDate.desc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return convertSliceProcessor.execute(users, pageable); + } + + @Override + public List findMyFollowingUsersByFollowingIdIn(Long followerId, List followingIdList){ + List users = + queryFactory + .select(user) + .from(follow) + .innerJoin(follow.following, user) + .where(follow.follower.id.eq(followerId) + .and(follow.following.id.in(followingIdList))) + .fetch(); + return users; + } + @Override + public Slice searchByName(String name, Pageable pageable){ + NumberExpression partOrder = new CaseBuilder() + .when(user.profile.part.eq(Part.PM)).then(1) + .when(user.profile.part.eq(Part.DESIGNER)).then(2) + .when(user.profile.part.eq(Part.PM_DESIGNER)).then(3) + .when(user.profile.part.eq(Part.FRONTEND)).then(4) + .when(user.profile.part.eq(Part.BACKEND)).then(5) + .otherwise(6); + + List users = + queryFactory + .select(user) + .from(user) + .innerJoin(user.universityInfo.university, university).fetchJoin() + .where(containsName(name)) + .offset(pageable.getOffset()) + .orderBy(partOrder.asc(), user.profile.name.asc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return convertSliceProcessor.execute(users, pageable); + } +} \ No newline at end of file diff --git a/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java b/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java index 504f4550..e99aabb8 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java +++ b/likelion-core/src/main/java/likelion/univ/domain/user/service/UserDomainService.java @@ -34,6 +34,12 @@ public User signUp(Profile profile, AuthInfo authInfo, UniversityInfo university .build(); return userAdaptor.save(user); } + @Transactional + public User editProfile(Long userId, Profile profile){ + User user = userAdaptor.findById(userId); + user.editProfile(profile); + return user; + } public User findByEmail(String email) { return userAdaptor.findByEmail(email); diff --git a/likelion-core/src/main/resources/application-core.yml b/likelion-core/src/main/resources/application-core.yml index 4cc8663b..7715dc11 100644 --- a/likelion-core/src/main/resources/application-core.yml +++ b/likelion-core/src/main/resources/application-core.yml @@ -5,6 +5,11 @@ spring: url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_NAME} username: ${MYSQL_USERNAME} password: ${MYSQL_PASSWORD} + + data: + web: + pageable: + one-indexed-parameters: true jpa: show-sql: true database: mysql @@ -17,12 +22,6 @@ spring: default_batch_fetch_size: 1000 format_sql: true -logging: - level: - org.springframework.orm.jpa: DEBUG - org.springframework.transaction: DEBUG - pattern: - console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" --- ## dev 환경 설정 spring: @@ -30,12 +29,41 @@ spring: activate: on-profile: dev + jpa: + properties: + hibernate: + show_sql: true + format_sql: true + +logging: + level: + org.springframework.orm.jpa: DEBUG + org.springframework.transaction: DEBUG + org: + hibernate: + type: + descriptor: + sql: trace + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" + --- ## staging환경 설정 spring: config: activate: on-profile: staging + jpa: + properties: + hibernate: + show_sql: false + format_sql: false + +logging: + level: + root: INFO + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" --- ## prod 환경 설정 spring: config: diff --git a/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java b/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java index 1d40b4db..e1cd4590 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java +++ b/likelion-redis/src/main/java/likelion/univ/common/base/BaseRedisRepository.java @@ -4,18 +4,24 @@ import org.springframework.data.redis.core.RedisTemplate; import java.util.Optional; +import java.util.concurrent.TimeUnit; + -@Slf4j public abstract class BaseRedisRepository { protected RedisTemplate redisTemplate; protected String prefix; + protected Long ttl; - public void save(Long id, T t) { - redisTemplate.opsForValue().set(generateKeyfromId(id), t); + public void save(Long id, T data) { + redisTemplate.opsForValue().set(generateKeyfromId(id), data, ttl, TimeUnit.SECONDS); } public Optional findById(Long id) { - return Optional.of(redisTemplate.opsForValue().get(generateKeyfromId(id))); + try{ + return Optional.of(redisTemplate.opsForValue().get(generateKeyfromId(id))); + }catch (NullPointerException e){ + return Optional.empty(); + } } public Boolean delete(Long id) { return redisTemplate.delete(generateKeyfromId(id)); diff --git a/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java b/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java index 98540ae3..1ab852f4 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java +++ b/likelion-redis/src/main/java/likelion/univ/common/config/RedisCacheManagerConfig.java @@ -46,7 +46,6 @@ private Map customConfigurationMap(RedisCacheCo Map customConfigurationMap = new HashMap<>(); customConfigurationMap.put(KAKAO_PUBLIC_KEYS, redisCacheConfiguration.entryTtl(Duration.ofDays(1L))); customConfigurationMap.put(GOOGLE_PUBLIC_KEYS, redisCacheConfiguration.entryTtl(Duration.ofDays(1L))); - customConfigurationMap.put(REFRESH_TOKEN, redisCacheConfiguration.entryTtl(Duration.ofDays(14L))); return customConfigurationMap; } } diff --git a/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java b/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java index 65d5c34e..3f4f8298 100644 --- a/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java +++ b/likelion-redis/src/main/java/likelion/univ/common/constant/RedisKey.java @@ -7,5 +7,9 @@ public class RedisKey { public static final String GOOGLE_PUBLIC_KEYS = "googlePublicKeys"; public static final String REFRESH_TOKEN = "refreshToken"; - public static final int REFRESH_TOKEN_EXPIRE_SEC = 1209600; + public static final String POST_COUNT_INFO = "postCount"; + public static final String USER_FOLLOW_NUM = "userFollowNum"; + public static final Long REFRESH_TOKEN_EXPIRE_SEC = 1209600L; + public static final Long POST_COUNT_INFO_EXPIRE_SEC = 86400L; + public static final Long USER_FOLLOW_NUM_EXPIRE_SEC = 86400L; } diff --git a/likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java b/likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java new file mode 100644 index 00000000..a8297c35 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/follow/dao/FollowNumRedisDao.java @@ -0,0 +1,19 @@ +package likelion.univ.follow.dao; + +import likelion.univ.annotation.RedisRepository; +import likelion.univ.common.base.BaseRedisRepository; +import likelion.univ.follow.entity.FollowNum; +import org.springframework.data.redis.core.RedisTemplate; + +import static likelion.univ.common.constant.RedisKey.USER_FOLLOW_NUM; +import static likelion.univ.common.constant.RedisKey.USER_FOLLOW_NUM_EXPIRE_SEC; + +@RedisRepository +public class FollowNumRedisDao extends BaseRedisRepository { + + public FollowNumRedisDao(RedisTemplate redisTemplate) { + this.prefix = USER_FOLLOW_NUM + ":"; + this.ttl = USER_FOLLOW_NUM_EXPIRE_SEC; + this.redisTemplate = redisTemplate; + } +} \ No newline at end of file diff --git a/likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java b/likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java new file mode 100644 index 00000000..7c88387a --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/follow/entity/FollowNum.java @@ -0,0 +1,15 @@ +package likelion.univ.follow.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FollowNum { + private Long followerNum; + private Long followingNum; +} diff --git a/likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java b/likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java new file mode 100644 index 00000000..b0cb6d41 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/follow/service/FollowNumRedisService.java @@ -0,0 +1,49 @@ +package likelion.univ.follow.service; + +import likelion.univ.follow.dao.FollowNumRedisDao; +import likelion.univ.follow.entity.FollowNum; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class FollowNumRedisService { + private final FollowNumRedisDao followNumRedisDao; + + public FollowNum save(Long userId, Long followerNum, Long followingNum){ + FollowNum followNum = FollowNum.builder() + .followerNum(followerNum) + .followingNum(followingNum) + .build(); + followNumRedisDao.save(userId, followNum); + return followNum; + } + public void followerUp(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum() + 1) + .followingNum(followNum.getFollowingNum()) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } + public void followerDown(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum() - 1) + .followingNum(followNum.getFollowingNum()) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } + public void followingUp(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum()) + .followingNum(followNum.getFollowingNum() + 1) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } + public void followingDown(Long userId, FollowNum followNum){ + FollowNum newFollowNum = FollowNum.builder() + .followerNum(followNum.getFollowerNum()) + .followingNum(followNum.getFollowingNum() - 1) + .build(); + followNumRedisDao.save(userId, newFollowNum); + } +} \ No newline at end of file diff --git a/likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java b/likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java new file mode 100644 index 00000000..b9e9b6e5 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/post/dao/PostCountInfoRedisDao.java @@ -0,0 +1,19 @@ +package likelion.univ.post.dao; + +import likelion.univ.annotation.RedisRepository; +import likelion.univ.common.base.BaseRedisRepository; +import likelion.univ.post.entity.PostCountInfo; +import org.springframework.data.redis.core.RedisTemplate; + +import static likelion.univ.common.constant.RedisKey.POST_COUNT_INFO; +import static likelion.univ.common.constant.RedisKey.POST_COUNT_INFO_EXPIRE_SEC; + +@RedisRepository +public class PostCountInfoRedisDao extends BaseRedisRepository { + + public PostCountInfoRedisDao(RedisTemplate redisTemplate) { + this.prefix = POST_COUNT_INFO + ":"; + this.ttl = POST_COUNT_INFO_EXPIRE_SEC; + this.redisTemplate = redisTemplate; + } +} diff --git a/likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java b/likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java new file mode 100644 index 00000000..a7f2158f --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/post/entity/PostCountInfo.java @@ -0,0 +1,15 @@ +package likelion.univ.post.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PostCountInfo { + private Long commentCount; + private Long likeCount; +} diff --git a/likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java b/likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java new file mode 100644 index 00000000..7c3f23a4 --- /dev/null +++ b/likelion-redis/src/main/java/likelion/univ/post/service/PostCountInfoRedisService.java @@ -0,0 +1,21 @@ +package likelion.univ.post.service; + +import likelion.univ.post.dao.PostCountInfoRedisDao; +import likelion.univ.post.entity.PostCountInfo; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PostCountInfoRedisService { + private final PostCountInfoRedisDao postCountInfoRedisDao; + + public PostCountInfo save(Long postId, Long commentCount, Long likeCount){ + PostCountInfo postCountInfo = PostCountInfo.builder() + .commentCount(commentCount) + .likeCount(likeCount) + .build(); + postCountInfoRedisDao.save(postId, postCountInfo); + return postCountInfo; + } +} diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java deleted file mode 100644 index 9cf0212c..00000000 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/adaptor/RefreshTokenRedisAdaptor.java +++ /dev/null @@ -1,21 +0,0 @@ -package likelion.univ.refreshtoken.adaptor; - -import likelion.univ.annotation.Adaptor; -import likelion.univ.refreshtoken.dao.RefreshTokenRedisDao; -import likelion.univ.refreshtoken.entity.RefreshToken; -import likelion.univ.refreshtoken.exception.ExpiredRefreshTokenException; -import lombok.RequiredArgsConstructor; - -@Adaptor -@RequiredArgsConstructor -public class RefreshTokenRedisAdaptor { - private final RefreshTokenRedisDao refreshTokenRedisDao; - - public void save(Long id, RefreshToken refreshToken){ - refreshTokenRedisDao.save(id, refreshToken); - } - public RefreshToken findById(Long id){ - return refreshTokenRedisDao.findById(id) - .orElseThrow(() -> new ExpiredRefreshTokenException()); - } -} diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java index a3d2da2e..836be70f 100644 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java +++ b/likelion-redis/src/main/java/likelion/univ/refreshtoken/dao/RefreshTokenRedisDao.java @@ -3,17 +3,17 @@ import likelion.univ.annotation.RedisRepository; import likelion.univ.common.base.BaseRedisRepository; import likelion.univ.refreshtoken.entity.RefreshToken; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; import static likelion.univ.common.constant.RedisKey.REFRESH_TOKEN; +import static likelion.univ.common.constant.RedisKey.REFRESH_TOKEN_EXPIRE_SEC; @RedisRepository public class RefreshTokenRedisDao extends BaseRedisRepository { - @Autowired + public RefreshTokenRedisDao(RedisTemplate redisTemplate) { this.prefix = REFRESH_TOKEN + ":"; + this.ttl = REFRESH_TOKEN_EXPIRE_SEC; this.redisTemplate = redisTemplate; } } diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java index f4faccb3..a00e2d38 100644 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java +++ b/likelion-redis/src/main/java/likelion/univ/refreshtoken/entity/RefreshToken.java @@ -13,7 +13,6 @@ @Builder public class RefreshToken { - private Long userId; private String token; } diff --git a/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java b/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java index b44d6809..4545a42d 100644 --- a/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java +++ b/likelion-redis/src/main/java/likelion/univ/refreshtoken/service/RefreshTokenRedisService.java @@ -1,28 +1,27 @@ package likelion.univ.refreshtoken.service; -import likelion.univ.refreshtoken.adaptor.RefreshTokenRedisAdaptor; +import likelion.univ.refreshtoken.dao.RefreshTokenRedisDao; import likelion.univ.refreshtoken.entity.RefreshToken; +import likelion.univ.refreshtoken.exception.ExpiredRefreshTokenException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -@Slf4j public class RefreshTokenRedisService { - private final RefreshTokenRedisAdaptor refreshTokenRedisAdaptor; - + private final RefreshTokenRedisDao refreshTokenRedisDao; public void save(Long id, String token){ RefreshToken refreshToken = RefreshToken.builder() .userId(id) .token(token) .build(); - refreshTokenRedisAdaptor.save(id, refreshToken); + refreshTokenRedisDao.save(id, refreshToken); } public Boolean checkToken(Long id, String token){ - RefreshToken refreshToken = refreshTokenRedisAdaptor.findById(id); + RefreshToken refreshToken = refreshTokenRedisDao.findById(id) + .orElseThrow(() -> new ExpiredRefreshTokenException()); if(token.equals(refreshToken.getToken())) return true; else return false; } From 4fa12bc67ad39c0c685a41ca6029fd56e4f5df4a Mon Sep 17 00:00:00 2001 From: seulgi99 Date: Tue, 14 Nov 2023 10:58:49 +0900 Subject: [PATCH 30/30] =?UTF-8?q?feat=20:=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?=EB=88=84=EB=A5=B8=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../univ/user/controller/UserController.java | 18 +++++++++--- .../usecase/GetUserLikedPostsUseCase.java | 28 +++++++++++++++++++ .../impl/PostCustomRepositoryImpl.java | 2 +- 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 likelion-client/src/main/java/likelion/univ/user/usecase/GetUserLikedPostsUseCase.java diff --git a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java index f8efaaec..12757e11 100644 --- a/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java +++ b/likelion-client/src/main/java/likelion/univ/user/controller/UserController.java @@ -28,6 +28,7 @@ public class UserController { private final GetPostsCommentedByMeUseCase getPostsCommentedByMeUseCase; private final GetFollowInfoUseCase getFollowingListUseCase; private final SearchUserByNameUseCase searchUserByNameUseCase; + private final GetUserLikedPostsUseCase getUserLikedPostsUseCase; @Operation(summary = "유저페이지 프로필 조회", description = "해당 유저의 프로필 정보를 조회합니다.") @GetMapping("/{userId}/profile") @@ -66,15 +67,24 @@ public SuccessResponse getMyPosts(@PathVariable Long userId, PageResponse myPagePostsPage = getMyPostsUseCase.execute(userId, pageable); return SuccessResponse.of(myPagePostsPage); } + @Operation(summary = "해당 유저가 좋아요 누른 게시글 조회", description = "해당 유저가 좋아요를 누른 게시글을 조회합니다.") + @GetMapping("/{userId}/posts/like") + public SuccessResponse getPostsLikedByUser(@PathVariable Long userId, + @ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ + PageResponse myPagePostsPageLikedByUser = getUserLikedPostsUseCase.execute(userId, pageable); + return SuccessResponse.of(myPagePostsPageLikedByUser); + } + @Operation(summary = "해당 유저가 댓글 쓴 게시글 조회", description = "해당 유저가 댓글을 작성한 게시글을 조회합니다.") - @GetMapping("/{userId}/comments") - public SuccessResponse getPostsCommentedByMe(@PathVariable Long userId, + @GetMapping("/{userId}/posts/comment") + public SuccessResponse getPostsCommentedByUser(@PathVariable Long userId, @ParameterObject @PageableDefault(size = 6, page = 1) Pageable pageable){ - PageResponse myPagePostsPageCommentedByMe = getPostsCommentedByMeUseCase.execute(userId, pageable); - return SuccessResponse.of(myPagePostsPageCommentedByMe); + PageResponse myPagePostsPageCommentedByUser = getPostsCommentedByMeUseCase.execute(userId, pageable); + return SuccessResponse.of(myPagePostsPageCommentedByUser); } + @Operation(summary = "유저 검색 (Simple Data) (project page)", description = "이름으로 유저를 검색합니다. (프로젝트 페이지 모달)") @GetMapping("/search") public SuccessResponse searchUser(@RequestParam(required = false) String name, diff --git a/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserLikedPostsUseCase.java b/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserLikedPostsUseCase.java new file mode 100644 index 00000000..da6649bf --- /dev/null +++ b/likelion-client/src/main/java/likelion/univ/user/usecase/GetUserLikedPostsUseCase.java @@ -0,0 +1,28 @@ +package likelion.univ.user.usecase; + +import likelion.univ.annotation.UseCase; +import likelion.univ.common.response.PageResponse; +import likelion.univ.domain.post.adaptor.PostAdaptor; +import likelion.univ.domain.post.entity.Post; +import likelion.univ.post.processor.GetOrCreatePostCountInfoProcessor; +import likelion.univ.user.dto.response.UserPagePostsDto; +import likelion.univ.utils.AuthentiatedUserUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +@UseCase +@RequiredArgsConstructor +public class GetUserLikedPostsUseCase { + private final AuthentiatedUserUtils authentiatedUserUtils; + private final PostAdaptor postAdaptor; + private final GetOrCreatePostCountInfoProcessor getOrCreatePostCountInfoProcessor; + + public PageResponse execute(Long userId, Pageable pageable){ + Long currentUserId = authentiatedUserUtils.getCurrentUserId(); + Page posts = postAdaptor.findByPostLikeAuthorId(userId, pageable); + + return PageResponse.of(posts.map(p-> UserPagePostsDto.of(p, currentUserId, getOrCreatePostCountInfoProcessor.execute(p.getId())))); + } + +} \ No newline at end of file diff --git a/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java b/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java index 1aef9152..a7c19882 100644 --- a/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java +++ b/likelion-core/src/main/java/likelion/univ/domain/post/repository/impl/PostCustomRepositoryImpl.java @@ -30,7 +30,7 @@ public Page findByCommentAuthorId(Long userId, Pageable pageable){ @Override public Page findByPostLikeAuthorId(Long userId, Pageable pageable){ - List ids = getCoveringIndexByComment(postLike.author.id.eq(userId)); + List ids = getCoveringIndexByPostLike(postLike.author.id.eq(userId)); return findByCoveringIndex(ids, pageable); }