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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.back.domain.mentoring.slot.dto.response.MentorSlotDto;
import com.back.domain.mentoring.slot.entity.MentorSlot;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

Expand All @@ -24,12 +25,7 @@ public interface MentorSlotRepository extends JpaRepository<MentorSlot, Long> {
ms.mentor.member.id,
ms.startDateTime,
ms.endDateTime,
CASE
WHEN ms.startDateTime < CURRENT_TIMESTAMP
AND ms.status = com.back.domain.mentoring.slot.constant.MentorSlotStatus.AVAILABLE
THEN com.back.domain.mentoring.slot.constant.MentorSlotStatus.EXPIRED
ELSE ms.status
END,
ms.status,
r.id
)
FROM MentorSlot ms
Expand Down Expand Up @@ -60,15 +56,16 @@ List<MentorSlotDto> findMySlots(
FROM MentorSlot ms
WHERE ms.mentor.id = :mentorId
AND ms.status = 'AVAILABLE'
AND ms.startDateTime >= CURRENT_TIMESTAMP
AND ms.startDateTime >= :now
AND ms.startDateTime < :end
AND ms.endDateTime >= :start
ORDER BY ms.startDateTime ASC
""")
List<MentorSlotDto> findAvailableSlots(
@Param("mentorId") Long mentorId,
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end
@Param("end") LocalDateTime end,
@Param("now") LocalDateTime now
);

@Query("""
Expand Down Expand Up @@ -100,4 +97,15 @@ boolean existsOverlappingExcept(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end
);

@Modifying
@Query("""
UPDATE MentorSlot ms
SET ms.status = com.back.domain.mentoring.slot.constant.MentorSlotStatus.EXPIRED
WHERE ms.startDateTime < :now
AND ms.status = com.back.domain.mentoring.slot.constant.MentorSlotStatus.AVAILABLE
""")
int expirePassedSlots(
@Param("now") LocalDateTime now
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.back.domain.mentoring.slot.repository.MentorSlotRepository;
import com.back.global.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -24,6 +26,7 @@

@Service
@RequiredArgsConstructor
@Slf4j
public class MentorSlotService {

private final MentorSlotRepository mentorSlotRepository;
Expand All @@ -40,7 +43,8 @@ public List<MentorSlotDto> getMyMentorSlots(Mentor mentor, LocalDateTime startDa
public List<MentorSlotDto> getAvailableMentorSlots(Long mentorId, LocalDateTime startDate, LocalDateTime endDate) {
DateTimeValidator.validateTime(startDate, endDate);

return mentorSlotRepository.findAvailableSlots(mentorId, startDate, endDate);
LocalDateTime now = LocalDateTime.now();
return mentorSlotRepository.findAvailableSlots(mentorId, startDate, endDate, now);
}

@Transactional(readOnly = true)
Expand Down Expand Up @@ -147,6 +151,24 @@ private LocalDate findNextOrSameDayOfWeek(LocalDate startDate, DayOfWeek targetD
}


// ===== 스케줄러 =====

/**
* 매 시간 30분에 지난 슬롯 만기 처리
* - AVAILABLE -> EXPIRED
*/
@Scheduled(cron = "0 */30 * * * *")
@Transactional
public void expirePassedSlots() {
LocalDateTime now = LocalDateTime.now();

int updateCount = mentorSlotRepository.expirePassedSlots(now);
if (updateCount > 0) {
log.info("만료된 슬롯 {}개 업데이트 완료 at {}", updateCount, now);
}
}


// ===== 검증 메서드 =====

private static void validateOwner(MentorSlot mentorSlot, Mentor mentor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,17 @@ void getAvailableMentorSlots() {
);

List<MentorSlotDto> availableSlots = List.of(slotDto1, slotDto2);
LocalDateTime now = LocalDateTime.now();

when(mentorSlotRepository.findAvailableSlots(mentor1.getId(), startDate, endDate))
when(mentorSlotRepository.findAvailableSlots(mentor1.getId(), startDate, endDate, now))
.thenReturn(availableSlots);

// when
List<MentorSlotDto> result = mentorSlotService.getAvailableMentorSlots(mentor1.getId(), startDate, endDate);

// then
assertThat(result).hasSize(2);
verify(mentorSlotRepository).findAvailableSlots(mentor1.getId(), startDate, endDate);
verify(mentorSlotRepository).findAvailableSlots(mentor1.getId(), startDate, endDate, now);
}
}

Expand Down