From 52d5ff90e2addb4af0dc4ac130f8936045b9bfdd Mon Sep 17 00:00:00 2001 From: 5ooyeon Date: Sun, 18 May 2025 07:21:18 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Refactor:=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EA=B8=B8=EC=9D=B4=20=EC=A0=9C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hiearth/fullquiz/service/request/MemberCreateDTO.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java b/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java index 2b1a564..1736803 100644 --- a/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java +++ b/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java @@ -1,8 +1,13 @@ package com.hiearth.fullquiz.service.request; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Getter; @Getter public class MemberCreateDTO { + + @NotNull + @Size(min = 2, max = 10, message = "닉네임은 2자 이상 10자 이하로 입력해주세요.") private String nickname; } From dde84ae21fea0db01c25f7c0df9fa4c453860c66 Mon Sep 17 00:00:00 2001 From: 5ooyeon Date: Sun, 18 May 2025 08:14:59 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Feat:=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EB=B0=8F=20validation=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 --- .../hiearth/fullquiz/global/error/ErrorType.java | 2 ++ .../fullquiz/repository/QuizProgressRepository.java | 2 ++ .../hiearth/fullquiz/service/MemberServiceImpl.java | 2 ++ .../hiearth/fullquiz/service/QuizServiceImpl.java | 13 +++++++++++-- .../fullquiz/service/RankingServiceImpl.java | 2 ++ .../fullquiz/service/request/MemberCreateDTO.java | 5 +++-- .../fullquiz/web/controller/MemberController.java | 3 ++- .../fullquiz/web/controller/QuizController.java | 3 ++- .../fullquiz/web/controller/RankingController.java | 4 +++- .../com/hiearth/fullquiz/web/dto/MemberRequest.java | 2 +- 10 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/hiearth/fullquiz/global/error/ErrorType.java b/src/main/java/com/hiearth/fullquiz/global/error/ErrorType.java index 4719edf..7c8fc09 100644 --- a/src/main/java/com/hiearth/fullquiz/global/error/ErrorType.java +++ b/src/main/java/com/hiearth/fullquiz/global/error/ErrorType.java @@ -17,6 +17,7 @@ public enum ErrorType { MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "01-001", "사용자를 찾을 수 없습니다."), NICKNAME_DUPLICATED(HttpStatus.BAD_REQUEST, "01-002", "이미 존재하는 닉네임입니다."), + // category (02) CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "02-001", "해당하는 카테고리가 존재하지 않습니다."), CHILD_CATEGORY_DOES_NOT_EXIXT(HttpStatus.NOT_FOUND, "02-002", "하위 카테고리가 존재하지 않습니다."), @@ -26,6 +27,7 @@ public enum ErrorType { // quiz progress(04) NO_QUIZ_IN_PROGRESS(HttpStatus.BAD_REQUEST, "04-001", "진행중인 퀴즈가 없습니다."), + ; // 커스텀 에러 작성 private final HttpStatus status; diff --git a/src/main/java/com/hiearth/fullquiz/repository/QuizProgressRepository.java b/src/main/java/com/hiearth/fullquiz/repository/QuizProgressRepository.java index 135eadf..c275c4f 100644 --- a/src/main/java/com/hiearth/fullquiz/repository/QuizProgressRepository.java +++ b/src/main/java/com/hiearth/fullquiz/repository/QuizProgressRepository.java @@ -11,4 +11,6 @@ public interface QuizProgressRepository extends JpaRepository findByMemberId(Long memberId); // List findByMemberId(Long memberId); Optional findByMemberIdAndCategoryId(Long memberId, Long categoryId); + + Optional findByMemberIdAndNotIsCompleted(Long memberId); } diff --git a/src/main/java/com/hiearth/fullquiz/service/MemberServiceImpl.java b/src/main/java/com/hiearth/fullquiz/service/MemberServiceImpl.java index 8907445..6af7667 100644 --- a/src/main/java/com/hiearth/fullquiz/service/MemberServiceImpl.java +++ b/src/main/java/com/hiearth/fullquiz/service/MemberServiceImpl.java @@ -5,6 +5,8 @@ import com.hiearth.fullquiz.global.exception.FullquizException; import com.hiearth.fullquiz.repository.MemberRepository; import com.hiearth.fullquiz.web.dto.MemberResponse; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/hiearth/fullquiz/service/QuizServiceImpl.java b/src/main/java/com/hiearth/fullquiz/service/QuizServiceImpl.java index 20b921c..f952d59 100644 --- a/src/main/java/com/hiearth/fullquiz/service/QuizServiceImpl.java +++ b/src/main/java/com/hiearth/fullquiz/service/QuizServiceImpl.java @@ -25,6 +25,8 @@ @Service //@AllArgsConstructor @RequiredArgsConstructor + +@Transactional public class QuizServiceImpl implements QuizSevice{ private final CategoryRepository categoryRepository; @@ -34,7 +36,6 @@ public class QuizServiceImpl implements QuizSevice{ private final MemberRepository memberRepository; @Override - @Transactional public TotalQuizResponse getQuizzes(Long memberId, String categoryName) { Category category = categoryRepository.findByName(categoryName) @@ -82,14 +83,15 @@ public TotalQuizResponse getQuizzes(Long memberId, String categoryName) { } @Override - @Transactional public void checkAnswer(Long quizId, Long memberId, CheckAnswerDTO checkAnswerDTO) { + Quiz quiz = quizRepository.findById(quizId) .orElseThrow(() -> new FullquizException(ErrorType.QUIZ_NOT_FOUND)); Member member = memberRepository.findById(memberId) .orElseThrow(() -> new FullquizException(ErrorType.MEMBER_NOT_FOUND)); + memberQuizRepository.save( MemberQuiz.builder() .member(member) @@ -98,6 +100,7 @@ public void checkAnswer(Long quizId, Long memberId, CheckAnswerDTO checkAnswerDT .build() ); + List quizProgresses = quizProgressRepository .findByMemberId(memberId); @@ -111,9 +114,12 @@ public void checkAnswer(Long quizId, Long memberId, CheckAnswerDTO checkAnswerDT } @Override + @Transactional(readOnly = true) public List resumeQuiz(Long quizProgressId) { + QuizProgress quizProgress = quizProgressRepository.findById(quizProgressId) .orElseThrow(() -> new FullquizException(ErrorType.NO_QUIZ_IN_PROGRESS)); + List quizzes = quizRepository.findAllById(quizProgress.getQuizIds()); if (quizzes.isEmpty()) { @@ -131,8 +137,10 @@ public List resumeQuiz(Long quizProgressId) { } @Override + @Transactional(readOnly = true) public QuizProgressDTO getQuizProgress(Long memberId) { + List quizProgresses = quizProgressRepository.findByMemberId(memberId); if(quizProgresses.isEmpty()){ throw new FullquizException(ErrorType.NO_QUIZ_IN_PROGRESS); @@ -153,6 +161,7 @@ public QuizProgressDTO getQuizProgress(Long memberId) { } @Override + @Transactional(readOnly = true) public List getMyStatus(String nickname) { Member member = memberRepository.findByNickname(nickname) .orElseThrow(() -> new FullquizException(ErrorType.MEMBER_NOT_FOUND)); diff --git a/src/main/java/com/hiearth/fullquiz/service/RankingServiceImpl.java b/src/main/java/com/hiearth/fullquiz/service/RankingServiceImpl.java index d759112..bd685bd 100644 --- a/src/main/java/com/hiearth/fullquiz/service/RankingServiceImpl.java +++ b/src/main/java/com/hiearth/fullquiz/service/RankingServiceImpl.java @@ -8,12 +8,14 @@ import com.hiearth.fullquiz.web.dto.UserRanking; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Service @AllArgsConstructor +@Transactional(readOnly = true) public class RankingServiceImpl implements RankingService{ private final RankingRepository rankingRepository; diff --git a/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java b/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java index 1736803..67b0b40 100644 --- a/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java +++ b/src/main/java/com/hiearth/fullquiz/service/request/MemberCreateDTO.java @@ -1,5 +1,6 @@ package com.hiearth.fullquiz.service.request; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Getter; @@ -7,7 +8,7 @@ @Getter public class MemberCreateDTO { - @NotNull - @Size(min = 2, max = 10, message = "닉네임은 2자 이상 10자 이하로 입력해주세요.") + @NotNull(message = "닉네임은 필수입니다.") + @Size(min = 2, max = 7, message = "닉네임은 2자 이상, 7자 이하로 입력해주세요.") private String nickname; } diff --git a/src/main/java/com/hiearth/fullquiz/web/controller/MemberController.java b/src/main/java/com/hiearth/fullquiz/web/controller/MemberController.java index 4a150f2..9a963c1 100644 --- a/src/main/java/com/hiearth/fullquiz/web/controller/MemberController.java +++ b/src/main/java/com/hiearth/fullquiz/web/controller/MemberController.java @@ -3,6 +3,7 @@ import com.hiearth.fullquiz.global.response.ApiResponse; import com.hiearth.fullquiz.service.MemberService; import com.hiearth.fullquiz.service.request.MemberCreateDTO; +import jakarta.validation.constraints.Size; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,7 +20,7 @@ public ResponseEntity registerMember(@RequestBody MemberCreateDTO memberCreat } @GetMapping("/api/members") - public ResponseEntity checkDuplicateNickname(@RequestParam String nickname) { + public ResponseEntity checkDuplicateNickname(@RequestParam @Size(min = 2, max = 7, message = "닉네임은 2자 이상, 7자 이하로 입력해주세요.") String nickname) { return ApiResponse.ok(memberService.existsByNickname(nickname)); } diff --git a/src/main/java/com/hiearth/fullquiz/web/controller/QuizController.java b/src/main/java/com/hiearth/fullquiz/web/controller/QuizController.java index 69ea19d..2293ce6 100644 --- a/src/main/java/com/hiearth/fullquiz/web/controller/QuizController.java +++ b/src/main/java/com/hiearth/fullquiz/web/controller/QuizController.java @@ -9,6 +9,7 @@ import com.hiearth.fullquiz.web.dto.StatusResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; @@ -27,7 +28,7 @@ public class QuizController { @Operation(summary = "퀴즈 불러오기", description = "카테고리 선택 시 퀴즈 리스트를 반환합니다.") @PostMapping("/api/members/{memberId}/quizzes") - public ResponseEntity getQuizzes(@RequestParam String nickname, + public ResponseEntity getQuizzes(@RequestParam @Size(min = 2, max = 7, message = "닉네임은 2자 이상, 7자 이하로 입력해주세요.") String nickname, @RequestParam("category") String category) { log.info("nickname : {} " + nickname); return ApiResponse.ok(quizService.getQuizzes(memberService.findByNickname(nickname).getId(), category)); diff --git a/src/main/java/com/hiearth/fullquiz/web/controller/RankingController.java b/src/main/java/com/hiearth/fullquiz/web/controller/RankingController.java index c4b6451..6d9a00d 100644 --- a/src/main/java/com/hiearth/fullquiz/web/controller/RankingController.java +++ b/src/main/java/com/hiearth/fullquiz/web/controller/RankingController.java @@ -5,10 +5,12 @@ import com.hiearth.fullquiz.web.dto.CategoriesResponse; import com.hiearth.fullquiz.web.dto.RankingResponse; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.Size; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -22,7 +24,7 @@ public class RankingController { private final RankingService rankingService; @GetMapping("/rank") - public ResponseEntity> getRanking (String nickname) { + public ResponseEntity> getRanking (@RequestParam @Size(min = 2, max = 7, message = "닉네임은 2자 이상, 7자 이하로 입력해주세요.") String nickname) { return ApiResponse.ok(rankingService.getRanking(nickname)); } } diff --git a/src/main/java/com/hiearth/fullquiz/web/dto/MemberRequest.java b/src/main/java/com/hiearth/fullquiz/web/dto/MemberRequest.java index 01261f4..3d95605 100644 --- a/src/main/java/com/hiearth/fullquiz/web/dto/MemberRequest.java +++ b/src/main/java/com/hiearth/fullquiz/web/dto/MemberRequest.java @@ -12,6 +12,6 @@ public class MemberRequest { @NotBlank(message = "닉네임은 필수입니다.") - @Size(max = 15, message = "닉네임은 15자 이하로 입력해주세요.") + @Size(min = 2, max = 7, message = "닉네임은 2자 이상, 7자 이하로 입력해주세요.") private String nickname; } From 6cb5181547f41aeadde52c26d9aeb63551038683 Mon Sep 17 00:00:00 2001 From: 5ooyeon Date: Sun, 18 May 2025 08:17:14 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Fix:=20error=20=EB=82=B4=20message=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 --- .../java/com/hiearth/fullquiz/global/response/ApiResponse.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/hiearth/fullquiz/global/response/ApiResponse.java b/src/main/java/com/hiearth/fullquiz/global/response/ApiResponse.java index c695a31..1d1c2ec 100644 --- a/src/main/java/com/hiearth/fullquiz/global/response/ApiResponse.java +++ b/src/main/java/com/hiearth/fullquiz/global/response/ApiResponse.java @@ -59,6 +59,7 @@ public static ResponseEntity> error(ErrorType errorType) { return ResponseEntity.status(errorType.getStatus()) .body(ApiResponse.builder() .status(errorType.getStatus().value()) + .message(errorType.getMessage()) .errorCode(errorType.getErrorCode()) .build()); }