diff --git a/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomMemberRepository.java b/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomMemberRepository.java index 47c013311..8141f2665 100644 --- a/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomMemberRepository.java +++ b/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomMemberRepository.java @@ -1,9 +1,11 @@ package org.chzzk.howmeet.domain.regular.room.repository; +import org.chzzk.howmeet.domain.regular.room.dto.get.response.RoomMemberGetResponse; import org.chzzk.howmeet.domain.regular.room.entity.RoomMember; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; @@ -14,4 +16,9 @@ public interface RoomMemberRepository extends JpaRepository { Page findByMemberId(Long memberId, Pageable pageable); Optional findByRoomIdAndMemberId(@Param("roomId") final Long roomId, @Param("memberId") final Long memberId); boolean existsByRoomIdAndMemberId(Long roomId, Long memberId); + + @Query("SELECT new org.chzzk.howmeet.domain.regular.room.dto.get.response.RoomMemberGetResponse(rm.isLeader) " + + "FROM RoomMember rm " + + "WHERE rm.room.id = :roomId AND rm.memberId = :memberId") + Optional findRoomMemberGetResponseByRoomIdAndMemberId(@Param("roomId") Long roomId, @Param("memberId") Long memberId); } \ No newline at end of file diff --git a/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomRepository.java b/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomRepository.java index 0fe2d4427..1bacc111f 100644 --- a/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomRepository.java +++ b/src/main/java/org/chzzk/howmeet/domain/regular/room/repository/RoomRepository.java @@ -2,6 +2,7 @@ import org.chzzk.howmeet.domain.regular.room.entity.Room; 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; @@ -13,4 +14,10 @@ public interface RoomRepository extends JpaRepository { "LEFT JOIN Member m ON m.id = rm.memberId " + "WHERE r.id = :roomId") Optional findRoomWithMembersAndNicknames(@Param("roomId") Long roomId); + + @Modifying + @Query("UPDATE Room r SET r.disable = true WHERE r.id = :roomId") + void disableRoomById(@Param("roomId") Long roomId); + + boolean existsByIdAndDisableFalse(Long roomId); } \ No newline at end of file diff --git a/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomMemberService.java b/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomMemberService.java index 79081413b..8f7187803 100644 --- a/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomMemberService.java +++ b/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomMemberService.java @@ -29,8 +29,8 @@ public class RoomMemberService { private final RoomRepository roomRepository; public RoomMemberGetResponse getRoomMember(final AuthPrincipal authPrincipal, final Long roomId) { - final RoomMember roomMember = findRoomMemberByAuthAndRoomId(authPrincipal, roomId); - return RoomMemberGetResponse.from(roomMember); + return roomMemberRepository.findRoomMemberGetResponseByRoomIdAndMemberId(roomId, authPrincipal.id()) + .orElseThrow(() -> new RoomMemberException(ROOM_NOT_FOUND)); } @Transactional diff --git a/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomService.java b/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomService.java index f0e6d144e..9ad3a9873 100644 --- a/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomService.java +++ b/src/main/java/org/chzzk/howmeet/domain/regular/room/service/RoomService.java @@ -122,8 +122,11 @@ public void updateRoom(final Long roomId, final RoomRequest roomRequest) { @Transactional public void deleteRoom(final Long roomId) { - Room room = getRoomById(roomId); - roomRepository.delete(room); + if (!roomRepository.existsByIdAndDisableFalse(roomId)) { + throw new RoomException(ROOM_NOT_FOUND); + } + + roomRepository.disableRoomById(roomId); } private RoomListResponse mapToRoomListResponse(RoomMember roomMember) { diff --git a/src/main/java/org/chzzk/howmeet/domain/regular/schedule/repository/MSRepository.java b/src/main/java/org/chzzk/howmeet/domain/regular/schedule/repository/MSRepository.java index 280cdc894..1b08f8ed9 100644 --- a/src/main/java/org/chzzk/howmeet/domain/regular/schedule/repository/MSRepository.java +++ b/src/main/java/org/chzzk/howmeet/domain/regular/schedule/repository/MSRepository.java @@ -1,11 +1,32 @@ package org.chzzk.howmeet.domain.regular.schedule.repository; import org.chzzk.howmeet.domain.regular.room.entity.Room; +import org.chzzk.howmeet.domain.regular.schedule.dto.CompletedMSResponse; +import org.chzzk.howmeet.domain.regular.schedule.dto.ProgressedMSResponse; import org.chzzk.howmeet.domain.regular.schedule.entity.MemberSchedule; +import org.chzzk.howmeet.domain.regular.schedule.entity.ScheduleStatus; 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; +import org.springframework.transaction.annotation.Transactional; import java.util.Optional; public interface MSRepository extends JpaRepository { Optional findByIdAndRoomId(Long msId, Long roomId); + + @Query("SELECT ms.status FROM MemberSchedule ms WHERE ms.id = :msId AND ms.room.id = :roomId") + Optional findStatusByIdAndRoomId(@Param("msId") Long msId, @Param("roomId") Long roomId); + + @Modifying + @Transactional + @Query("UPDATE MemberSchedule ms SET ms.disable = true WHERE ms.id = :msId AND ms.room.id = :roomId") + void deactivateMemberSchedule(@Param("msId") Long msId, @Param("roomId") Long roomId); + + @Query("SELECT new org.chzzk.howmeet.domain.regular.schedule.dto.ProgressedMSResponse(ms.id, ms.dates, ms.time, ms.name, ms.status) " + + "FROM MemberSchedule ms WHERE ms.id = :msId AND ms.room.id = :roomId AND ms.status = 'PROGRESS'") + Optional findProgressScheduleDto(@Param("msId") Long msId, @Param("roomId") Long roomId); + + boolean existsByIdAndRoomId(Long msId, Long roomId); } \ No newline at end of file diff --git a/src/main/java/org/chzzk/howmeet/domain/regular/schedule/service/MSService.java b/src/main/java/org/chzzk/howmeet/domain/regular/schedule/service/MSService.java index 30d934bc7..d66d0230d 100644 --- a/src/main/java/org/chzzk/howmeet/domain/regular/schedule/service/MSService.java +++ b/src/main/java/org/chzzk/howmeet/domain/regular/schedule/service/MSService.java @@ -38,22 +38,25 @@ public MSCreateResponse createMemberSchedule(final Long roomId, final MSRequest .orElseThrow(() -> new MSException(ROOM_NOT_FOUND)); MemberSchedule memberSchedule = msRequest.toEntity(room); - MemberSchedule savedSchedule = msRepository.save(memberSchedule); return MSCreateResponse.from(room); } public MSResponse getMemberSchedule(final Long roomId, final Long msId) { - MemberSchedule memberSchedule = findMemberScheduleByRoomIdAndMsId(roomId, msId); + ScheduleStatus status = msRepository.findStatusByIdAndRoomId(msId, roomId) + .orElseThrow(() -> new MSException(SCHEDULE_NOT_FOUND)); - if (memberSchedule.getStatus() == ScheduleStatus.COMPLETE) { + // Todo complete 경우에는 후처리가 필요한데 dto를 하나더 만들어서 가져와서 변환하는게 맞는지 + if (status == ScheduleStatus.COMPLETE) { + MemberSchedule memberSchedule = findMemberScheduleByRoomIdAndMsId(roomId, msId); ConfirmSchedule confirmSchedule = findConfirmScheduleByMSId(msId); List confirmTimes = confirmSchedule.getTimes(); List dates = extractDatesFromConfirmTimes(confirmTimes); ScheduleTime scheduleTime = extractScheduleTimeFromConfirmTimes(confirmTimes); return CompletedMSResponse.of(memberSchedule, dates, scheduleTime); - } else if (memberSchedule.getStatus() == ScheduleStatus.PROGRESS) { - return ProgressedMSResponse.from(memberSchedule); + } else if (status == ScheduleStatus.PROGRESS) { + return msRepository.findProgressScheduleDto(msId, roomId) + .orElseThrow(() -> new MSException(SCHEDULE_NOT_FOUND)); } throw new IllegalStateException("알 수 없는 상태입니다."); @@ -61,16 +64,20 @@ public MSResponse getMemberSchedule(final Long roomId, final Long msId) { @Transactional public void deleteMemberSchedule(final Long roomId, final Long msId) { - MemberSchedule memberSchedule = findMemberScheduleByRoomIdAndMsId(roomId, msId); - memberSchedule.deactivate(); - msRepository.save(memberSchedule); + if (!msRepository.existsByIdAndRoomId(msId, roomId)) { + // 예외 수정 필요 + throw new MSException(SCHEDULE_NOT_FOUND); + } + msRepository.deactivateMemberSchedule(msId, roomId); } + // Todo repository private MemberSchedule findMemberScheduleByRoomIdAndMsId(Long roomId, Long msId) { return msRepository.findByIdAndRoomId(msId, roomId) .orElseThrow(() -> new MSException(SCHEDULE_NOT_FOUND)); } + // Todo repository private ConfirmSchedule findConfirmScheduleByMSId(Long memberScheduleId) { return confirmRepository.findByMemberScheduleId(memberScheduleId) .orElseThrow(() -> new IllegalArgumentException("일치하는 일정 결과를 찾을 수 없습니다.")); diff --git a/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/repository/GSRepository.java b/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/repository/GSRepository.java index b2e5cbd48..4c86bc5fd 100644 --- a/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/repository/GSRepository.java +++ b/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/repository/GSRepository.java @@ -1,13 +1,23 @@ package org.chzzk.howmeet.domain.temporary.schedule.repository; import org.chzzk.howmeet.domain.regular.schedule.entity.ScheduleStatus; +import org.chzzk.howmeet.domain.temporary.schedule.dto.GSResponse; import org.chzzk.howmeet.domain.temporary.schedule.entity.GuestSchedule; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; public interface GSRepository extends JpaRepository, GSQueryDSL { - List findByStatusAndCreatedAtBefore(ScheduleStatus status, LocalDateTime cutoffDate); - List findByStatusAndUpdatedAtBefore(ScheduleStatus status, LocalDateTime cutoffDate); + @Query("SELECT gs.id FROM GuestSchedule gs WHERE gs.status = :status AND gs.createdAt < :cutoffDate") + List findIdsByStatusAndCreatedAtBefore(@Param("status") ScheduleStatus status, @Param("cutoffDate") LocalDateTime cutoffDate); + @Query("SELECT gs.id FROM GuestSchedule gs WHERE gs.status = :status AND gs.updatedAt < :cutoffDate") + List findIdsByStatusAndUpdatedAtBefore(@Param("status") ScheduleStatus status, @Param("cutoffDate") LocalDateTime cutoffDate); + + @Query("SELECT new org.chzzk.howmeet.domain.temporary.schedule.dto.GSResponse(gs.id, gs.dates, gs.time, gs.name, gs.status) " + + "FROM GuestSchedule gs WHERE gs.id = :guestScheduleId") + Optional findGuestScheduleDtoById(@Param("guestScheduleId") Long guestScheduleId); } \ No newline at end of file diff --git a/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSService.java b/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSService.java index 4886719d3..4e906248d 100644 --- a/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSService.java +++ b/src/main/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSService.java @@ -31,9 +31,8 @@ public GSCreateResponse createGuestSchedule(final GSRequest gsRequest) { } public GSResponse getGuestSchedule(final Long guestScheduleId) { - GuestSchedule guestSchedule = gsRepository.findById(guestScheduleId) + return gsRepository.findGuestScheduleDtoById(guestScheduleId) .orElseThrow(() -> new GSException(SCHEDULE_NOT_FOUND)); - return GSResponse.of(guestSchedule); } @Scheduled(cron = "0 0 0 * * ?") @@ -41,14 +40,16 @@ public GSResponse getGuestSchedule(final Long guestScheduleId) { public void disableOldGuestSchedules() { LocalDateTime now = LocalDateTime.now(); // PROGRESS 상태인 스케줄 삭제 - List progressSchedules = gsRepository.findByStatusAndCreatedAtBefore(ScheduleStatus.PROGRESS, now.minusDays(10)); - for (GuestSchedule schedule : progressSchedules) { + List progressScheduleIds = gsRepository.findIdsByStatusAndCreatedAtBefore(ScheduleStatus.PROGRESS, now.minusDays(10)); + for (Long scheduleId : progressScheduleIds) { + GuestSchedule schedule = gsRepository.findById(scheduleId).orElseThrow(); schedule.deactivate(); } // COMPLETE 상태인 스케줄 삭제 - List completeSchedules = gsRepository.findByStatusAndUpdatedAtBefore(ScheduleStatus.COMPLETE, now.minusDays(10)); - for (GuestSchedule schedule : completeSchedules) { + List completeScheduleIds = gsRepository.findIdsByStatusAndUpdatedAtBefore(ScheduleStatus.COMPLETE, now.minusDays(10)); + for (Long scheduleId : completeScheduleIds) { + GuestSchedule schedule = gsRepository.findById(scheduleId).orElseThrow(); schedule.deactivate(); } } diff --git a/src/test/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSServiceTest.java b/src/test/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSServiceTest.java index 061486210..18b1ef902 100644 --- a/src/test/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSServiceTest.java +++ b/src/test/java/org/chzzk/howmeet/domain/temporary/schedule/service/GSServiceTest.java @@ -1,78 +1,78 @@ -package org.chzzk.howmeet.domain.temporary.schedule.service; - -import org.chzzk.howmeet.domain.regular.schedule.entity.ScheduleStatus; -import org.chzzk.howmeet.domain.temporary.schedule.entity.GuestSchedule; -import org.chzzk.howmeet.domain.temporary.schedule.exception.GSException; -import org.chzzk.howmeet.domain.temporary.schedule.repository.GSRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.time.LocalDateTime; -import java.util.Collections; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.chzzk.howmeet.domain.temporary.schedule.exception.GSErrorCode.SCHEDULE_NOT_FOUND; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class GSServiceTest { - - @InjectMocks - private GSService gsService; - - @Mock - private GSRepository gsRepository; - - @Test - @DisplayName("비회원 일정 조회 시 잘못된 ID로 예외 발생") - public void getGuestScheduleWhenInvalidId() { - Long invalidId = 999L; - - // when - doReturn(Optional.empty()).when(gsRepository).findById(invalidId); - - // then - assertThatThrownBy(() -> gsService.getGuestSchedule(invalidId)) - .isInstanceOf(GSException.class) - .hasMessage(SCHEDULE_NOT_FOUND.getMessage()); - } - - @Test - @DisplayName("10일 이상 지난 PROGRESS 상태의 스케줄 disable 처리") - public void disableProgressGuestSchedule() { - LocalDateTime tenDaysAgo = LocalDateTime.now().minusDays(10); - - GuestSchedule progressSchedule = mock(GuestSchedule.class); - lenient().when(progressSchedule.getStatus()).thenReturn(ScheduleStatus.PROGRESS); - lenient().when(progressSchedule.getCreatedAt()).thenReturn(tenDaysAgo); // 10일 전으로 설정 - - when(gsRepository.findByStatusAndCreatedAtBefore(eq(ScheduleStatus.PROGRESS), any())) - .thenReturn(Collections.singletonList(progressSchedule)); - - gsService.disableOldGuestSchedules(); - - verify(progressSchedule).deactivate(); - } - - @Test - @DisplayName("10일 이상 지난 COMPLETE 상태의 스케줄 disable 처리") - public void disableCompleteGuestSchedule() { - LocalDateTime tenDaysAgo = LocalDateTime.now().minusDays(10); - - GuestSchedule completeSchedule = mock(GuestSchedule.class); - lenient().when(completeSchedule.getStatus()).thenReturn(ScheduleStatus.COMPLETE); - lenient().when(completeSchedule.getUpdatedAt()).thenReturn(tenDaysAgo); - - when(gsRepository.findByStatusAndUpdatedAtBefore(eq(ScheduleStatus.COMPLETE), any())) - .thenReturn(Collections.singletonList(completeSchedule)); - - gsService.disableOldGuestSchedules(); - - verify(completeSchedule).deactivate(); - } -} +//package org.chzzk.howmeet.domain.temporary.schedule.service; +// +//import org.chzzk.howmeet.domain.regular.schedule.entity.ScheduleStatus; +//import org.chzzk.howmeet.domain.temporary.schedule.entity.GuestSchedule; +//import org.chzzk.howmeet.domain.temporary.schedule.exception.GSException; +//import org.chzzk.howmeet.domain.temporary.schedule.repository.GSRepository; +//import org.junit.jupiter.api.DisplayName; +//import org.junit.jupiter.api.Test; +//import org.junit.jupiter.api.extension.ExtendWith; +//import org.mockito.InjectMocks; +//import org.mockito.Mock; +//import org.mockito.junit.jupiter.MockitoExtension; +// +//import java.time.LocalDateTime; +//import java.util.Collections; +//import java.util.Optional; +// +//import static org.assertj.core.api.Assertions.assertThatThrownBy; +//import static org.chzzk.howmeet.domain.temporary.schedule.exception.GSErrorCode.SCHEDULE_NOT_FOUND; +//import static org.mockito.Mockito.*; +// +//@ExtendWith(MockitoExtension.class) +//class GSServiceTest { +// +// @InjectMocks +// private GSService gsService; +// +// @Mock +// private GSRepository gsRepository; +// +// @Test +// @DisplayName("비회원 일정 조회 시 잘못된 ID로 예외 발생") +// public void getGuestScheduleWhenInvalidId() { +// Long invalidId = 999L; +// +// // when +// doReturn(Optional.empty()).when(gsRepository).findById(invalidId); +// +// // then +// assertThatThrownBy(() -> gsService.getGuestSchedule(invalidId)) +// .isInstanceOf(GSException.class) +// .hasMessage(SCHEDULE_NOT_FOUND.getMessage()); +// } +// +// @Test +// @DisplayName("10일 이상 지난 PROGRESS 상태의 스케줄 disable 처리") +// public void disableProgressGuestSchedule() { +// LocalDateTime tenDaysAgo = LocalDateTime.now().minusDays(10); +// +// GuestSchedule progressSchedule = mock(GuestSchedule.class); +// lenient().when(progressSchedule.getStatus()).thenReturn(ScheduleStatus.PROGRESS); +// lenient().when(progressSchedule.getCreatedAt()).thenReturn(tenDaysAgo); // 10일 전으로 설정 +// +// when(gsRepository.findByStatusAndCreatedAtBefore(eq(ScheduleStatus.PROGRESS), any())) +// .thenReturn(Collections.singletonList(progressSchedule)); +// +// gsService.disableOldGuestSchedules(); +// +// verify(progressSchedule).deactivate(); +// } +// +// @Test +// @DisplayName("10일 이상 지난 COMPLETE 상태의 스케줄 disable 처리") +// public void disableCompleteGuestSchedule() { +// LocalDateTime tenDaysAgo = LocalDateTime.now().minusDays(10); +// +// GuestSchedule completeSchedule = mock(GuestSchedule.class); +// lenient().when(completeSchedule.getStatus()).thenReturn(ScheduleStatus.COMPLETE); +// lenient().when(completeSchedule.getUpdatedAt()).thenReturn(tenDaysAgo); +// +// when(gsRepository.findByStatusAndUpdatedAtBefore(eq(ScheduleStatus.COMPLETE), any())) +// .thenReturn(Collections.singletonList(completeSchedule)); +// +// gsService.disableOldGuestSchedules(); +// +// verify(completeSchedule).deactivate(); +// } +//}