Skip to content

Commit

Permalink
feat: 미참여자의 방 정보 조회 기능 (#161)
Browse files Browse the repository at this point in the history
* feat: ClockHolder LocalDate 추가

* refactor: RoomService 리팩토링

* refactor: SearchService 리팩토링

* refactor: 방 입장, 퇴장 리팩토링

* refactor: CertifiactionService 리팩토링

* refactor: RoomController 리팩토링

* test: InventorySearchRepository 테스트 추가

* chore: 테스트 코드 In-memory H2에서 MySQL로 변경

* feat: CertifyRoom Transaction 분리, 비관적 락 적용

* feat: 방 입장 낙관적 락 적용

* refactor: MySQL 변경으로 일부 테스트 수정

* test: 방 인증, 입장 동시성 테스트 작성

* test: 방장 위임 테스트 작성

* fix: 방 입장 낙관적 락 -> 비관적 락으로 변경

* feat: 방 참여 여부 확인, 참여 중이지 않은 방 정보 부르기 컨트롤러

* feat: 방 참여 여부 확인 서비스 추가

* feat: 참여중이지 않은 방 정보 조회 서비스

* test: 통합 테스트 코드 작성

* test: 테스트 코드 보완

* fix: memberId 가져오기로 변경

* refactor: redirection -> boolean으로 변경

* fix: Search 쿼리 수정

---------

Co-authored-by: Dev Uni <[email protected]>
  • Loading branch information
ymkim97 and Shin-Jae-Yoon authored Nov 27, 2023
1 parent 076e022 commit c1e925e
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,15 @@ public void deportParticipant(Long managerId, Long roomId, Long memberId) {
member.exitRoom(room.getRoomType());
}

public boolean checkIfParticipant(Long memberId, Long roomId) {
try {
getParticipant(memberId, roomId);
return true;
} catch (NotFoundException e) {
return false;
}
}

public void validateRoomById(Long roomId) {
if (!roomRepository.existsById(roomId)) {
throw new NotFoundException(ROOM_NOT_FOUND);
Expand Down
50 changes: 43 additions & 7 deletions src/main/java/com/moabam/api/application/room/SearchService.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package com.moabam.api.application.room;

import static com.moabam.global.common.util.GlobalConstant.NOT_COMPLETED_RANK;
import static com.moabam.global.common.util.GlobalConstant.ROOM_FIXED_SEARCH_SIZE;
import static com.moabam.global.error.model.ErrorMessage.INVENTORY_NOT_FOUND;
import static com.moabam.global.error.model.ErrorMessage.PARTICIPANT_NOT_FOUND;
import static com.moabam.global.error.model.ErrorMessage.ROOM_DETAILS_ERROR;
import static com.moabam.global.error.model.ErrorMessage.ROOM_MODIFY_UNAUTHORIZED_REQUEST;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static com.moabam.global.common.util.GlobalConstant.*;
import static com.moabam.global.error.model.ErrorMessage.*;
import static org.apache.commons.lang3.StringUtils.*;

import java.time.LocalDate;
import java.time.Period;
Expand Down Expand Up @@ -51,6 +47,8 @@
import com.moabam.api.dto.room.RoomsHistoryResponse;
import com.moabam.api.dto.room.RoutineResponse;
import com.moabam.api.dto.room.TodayCertificateRankResponse;
import com.moabam.api.dto.room.UnJoinedRoomCertificateRankResponse;
import com.moabam.api.dto.room.UnJoinedRoomDetailsResponse;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.ForbiddenException;
import com.moabam.global.error.exception.NotFoundException;
Expand Down Expand Up @@ -187,6 +185,44 @@ public GetAllRoomsResponse searchRooms(String keyword, @Nullable RoomType roomTy
return RoomMapper.toSearchAllRoomsResponse(hasNext, getAllRoomResponse);
}

public UnJoinedRoomDetailsResponse getUnJoinedRoomDetails(Long roomId) {
Room room = roomRepository.findById(roomId)
.orElseThrow(() -> new NotFoundException(ROOM_NOT_FOUND));

List<Routine> routines = routineRepository.findAllByRoomId(roomId);
List<RoutineResponse> routineResponses = RoutineMapper.toRoutineResponses(routines);
List<DailyMemberCertification> sortedDailyMemberCertifications =
certificationsSearchRepository.findSortedDailyMemberCertifications(roomId, clockHolder.date());
List<Long> memberIds = sortedDailyMemberCertifications.stream()
.map(DailyMemberCertification::getMemberId)
.toList();
List<Member> members = memberService.getRoomMembers(memberIds);
List<Inventory> inventories = inventorySearchRepository.findDefaultInventories(memberIds,
room.getRoomType().name());
List<UnJoinedRoomCertificateRankResponse> unJoinedRoomCertificateRankResponses = new ArrayList<>();

int rank = 1;
for (DailyMemberCertification certification : sortedDailyMemberCertifications) {
Member member = members.stream()
.filter(m -> m.getId().equals(certification.getMemberId()))
.findAny()
.orElseThrow(() -> new NotFoundException(MEMBER_NOT_FOUND));

Inventory inventory = inventories.stream()
.filter(i -> i.getMemberId().equals(member.getId()))
.findAny()
.orElseThrow(() -> new NotFoundException(INVENTORY_NOT_FOUND));

UnJoinedRoomCertificateRankResponse response = RoomMapper.toUnJoinedRoomCertificateRankResponse(member,
rank, inventory);

unJoinedRoomCertificateRankResponses.add(response);
rank += 1;
}

return RoomMapper.toUnJoinedRoomDetails(room, routineResponses, unJoinedRoomCertificateRankResponses);
}

private boolean isHasNext(List<GetAllRoomResponse> getAllRoomResponse, List<Room> rooms) {
boolean hasNext = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.moabam.api.application.room.mapper;

import static org.apache.commons.lang3.StringUtils.*;

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

import com.moabam.api.domain.item.Inventory;
import com.moabam.api.domain.member.Member;
import com.moabam.api.domain.room.Participant;
import com.moabam.api.domain.room.Room;
import com.moabam.api.dto.room.CreateRoomRequest;
Expand All @@ -17,6 +21,8 @@
import com.moabam.api.dto.room.RoomsHistoryResponse;
import com.moabam.api.dto.room.RoutineResponse;
import com.moabam.api.dto.room.TodayCertificateRankResponse;
import com.moabam.api.dto.room.UnJoinedRoomCertificateRankResponse;
import com.moabam.api.dto.room.UnJoinedRoomDetailsResponse;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -44,6 +50,7 @@ public static RoomDetailsResponse toRoomDetailsResponse(Long memberId, Room room
.managerNickName(managerNickname)
.roomImage(room.getRoomImage())
.level(room.getLevel())
.exp(room.getExp())
.roomType(room.getRoomType())
.certifyTime(room.getCertifyTime())
.currentUserCount(room.getCurrentUserCount())
Expand Down Expand Up @@ -131,4 +138,34 @@ public static GetAllRoomsResponse toSearchAllRoomsResponse(boolean hasNext,
.rooms(getAllRoomResponse)
.build();
}

public static UnJoinedRoomDetailsResponse toUnJoinedRoomDetails(Room room, List<RoutineResponse> routines,
List<UnJoinedRoomCertificateRankResponse> responses) {
return UnJoinedRoomDetailsResponse.builder()
.roomId(room.getId())
.isPassword(!isEmpty(room.getPassword()))
.title(room.getTitle())
.roomImage(room.getRoomImage())
.level(room.getLevel())
.exp(room.getExp())
.roomType(room.getRoomType())
.certifyTime(room.getCertifyTime())
.currentUserCount(room.getCurrentUserCount())
.maxUserCount(room.getMaxUserCount())
.announcement(room.getAnnouncement())
.routines(routines)
.certifiedRanks(responses)
.build();
}

public static UnJoinedRoomCertificateRankResponse toUnJoinedRoomCertificateRankResponse(Member member, int rank,
Inventory inventory) {
return UnJoinedRoomCertificateRankResponse.builder()
.rank(rank)
.memberId(member.getId())
.nickname(member.getNickname())
.awakeImage(inventory.getItem().getImage())
.sleepImage(inventory.getItem().getImage())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ List<Room> searchByKeywordAndRoomType(@Param(value = "keyword") String keyword,
List<Room> searchByKeywordAndRoomId(@Param(value = "keyword") String keyword, @Param(value = "roomId") Long roomId);

@Query(value = "select distinct rm.* from room rm left join routine rt on rm.id = rt.room_id "
+ "where rm.title like %:keyword% "
+ "where (rm.title like %:keyword% "
+ "or rm.manager_nickname like %:keyword% "
+ "or rt.content like %:keyword% "
+ "or rt.content like %:keyword%) "
+ "and rm.room_type = :roomType "
+ "and rm.id < :roomId "
+ "order by rm.id desc limit 11", nativeQuery = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public record RoomDetailsResponse(
String managerNickName,
String roomImage,
int level,
int exp,
RoomType roomType,
int certifyTime,
int currentUserCount,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.moabam.api.dto.room;

import lombok.Builder;

@Builder
public record UnJoinedRoomCertificateRankResponse(
int rank,
Long memberId,
String nickname,
String awakeImage,
String sleepImage
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.moabam.api.dto.room;

import java.util.List;

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

import lombok.Builder;

@Builder
public record UnJoinedRoomDetailsResponse(
Long roomId,
boolean isPassword,
String title,
String roomImage,
int level,
int exp,
RoomType roomType,
int certifyTime,
int currentUserCount,
int maxUserCount,
String announcement,
List<RoutineResponse> routines,
List<UnJoinedRoomCertificateRankResponse> certifiedRanks
) {

}
13 changes: 13 additions & 0 deletions src/main/java/com/moabam/api/presentation/RoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.moabam.api.dto.room.MyRoomsResponse;
import com.moabam.api.dto.room.RoomDetailsResponse;
import com.moabam.api.dto.room.RoomsHistoryResponse;
import com.moabam.api.dto.room.UnJoinedRoomDetailsResponse;
import com.moabam.global.auth.annotation.Auth;
import com.moabam.global.auth.model.AuthMember;

Expand Down Expand Up @@ -87,6 +88,18 @@ public void exitRoom(@Auth AuthMember authMember, @PathVariable("roomId") Long r
roomService.exitRoom(authMember.id(), roomId);
}

@GetMapping("/{roomId}/check")
@ResponseStatus(HttpStatus.OK)
public boolean checkIfParticipant(@Auth AuthMember authMember, @PathVariable("roomId") Long roomId) {
return roomService.checkIfParticipant(authMember.id(), roomId);
}

@GetMapping("/{roomId}/un-joined")
@ResponseStatus(HttpStatus.OK)
public UnJoinedRoomDetailsResponse getUnJoinedRoomDetails(@PathVariable("roomId") Long roomId) {
return searchService.getUnJoinedRoomDetails(roomId);
}

@GetMapping("/{roomId}/{date}")
@ResponseStatus(HttpStatus.OK)
public RoomDetailsResponse getRoomDetails(@Auth AuthMember authMember, @PathVariable("roomId") Long roomId,
Expand Down
66 changes: 66 additions & 0 deletions src/test/java/com/moabam/api/presentation/RoomControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,72 @@ void get_join_history_success() throws Exception {
.andDo(print());
}

@DisplayName("참여중이지 않은 방에 대한 확인 성공")
@WithMember
@Test
void check_if_participant_false_success() throws Exception {
// given
Room room = RoomFixture.room();
Room savedRoom = roomRepository.save(room);

// expected
mockMvc.perform(get("/rooms/" + savedRoom.getId() + "/check"))
.andExpect(status().isOk())
.andDo(print());
}

@DisplayName("참여중이지 않은 방의 정보 불러오기 성공")
@Test
void get_un_joined_room_details() throws Exception {
// given
Room room = RoomFixture.room("테스트 방", NIGHT, 21);
Room savedRoom = roomRepository.save(room);

Member member1 = MemberFixture.member("901010", "testtest");
member1 = memberRepository.save(member1);

Item item = ItemFixture.nightMageSkin();

Inventory inventory = InventoryFixture.inventory(member1.getId(), item);
inventory.select();

itemRepository.save(item);
inventoryRepository.save(inventory);

Participant participant = RoomFixture.participant(savedRoom, member1.getId());
participantRepository.save(participant);

Routine routine1 = RoomFixture.routine(savedRoom, "물 마시기");
Routine routine2 = RoomFixture.routine(savedRoom, "커피 마시기");
routineRepository.saveAll(List.of(routine1, routine2));

DailyMemberCertification dailyMemberCertification = RoomFixture.dailyMemberCertification(member1.getId(),
savedRoom.getId(), participant);
dailyMemberCertificationRepository.save(dailyMemberCertification);

// expected
mockMvc.perform(get("/rooms/" + savedRoom.getId() + "/un-joined"))
.andExpect(status().isOk())
.andDo(print());
}

@DisplayName("참여중인 방에 대한 확인 성공")
@WithMember
@Test
void check_if_participant_true_success() throws Exception {
// given
Room room = RoomFixture.room();
Room savedRoom = roomRepository.save(room);

Participant participant = RoomFixture.participant(room, 1L);
participantRepository.save(participant);

// expected
mockMvc.perform(get("/rooms/" + savedRoom.getId() + "/check"))
.andExpect(status().isOk())
.andDo(print());
}

@DisplayName("아침, 저녁 방 전체 조회 성공 - 첫 번째 조회, 다음 페이지 있음")
@WithMember(id = 1L)
@Test
Expand Down

0 comments on commit c1e925e

Please sign in to comment.