Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 참여중인 방 목록 조회 #95

Merged
merged 5 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -112,6 +112,15 @@ public void certifyRoom(Long memberId, Long roomId, List<MultipartFile> multipar
}
}

public boolean existsMemberCertification(Long memberId, Long roomId, LocalDate date) {
return dailyMemberCertificationRepository.existsByMemberIdAndRoomIdAndCreatedAtBetween(memberId, roomId,
date.atStartOfDay(), date.atTime(LocalTime.MAX));
}

public boolean existsRoomCertification(Long roomId, LocalDate date) {
return dailyRoomCertificationRepository.existsByRoomIdAndCertifiedAt(roomId, date);
}

private void validateCertifyTime(LocalDateTime now, int certifyTime) {
LocalTime targetTime = LocalTime.of(certifyTime, 0);
LocalDateTime minusTenMinutes = LocalDateTime.of(now.toLocalDate(), targetTime).minusMinutes(10);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import com.moabam.api.domain.room.repository.ParticipantSearchRepository;
import com.moabam.api.domain.room.repository.RoutineSearchRepository;
import com.moabam.api.dto.room.CertificationImageResponse;
import com.moabam.api.dto.room.MyRoomResponse;
import com.moabam.api.dto.room.MyRoomsResponse;
import com.moabam.api.dto.room.RoomDetailsResponse;
import com.moabam.api.dto.room.RoutineResponse;
import com.moabam.api.dto.room.TodayCertificateRankResponse;
Expand All @@ -42,6 +44,7 @@ public class RoomSearchService {
private final ParticipantSearchRepository participantSearchRepository;
private final RoutineSearchRepository routineSearchRepository;
private final MemberService memberService;
private final RoomCertificationService roomCertificationService;

public RoomDetailsResponse getRoomDetails(Long memberId, Long roomId) {
LocalDate today = LocalDate.now();
Expand All @@ -63,6 +66,23 @@ public RoomDetailsResponse getRoomDetails(Long memberId, Long roomId) {
todayCertificateRankResponses, completePercentage);
}

public MyRoomsResponse getMyRooms(Long memberId) {
LocalDate today = LocalDate.now();
List<MyRoomResponse> myRoomResponses = new ArrayList<>();
List<Participant> participants = participantSearchRepository.findParticipantsByMemberId(memberId);

for (Participant participant : participants) {
Room room = participant.getRoom();
boolean isMemberCertified = roomCertificationService.existsMemberCertification(memberId, room.getId(),
today);
boolean isRoomCertified = roomCertificationService.existsRoomCertification(room.getId(), today);

myRoomResponses.add(RoomMapper.toMyRoomResponse(room, isMemberCertified, isRoomCertified));
}

return RoomMapper.toMyRoomsResponse(myRoomResponses);
}

private List<RoutineResponse> getRoutineResponses(Long roomId) {
List<Routine> roomRoutines = routineSearchRepository.findAllByRoomId(roomId);

Expand All @@ -74,7 +94,7 @@ private List<TodayCertificateRankResponse> getTodayCertificateRankResponses(Long

List<TodayCertificateRankResponse> responses = new ArrayList<>();
List<Certification> certifications = certificationsSearchRepository.findCertifications(roomId, today);
List<Participant> participants = participantSearchRepository.findParticipants(roomId);
List<Participant> participants = participantSearchRepository.findParticipantsByRoomId(roomId);
List<Member> members = memberService.getRoomMembers(participants.stream()
.map(Participant::getMemberId)
.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import com.moabam.api.domain.room.Room;
import com.moabam.api.dto.room.CreateRoomRequest;
import com.moabam.api.dto.room.MyRoomResponse;
import com.moabam.api.dto.room.MyRoomsResponse;
import com.moabam.api.dto.room.RoomDetailsResponse;
import com.moabam.api.dto.room.RoutineResponse;
import com.moabam.api.dto.room.TodayCertificateRankResponse;
Expand Down Expand Up @@ -45,4 +47,25 @@ public static RoomDetailsResponse toRoomDetailsResponse(Room room, String manage
.todayCertificateRank(todayCertificateRankResponses)
.build();
}

public static MyRoomResponse toMyRoomResponse(Room room, boolean isMemberCertifiedToday,
boolean isRoomCertifiedToday) {
return MyRoomResponse.builder()
.roomId(room.getId())
.title(room.getTitle())
.roomType(room.getRoomType())
.certifyTime(room.getCertifyTime())
.currentUserCount(room.getCurrentUserCount())
.maxUserCount(room.getMaxUserCount())
.obtainedBugs(room.getLevel())
.isMemberCertifiedToday(isMemberCertifiedToday)
.isRoomCertifiedToday(isRoomCertifiedToday)
.build();
}

public static MyRoomsResponse toMyRoomsResponse(List<MyRoomResponse> myRoomResponses) {
return MyRoomsResponse.builder()
.participatingRooms(myRoomResponses)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.moabam.api.domain.room.repository;

import java.time.LocalDateTime;

import org.springframework.data.jpa.repository.JpaRepository;

import com.moabam.api.domain.room.DailyMemberCertification;

public interface DailyMemberCertificationRepository extends JpaRepository<DailyMemberCertification, Long> {

boolean existsByMemberIdAndRoomIdAndCreatedAtBetween(Long memberId, Long roomId, LocalDateTime startTime,
LocalDateTime endTime);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.moabam.api.domain.room.repository;

import java.time.LocalDate;

import org.springframework.data.jpa.repository.JpaRepository;

import com.moabam.api.domain.room.DailyRoomCertification;

public interface DailyRoomCertificationRepository extends JpaRepository<DailyRoomCertification, Long> {

boolean existsByRoomIdAndCertifiedAt(Long roomId, LocalDate date);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Optional<Participant> findOne(Long memberId, Long roomId) {
);
}

public List<Participant> findParticipants(Long roomId) {
public List<Participant> findParticipantsByRoomId(Long roomId) {
return jpaQueryFactory
.selectFrom(participant)
.where(
Expand All @@ -44,6 +44,17 @@ public List<Participant> findParticipants(Long roomId) {
.fetch();
}

public List<Participant> findParticipantsByMemberId(Long memberId) {
return jpaQueryFactory
.selectFrom(participant)
.join(participant.room, room).fetchJoin()
.where(
participant.memberId.eq(memberId),
participant.deletedAt.isNull()
)
.fetch();
}

public List<Participant> findOtherParticipantsInRoom(Long memberId, Long roomId) {
return jpaQueryFactory
.selectFrom(participant)
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/com/moabam/api/dto/room/MyRoomResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.moabam.api.dto.room;

import com.moabam.api.domain.room.RoomType;

import lombok.Builder;

@Builder
public record MyRoomResponse(
Long roomId,
String title,
RoomType roomType,
int certifyTime,
int currentUserCount,
int maxUserCount,
int obtainedBugs,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obtainedBug 먼가 했네 ㅋ.ㅋ 근데 생각해보니까 이거 있으면 걍 이것도 더하면 되는건데 괜히 API 따로 만든듯..
image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오잉 그러네요 ㅋㅋㅋㅋㅋ 일단은 필요할지도 모르니 keep~ ㅎ.ㅎ

boolean isMemberCertifiedToday,
boolean isRoomCertifiedToday
) {

}
12 changes: 12 additions & 0 deletions src/main/java/com/moabam/api/dto/room/MyRoomsResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.moabam.api.dto.room;

import java.util.List;

import lombok.Builder;

@Builder
public record MyRoomsResponse(
List<MyRoomResponse> participatingRooms
) {

}
7 changes: 7 additions & 0 deletions src/main/java/com/moabam/api/presentation/RoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.moabam.api.dto.room.CreateRoomRequest;
import com.moabam.api.dto.room.EnterRoomRequest;
import com.moabam.api.dto.room.ModifyRoomRequest;
import com.moabam.api.dto.room.MyRoomsResponse;
import com.moabam.api.dto.room.RoomDetailsResponse;
import com.moabam.global.auth.annotation.CurrentMember;
import com.moabam.global.auth.model.AuthorizationMember;
Expand Down Expand Up @@ -98,4 +99,10 @@ public void deportParticipant(@CurrentMember AuthorizationMember authorizationMe

roomService.deportParticipant(authorizationMember.id(), roomId, memberId);
}

@GetMapping("/my-join")
@ResponseStatus(HttpStatus.OK)
public MyRoomsResponse getMyRooms(@CurrentMember AuthorizationMember authorizationMember) {
return roomSearchService.getMyRooms(authorizationMember.id());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.moabam.api.application.room;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

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

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 com.moabam.api.application.member.MemberService;
import com.moabam.api.domain.room.Participant;
import com.moabam.api.domain.room.Room;
import com.moabam.api.domain.room.RoomType;
import com.moabam.api.domain.room.repository.CertificationsSearchRepository;
import com.moabam.api.domain.room.repository.ParticipantSearchRepository;
import com.moabam.api.domain.room.repository.RoutineSearchRepository;
import com.moabam.api.dto.room.MyRoomsResponse;
import com.moabam.support.fixture.RoomFixture;

@ExtendWith(MockitoExtension.class)
class RoomSearchServiceTest {

@InjectMocks
private RoomSearchService roomSearchService;

@Mock
private CertificationsSearchRepository certificationsSearchRepository;

@Mock
private ParticipantSearchRepository participantSearchRepository;

@Mock
private RoutineSearchRepository routineSearchRepository;

@Mock
private MemberService memberService;

@Mock
private RoomCertificationService certificationService;

@DisplayName("유저가 참여중인 방 목록 조회 성공")
@Test
void get_my_rooms_success() {
// given
LocalDate today = LocalDate.now();
Long memberId = 1L;
Room room1 = spy(RoomFixture.room("아침 - 첫 번째 방", RoomType.MORNING, 10));
Room room2 = spy(RoomFixture.room("아침 - 두 번째 방", RoomType.MORNING, 9));
Room room3 = spy(RoomFixture.room("밤 - 첫 번째 방", RoomType.NIGHT, 22));

lenient().when(room1.getId()).thenReturn(1L);
lenient().when(room2.getId()).thenReturn(2L);
lenient().when(room3.getId()).thenReturn(3L);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: lenient를 사용한 이유가 있나요?

doReturn으로는 대체가 안되는 건가요?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 우선, lenient와 doReturn은 비교대상이 아닌 것 같아서, doReturn-when 구조가 아닌 when-thenReturn 구조를 사용한 이유를 설명드리겠습니다.
  • thenReturn은 실제 메서드를 호출하면서 임의의 값 지정, doReturn은 실제 메서드를 호출하지 않으면서 임의의 값 지정으로, 테스트 속도에 있어서는 doReturn이 빠릅니다. 따라서, room.getId()의 경우 실제 메서드를 굳이 호출할 필요가 없어서 doReturn이 적절할 수 있습니다.
  • 다만, Mockito doReturn vs whenReturn를 참고하였을 때, doReturn은 type-safety 하지 않은 점이 있었습니다. 따라서, 저희는 when-thenReturn 구조를 채택했습니다.
  1. lenient()는, 여러 stubbing으로 인하여 제약조건에 위배가 되어 그를 느슨하게 해주기 위함인데, 다시 생각해보니, 제약조건에 맞게 코드를 짜는게 더 맞다고 생각하여, 불필요한 stubbing을 제거하고 lenient 또한 제거하였습니다.


Participant participant1 = RoomFixture.participant(room1, memberId);
Participant participant2 = RoomFixture.participant(room2, memberId);
Participant participant3 = RoomFixture.participant(room3, memberId);
List<Participant> participants = List.of(participant1, participant2, participant3);

given(participantSearchRepository.findParticipantsByMemberId(memberId)).willReturn(participants);
given(certificationService.existsMemberCertification(memberId, room1.getId(), today)).willReturn(true);
given(certificationService.existsMemberCertification(memberId, room2.getId(), today)).willReturn(false);
given(certificationService.existsMemberCertification(memberId, room3.getId(), today)).willReturn(true);

given(certificationService.existsRoomCertification(room1.getId(), today)).willReturn(true);
given(certificationService.existsRoomCertification(room2.getId(), today)).willReturn(false);
given(certificationService.existsRoomCertification(room3.getId(), today)).willReturn(false);

// when
MyRoomsResponse myRooms = roomSearchService.getMyRooms(memberId);

// then
assertThat(myRooms.participatingRooms()).hasSize(3);

assertThat(myRooms.participatingRooms().get(0).isMemberCertifiedToday()).isTrue();
assertThat(myRooms.participatingRooms().get(0).isRoomCertifiedToday()).isTrue();

assertThat(myRooms.participatingRooms().get(1).isMemberCertifiedToday()).isFalse();
assertThat(myRooms.participatingRooms().get(1).isRoomCertifiedToday()).isFalse();

assertThat(myRooms.participatingRooms().get(2).isMemberCertifiedToday()).isTrue();
assertThat(myRooms.participatingRooms().get(2).isRoomCertifiedToday()).isFalse();
}
}
27 changes: 27 additions & 0 deletions src/test/java/com/moabam/api/presentation/RoomControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -858,4 +858,31 @@ void deport_member_success() throws Exception {
assertThat(getMemberParticipant.getDeletedAt()).isNotNull();
assertThat(participantSearchRepository.findOne(member.getId(), room.getId())).isEmpty();
}

@DisplayName("현재 참여중인 모든 방 조회 성공 - 첫번째 방은 개인과 방 모두 인증 성공")
@WithMember(id = 1L)
@Test
void get_all_my_rooms_success() throws Exception {
// given
Room room1 = RoomFixture.room("아침 - 첫 번째 방", MORNING, 10);
Room room2 = RoomFixture.room("아침 - 두 번째 방", MORNING, 8);
Room room3 = RoomFixture.room("밤 - 세 번째 방", NIGHT, 22);

Participant participant1 = RoomFixture.participant(room1, 1L);
Participant participant2 = RoomFixture.participant(room2, 1L);
Participant participant3 = RoomFixture.participant(room3, 1L);

DailyMemberCertification dailyMemberCertification = RoomFixture.dailyMemberCertification(1L, 1L, participant1);
DailyRoomCertification dailyRoomCertification = RoomFixture.dailyRoomCertification(1L, LocalDate.now());

roomRepository.saveAll(List.of(room1, room2, room3));
participantRepository.saveAll(List.of(participant1, participant2, participant3));
dailyMemberCertificationRepository.save(dailyMemberCertification);
dailyRoomCertificationRepository.save(dailyRoomCertification);

// expected
mockMvc.perform(get("/rooms/my-join"))
.andExpect(status().isOk())
.andDo(print());
}
}
17 changes: 17 additions & 0 deletions src/test/java/com/moabam/support/fixture/RoomFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ public static Room room(int certifyTime) {
.build();
}

public static Room room(String title, RoomType roomType, int certifyTime) {
return Room.builder()
.title(title)
.roomType(roomType)
.certifyTime(certifyTime)
.maxUserCount(8)
.build();
}

public static List<Room> rooms() {
return List.of(
room("아침 - 첫 번째 방", RoomType.MORNING, 10),
room("아침 - 두 번째 방", RoomType.MORNING, 9),
room("밤 - 첫 번째 방", RoomType.NIGHT, 22)
);
}

public static Participant participant(Room room, Long memberId) {
return Participant.builder()
.room(room)
Expand Down