Skip to content

Commit

Permalink
fix: ✏️ 채팅방 정보 조회 응답 수정 (#191)
Browse files Browse the repository at this point in the history
* fix: 멤버 정보 조회 시, user_id 정보를 위한 쿼리 수정

* fix: 채팅 멤버 및 방 응답 dto 필드 추가

* fix: dto 변경에 따른 mapping 전략 수정

* fix: api 모듈 내 service 비즈니스 로직 수정

* feat: admin 조회 쿼리 추가

* fix: query dsl 응답 dto name 필드 타입 수정 long -> string

* rename: other_member_ids -> other_participants 필드 이름 수정

* fix: admin 조회 시, query dsl을 활용하여 dto 타입으로 조회하도록 수정

* rename: dto 필드명 수정에 따른 네이밍 수정

* fix: 불변식 list add 에러 추가

* test: 비즈니스 로직 및 응답 타입 수정에 따른 테스트 수정

* fix: 최근 활동 이력에 관리자 정보 포함된 경우 쿼리 호출 제외

* fix: 관리자 정보 추가 조회 조건식 수정
  • Loading branch information
psychology50 authored Nov 5, 2024
1 parent ab6e3db commit 727c2df
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import kr.co.pennyway.domain.domains.member.domain.ChatMember;
import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult;
import kr.co.pennyway.domain.domains.member.type.ChatMemberRole;

import java.time.LocalDateTime;
Expand All @@ -15,6 +15,8 @@ public final class ChatMemberRes {
public record MemberDetail(
@Schema(description = "채팅방 참여자 ID", type = "long")
Long id,
@Schema(description = "채팅방 사용자의 애플리케이션 내 고유 식별자 (userId)")
Long userId,
@Schema(description = "채팅방 참여자 이름")
String name,
@Schema(description = "채팅방 참여자 역할")
Expand All @@ -27,13 +29,29 @@ public record MemberDetail(
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createdAt
) {
public static MemberDetail from(ChatMember chatMember, boolean isContainNotifyEnabled) {
public static MemberDetail from(ChatMemberResult.Detail chatMember, boolean isContainNotifyEnabled) {
return new MemberDetail(
chatMember.getId(),
chatMember.getName(),
chatMember.getRole(),
isContainNotifyEnabled ? chatMember.isNotifyEnabled() : null,
chatMember.getCreatedAt()
chatMember.id(),
chatMember.userId(),
chatMember.name(),
chatMember.role(),
isContainNotifyEnabled ? chatMember.notifyEnabled() : null,
chatMember.createdAt()
);
}
}

@Schema(description = "채팅방 참여자 요약 정보")
public record MemberSummary(
@Schema(description = "채팅방 참여자 ID", type = "long")
Long id,
@Schema(description = "채팅방 참여자 이름")
String name
) {
public static MemberSummary from(ChatMemberResult.Summary chatMember) {
return new MemberSummary(
chatMember.id(),
String.valueOf(chatMember.name())
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ public record Summary(
public record RoomWithParticipants(
@Schema(description = "채팅방에서 내 정보")
ChatMemberRes.MemberDetail myInfo,
@Schema(description = "최근에 채팅 메시지를 보낸 참여자의 상세 정보 목록")
@Schema(description = "최근에 채팅 메시지를 보낸 참여자의 상세 정보 목록. 내가 방장이 아니라면, 최근에 활동 내역이 없어도 방장 정보가 포함된다.")
List<ChatMemberRes.MemberDetail> recentParticipants,
@Schema(description = "채팅방에서 내 정보와 최근 활동자를 제외한 참여자 ID 목록")
List<Long> otherParticipantIds,
@Schema(description = "채팅방에서 내 정보와 최근 활동자를 제외한 참여자 ID, Name 목록")
List<ChatMemberRes.MemberSummary> otherParticipants,
@Schema(description = "최근 채팅 이력. 메시지는 최신순으로 정렬되어 반환.")
List<ChatRes.ChatDetail> recentMessages
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import kr.co.pennyway.api.apis.chat.dto.ChatMemberRes;
import kr.co.pennyway.common.annotation.Mapper;
import kr.co.pennyway.domain.domains.member.domain.ChatMember;
import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult;

import java.util.List;

@Mapper
public final class ChatMemberMapper {
public static List<ChatMemberRes.MemberDetail> toChatMemberResDetail(List<ChatMember> chatMembers) {
public static List<ChatMemberRes.MemberDetail> toChatMemberResDetail(List<ChatMemberResult.Detail> chatMembers) {
return chatMembers.stream()
.map(chatMember -> ChatMemberRes.MemberDetail.from(chatMember, false))
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import kr.co.pennyway.domain.common.redis.message.domain.ChatMessage;
import kr.co.pennyway.domain.domains.chatroom.domain.ChatRoom;
import kr.co.pennyway.domain.domains.chatroom.dto.ChatRoomDetail;
import kr.co.pennyway.domain.domains.member.domain.ChatMember;
import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

Expand Down Expand Up @@ -66,10 +66,13 @@ public static ChatRoomRes.Detail toChatRoomResDetail(ChatRoom chatRoom, boolean
return ChatRoomRes.Detail.of(chatRoom, isAdmin, participantCount, unreadMessageCount);
}

public static ChatRoomRes.RoomWithParticipants toChatRoomResRoomWithParticipants(ChatMember myInfo, List<ChatMember> recentParticipants, List<Long> otherMemberIds, List<ChatMessage> chatMessages) {
public static ChatRoomRes.RoomWithParticipants toChatRoomResRoomWithParticipants(ChatMemberResult.Detail myInfo, List<ChatMemberResult.Detail> recentParticipants, List<ChatMemberResult.Summary> otherParticipants, List<ChatMessage> chatMessages) {
List<ChatMemberRes.MemberDetail> recentParticipantsRes = recentParticipants.stream()
.map(participant -> ChatMemberRes.MemberDetail.from(participant, false))
.toList();
List<ChatMemberRes.MemberSummary> otherParticipantsRes = otherParticipants.stream()
.map(ChatMemberRes.MemberSummary::from)
.toList();

List<ChatRes.ChatDetail> chatMessagesRes = chatMessages.stream()
.map(ChatRes.ChatDetail::from)
Expand All @@ -78,7 +81,7 @@ public static ChatRoomRes.RoomWithParticipants toChatRoomResRoomWithParticipants
return ChatRoomRes.RoomWithParticipants.builder()
.myInfo(ChatMemberRes.MemberDetail.from(myInfo, true))
.recentParticipants(recentParticipantsRes)
.otherParticipantIds(otherMemberIds)
.otherParticipants(otherParticipantsRes)
.recentMessages(chatMessagesRes)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package kr.co.pennyway.api.apis.chat.service;

import kr.co.pennyway.domain.domains.member.domain.ChatMember;
import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult;
import kr.co.pennyway.domain.domains.member.service.ChatMemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -19,7 +19,7 @@ public Set<Long> readJoinedChatRoomIds(Long userId) {
return chatMemberService.readChatRoomIdsByUserId(userId);
}

public List<ChatMember> readChatMembers(Long chatRoomId, Set<Long> chatMemberIds) {
public List<ChatMemberResult.Detail> readChatMembers(Long chatRoomId, Set<Long> chatMemberIds) {
return chatMemberService.readChatMembersByIdIn(chatRoomId, chatMemberIds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
import kr.co.pennyway.domain.common.redis.message.domain.ChatMessage;
import kr.co.pennyway.domain.common.redis.message.service.ChatMessageService;
import kr.co.pennyway.domain.domains.member.domain.ChatMember;
import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult;
import kr.co.pennyway.domain.domains.member.exception.ChatMemberErrorCode;
import kr.co.pennyway.domain.domains.member.exception.ChatMemberErrorException;
import kr.co.pennyway.domain.domains.member.service.ChatMemberService;
import kr.co.pennyway.domain.domains.member.type.ChatMemberRole;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -28,21 +31,37 @@ public class ChatRoomWithParticipantsSearchService {

@Transactional(readOnly = true)
public ChatRoomRes.RoomWithParticipants execute(Long userId, Long chatRoomId) {
// 내 정보 조회
ChatMember myInfo = chatMemberService.readChatMember(userId, chatRoomId)
.orElseThrow(() -> new ChatMemberErrorException(ChatMemberErrorCode.NOT_FOUND));
ChatMemberResult.Detail myDetail = new ChatMemberResult.Detail(myInfo.getId(), myInfo.getName(), myInfo.getRole(), myInfo.isNotifyEnabled(), userId, myInfo.getCreatedAt());

// 최근 메시지 조회 (15건)
List<ChatMessage> chatMessages = chatMessageService.readRecentMessages(chatRoomId, MESSAGE_LIMIT);

// 최근 메시지의 발신자 조회
Set<Long> recentParticipantIds = chatMessages.stream()
.map(ChatMessage::getSender)
.filter(sender -> !sender.equals(userId))
.collect(Collectors.toSet());

List<ChatMember> recentParticipants = chatMemberService.readChatMembersByUserIdIn(chatRoomId, recentParticipantIds);
// 최근 메시지의 발신자 상세 정보 조회
List<ChatMemberResult.Detail> recentParticipants = new ArrayList<>(
chatMemberService.readChatMembersByUserIdIn(chatRoomId, recentParticipantIds)
);

// 내가 관리자가 아니거나, 최근 활동자에 관리자가 없다면 관리자 정보 조회
if (!myInfo.getRole().equals(ChatMemberRole.ADMIN) && recentParticipants.stream().noneMatch(participant -> participant.role().equals(ChatMemberRole.ADMIN))) {
ChatMemberResult.Detail admin = chatMemberService.readAdmin(chatRoomId)
.orElseThrow(() -> new ChatMemberErrorException(ChatMemberErrorCode.NOT_FOUND));
recentParticipantIds.add(admin.userId());
recentParticipants.add(admin);
}
recentParticipantIds.add(userId);
List<Long> otherMemberIds = chatMemberService.readChatMemberIdsByUserIdNotIn(chatRoomId, recentParticipantIds);

return ChatRoomMapper.toChatRoomResRoomWithParticipants(myInfo, recentParticipants, otherMemberIds, chatMessages);
// 채팅방에 속한 다른 사용자 요약 정보 조회
List<ChatMemberResult.Summary> otherMemberIds = chatMemberService.readChatMemberIdsByUserIdNotIn(chatRoomId, recentParticipantIds);

return ChatRoomMapper.toChatRoomResRoomWithParticipants(myDetail, recentParticipants, otherMemberIds, chatMessages);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import kr.co.pennyway.api.apis.chat.service.ChatMemberSearchService;
import kr.co.pennyway.common.annotation.UseCase;
import kr.co.pennyway.domain.domains.chatroom.domain.ChatRoom;
import kr.co.pennyway.domain.domains.member.domain.ChatMember;
import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Triple;
Expand All @@ -30,7 +30,7 @@ public ChatRoomRes.Detail joinChatRoom(Long userId, Long chatRoomId, Integer pas
}

public List<ChatMemberRes.MemberDetail> readChatMembers(Long chatRoomId, Set<Long> chatMemberIds) {
List<ChatMember> chatMembers = chatMemberSearchService.readChatMembers(chatRoomId, chatMemberIds);
List<ChatMemberResult.Detail> chatMembers = chatMemberSearchService.readChatMembers(chatRoomId, chatMemberIds);

return ChatMemberMapper.toChatMemberResDetail(chatMembers);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ void failReadChatMembersWhenIdsIsEmpty() throws Exception {

private List<ChatMemberRes.MemberDetail> createMockMemberDetails() {
return List.of(
new ChatMemberRes.MemberDetail(1L, "User1", ChatMemberRole.MEMBER, null, LocalDateTime.now()),
new ChatMemberRes.MemberDetail(2L, "User2", ChatMemberRole.MEMBER, null, LocalDateTime.now()),
new ChatMemberRes.MemberDetail(3L, "User3", ChatMemberRole.MEMBER, null, LocalDateTime.now())
new ChatMemberRes.MemberDetail(1L, 2L, "User1", ChatMemberRole.MEMBER, null, LocalDateTime.now()),
new ChatMemberRes.MemberDetail(2L, 3L, "User2", ChatMemberRole.MEMBER, null, LocalDateTime.now()),
new ChatMemberRes.MemberDetail(3L, 4L, "User3", ChatMemberRole.MEMBER, null, LocalDateTime.now())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void successGetChatRoomDetail() {
assertEquals(ownerMember.getRole(), ChatMemberRole.ADMIN, "나는 방장 권한이어야 한다");
assertEquals(expectedRecentParticipantCount, payload.recentParticipants().size(), "최근 참여자 개수가 일치해야 한다");
assertEquals(expectedMessageCount, payload.recentMessages().size(), "최근 메시지 개수가 일치해야 한다");
assertTrue(payload.otherParticipantIds().isEmpty(), "다른 참여자가 없어야 한다");
assertTrue(payload.otherParticipants().isEmpty(), "다른 참여자가 없어야 한다");
}
);
}
Expand Down Expand Up @@ -187,7 +187,7 @@ void successGetChatRoomDetailWithManyParticipants() {
assertAll(
() -> assertNotNull(payload),
() -> assertEquals(payload.recentParticipants().size(), 2, "최근 참여자 개수가 일치해야 한다."),
() -> assertEquals(payload.otherParticipantIds().size(), expectedParticipantCount - 2, "다른 참여자 개수가 일치해야 한다.")
() -> assertEquals(payload.otherParticipants().size(), expectedParticipantCount - 2, "다른 참여자 개수가 일치해야 한다.")
);
}

Expand Down
Loading

0 comments on commit 727c2df

Please sign in to comment.