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
5 changes: 5 additions & 0 deletions src/main/java/com/daytodo/domain/course/entity/Course.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ public Course(
this.courseStatus = CourseStatus.PLANNING;
}

// 코스 시작 (계획 중 -> 진행 중). courseDate 가 도래해 투데이 조회 시점에 승격된다.
public void start() {
this.courseStatus = CourseStatus.IN_PROGRESS;
}

// 코스 종료
public void complete() {
this.courseStatus = CourseStatus.COMPLETED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.data.repository.query.Param;

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

Expand Down Expand Up @@ -38,21 +39,22 @@ List<Course> findAllByOwnerIdAndCourseDateBetweenOrderByCreatedAtDesc(

/*
* 투데이 코스 조회
* 사용자가 참여 중인 코스 중 해당 날짜의 진행 중 코스를 조회한다.
* 사용자가 참여 중인 코스 중 해당 날짜의 코스를 조회한다.
* PLANNING 은 조회 시점에 IN_PROGRESS 로 승격되므로 두 상태를 모두 대상으로 한다.
* 이론상 1건이지만 데이터 이상으로 여러 건일 수 있어 최근 생성 순으로 정렬해 첫 건을 사용한다.
*/
@Query("""
select cm.course from CourseMember cm
where cm.user.id = :userId
and cm.memberStatus = :memberStatus
and cm.course.courseDate = :courseDate
and cm.course.courseStatus = :courseStatus
and cm.course.courseStatus in :courseStatuses
order by cm.course.createdAt desc, cm.course.courseId desc
""")
List<Course> findMemberCoursesByDateAndStatus(
List<Course> findMemberCoursesByDateAndStatuses(
@Param("userId") Long userId,
@Param("courseDate") LocalDate courseDate,
@Param("courseStatus") CourseStatus courseStatus,
@Param("courseStatuses") Collection<CourseStatus> courseStatuses,
@Param("memberStatus") MemberStatus memberStatus
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,20 @@ public class CourseService {
private final RecommendationLikeRepository recommendationLikeRepository;
private final PlaceRepository placeRepository;
private final RecommendationCommentRepository recommendationCommentRepository;
private final TodayCoursePromoter todayCoursePromoter;

private final Clock clock;

// 진행중 목록/배너가 IN_PROGRESS 상태에 의존하므로, 조회 전에 오늘 날짜의
// PLANNING 코스를 IN_PROGRESS 로 승격시킨다(투데이 조회와 동일 규칙). 쓰기 발생.
@Transactional
public CourseResponse.Courses getCourses(Long userId, LocalDate startDate, LocalDate endDate) {
userService.getActiveUser(userId);
validatePeriod(startDate, endDate);
LocalDate today = LocalDate.now(clock);

todayCoursePromoter.promoteDueCourses(userId, today);

List<Course> inProgress = courseRepository.findMemberCoursesByStatus(
userId, MemberStatus.JOINED, CourseStatus.IN_PROGRESS
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.daytodo.domain.course.service;

import com.daytodo.domain.course.entity.Course;
import com.daytodo.domain.course.enums.CourseStatus;
import com.daytodo.domain.course.enums.MemberStatus;
import com.daytodo.domain.course.repository.CourseRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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

/**
* 코스 상태 지연 전환 헬퍼.
* 별도 스케줄러가 없으므로, courseDate 가 도래한 PLANNING 코스를
* 홈/투데이 조회 진입 시점에 IN_PROGRESS 로 승격시킨다.
* 두 조회 경로가 같은 규칙을 쓰도록 승격 로직을 한곳에 모은다.
*/
@Component
@RequiredArgsConstructor
public class TodayCoursePromoter {

private final CourseRepository courseRepository;

/**
* 사용자가 참여 중인 코스 중 courseDate 가 today 인 PLANNING 코스를 IN_PROGRESS 로 승격.
* 호출 측 트랜잭션에 합류하며(REQUIRED), 변경 감지로 커밋 시 반영된다.
*/
@Transactional
public void promoteDueCourses(Long userId, LocalDate today) {
courseRepository.findMemberCoursesByDateAndStatuses(
userId,
today,
List.of(CourseStatus.PLANNING),
MemberStatus.JOINED
).forEach(Course::start);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Clock;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
Expand All @@ -35,17 +36,24 @@ public class TodayCourseService {
private final CourseMemberRepository courseMemberRepository;
private final CoursePlaceRepository coursePlaceRepository;
private final MemoryPhotoRepository memoryPhotoRepository;
private final TodayCoursePromoter todayCoursePromoter;
private final Clock clock;

/*
* 투데이 코스 조회
* 오늘 진행 중인 코스가 없으면 예외가 아니라 todayCourse: null 로 응답한다.
* 오늘 날짜의 코스가 없으면 예외가 아니라 todayCourse: null 로 응답한다.
* 별도의 상태 전이 스케줄러가 없으므로, 조회 진입 시점에 오늘 날짜의 PLANNING
* 코스를 IN_PROGRESS 로 승격시킨다(홈/투데이 공용 규칙).
*/
@Transactional(readOnly = true)
@Transactional
public TodayCourseResponse.GetTodayCourse getTodayCourse(Long userId) {
Optional<Course> todayCourse = courseRepository.findMemberCoursesByDateAndStatus(
LocalDate today = LocalDate.now(clock);
todayCoursePromoter.promoteDueCourses(userId, today);

Optional<Course> todayCourse = courseRepository.findMemberCoursesByDateAndStatuses(
userId,
LocalDate.now(),
CourseStatus.IN_PROGRESS,
today,
List.of(CourseStatus.IN_PROGRESS),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
MemberStatus.JOINED
).stream().findFirst();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ class CourseQueryValidationTest {
@Test
@DisplayName("투데이 코스 관련 JPQL이 정상적으로 실행된다")
void queriesRun() {
assertThat(courseRepository.findMemberCoursesByDateAndStatus(
1L, LocalDate.now(), CourseStatus.IN_PROGRESS, MemberStatus.JOINED
assertThat(courseRepository.findMemberCoursesByDateAndStatuses(
1L, LocalDate.now(),
java.util.List.of(CourseStatus.PLANNING, CourseStatus.IN_PROGRESS),
MemberStatus.JOINED
)).isEmpty();

assertThat(courseMemberRepository.findMembersByCourseId(1L, MemberStatus.JOINED)).isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class CourseServiceTest {
@Mock RecommendationLikeRepository recommendationLikeRepository;
@Mock PlaceRepository placeRepository;
@Mock RecommendationCommentRepository recommendationCommentRepository;
@Mock TodayCoursePromoter todayCoursePromoter;

CourseService courseService;
User user;
Expand All @@ -88,6 +89,7 @@ void setUp() {
recommendationLikeRepository,
placeRepository,
recommendationCommentRepository,
todayCoursePromoter,
CLOCK
);
user = new User("user@example.com", "password", "user", null, LoginType.LOCAL);
Expand Down
Loading