diff --git a/src/main/java/com/ject/studytrip/studylog/application/service/StudyLogQueryService.java b/src/main/java/com/ject/studytrip/studylog/application/service/StudyLogQueryService.java index 5a60e00..de816ba 100644 --- a/src/main/java/com/ject/studytrip/studylog/application/service/StudyLogQueryService.java +++ b/src/main/java/com/ject/studytrip/studylog/application/service/StudyLogQueryService.java @@ -56,4 +56,8 @@ public Slice getStudyLogsSliceByTripReportId(Long tripReportId, int pa return studyLogQueryRepository.findSliceByTripReportIdOrderByCreatedAtDesc( tripReportId, PageRequest.of(page, size)); } + + public List getStudyLogIdsByTripId(Long tripId) { + return studyLogQueryRepository.findAllIdsByTripIdOrderByCreatedDesc(tripId); + } } diff --git a/src/main/java/com/ject/studytrip/studylog/domain/repository/StudyLogQueryRepository.java b/src/main/java/com/ject/studytrip/studylog/domain/repository/StudyLogQueryRepository.java index 566a8b2..8568d58 100644 --- a/src/main/java/com/ject/studytrip/studylog/domain/repository/StudyLogQueryRepository.java +++ b/src/main/java/com/ject/studytrip/studylog/domain/repository/StudyLogQueryRepository.java @@ -1,6 +1,7 @@ package com.ject.studytrip.studylog.domain.repository; import com.ject.studytrip.studylog.domain.model.StudyLog; +import java.util.List; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -19,4 +20,6 @@ public interface StudyLogQueryRepository { Slice findSliceByTripReportIdOrderByCreatedAtDesc( Long tripReportId, Pageable pageable); + + List findAllIdsByTripIdOrderByCreatedDesc(Long tripId); } diff --git a/src/main/java/com/ject/studytrip/studylog/infra/querydsl/StudyLogQueryRepositoryAdapter.java b/src/main/java/com/ject/studytrip/studylog/infra/querydsl/StudyLogQueryRepositoryAdapter.java index dc43d38..eb52064 100644 --- a/src/main/java/com/ject/studytrip/studylog/infra/querydsl/StudyLogQueryRepositoryAdapter.java +++ b/src/main/java/com/ject/studytrip/studylog/infra/querydsl/StudyLogQueryRepositoryAdapter.java @@ -126,6 +126,20 @@ public Slice findSliceByTripReportIdOrderByCreatedAtDesc( return new SliceImpl<>(result, pageable, hasNext); } + @Override + public List findAllIdsByTripIdOrderByCreatedDesc(Long tripId) { + return queryFactory + .select(studyLog.id) + .from(studyLog) + .join(studyLog.dailyGoal, dailyGoal) + .where( + dailyGoal.trip.id.eq(tripId), + studyLog.deletedAt.isNull(), + dailyGoal.deletedAt.isNull()) + .orderBy(studyLog.createdAt.desc()) + .fetch(); + } + private OrderSpecifier[] orderSpecifiers(String order) { return (order.equalsIgnoreCase("OLDEST")) ? new OrderSpecifier[] {studyLog.createdAt.asc(), studyLog.id.asc()} diff --git a/src/main/java/com/ject/studytrip/trip/application/dto/TripRetrospectSummary.java b/src/main/java/com/ject/studytrip/trip/application/dto/TripRetrospectSummary.java index e5943e4..a442fc9 100644 --- a/src/main/java/com/ject/studytrip/trip/application/dto/TripRetrospectSummary.java +++ b/src/main/java/com/ject/studytrip/trip/application/dto/TripRetrospectSummary.java @@ -1,12 +1,15 @@ package com.ject.studytrip.trip.application.dto; +import java.util.List; + public record TripRetrospectSummary( long studyLogCount, // 학습 로그 개수 long totalFocusHours, // 총 집중 시간(시간 단위) - long studyDays // 학습한 일수(중복 날짜 제거) + long studyDays, // 학습한 일수(중복 날짜 제거) + List studyLogIds // 학습 로그 ID 목록 ) { public static TripRetrospectSummary of( - long studyLogCount, long totalFocusHours, long studyDays) { - return new TripRetrospectSummary(studyLogCount, totalFocusHours, studyDays); + long studyLogCount, long totalFocusHours, long studyDays, List studyLogIds) { + return new TripRetrospectSummary(studyLogCount, totalFocusHours, studyDays, studyLogIds); } } diff --git a/src/main/java/com/ject/studytrip/trip/application/facade/TripReportFacade.java b/src/main/java/com/ject/studytrip/trip/application/facade/TripReportFacade.java index eaae684..8d422e9 100644 --- a/src/main/java/com/ject/studytrip/trip/application/facade/TripReportFacade.java +++ b/src/main/java/com/ject/studytrip/trip/application/facade/TripReportFacade.java @@ -61,9 +61,10 @@ public TripRetrospectDetail getTripRetrospect(Long memberId, Long tripId, int pa 0, ChronoUnit.DAYS.between(trip.getStartDate(), trip.getEndDate()) + 1) : 0L; + List studyLogIds = studyLogQueryService.getStudyLogIdsByTripId(trip.getId()); TripRetrospectSummary summary = - TripRetrospectSummary.of(studyLogCount, totalFocusHours, studyDays); + TripRetrospectSummary.of(studyLogCount, totalFocusHours, studyDays, studyLogIds); TripInfo tripInfo = TripInfo.from(trip, 0, 100); StudyLogSliceInfo studyLogDetailSlice = buildStudyLogDetailsSlice(studyLogSlice); diff --git a/src/main/java/com/ject/studytrip/trip/presentation/dto/response/LoadTripRetrospectDetailResponse.java b/src/main/java/com/ject/studytrip/trip/presentation/dto/response/LoadTripRetrospectDetailResponse.java index 2a4bc4d..0b8b600 100644 --- a/src/main/java/com/ject/studytrip/trip/presentation/dto/response/LoadTripRetrospectDetailResponse.java +++ b/src/main/java/com/ject/studytrip/trip/presentation/dto/response/LoadTripRetrospectDetailResponse.java @@ -5,6 +5,7 @@ import com.ject.studytrip.trip.application.dto.TripInfo; import com.ject.studytrip.trip.application.dto.TripRetrospectSummary; import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; public record LoadTripRetrospectDetailResponse( @Schema(description = "여행 이름") String name, @@ -13,6 +14,7 @@ public record LoadTripRetrospectDetailResponse( @Schema(description = "총 학습 시간") long totalFocusHours, @Schema(description = "학습 로그 개수 (세션 성공)") long studyLogCount, @Schema(description = "연속 학습일") long studyDays, + @Schema(description = "학습 로그 ID 목록") List studyLogIds, @Schema(description = "학습 로그 히스토리") LoadStudyLogsSliceResponse history) { public static LoadTripRetrospectDetailResponse of( TripRetrospectSummary tripRetrospectSummary, @@ -25,6 +27,7 @@ public static LoadTripRetrospectDetailResponse of( tripRetrospectSummary.totalFocusHours(), tripRetrospectSummary.studyLogCount(), tripRetrospectSummary.studyDays(), + tripRetrospectSummary.studyLogIds(), LoadStudyLogsSliceResponse.of( studyLogDetailSlice.studyLogDetails(), studyLogDetailSlice.hasNext())); } diff --git a/src/test/java/com/ject/studytrip/studylog/application/service/StudyLogQueryServiceTest.java b/src/test/java/com/ject/studytrip/studylog/application/service/StudyLogQueryServiceTest.java index d23acb9..0c6f5dc 100644 --- a/src/test/java/com/ject/studytrip/studylog/application/service/StudyLogQueryServiceTest.java +++ b/src/test/java/com/ject/studytrip/studylog/application/service/StudyLogQueryServiceTest.java @@ -278,4 +278,45 @@ void shouldReturnStudyLogsByTripReportIdWithSlice() { assertThat(result.getContent().get(1)).isEqualTo(studyLog2); } } + + @Nested + @DisplayName("getStudyLogIdsByTripId 메서드는") + class GetStudyLogIdsByTripId { + + @Test + @DisplayName("학습 로그가 존재하지 않으면 빈 리스트를 반환한다.") + void shouldReturnEmptyListWhenStudyLogDoesNotExist() { + // given + Long tripId = courseTrip.getId(); + studyLog1.updateDeletedAt(); + studyLog2.updateDeletedAt(); + given(studyLogQueryRepository.findAllIdsByTripIdOrderByCreatedDesc(tripId)) + .willReturn(List.of()); + + // when + List result = studyLogQueryService.getStudyLogIdsByTripId(tripId); + + // then + assertThat(result).isEmpty(); + } + + @Test + @DisplayName("학습 로그가 하나라도 존재하면 학습 로그 ID 목록을 반환한다.") + void shouldReturnStudyLogIdsWhenStudyLogExists() { + // given + Long tripId = courseTrip.getId(); + Long studyLogId1 = studyLog1.getId(); + Long studyLogId2 = studyLog2.getId(); + given(studyLogQueryRepository.findAllIdsByTripIdOrderByCreatedDesc(tripId)) + .willReturn(List.of(studyLogId1, studyLogId2)); + + // when + List result = studyLogQueryService.getStudyLogIdsByTripId(tripId); + + // then + assertThat(result).hasSize(2); + assertThat(result.get(0)).isEqualTo(studyLogId1); + assertThat(result.get(1)).isEqualTo(studyLogId2); + } + } } diff --git a/src/test/java/com/ject/studytrip/trip/presentation/controller/TripReportControllerIntegrationTest.java b/src/test/java/com/ject/studytrip/trip/presentation/controller/TripReportControllerIntegrationTest.java index 72abf59..85ea951 100644 --- a/src/test/java/com/ject/studytrip/trip/presentation/controller/TripReportControllerIntegrationTest.java +++ b/src/test/java/com/ject/studytrip/trip/presentation/controller/TripReportControllerIntegrationTest.java @@ -302,6 +302,7 @@ void shouldReturnTripRetrospectWhenTripIdIsValid() throws Exception { .andExpect(jsonPath("$.data.name").isString()) .andExpect(jsonPath("$.data.totalFocusHours").isNumber()) .andExpect(jsonPath("$.data.studyLogCount").isNumber()) + .andExpect(jsonPath("$.data.studyLogIds").isArray()) .andExpect(jsonPath("$.data.studyDays").isNumber()) .andExpect(jsonPath("$.data.history").isNotEmpty()); }