Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.umc.training.domain.member.entity.repository;

import com.umc.training.domain.member.entity.MemberMission;
import com.umc.training.domain.mission.entity.enums.MissionStatus;

import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;

import java.util.List;

public interface MemberMissionRepository extends Repository<MemberMission, Long> {

MemberMission save(MemberMission memberMission);

List<MemberMission> findByMemberIdAndStatus(Long memberId, MissionStatus status, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
import com.umc.training.domain.member.entity.Member;
import org.springframework.data.repository.Repository;

import java.util.Optional;

public interface MemberRepository extends Repository<Member, Long> {

// 미션 2
Member findById(Member member);

Optional<Member> findById(Long id);

Integer countById(Long id);

boolean existsById(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.umc.training.domain.mission.controller;

import com.umc.training.domain.mission.dto.response.MemberMissionResponseDTO;
import com.umc.training.domain.mission.dto.response.MissionResponseDTO;
import com.umc.training.domain.mission.service.MissionService;
import com.umc.training.global.apiPayload.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
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;

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

private final MissionService missionService;

@Override
@PostMapping("/{missionId}/user/{userId}/challenge")
public ApiResponse<Void> challengeMission(
@PathVariable("missionId") Long missionId,
@PathVariable("userId") Long userId) {

missionService.challengeMission(missionId, userId);
return ApiResponse.onSuccess(null);
}

@Override
@GetMapping("/store/{storeId}")
public ApiResponse<List<MissionResponseDTO>> getStoreMissions(
@PathVariable("storeId") Long storeId,
@RequestParam("page") int page,
@RequestParam("size") int size) {

return ApiResponse.onSuccess(missionService.getStoreMissions(storeId, page, size));
}

@Override
@GetMapping("/user/{userId}/in-progress")
public ApiResponse<List<MemberMissionResponseDTO>> getMyInProgressMissions(
@PathVariable("userId") Long userId,
@RequestParam("page") int page,
@RequestParam("size") int size) {

return ApiResponse.onSuccess(missionService.getMyInProgressMissions(userId, page, size));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.umc.training.domain.mission.controller;

import com.umc.training.domain.mission.dto.response.MemberMissionResponseDTO;
import com.umc.training.domain.mission.dto.response.MissionResponseDTO;
import com.umc.training.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;

import java.util.List;

@Tag(name = "미션", description = "미션 관련 API")
public interface MissionControllerDocs {

@Operation(
summary = "미션 도전하기",
description = "특정 미션을 사용자의 진행 중인 미션 목록에 추가합니다."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "미션 도전 성공",
content = @Content(schema = @Schema(implementation = ApiResponse.class))
)
})
ApiResponse<Void> challengeMission(
@Parameter(description = "미션 ID", required = true) Long missionId,
@Parameter(description = "사용자 ID", required = true) Long userId
);

@Operation(
summary = "특정 가게의 미션 목록 조회",
description = "페이징을 적용하여 특정 가게의 모든 미션을 조회합니다."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "조회 성공",
content = @Content(schema = @Schema(implementation = ApiResponse.class))
)
})
ApiResponse<List<MissionResponseDTO>> getStoreMissions(
@Parameter(description = "가게 ID", required = true) Long storeId,
@Parameter(description = "페이지 번호 (0부터 시작)", required = true) int page,
@Parameter(description = "페이지 크기", required = true) int size
);

@Operation(
summary = "내가 진행중인 미션 목록 조회",
description = "페이징을 적용하여 사용자가 진행 중인 모든 미션을 조회합니다."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "조회 성공",
content = @Content(schema = @Schema(implementation = ApiResponse.class))
)
})
ApiResponse<List<MemberMissionResponseDTO>> getMyInProgressMissions(
@Parameter(description = "사용자 ID", required = true) Long userId,
@Parameter(description = "페이지 번호 (0부터 시작)", required = true) int page,
@Parameter(description = "페이지 크기", required = true) int size
);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.umc.training.domain.mission.dto.response;

import com.umc.training.domain.member.entity.MemberMission;
import com.umc.training.domain.mission.entity.enums.MissionStatus;

import java.time.LocalDate;

public record MemberMissionResponseDTO(
Long id,
Long missionId,
Long storeId,
String storeName,
LocalDate deadline,
MissionStatus status,
String missionContent,
LocalDate createdAt
) {
public MemberMissionResponseDTO(MemberMission memberMission) {
this(
memberMission.getId(),
memberMission.getMission().getId(),
memberMission.getStore().getId(),
memberMission.getStore().getName(),
memberMission.getDeadline(),
memberMission.getStatus(),
memberMission.getMissionContent(),
memberMission.getCreatedAt()
);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.umc.training.domain.mission.dto.response;

import com.umc.training.domain.mission.entity.Mission;

import java.time.LocalDate;

public record MissionResponseDTO(
Long id,
Integer reward,
LocalDate deadline,
String missionSpec
) {
public MissionResponseDTO(Mission mission) {
this(
mission.getId(),
mission.getReward(),
mission.getDeadline(),
mission.getMissionSpec()
);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,58 @@

import com.umc.training.domain.member.entity.Member;
import com.umc.training.domain.member.entity.MemberMission;
import com.umc.training.domain.member.entity.enums.MemberStatus;
import com.umc.training.domain.mission.entity.Mission;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;

public interface MissionRepository extends Repository<Mission, Long> {
import java.util.List;
import java.util.Optional;

public interface MissionRepository extends Repository<Mission, Long> {

// 미션 3
@Query(
value = "SELECT m " +
"FROM MemberMission m " +
"left join fetch Mission " +
"where m.member.id = :member " +
"AND m.status IN (" +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_PROGRESS, " +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS" +
") " +
"order by m.createdAt DESC",
countQuery = "SELECT COUNT(m) " +
"FROM MemberMission m " +
"WHERE m.member = :member " +
"AND m.status IN (" +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_PROGRESS, " +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS" +
")"

)
Page<MemberMission> findMissionInProgressOrCompletedByMember(
@Param("member") Member member, Pageable pageable);


@Query(
value = "SELECT m " +
"FROM MemberMission m " +
"left join fetch Store s " +
"left join fetch Mission " +
"WHERE s.region.id = :region_id " +
"AND m.member.id IS NULL " +
"AND m.status = com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS " +
"ORDER BY m.createdAt DESC",

countQuery = "SELECT COUNT(m) " +
"FROM MemberMission m " +
"LEFT JOIN m.store s " +
"WHERE s.region.id = :region_id " +
"AND m.member IS NULL " +
"AND m.status = com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS"
)
Page<MemberMission> findChallengingMissionByMember(
@Param("region_id") Long region_id, Pageable pageable);
Optional<Mission> findById(Long id);

List<Mission> findByStoreId(Long storeId, Pageable pageable);

// 미션 3
@Query(value = "SELECT m " +
"FROM MemberMission m " +
"left join fetch Mission " +
"where m.member.id = :member " +
"AND m.status IN (" +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_PROGRESS, " +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS" +
") " +
"order by m.createdAt DESC", countQuery = "SELECT COUNT(m) " +
"FROM MemberMission m " +
"WHERE m.member = :member " +
"AND m.status IN (" +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_PROGRESS, " +
"com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS" +
")"

)
Page<MemberMission> findMissionInProgressOrCompletedByMember(
@Param("member") Member member, Pageable pageable);

@Query(value = "SELECT m " +
"FROM MemberMission m " +
"left join fetch Store s " +
"left join fetch Mission " +
"WHERE s.region.id = :region_id " +
"AND m.member.id IS NULL " +
"AND m.status = com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS " +
"ORDER BY m.createdAt DESC",

countQuery = "SELECT COUNT(m) " +
"FROM MemberMission m " +
"LEFT JOIN m.store s " +
"WHERE s.region.id = :region_id " +
"AND m.member IS NULL " +
"AND m.status = com.umc.training.domain.mission.entity.enums.MissionStatus.IN_THE_WORKS")
Page<MemberMission> findChallengingMissionByMember(
@Param("region_id") Long region_id, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.umc.training.domain.mission.exception;

import com.umc.training.domain.mission.exception.code.MissionErrorCode;
import com.umc.training.global.apiPayload.exception.GeneralException;

public class MissionException extends GeneralException {

public MissionException(MissionErrorCode code) {
super(code);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.umc.training.domain.mission.exception.code;

import com.umc.training.global.apiPayload.code.BaseErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum MissionErrorCode implements BaseErrorCode {

MISSION_NOT_FOUND(HttpStatus.NOT_FOUND, "MISSION_NOT_FOUND_4001", "Mission not found.");

private final HttpStatus status;
private final String message;
private final String code;
}

Loading