diff --git a/src/main/java/com/example/umc9th2/domain/mission/controller/MissionController.java b/src/main/java/com/example/umc9th2/domain/mission/controller/MissionController.java index f1ac845..1fa9e24 100644 --- a/src/main/java/com/example/umc9th2/domain/mission/controller/MissionController.java +++ b/src/main/java/com/example/umc9th2/domain/mission/controller/MissionController.java @@ -30,4 +30,17 @@ public ApiResponse createMission( ) ); } + + //특정가게의미션을 조회 + @GetMapping("/stores/{storeId}") + @Operation(summary = "특정 가게의 미션 목록 조회", description = "특정 가게에 등록된 미션 목록을 페이징하여 조회합니다.") + public ApiResponse> getStoreMissions( + @PathVariable Long storeId, + @ValidPage @RequestParam Integer page + ) { + Pageable pageable = PageRequest.of(page - 1, 10); + Page missionPage = missionService.getStoreMissions(storeId, pageable); + List result = MissionConverter.toMissionListDTO(missionPage.getContent()); + return ApiResponse.onSuccess(GeneralSuccessCode.OK, result); + } } diff --git a/src/main/java/com/example/umc9th2/domain/mission/converter/MissionConverter.java b/src/main/java/com/example/umc9th2/domain/mission/converter/MissionConverter.java index 41fdf75..74b4834 100644 --- a/src/main/java/com/example/umc9th2/domain/mission/converter/MissionConverter.java +++ b/src/main/java/com/example/umc9th2/domain/mission/converter/MissionConverter.java @@ -29,4 +29,17 @@ public static MissionResDTO.CreateMission toCreateMissionDTO(Mission mission) { mission.getStore().getStoreName() ); } + +// 미션목록반환 +public static List toMissionListDTO(List missionList) { + return missionList.stream() + .map(mission -> new MissionResDTO.MissionList( + mission.getMissionId(), + mission.getTitle(), + mission.getDescription(), + mission.getRewardPoints(), + mission.getIsActive() + )) + .toList(); +} } \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/domain/mission/dto/res/MissionResDTO.java b/src/main/java/com/example/umc9th2/domain/mission/dto/res/MissionResDTO.java index feb74ce..0f6e6ef 100644 --- a/src/main/java/com/example/umc9th2/domain/mission/dto/res/MissionResDTO.java +++ b/src/main/java/com/example/umc9th2/domain/mission/dto/res/MissionResDTO.java @@ -10,4 +10,12 @@ public record CreateMission( Integer rewardPoints, String storeName //store 에서 ) {} + //미션 week 9 + public record MissionList( + Long missionId, + String title, + String description, + Integer rewardPoints, + Boolean isActive +) {} } \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/domain/mission/entity/Mission.java b/src/main/java/com/example/umc9th2/domain/mission/entity/Mission.java index 155c184..834b18b 100644 --- a/src/main/java/com/example/umc9th2/domain/mission/entity/Mission.java +++ b/src/main/java/com/example/umc9th2/domain/mission/entity/Mission.java @@ -11,6 +11,7 @@ @Getter @Setter @NoArgsConstructor +@Builder public class Mission { @Id diff --git a/src/main/java/com/example/umc9th2/domain/mission/repository/MissionRepository.java b/src/main/java/com/example/umc9th2/domain/mission/repository/MissionRepository.java index ca79ae5..dd719ea 100644 --- a/src/main/java/com/example/umc9th2/domain/mission/repository/MissionRepository.java +++ b/src/main/java/com/example/umc9th2/domain/mission/repository/MissionRepository.java @@ -4,4 +4,7 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface MissionRepository extends JpaRepository { + //특정 가게의 미션 목록 + Page findByStore_StoreId(Long storeId, Pageable pageable); + } diff --git a/src/main/java/com/example/umc9th2/domain/review/controller/ReviewController.java b/src/main/java/com/example/umc9th2/domain/review/controller/ReviewController.java index f14aeca..6f6ef7e 100644 --- a/src/main/java/com/example/umc9th2/domain/review/controller/ReviewController.java +++ b/src/main/java/com/example/umc9th2/domain/review/controller/ReviewController.java @@ -45,4 +45,16 @@ public ApiResponse createReview( ReviewResDTO.CreateReview result = reviewCommandService.createReview(request, userId); return ApiResponse.onSuccess(code, result); } + //작성한 리뷰 목록조회 + @GetMapping("/my-reviews") + @Operation(summary = "내가 작성한 리뷰 목록 조회", description = "특정 사용자가 작성한 리뷰 목록을 페이징하여 조회합니다.") + public ApiResponse> getMyReviews( + @RequestParam Long userId, + @ValidPage @RequestParam Integer page + ) { + Pageable pageable = PageRequest.of(page - 1, 10); + Page reviewPage = reviewQueryService.getMyReviews(userId, pageable); + List result = ReviewConverter.toMyReviewListDTO(reviewPage.getContent()); + return ApiResponse.onSuccess(GeneralSuccessCode.OK, result); + } } \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/domain/review/converter/ReviewConverter.java b/src/main/java/com/example/umc9th2/domain/review/converter/ReviewConverter.java index bd4510c..399043e 100644 --- a/src/main/java/com/example/umc9th2/domain/review/converter/ReviewConverter.java +++ b/src/main/java/com/example/umc9th2/domain/review/converter/ReviewConverter.java @@ -59,4 +59,19 @@ public static ReviewResDTO.CreateReview toCreateReviewResultDto(Review review) { LocalDateTime.now() ); } + + //내가 작성한 리뷰 DTO 반환해 + public static List toMyReviewListDTO(List reviewList) { + return reviewList.stream() + .map(review -> new ReviewResDTO.MyReviewList( + review.getReviewId(), + review.getStore() != null ? review.getStore().getStoreName() : null, + review.getRating(), + review.getContent(), + review.getCreatedAt() + )) + .toList(); + } + + } \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/domain/review/dto/res/ReviewResDTO.java b/src/main/java/com/example/umc9th2/domain/review/dto/res/ReviewResDTO.java index fa4587c..9a72898 100644 --- a/src/main/java/com/example/umc9th2/domain/review/dto/res/ReviewResDTO.java +++ b/src/main/java/com/example/umc9th2/domain/review/dto/res/ReviewResDTO.java @@ -12,4 +12,12 @@ public record CreateReview( String storeName, LocalDateTime createdAt ) {} + //내가 작성한 review 목ㄹ곻 + public record MyReviewList( + Long reviewId, + String storeName, + Integer rating, + String content, + LocalDateTime createdAt +) {} } diff --git a/src/main/java/com/example/umc9th2/domain/review/entity/Review.java b/src/main/java/com/example/umc9th2/domain/review/entity/Review.java index 525ecbc..86e59ee 100644 --- a/src/main/java/com/example/umc9th2/domain/review/entity/Review.java +++ b/src/main/java/com/example/umc9th2/domain/review/entity/Review.java @@ -2,7 +2,9 @@ import com.example.umc9th2.domain.user.entity.User; import com.example.umc9th2.domain.store.entity.Store; +import com.example.umc9th2.global.BaseEntity; import jakarta.persistence.*; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -13,8 +15,9 @@ @Getter @Setter @NoArgsConstructor +@AllArgsConstructor @Builder -public class Review { +public class Review extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/example/umc9th2/domain/review/repository/ReviewRepository.java b/src/main/java/com/example/umc9th2/domain/review/repository/ReviewRepository.java index 577ae83..2bed3b7 100644 --- a/src/main/java/com/example/umc9th2/domain/review/repository/ReviewRepository.java +++ b/src/main/java/com/example/umc9th2/domain/review/repository/ReviewRepository.java @@ -4,4 +4,7 @@ import org.springframework.data.jpa.repository.*; public interface ReviewRepository extends JpaRepository, ReviewQueryDsl { +//내가 작성한 리뷰 목록 + Page findByUser_UserId(Long userId, Pageable pageable); + } diff --git a/src/main/java/com/example/umc9th2/domain/review/service/ReviewQueryService.java b/src/main/java/com/example/umc9th2/domain/review/service/ReviewQueryService.java index 36ceed8..9ee0bb0 100644 --- a/src/main/java/com/example/umc9th2/domain/review/service/ReviewQueryService.java +++ b/src/main/java/com/example/umc9th2/domain/review/service/ReviewQueryService.java @@ -43,5 +43,10 @@ public List searchReview(String type, String query) { List reviewList = reviewRepository.searchReview(builder); return reviewList; + + + } + public Page getMyReviews(Long userId, Pageable pageable) { + return reviewRepository.findByUser_UserId(userId, pageable); } } diff --git a/src/main/java/com/example/umc9th2/domain/user/controller/UserMissionController.java b/src/main/java/com/example/umc9th2/domain/user/controller/UserMissionController.java index 85eb11d..f7babff 100644 --- a/src/main/java/com/example/umc9th2/domain/user/controller/UserMissionController.java +++ b/src/main/java/com/example/umc9th2/domain/user/controller/UserMissionController.java @@ -36,4 +36,16 @@ public ApiResponse challengeMission( UserMissionResDTO.ChallengeMission result = userMissionService.challengeMission(missionId); return ApiResponse.onSuccess(code, result); } + //진행중인 미션목록죄회 + @GetMapping("/in-progress") + @Operation(summary = "내가 진행중인 미션 목록 조회", description = "특정 사용자가 진행중인 미션 목록을 페이징하여 조회합니다.") + public ApiResponse> getInProgressMissions( + @RequestParam Long userId, + @ValidPage @RequestParam Integer page + ) { + Pageable pageable = PageRequest.of(page - 1, 10); + Page missionPage = userMissionService.getInProgressMissions(userId, pageable); + return ApiResponse.onSuccess(GeneralSuccessCode.OK, missionPage.getContent()); + } + } \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/domain/user/dto/MyMissionDTO.java b/src/main/java/com/example/umc9th2/domain/user/dto/MyMissionDTO.java index 252a0aa..aa64d55 100644 --- a/src/main/java/com/example/umc9th2/domain/user/dto/MyMissionDTO.java +++ b/src/main/java/com/example/umc9th2/domain/user/dto/MyMissionDTO.java @@ -7,8 +7,8 @@ public record MyMissionDTO( String title, String description, Integer rewardPoints, - String status, - LocalDateTime clearedAt, + boolean status, // String에서 바꿈 + LocalDateTime clearedAt, LocalDateTime clearedAt, String storeName, String regionName ) {} \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/domain/user/repository/UserMissionRepository.java b/src/main/java/com/example/umc9th2/domain/user/repository/UserMissionRepository.java index be7c94f..3c51afe 100644 --- a/src/main/java/com/example/umc9th2/domain/user/repository/UserMissionRepository.java +++ b/src/main/java/com/example/umc9th2/domain/user/repository/UserMissionRepository.java @@ -29,4 +29,26 @@ public interface UserMissionRepository extends JpaRepository order by um.status asc, um.clearedAt desc """) List findMyMissions(@Param("userId") Long userId, Pageable pageable); + @Query(""" + select new com.example.umc9th2.domain.user.dto.MyMissionDTO( + m.missionId, + m.title, + m.description, + m.rewardPoints, + um.status, + um.clearedAt, + s.storeName, + rg.regionName + ) + from UserMission um + join um.mission m + join m.store s + join s.region rg + where um.user.userId = :userId + and um.status = false + order by um.clearedAt desc + """) + Page findInProgressMissions(@Param("userId") Long userId, Pageable pageable); + + } diff --git a/src/main/java/com/example/umc9th2/domain/user/service/UserMissionService.java b/src/main/java/com/example/umc9th2/domain/user/service/UserMissionService.java index d04b9dd..a25b7b4 100644 --- a/src/main/java/com/example/umc9th2/domain/user/service/UserMissionService.java +++ b/src/main/java/com/example/umc9th2/domain/user/service/UserMissionService.java @@ -27,6 +27,11 @@ public class UserMissionService { public List getMyMissions(Long userId, Pageable pageable) { return userMissionRepository.findMyMissions(userId, pageable); } + + public Page getInProgressMissions(Long userId, Pageable pageable) { + return userMissionRepository.findInProgressMissions(userId, pageable); + } + //미션 도전 @Transactional diff --git a/src/main/java/com/example/umc9th2/global/annotation/PageValidator.java b/src/main/java/com/example/umc9th2/global/annotation/PageValidator.java new file mode 100644 index 0000000..eefba7e --- /dev/null +++ b/src/main/java/com/example/umc9th2/global/annotation/PageValidator.java @@ -0,0 +1,26 @@ +package com.example.umc9th2.global.annotation; + +import com.example.umc9th2.global.apiPayload.code.GeneralErrorCode; +import com.example.umc9th2.global.apiPayload.exception.GeneralException; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +//tnwjdwnd + +public class PageValidator implements ConstraintValidator { + + @Override + public void initialize(ValidPage constraintAnnotation) { + } + + @Override + public boolean isValid(Integer page, ConstraintValidatorContext context) { + if (page == null) { + throw new GeneralException(GeneralErrorCode.INVALID_PAGE); + } + if (page <= 0) { + throw new GeneralException(GeneralErrorCode.INVALID_PAGE); + } + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/umc9th2/global/annotation/ValidPage.java b/src/main/java/com/example/umc9th2/global/annotation/ValidPage.java new file mode 100644 index 0000000..06be912 --- /dev/null +++ b/src/main/java/com/example/umc9th2/global/annotation/ValidPage.java @@ -0,0 +1,17 @@ +package com.example.umc9th2.global.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = PageValidator.class) +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidPage { + String message() default "페이지 번호는 1 이상이어야 합니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} + diff --git a/src/main/java/com/example/umc9th2/global/apiPayload/code/GeneralErrorCode.java b/src/main/java/com/example/umc9th2/global/apiPayload/code/GeneralErrorCode.java index 8552161..3bd1b33 100644 --- a/src/main/java/com/example/umc9th2/global/apiPayload/code/GeneralErrorCode.java +++ b/src/main/java/com/example/umc9th2/global/apiPayload/code/GeneralErrorCode.java @@ -20,6 +20,10 @@ public enum GeneralErrorCode implements BaseErrorCode{ NOT_FOUND(HttpStatus.NOT_FOUND, "COMMON404_1", "요청한 리소스를 찾을 수 없습니다."), + //추가함 + INVALID_PAGE(HttpStatus.BAD_REQUEST, + "COMMON400_2", + "페이지 번호는 1 이상이어야 합니다."), //에러 핸들러 추가된 enum INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500_1",