diff --git a/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryCustom.java b/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryCustom.java index f318c66c4..38ed4573a 100644 --- a/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryCustom.java +++ b/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryCustom.java @@ -2,12 +2,10 @@ import com.depromeet.domain.member.domain.Member; import com.depromeet.domain.mission.domain.Mission; -import java.util.Optional; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; public interface MissionRepositoryCustom { - Optional findByMissionId(Long missionId); Slice findAllMission(Member member, Pageable pageable, Long lastId); } diff --git a/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryImpl.java b/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryImpl.java index e205724cf..85830dc04 100644 --- a/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryImpl.java +++ b/src/main/java/com/depromeet/domain/mission/dao/MissionRepositoryImpl.java @@ -9,7 +9,6 @@ import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import java.util.List; -import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -21,18 +20,6 @@ public class MissionRepositoryImpl implements MissionRepositoryCustom { private final JPAQueryFactory jpaQueryFactory; - @Override - public Optional findByMissionId(Long missionId) { - Mission findMission = - jpaQueryFactory - .selectFrom(mission) - .leftJoin(mission.missionRecords, missionRecord) - .fetchJoin() - .where(mission.id.eq(missionId)) - .fetchOne(); - return Optional.ofNullable(findMission); - } - @Override public Slice findAllMission(Member member, Pageable pageable, Long lastId) { JPAQuery query = diff --git a/src/main/java/com/depromeet/domain/mission/service/MissionService.java b/src/main/java/com/depromeet/domain/mission/service/MissionService.java index 2655129e7..8a3cf2166 100644 --- a/src/main/java/com/depromeet/domain/mission/service/MissionService.java +++ b/src/main/java/com/depromeet/domain/mission/service/MissionService.java @@ -37,7 +37,7 @@ public MissionCreateResponse createMission(MissionCreateRequest missionCreateReq public MissionFindResponse findOneMission(Long missionId) { Mission mission = missionRepository - .findByMissionId(missionId) + .findById(missionId) .orElseThrow(() -> new CustomException(ErrorCode.MISSION_NOT_FOUND)); return MissionFindResponse.from(mission); } diff --git a/src/main/java/com/depromeet/domain/missionRecord/api/MissionRecordController.java b/src/main/java/com/depromeet/domain/missionRecord/api/MissionRecordController.java index 7b19fe9e6..9176fab2b 100644 --- a/src/main/java/com/depromeet/domain/missionRecord/api/MissionRecordController.java +++ b/src/main/java/com/depromeet/domain/missionRecord/api/MissionRecordController.java @@ -1,16 +1,21 @@ package com.depromeet.domain.missionRecord.api; import com.depromeet.domain.missionRecord.dto.request.MissionRecordCreateRequest; +import com.depromeet.domain.missionRecord.dto.response.MissionRecordFindResponse; import com.depromeet.domain.missionRecord.service.MissionRecordService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import java.time.YearMonth; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Tag(name = "3. [미션 기록]", description = "미션 기록 관련 API") @@ -27,4 +32,12 @@ public ResponseEntity missionRecordCreate( Long missionRecordId = missionRecordService.createMissionRecord(request); return ResponseEntity.status(HttpStatus.CREATED).body(missionRecordId); } + + @Operation(summary = "미션 기록 조회 (캘린더 뷰)", description = "미션 기록을 조회합니다.") + @GetMapping + public List missionRecordFind( + @RequestParam("missionId") Long missionId, + @RequestParam("yearMonth") YearMonth yearMonth) { + return missionRecordService.findAllMissionRecord(missionId, yearMonth); + } } diff --git a/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepository.java b/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepository.java index a7ab40b28..d8b6ff960 100644 --- a/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepository.java +++ b/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepository.java @@ -3,4 +3,5 @@ import com.depromeet.domain.missionRecord.domain.MissionRecord; import org.springframework.data.jpa.repository.JpaRepository; -public interface MissionRecordRepository extends JpaRepository {} +public interface MissionRecordRepository + extends JpaRepository, MissionRecordRepositoryCustom {} diff --git a/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepositoryCustom.java b/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepositoryCustom.java new file mode 100644 index 000000000..df0abc76d --- /dev/null +++ b/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepositoryCustom.java @@ -0,0 +1,10 @@ +package com.depromeet.domain.missionRecord.dao; + +import com.depromeet.domain.missionRecord.domain.MissionRecord; +import java.time.YearMonth; +import java.util.List; + +public interface MissionRecordRepositoryCustom { + + List findAllByMissionIdAndYearMonth(Long missionId, YearMonth yearMonth); +} diff --git a/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepositoryImpl.java b/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepositoryImpl.java new file mode 100644 index 000000000..0da65a921 --- /dev/null +++ b/src/main/java/com/depromeet/domain/missionRecord/dao/MissionRecordRepositoryImpl.java @@ -0,0 +1,42 @@ +package com.depromeet.domain.missionRecord.dao; + +import static com.depromeet.domain.missionRecord.domain.QMissionRecord.*; + +import com.depromeet.domain.missionRecord.domain.MissionRecord; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.time.YearMonth; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class MissionRecordRepositoryImpl implements MissionRecordRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public List findAllByMissionIdAndYearMonth(Long missionId, YearMonth yearMonth) { + return jpaQueryFactory + .selectFrom(missionRecord) + .where( + missionIdEq(missionId), + yearEq(yearMonth.getYear()), + monthEq(yearMonth.getMonthValue())) + .orderBy(missionRecord.startedAt.asc()) + .fetch(); + } + + private BooleanExpression missionIdEq(Long missionId) { + return missionRecord.mission.id.eq(missionId); + } + + private BooleanExpression yearEq(int year) { + return missionRecord.startedAt.year().eq(year); + } + + private BooleanExpression monthEq(int month) { + return missionRecord.startedAt.month().eq(month); + } +} diff --git a/src/main/java/com/depromeet/domain/missionRecord/dto/.gitkeep b/src/main/java/com/depromeet/domain/missionRecord/dto/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/main/java/com/depromeet/domain/missionRecord/dto/response/MissionRecordFindResponse.java b/src/main/java/com/depromeet/domain/missionRecord/dto/response/MissionRecordFindResponse.java new file mode 100644 index 000000000..2cf6611a5 --- /dev/null +++ b/src/main/java/com/depromeet/domain/missionRecord/dto/response/MissionRecordFindResponse.java @@ -0,0 +1,22 @@ +package com.depromeet.domain.missionRecord.dto.response; + +import com.depromeet.domain.missionRecord.domain.MissionRecord; +import java.time.LocalDateTime; + +public record MissionRecordFindResponse( + Long recordId, + String remark, + String imageUrl, + int missionDay, + LocalDateTime startedAt, + LocalDateTime finishedAt) { + public static MissionRecordFindResponse from(MissionRecord missionRecord) { + return new MissionRecordFindResponse( + missionRecord.getId(), + missionRecord.getRemark(), + missionRecord.getImageUrl(), + missionRecord.getStartedAt().getDayOfMonth(), + missionRecord.getStartedAt(), + missionRecord.getFinishedAt()); + } +} diff --git a/src/main/java/com/depromeet/domain/missionRecord/service/.gitkeep b/src/main/java/com/depromeet/domain/missionRecord/service/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/main/java/com/depromeet/domain/missionRecord/service/MissionRecordService.java b/src/main/java/com/depromeet/domain/missionRecord/service/MissionRecordService.java index 2ea30e037..a5931987d 100644 --- a/src/main/java/com/depromeet/domain/missionRecord/service/MissionRecordService.java +++ b/src/main/java/com/depromeet/domain/missionRecord/service/MissionRecordService.java @@ -6,10 +6,13 @@ import com.depromeet.domain.missionRecord.dao.MissionRecordRepository; import com.depromeet.domain.missionRecord.domain.MissionRecord; import com.depromeet.domain.missionRecord.dto.request.MissionRecordCreateRequest; +import com.depromeet.domain.missionRecord.dto.response.MissionRecordFindResponse; import com.depromeet.global.error.exception.CustomException; import com.depromeet.global.error.exception.ErrorCode; import com.depromeet.global.util.MemberUtil; import java.time.Duration; +import java.time.YearMonth; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -38,9 +41,16 @@ public Long createMissionRecord(MissionRecordCreateRequest request) { return missionRecordRepository.save(missionRecord).getId(); } + public List findAllMissionRecord( + Long missionId, YearMonth yearMonth) { + List missionRecords = + missionRecordRepository.findAllByMissionIdAndYearMonth(missionId, yearMonth); + return missionRecords.stream().map(MissionRecordFindResponse::from).toList(); + } + private Mission findMission(MissionRecordCreateRequest request) { return missionRepository - .findByMissionId(request.missionId()) + .findById(request.missionId()) .orElseThrow(() -> new CustomException(ErrorCode.MISSION_NOT_FOUND)); } diff --git a/src/test/java/com/depromeet/domain/mission/repository/MissionRepositoryTest.java b/src/test/java/com/depromeet/domain/mission/repository/MissionRepositoryTest.java index f8d23d62b..db0e5020a 100644 --- a/src/test/java/com/depromeet/domain/mission/repository/MissionRepositoryTest.java +++ b/src/test/java/com/depromeet/domain/mission/repository/MissionRepositoryTest.java @@ -128,7 +128,7 @@ void setUp() { startedAt.plusWeeks(2), saveMember)); // when - Optional findMission = missionRepository.findByMissionId(saveMission.getId()); + Optional findMission = missionRepository.findById(saveMission.getId()); // then assertThat(findMission).isPresent();