diff --git a/src/backend/common-module/src/main/java/com/bbebig/commonmodule/clientDto/StateFeignResponseDto.java b/src/backend/common-module/src/main/java/com/bbebig/commonmodule/clientDto/StateFeignResponseDto.java index 75a06960..246bed7c 100644 --- a/src/backend/common-module/src/main/java/com/bbebig/commonmodule/clientDto/StateFeignResponseDto.java +++ b/src/backend/common-module/src/main/java/com/bbebig/commonmodule/clientDto/StateFeignResponseDto.java @@ -43,6 +43,7 @@ public static class ServerMemberPresenceResponseDto { @Builder @NoArgsConstructor @AllArgsConstructor + public static class MemberPresenceResponseDto { private Long memberId; private PresenceType globalStatus; @@ -51,4 +52,3 @@ public static class MemberPresenceResponseDto { } -} diff --git a/src/backend/common-module/src/main/java/com/bbebig/commonmodule/kafka/dto/notification/FriendPresenceEventDto.java b/src/backend/common-module/src/main/java/com/bbebig/commonmodule/kafka/dto/notification/FriendPresenceEventDto.java index 06f6bf7a..ba69b282 100644 --- a/src/backend/common-module/src/main/java/com/bbebig/commonmodule/kafka/dto/notification/FriendPresenceEventDto.java +++ b/src/backend/common-module/src/main/java/com/bbebig/commonmodule/kafka/dto/notification/FriendPresenceEventDto.java @@ -26,6 +26,7 @@ public FriendPresenceEventDto( super(memberId, type); this.friendMemberId = friendMemberId; this.globalStatus = globalStatus; + this.actualStatus = actualStatus; } diff --git a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/controller/FriendController.java b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/controller/FriendController.java index 7a5f939a..d54f8d09 100644 --- a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/controller/FriendController.java +++ b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/controller/FriendController.java @@ -5,6 +5,8 @@ import com.bbebig.commonmodule.proto.PassportProto.Passport; import com.bbebig.userserver.friend.dto.request.FriendCreateRequestDto; import com.bbebig.userserver.friend.dto.response.*; +import com.bbebig.userserver.friend.dto.response.FriendResponseDto.FriendListResponseDto; +import com.bbebig.userserver.friend.dto.response.FriendResponseDto.PendingFriendListResponseDto; import com.bbebig.userserver.friend.service.FriendService; import com.bbebig.userserver.friend.entity.FriendStatus; import io.swagger.v3.oas.annotations.Operation; @@ -48,20 +50,20 @@ public CommonResponse createFriend( @ApiResponse(responseCode = "400", description = "", content = @Content) }) @GetMapping("/pending") - public CommonResponse> getPendingFriends( + public CommonResponse getPendingFriends( @Parameter(hidden = true) @PassportUser Passport passport ) { log.info("[Member] 요청 대기 중인 친구 조회 요청: memberId = {}", passport.getMemberId()); return CommonResponse.onSuccess(friendService.getPendingFriends(passport.getMemberId())); } - @Operation(summary = "요청 수락한 친구 조회", description = "요청 수락한 친구 조회합니다.") + @Operation(summary = "친구 목록 조회", description = "전체 친구 목록을 조회합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "요청 수락한 친구 조회 성공", useReturnTypeSchema = true), @ApiResponse(responseCode = "400", description = "", content = @Content) }) - @GetMapping("/accepted") - public CommonResponse> getAcceptedFriends( + @GetMapping + public CommonResponse getAcceptedFriends( @Parameter(hidden = true) @PassportUser Passport passport ) { log.info("[Member] 요청 수락한 친구 조회 요청: memberId = {}", passport.getMemberId()); diff --git a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/dto/response/FriendListResponseDto.java b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/dto/response/FriendListResponseDto.java deleted file mode 100644 index fca84886..00000000 --- a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/dto/response/FriendListResponseDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.bbebig.userserver.friend.dto.response; - -import com.bbebig.userserver.friend.entity.Friend; -import com.bbebig.userserver.member.entity.Member; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class FriendListResponseDto { - - private final Long friendId; - private final Long friendMemberId; - private final String friendName; - private final String friendNickname; - private final String friendAvatarUrl; - private final String friendBannerUrl; - private final String friendIntroduce; - private final String friendEmail; - - public static FriendListResponseDto convertToFriendListResponseDto(Friend friend, Member member) { - return FriendListResponseDto.builder() - .friendId(friend.getId()) - .friendMemberId(member.getId()) - .friendName(member.getName()) - .friendNickname(member.getNickname()) - .friendAvatarUrl(member.getAvatarUrl()) - .friendBannerUrl(member.getBannerUrl()) - .friendIntroduce(member.getIntroduce()) - .friendEmail(member.getEmail()) - .build(); - } -} diff --git a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/dto/response/FriendResponseDto.java b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/dto/response/FriendResponseDto.java new file mode 100644 index 00000000..ea576589 --- /dev/null +++ b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/dto/response/FriendResponseDto.java @@ -0,0 +1,93 @@ +package com.bbebig.userserver.friend.dto.response; + +import com.bbebig.commonmodule.clientDto.StateFeignResponseDto; +import com.bbebig.commonmodule.clientDto.StateFeignResponseDto.MemberPresenceStatusDto; +import com.bbebig.commonmodule.kafka.dto.model.PresenceType; +import com.bbebig.commonmodule.redis.domain.MemberPresenceStatus; +import com.bbebig.userserver.friend.entity.Friend; +import com.bbebig.userserver.member.entity.Member; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +public class FriendResponseDto { + + @Data + @Builder + public static class FriendListResponseDto { + private Long memberId; + private int friendsCount; + private List friends; + } + + @Data + @Builder + public static class PendingFriendListResponseDto { + private Long memberId; + private int pendingFriendsCount; + private int receivePendingFriendsCount; + private List sendPendingFriends; + private List receivePendingFriends; + } + + @Data + @Builder + public static class FriendInfoResponseDto { + private Long friendId; + private Long memberId; + private String memberName; + private String memberNickname; + private String memberAvatarUrl; + private String memberBannerUrl; + private String memberIntroduce; + private String memberEmail; + private PresenceType actualStatus; + private PresenceType globalStatus; + private LocalDateTime createdAt; + } + + @Data + @Builder + public static class PendingFriendInfoResponseDto { + private Long friendId; + private Long memberId; + private String memberName; + private String memberNickname; + private String memberAvatarUrl; + private String memberBannerUrl; + private String memberIntroduce; + private String memberEmail; + private LocalDateTime createdAt; + } + + public static FriendInfoResponseDto convertToFriendListResponseDto(Friend friend, Member member, MemberPresenceStatus statusDto) { + return FriendInfoResponseDto.builder() + .friendId(friend.getId()) + .memberId(member.getId()) + .memberName(member.getName()) + .memberNickname(member.getNickname()) + .memberAvatarUrl(member.getAvatarUrl()) + .memberBannerUrl(member.getBannerUrl()) + .memberIntroduce(member.getIntroduce()) + .memberEmail(member.getEmail()) + .actualStatus(statusDto.getActualStatus()) + .globalStatus(statusDto.getGlobalStatus()) + .build(); + } + + public static PendingFriendInfoResponseDto convertToPendingFriendListResponseDto(Friend friend, Member member) { + return PendingFriendInfoResponseDto.builder() + .friendId(friend.getId()) + .memberId(member.getId()) + .memberName(member.getName()) + .memberNickname(member.getNickname()) + .memberAvatarUrl(member.getAvatarUrl()) + .memberBannerUrl(member.getBannerUrl()) + .memberIntroduce(member.getIntroduce()) + .memberEmail(member.getEmail()) + .createdAt(friend.getCreatedAt()) + .build(); + } +} diff --git a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/service/FriendService.java b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/service/FriendService.java index 7545975a..f35c9848 100644 --- a/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/service/FriendService.java +++ b/src/backend/user-server/src/main/java/com/bbebig/userserver/friend/service/FriendService.java @@ -2,10 +2,16 @@ import com.bbebig.commonmodule.global.response.code.error.ErrorStatus; import com.bbebig.commonmodule.global.response.exception.ErrorHandler; +import com.bbebig.commonmodule.kafka.dto.model.PresenceType; import com.bbebig.commonmodule.kafka.dto.notification.FriendActionEventDto; import com.bbebig.commonmodule.kafka.dto.notification.NotificationEventType; import com.bbebig.commonmodule.kafka.dto.notification.status.FriendActionStatus; +import com.bbebig.commonmodule.redis.domain.MemberPresenceStatus; import com.bbebig.userserver.friend.dto.response.*; +import com.bbebig.userserver.friend.dto.response.FriendResponseDto.FriendInfoResponseDto; +import com.bbebig.userserver.friend.dto.response.FriendResponseDto.FriendListResponseDto; +import com.bbebig.userserver.friend.dto.response.FriendResponseDto.PendingFriendInfoResponseDto; +import com.bbebig.userserver.friend.dto.response.FriendResponseDto.PendingFriendListResponseDto; import com.bbebig.userserver.friend.entity.Friend; import com.bbebig.userserver.friend.entity.FriendStatus; import com.bbebig.userserver.friend.repository.FriendRepository; @@ -18,6 +24,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -100,38 +107,63 @@ public FriendCreateResponseDto createFriend(Long memberId, FriendCreateRequestDt * 요청 대기 중인 친구 목록 조회 */ @Transactional(readOnly = true) - public List getPendingFriends(Long memberId) { + public PendingFriendListResponseDto getPendingFriends(Long memberId) { memberRepository.findById(memberId) .orElseThrow(() -> new ErrorHandler(ErrorStatus.MEMBER_NOT_FOUND)); List friendList = friendRepository.findFriendsByMemberIdAndStatus(memberId, FriendStatus.PENDING); + List sendPendingFriends = new ArrayList<>(); + List receivePendingFriends = new ArrayList<>(); + + for (Friend friend : friendList) { + if (friend.getFromMember().getId().equals(memberId)) { + PendingFriendInfoResponseDto dto = FriendResponseDto.convertToPendingFriendListResponseDto(friend, friend.getToMember()); + sendPendingFriends.add(dto); + } else { + PendingFriendInfoResponseDto dto = FriendResponseDto.convertToPendingFriendListResponseDto(friend, friend.getFromMember()); + receivePendingFriends.add(dto); + } + } + return PendingFriendListResponseDto.builder() + .memberId(memberId) + .pendingFriendsCount(sendPendingFriends.size()) + .receivePendingFriendsCount(receivePendingFriends.size()) + .sendPendingFriends(sendPendingFriends) + .receivePendingFriends(receivePendingFriends) + .build(); - return friendList.stream() - .map(friend -> { - Member friendMember = friend.getFromMember().getId().equals(memberId) - ? friend.getToMember() : friend.getFromMember(); - return FriendListResponseDto.convertToFriendListResponseDto(friend, friendMember); - }) - .toList(); } /** * 요청 수락한 친구 목록 조회 */ @Transactional(readOnly = true) - public List getAcceptedFriends(Long memberId) { + public FriendListResponseDto getAcceptedFriends(Long memberId) { memberRepository.findById(memberId) .orElseThrow(() -> new ErrorHandler(ErrorStatus.MEMBER_NOT_FOUND)); List friendList = friendRepository.findFriendsByMemberIdAndStatus(memberId, FriendStatus.ACCEPTED); - - return friendList.stream() + List friends = friendList.stream() .map(friend -> { Member friendMember = friend.getFromMember().getId().equals(memberId) ? friend.getToMember() : friend.getFromMember(); - return FriendListResponseDto.convertToFriendListResponseDto(friend, friendMember); + MemberPresenceStatus memberPresenceStatus = memberRedisRepository.getMemberPresenceStatus(friendMember.getId()); + if (memberPresenceStatus == null) { + memberPresenceStatus = MemberPresenceStatus.builder() + .memberId(friendMember.getId()) + .globalStatus(friendMember.getCustomPresenceStatus()) + .actualStatus(PresenceType.OFFLINE) + .build(); + } + return FriendResponseDto.convertToFriendListResponseDto(friend, friendMember, memberPresenceStatus); }) .toList(); + + return FriendListResponseDto.builder() + .memberId(memberId) + .friendsCount(friends.size()) + .friends(friends) + .build(); } /** diff --git a/src/backend/user-server/src/main/java/com/bbebig/userserver/global/kafka/PresenceEventConsumerService.java b/src/backend/user-server/src/main/java/com/bbebig/userserver/global/kafka/PresenceEventConsumerService.java index eed57820..67ff8f90 100644 --- a/src/backend/user-server/src/main/java/com/bbebig/userserver/global/kafka/PresenceEventConsumerService.java +++ b/src/backend/user-server/src/main/java/com/bbebig/userserver/global/kafka/PresenceEventConsumerService.java @@ -43,6 +43,7 @@ private void handleEvent(PresenceEventDto presenceEventDto) { .memberId(friendMemberId) .friendMemberId(memberId) .globalStatus(presenceEventDto.getGlobalStatus()) + .actualStatus(presenceEventDto.getActualStatus()) .build(); kafkaProducerService.sendNotificationEvent(friendPresenceEventDto); }