Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/com/example/umc9th/Umc9thApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class Umc9thApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.example.umc9th.domain.member.repository;

import com.example.umc9th.domain.member.entity.Member;
import jakarta.persistence.Id;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member,Long> {
// 활성 상태인 회원 단건 조회
Optional<Member> findByIdAndIsActiveTrue(Long id);

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,43 @@
import com.example.umc9th.domain.mission.dto.res.MemberMissionResDTO;
import com.example.umc9th.domain.mission.exception.code.MissionSuccessCode;
import com.example.umc9th.domain.mission.service.command.MemberMissionCommandService;
import com.example.umc9th.domain.mission.service.query.MemberMissionQueryService;
import com.example.umc9th.global.annotation.ValidPage;
import com.example.umc9th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class MemberMissionController {
@Validated
public class MemberMissionController implements MemberMissionControllerDocs {
private final MemberMissionCommandService memberMissionCommandService;
private final MemberMissionQueryService memberMissionQueryService;

@Operation(
summary = "미션 도전하기",
description = "현재 회원(me)에 대해 특정 미션 도전 상태를 추가합니다. (과제에서는 하드코딩 회원 사용)"
)
@Override
@PostMapping("/members/me/missions")
public ApiResponse<MemberMissionResDTO.ChallengeDTO> challengeMission(
@Valid @RequestBody MemberMissionReqDTO.ChallengeDTO dto
) {
MemberMissionResDTO.ChallengeDTO response = memberMissionCommandService.challengeMission(dto);
return ApiResponse.onSuccess(MissionSuccessCode.MISSION_CHALLENGED, response);
}

// 내가 진행중인 미션 목록 조회
@Override
@GetMapping("/members/me/missions/in-progress")
public ApiResponse<MemberMissionResDTO.OngoingMissionListDTO> getMyOngoingMissions(
@RequestParam Long memberId,
@RequestParam @Valid @ValidPage Integer page
) {
MemberMissionResDTO.OngoingMissionListDTO dto =
memberMissionQueryService.getMyOngoingMissions(memberId, page);

return ApiResponse.onSuccess(MissionSuccessCode.MY_ONGOING_MISSIONS_FOUND, dto);
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.example.umc9th.domain.mission.controller;

import com.example.umc9th.domain.mission.dto.req.MemberMissionReqDTO;
import com.example.umc9th.domain.mission.dto.res.MemberMissionResDTO;
import com.example.umc9th.domain.mission.dto.res.MissionResDTO;
import com.example.umc9th.global.annotation.ValidPage;
import com.example.umc9th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

public interface MemberMissionControllerDocs {

@Operation(
summary = "미션 도전하기",
description = "현재 회원(me)에 대해 특정 미션 도전 상태를 추가합니다. (과제에서는 하드코딩 회원 사용)"
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공"),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "실패")
})
ApiResponse<MemberMissionResDTO.ChallengeDTO> challengeMission(
@Valid @RequestBody MemberMissionReqDTO.ChallengeDTO dto
);

@Operation(
summary = "내가 진행 중인 미션 목록 조회",
description = "현재 회원(me)이 도전 중이며 아직 완료하지 않은 미션들을 page 단위(1페이지당 10개)로 조회합니다. page는 1 이상의 정수입니다."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공"),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "실패")
})
ApiResponse<MemberMissionResDTO.OngoingMissionListDTO> getMyOngoingMissions(
@RequestParam Long memberId,
@RequestParam @Valid @ValidPage Integer page
);



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.umc9th.domain.mission.controller;

import com.example.umc9th.domain.mission.dto.res.MissionResDTO;
import com.example.umc9th.domain.mission.exception.code.MissionSuccessCode;
import com.example.umc9th.domain.mission.service.query.MissionQueryService;
import com.example.umc9th.global.annotation.ValidPage;
import com.example.umc9th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
@Validated
public class MissionController implements MissionControllerDocs {

private final MissionQueryService missionQueryService;

@Override
@GetMapping("/restaurants/{restaurantId}/missions")
public ApiResponse<MissionResDTO.RestaurantMissionListDTO> getMissionsByRestaurant(
@PathVariable Long restaurantId,
@RequestParam @Valid @ValidPage Integer page
) {
MissionResDTO.RestaurantMissionListDTO dto =
missionQueryService.findMissionsByRestaurant(restaurantId, page);

return ApiResponse.onSuccess(MissionSuccessCode.RESTAURANT_MISSIONS_FOUND, dto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.umc9th.domain.mission.controller;

import com.example.umc9th.domain.mission.dto.res.MissionResDTO;
import com.example.umc9th.domain.review.dto.res.ReviewResDTO;
import com.example.umc9th.global.annotation.ValidPage;
import com.example.umc9th.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

public interface MissionControllerDocs {

@Operation(
summary = "특정 가게의 미션 목록 조회",
description = "restaurantId에 해당하는 가게의 미션 목록을 page 단위(1페이지당 10개)로 조회합니다. page는 1 이상의 값이어야 합니다."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "성공"),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "실패")
})
ApiResponse<MissionResDTO.RestaurantMissionListDTO> getMissionsByRestaurant(
@PathVariable Long restaurantId,
@RequestParam @Valid @ValidPage Integer page
);

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

import com.example.umc9th.domain.member.entity.Member;
import com.example.umc9th.domain.mission.dto.res.MemberMissionResDTO;
import com.example.umc9th.domain.mission.dto.res.MissionResDTO;
import com.example.umc9th.domain.mission.entity.Mission;
import com.example.umc9th.domain.mission.entity.mapping.MemberMission;
import org.springframework.data.domain.Page;

import java.util.List;
import java.util.Objects;

public class MemberMissionConverter {

Expand All @@ -26,4 +31,40 @@ public static MemberMissionResDTO.ChallengeDTO toChallengeDTO(MemberMission memb
.createdAt(memberMission.getCreatedAt())
.build();
}


// 진행중인 미션 1개 -> DTO
public static MemberMissionResDTO.OngoingMissionDTO toOngoingMissionDTO(MemberMission memberMission) {
Mission mission = memberMission.getMission();

return MemberMissionResDTO.OngoingMissionDTO.builder()
.memberMissionId(memberMission.getId())
.missionId(mission.getId())
.missionName(mission.getMissionName())
.deadline(mission.getDeadline())
.missionPoint(mission.getMissionPoint())
.restaurantId(mission.getRestaurant().getId())
.restaurantName(mission.getRestaurant().getRestaurantName())
.challengedAt(memberMission.getCreatedAt())
.build();
}

// Page<MemberMission> -> OngoingMissionPageDTO
public static MemberMissionResDTO.OngoingMissionListDTO toOngoingMissionListDTO(Page<MemberMission> page) {

List<MemberMissionResDTO.OngoingMissionDTO> missionList =
page.getContent().stream()
.filter(Objects::nonNull)
.map(MemberMissionConverter::toOngoingMissionDTO)
.toList();

return MemberMissionResDTO.OngoingMissionListDTO.builder()
.missions(missionList)
.listSize(page.getSize())
.totalPage(page.getTotalPages())
.totalElements(page.getTotalElements())
.isFirst(page.isFirst())
.isLast(page.isLast())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.umc9th.domain.mission.converter;

import com.example.umc9th.domain.mission.dto.res.MissionResDTO;
import com.example.umc9th.domain.mission.entity.Mission;
import org.springframework.data.domain.Page;

import java.util.Objects;

public class MissionConverter {

public static MissionResDTO.RestaurantMissionDTO toRestaurantMissionDTO(Mission mission) {
return MissionResDTO.RestaurantMissionDTO.builder()
.missionId(mission.getId())
.missionName(mission.getMissionName())
.deadline(mission.getDeadline())
.missionPoint(mission.getMissionPoint())
.restaurantId(mission.getRestaurant().getId())
.restaurantName(mission.getRestaurant().getRestaurantName())
.build();
}

public static MissionResDTO.RestaurantMissionListDTO toRestaurantMissionPageDTO(Page<Mission> page) {
return MissionResDTO.RestaurantMissionListDTO.builder()
.missions(page.getContent().stream()
.filter(Objects::nonNull)
.map(MissionConverter::toRestaurantMissionDTO)
.toList())
.listSize(page.getSize())
.totalPage(page.getTotalPages())
.totalElements(page.getTotalElements())
.isFirst(page.isFirst())
.isLast(page.isLast())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import lombok.Builder;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

public class MemberMissionResDTO {

Expand All @@ -14,4 +16,29 @@ public record ChallengeDTO(
Boolean isCompleted,
LocalDateTime createdAt
) {}


// 진행중인(미완료) 미션 1개 정보
@Builder
public record OngoingMissionDTO(
Long memberMissionId,
Long missionId,
String missionName,
LocalDate deadline,
Integer missionPoint,
Long restaurantId,
String restaurantName,
LocalDateTime challengedAt
) {}

// 내가 진행중인 미션 목록 + 페이징 정보
@Builder
public record OngoingMissionListDTO(
List<OngoingMissionDTO> missions,
Integer listSize,
Integer totalPage,
Long totalElements,
Boolean isFirst,
Boolean isLast
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.example.umc9th.domain.mission.dto.res;

import lombok.Builder;

import java.time.LocalDate;
import java.util.List;

public class MissionResDTO {

// 단일 미션 정보
@Builder
public record RestaurantMissionDTO(
Long missionId,
String missionName,
LocalDate deadline,
Integer missionPoint,
Long restaurantId,
String restaurantName
) {}

// 특정 가게의 미션 목록 + 페이징 정보
@Builder
public record RestaurantMissionListDTO(
List<RestaurantMissionDTO> missions,
Integer listSize,
Integer totalPage,
Long totalElements,
Boolean isFirst,
Boolean isLast
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ public enum MissionSuccessCode implements BaseSuccessCode {
HttpStatus.CREATED,
"MISSION201_1",
"미션 도전에 성공했습니다."
),
RESTAURANT_MISSIONS_FOUND(
HttpStatus.OK,
"MISSION200_1",
"특정 가게의 미션 목록을 성공적으로 조회했습니다."
),

MY_ONGOING_MISSIONS_FOUND(
HttpStatus.OK,
"MISSION200_2",
"내가 진행 중인 미션 목록을 성공적으로 조회했습니다."
);

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.example.umc9th.domain.mission.repository;

import com.example.umc9th.domain.mission.entity.Mission;
import com.example.umc9th.domain.restaurant.entity.Restaurant;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -28,4 +30,9 @@ Page<Mission> findAvailableMissionsByRegionId(
@Param("today") LocalDate today,
Pageable pageable
);

Page<Mission> findAllByRestaurant(
Restaurant restaurant,
PageRequest pageRequest
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.umc9th.domain.mission.service.query;

import com.example.umc9th.domain.mission.dto.res.MemberMissionResDTO;

public interface MemberMissionQueryService {
MemberMissionResDTO.OngoingMissionListDTO getMyOngoingMissions(Long memberId, Integer page);
}
Loading