Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -32,6 +32,13 @@ public interface BrandRepository extends JpaRepository<Brand, Long> {
""")
Optional<Brand> findByUserId(@Param("userId") Long userId);

@Query("""
select distinct b from Brand b
join fetch b.user
where b.user.id in :userIds
""")
List<Brand> findByUserIdIn(@Param("userIds") List<Long> userIds);
Comment thread
1000hyehyang marked this conversation as resolved.

@Query("""
select b.id
from Brand b
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.example.RealMatch.chat.domain.entity.ChatRoom;
import com.example.RealMatch.chat.domain.entity.ChatRoomMember;
import com.example.RealMatch.chat.domain.enums.ChatRoomFilterStatus;
import com.example.RealMatch.chat.domain.enums.ChatRoomMemberRole;
import com.example.RealMatch.chat.domain.enums.ChatSystemMessageKind;
import com.example.RealMatch.chat.domain.repository.ChatMessageRepository;
import com.example.RealMatch.chat.domain.repository.ChatRoomMemberRepository;
Expand Down Expand Up @@ -151,23 +152,26 @@ private ChatRoomListResponse loadChatRoomList(

@Override
public ChatRoomDetailResponse getChatRoomDetailWithOpponent(Long userId, Long roomId) {
chatRoomMemberService.getActiveMemberOrThrow(roomId, userId);
ChatRoomMember myMember = chatRoomMemberService.getActiveMemberOrThrow(roomId, userId);

return chatRoomDetailCache.get(roomId, userId)
.orElseGet(() -> {
ChatRoomDetailResponse response = loadChatRoomDetail(userId, roomId);
ChatRoomDetailResponse response = loadChatRoomDetail(userId, roomId, myMember.getRole());
chatRoomDetailCache.put(roomId, userId, response);
return response;
});
}

private ChatRoomDetailResponse loadChatRoomDetail(Long userId, Long roomId) {
private ChatRoomDetailResponse loadChatRoomDetail(Long userId, Long roomId, ChatRoomMemberRole myRole) {
ChatRoom room = chatRoomRepository.findById(roomId)
.orElseThrow(() -> new CustomException(ChatErrorCode.ROOM_NOT_FOUND));

// 상대방 멤버 조회 (1:1 채팅방이므로 상대방은 1명)
ChatRoomMember opponentMember = opponentInfoService.getOpponentMember(roomId, userId);
OpponentInfo opponent = opponentInfoService.getOpponentInfo(opponentMember.getUserId());
OpponentInfo opponent = opponentInfoService.getOpponentInfo(
opponentMember.getUserId(),
opponentMember.getRole()
);

// 협업중 여부 판단
boolean isCollaborating = room.isCollaborating();
Expand All @@ -187,7 +191,8 @@ private ChatRoomDetailResponse loadChatRoomDetail(Long userId, Long roomId) {
opponent.profileImageUrl(),
isCollaborating,
campaignSummary,
latestProposalId
latestProposalId,
myRole
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import java.util.Map;

import com.example.RealMatch.chat.domain.entity.ChatRoomMember;
import com.example.RealMatch.chat.domain.enums.ChatRoomMemberRole;

public interface OpponentInfoService {

OpponentInfo getOpponentInfo(Long opponentUserId);
OpponentInfo getOpponentInfo(Long opponentUserId, ChatRoomMemberRole role);

Map<Long, OpponentInfo> getOpponentInfoMapBatch(Long userId, List<Long> roomIds);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@

import org.springframework.stereotype.Service;

import com.example.RealMatch.brand.domain.entity.Brand;
import com.example.RealMatch.brand.domain.repository.BrandRepository;
import com.example.RealMatch.chat.application.util.ChatConstants;
import com.example.RealMatch.chat.application.util.ChatRoomValidator;
import com.example.RealMatch.chat.code.ChatErrorCode;
import com.example.RealMatch.chat.domain.entity.ChatRoomMember;
import com.example.RealMatch.chat.domain.enums.ChatRoomMemberRole;
import com.example.RealMatch.chat.domain.repository.ChatRoomMemberRepository;
import com.example.RealMatch.global.exception.CustomException;
import com.example.RealMatch.user.domain.entity.User;
Expand All @@ -25,9 +28,10 @@ public class OpponentInfoServiceImpl implements OpponentInfoService {

private final ChatRoomMemberRepository chatRoomMemberRepository;
private final UserRepository userRepository;
private final BrandRepository brandRepository;

@Override
public OpponentInfo getOpponentInfo(Long opponentUserId) {
public OpponentInfo getOpponentInfo(Long opponentUserId, ChatRoomMemberRole role) {
if (opponentUserId == null) {
return unknownOpponentInfo(null);
}
Expand All @@ -37,7 +41,12 @@ public OpponentInfo getOpponentInfo(Long opponentUserId) {
return unknownOpponentInfo(opponentUserId);
}

return new OpponentInfo(opponentUserId, user.getNickname(), user.getProfileImageUrl());
Brand brand = null;
if (role == ChatRoomMemberRole.BRAND) {
brand = brandRepository.findByUserId(opponentUserId).orElse(null);
}

return toOpponentInfo(opponentUserId, role, user, brand);
}

@Override
Expand All @@ -47,13 +56,14 @@ public Map<Long, OpponentInfo> getOpponentInfoMapBatch(Long userId, List<Long> r
}

Map<Long, List<ChatRoomMember>> opponentByRoom = findOpponentMembersByRoom(userId, roomIds);
Map<Long, Long> roomToOpponentUserIdMap = buildOpponentUserIdMap(roomIds, opponentByRoom);
Map<Long, User> userMap = loadOpponentUsers(roomToOpponentUserIdMap);
Map<Long, OpponentMember> roomToOpponentMemberMap = buildOpponentMemberMap(roomIds, opponentByRoom);
Map<Long, User> userMap = loadOpponentUsers(roomToOpponentMemberMap);
Map<Long, Brand> brandMap = loadOpponentBrands(roomToOpponentMemberMap);

return roomIds.stream()
.collect(Collectors.toMap(
roomId -> roomId,
roomId -> toOpponentInfo(roomToOpponentUserIdMap.get(roomId), userMap)
roomId -> toOpponentInfo(roomToOpponentMemberMap.get(roomId), userMap, brandMap)
));
}

Expand All @@ -73,7 +83,7 @@ private Map<Long, List<ChatRoomMember>> findOpponentMembersByRoom(Long userId, L
.collect(Collectors.groupingBy(ChatRoomMember::getRoomId));
}

private Map<Long, Long> buildOpponentUserIdMap(
private Map<Long, OpponentMember> buildOpponentMemberMap(
List<Long> roomIds,
Map<Long, List<ChatRoomMember>> opponentByRoom
) {
Expand All @@ -83,32 +93,68 @@ private Map<Long, Long> buildOpponentUserIdMap(
roomId -> {
List<ChatRoomMember> members = opponentByRoom.get(roomId);
ChatRoomValidator.validateDirectRoomOpponent(members, roomId);
return members.getFirst().getUserId();
ChatRoomMember member = members.getFirst();
return new OpponentMember(member.getUserId(), member.getRole());
}
));
}

private Map<Long, User> loadOpponentUsers(Map<Long, Long> roomToOpponentUserIdMap) {
Set<Long> opponentUserIds = new HashSet<>(roomToOpponentUserIdMap.values());
private Map<Long, User> loadOpponentUsers(Map<Long, OpponentMember> roomToOpponentMemberMap) {
Set<Long> opponentUserIds = roomToOpponentMemberMap.values().stream()
.map(OpponentMember::userId)
.filter(id -> id != null)
.collect(Collectors.toCollection(HashSet::new));
if (opponentUserIds.isEmpty()) {
return Map.of();
}
return userRepository.findAllById(opponentUserIds).stream()
.collect(Collectors.toMap(User::getId, u -> u));
}

private OpponentInfo toOpponentInfo(Long opponentUserId, Map<Long, User> userMap) {
if (opponentUserId == null) {
private Map<Long, Brand> loadOpponentBrands(Map<Long, OpponentMember> roomToOpponentMemberMap) {
List<Long> brandUserIds = roomToOpponentMemberMap.values().stream()
.filter(member -> member.role() == ChatRoomMemberRole.BRAND)
.map(OpponentMember::userId)
.filter(id -> id != null)
.distinct()
.toList();
if (brandUserIds.isEmpty()) {
return Map.of();
}
return brandRepository.findByUserIdIn(brandUserIds).stream()
.collect(Collectors.toMap(b -> b.getUser().getId(), b -> b));
}

private OpponentInfo toOpponentInfo(
OpponentMember opponentMember,
Map<Long, User> userMap,
Map<Long, Brand> brandMap
) {
if (opponentMember == null || opponentMember.userId() == null) {
return unknownOpponentInfo(null);
}
User user = userMap.get(opponentUserId);
User user = userMap.get(opponentMember.userId());
if (user == null) {
return unknownOpponentInfo(opponentUserId);
return unknownOpponentInfo(opponentMember.userId());
}
Brand brand = brandMap.get(opponentMember.userId());
return toOpponentInfo(opponentMember.userId(), opponentMember.role(), user, brand);
}

private OpponentInfo toOpponentInfo(Long opponentUserId, ChatRoomMemberRole role, User user, Brand brand) {
if (role == ChatRoomMemberRole.BRAND) {
String brandName = brand != null ? brand.getBrandName() : ChatConstants.UNKNOWN_OPPONENT_NAME;
String brandImageUrl = brand != null ? brand.getLogoUrl() : null;
String profileImageUrl = brandImageUrl != null ? brandImageUrl : user.getProfileImageUrl();
return new OpponentInfo(opponentUserId, brandName, profileImageUrl);
}
return new OpponentInfo(opponentUserId, user.getNickname(), user.getProfileImageUrl());
}

private OpponentInfo unknownOpponentInfo(Long opponentUserId) {
return new OpponentInfo(opponentUserId, ChatConstants.UNKNOWN_OPPONENT_NAME, null);
}

private record OpponentMember(Long userId, ChatRoomMemberRole role) {
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.example.RealMatch.chat.presentation.dto.response;

import com.example.RealMatch.chat.domain.enums.ChatRoomMemberRole;

public record ChatRoomDetailResponse(
Long roomId,
Long opponentUserId,
String opponentName,
String opponentProfileImageUrl,
boolean isCollaborating, // 협업중 여부
CampaignSummaryResponse campaignSummary, // 협업 요약 바 정보 (제안이 있는 경우에만 null이 아님)
Long latestProposalId // 재제안 폼 진입용. 해당 채팅방의 최신 PROPOSAL_CARD/RE_PROPOSAL_CARD 메시지의 proposalId (제안 없으면 null)
Long latestProposalId, // 재제안 폼 진입용. 해당 채팅방의 최신 PROPOSAL_CARD/RE_PROPOSAL_CARD 메시지의 proposalId (제안 없으면 null)
ChatRoomMemberRole myRole // 현재 사용자의 채팅방 내 역할 (BRAND 또는 CREATOR)
) {
}
Loading