diff --git a/src/main/java/com/moive/MoiveBE/domain/meeting/repository/DateVoteRepository.java b/src/main/java/com/moive/MoiveBE/domain/meeting/repository/DateVoteRepository.java index 80f1c3f..b815e98 100644 --- a/src/main/java/com/moive/MoiveBE/domain/meeting/repository/DateVoteRepository.java +++ b/src/main/java/com/moive/MoiveBE/domain/meeting/repository/DateVoteRepository.java @@ -15,6 +15,9 @@ public interface DateVoteRepository extends JpaRepository { void deleteByMeetingIdAndParticipantId(Long meetingId, Long participantId); + // 모임 생성 시 일정 확정된 케이스와 투표를 통한 일정 확정된 케이스 구분용 + boolean existsByMeetingId(Long meetingId); + // 일정 투표 참여 인원 수 // - participantIds: 탈퇴하지 않은 유효 참여자 id 목록 (탈퇴한 참여자의 투표는 집계에서 제외) @Query(""" diff --git a/src/main/java/com/moive/MoiveBE/domain/vote/service/VoteService.java b/src/main/java/com/moive/MoiveBE/domain/vote/service/VoteService.java index 5f3e1bd..c061669 100644 --- a/src/main/java/com/moive/MoiveBE/domain/vote/service/VoteService.java +++ b/src/main/java/com/moive/MoiveBE/domain/vote/service/VoteService.java @@ -89,7 +89,7 @@ public DateVoteResultResponse getMeetingScheduleVoteResult(Long userId, Long mee .orElseThrow(() -> new CustomException(VOTE_ACCESS_DENIED)); // Case A. 모임 생성 시 일정 확정 => 투표 생략 - if (isScheduleConfirmed(meeting)) { + if (isScheduleConfirmed(meeting) && !dateVoteRepository.existsByMeetingId(meetingId)) { return DateVoteResultResponse.of( true, null, diff --git a/src/test/java/com/moive/MoiveBE/domain/vote/service/VoteServiceTest.java b/src/test/java/com/moive/MoiveBE/domain/vote/service/VoteServiceTest.java index f725f97..94345d8 100644 --- a/src/test/java/com/moive/MoiveBE/domain/vote/service/VoteServiceTest.java +++ b/src/test/java/com/moive/MoiveBE/domain/vote/service/VoteServiceTest.java @@ -59,6 +59,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -137,6 +138,7 @@ void setUp() { when(meeting.getScheduledDate()).thenReturn(scheduledDate); when(meeting.getScheduledTime()).thenReturn(scheduledTime); stubMeetingAndParticipant(meeting); + when(dateVoteRepository.existsByMeetingId(MEETING_ID)).thenReturn(false); // when DateVoteResultResponse response = voteService.getMeetingScheduleVoteResult(USER_ID, MEETING_ID); @@ -152,8 +154,35 @@ void setUp() { assertThat(candidate.voterCnt()).isNull(); assertThat(candidate.isVotedByMe()).isFalse(); - // 투표 집계 진행 x - verifyNoInteractions(dateVoteRepository); + // DateVote 존재 여부만 확인, 집계는 생략 + verify(dateVoteRepository).existsByMeetingId(MEETING_ID); + verifyNoMoreInteractions(dateVoteRepository); + } + + @Test + void 일정_미정으로_생성됐지만_투표로_이미_확정된_모임을_재조회하면_투표_집계_결과를_그대로_반환한다() { + // given + Meeting meeting = mock(Meeting.class); + when(meeting.getScheduledDate()).thenReturn(LocalDate.of(2026, 9, 15)); + when(meeting.getScheduledTime()).thenReturn(LocalTime.of(18, 0)); + stubMeetingAndParticipant(meeting, MY_PARTICIPANT_ID); + + when(dateVoteRepository.existsByMeetingId(MEETING_ID)).thenReturn(true); + when(dateVoteRepository.countDistinctVoters(eq(MEETING_ID), anyList())).thenReturn(4L); + when(dateVoteRepository.aggregateTopDates(eq(MEETING_ID), eq(MY_PARTICIPANT_ID), anyList(), any())) + .thenReturn(List.of( + new DateVoteSummary(LocalDate.of(2026, 9, 15), LocalTime.of(18, 0), 4L, 1L) + )); + + // when + DateVoteResultResponse response = voteService.getMeetingScheduleVoteResult(USER_ID, MEETING_ID); + + // then: 집계 결과 확인, 이미 일정이 확정된 상태이므로 재확정 시도는 생략 + assertThat(response.isVoteSkipped()).isFalse(); + assertThat(response.totalVoterCnt()).isEqualTo(4); + assertThat(response.candidates()).hasSize(1); + + verify(meeting, never()).confirmSchedule(any(), any()); } @Test