From 331cf697c12c1bbb2d6f0298b1af23bb5c6ec9da Mon Sep 17 00:00:00 2001 From: Kijun Kwon <39583312+kkjsw17@users.noreply.github.com> Date: Fri, 13 Sep 2024 00:19:53 +0900 Subject: [PATCH] =?UTF-8?q?[SAMBAD-327]=20=EB=AA=A8=EC=9E=84=EC=9B=90=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9D=91=EB=8B=B5=EC=97=90=20=EB=B3=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=97=AC=EB=B6=80,=20=EC=86=90=20=ED=9D=94?= =?UTF-8?q?=EB=93=A4=EA=B8=B0=20=EC=83=81=ED=83=9C=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#157)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/MeetingMemberController.java | 3 +- .../domain/common/utils/UserIdResolver.java | 16 +++++++++ .../application/HandWavingRepository.java | 4 +-- .../handwaving/domain/HandWavedMemberDto.java | 16 +++++++++ .../HandWavingRepositoryImpl.java | 16 ++++++--- .../application/MeetingMemberRepository.java | 3 +- .../application/MeetingMemberService.java | 17 ++++++--- .../meeting/member/domain/MeetingMember.java | 5 +++ .../MeetingMemberJpaRepository.java | 4 ++- .../MeetingMemberRepositoryImpl.java | 12 ++++--- .../request/MeetingMemberPersistRequest.java | 1 - .../response/MeetingMemberListResponse.java | 32 +++++++++++++++-- .../MeetingMemberListResponseDetail.java | 35 +++++++++++++++++-- .../application/MeetingQuestionService.java | 6 ++-- 14 files changed, 142 insertions(+), 28 deletions(-) create mode 100644 moring-domain/src/main/java/org/depromeet/sambad/moring/domain/common/utils/UserIdResolver.java create mode 100644 moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/domain/HandWavedMemberDto.java diff --git a/moring-api/src/main/java/org/depromeet/sambad/moring/api/meeting/member/MeetingMemberController.java b/moring-api/src/main/java/org/depromeet/sambad/moring/api/meeting/member/MeetingMemberController.java index 7ab5a229..b9635806 100644 --- a/moring-api/src/main/java/org/depromeet/sambad/moring/api/meeting/member/MeetingMemberController.java +++ b/moring-api/src/main/java/org/depromeet/sambad/moring/api/meeting/member/MeetingMemberController.java @@ -100,8 +100,7 @@ public ResponseEntity getMyMeetingMember( return ResponseEntity.ok(response); } - @Operation(summary = "모임원 목록 조회", description = "- 특정 모임의 모임원 목록을 조회합니다.\n" - + "- 자기 자신은 목록에서 제외합니다.") + @Operation(summary = "모임원 목록 조회", description = "- 특정 모임의 모임원 목록을 조회합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "모임원 목록 조회 성공"), @ApiResponse(responseCode = "403", description = "USER_NOT_MEMBER_OF_MEETING") diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/common/utils/UserIdResolver.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/common/utils/UserIdResolver.java new file mode 100644 index 00000000..1d298714 --- /dev/null +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/common/utils/UserIdResolver.java @@ -0,0 +1,16 @@ +package org.depromeet.sambad.moring.domain.common.utils; + +import java.util.Optional; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +public class UserIdResolver { + + public static Long resolveRequestedUserId() { + return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) + .map(Authentication::getName) + .map(Long::valueOf) + .orElse(null); + } +} diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/application/HandWavingRepository.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/application/HandWavingRepository.java index c6942dd0..93f7b494 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/application/HandWavingRepository.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/application/HandWavingRepository.java @@ -3,8 +3,8 @@ import java.util.List; import java.util.Optional; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavedMemberDto; import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWaving; -import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMember; public interface HandWavingRepository { @@ -14,7 +14,7 @@ public interface HandWavingRepository { Optional findFirstBySenderIdAndReceiverIdOrderByIdDesc(Long senderMemberId, Long receiverMemberId); - List findHandWavedMembersByMeetingMemberId(Long meetingMemberId); + List findHandWavedMembersByMeetingMemberId(Long meetingMemberId); List findAllByEventIdIn(List eventIds); } diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/domain/HandWavedMemberDto.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/domain/HandWavedMemberDto.java new file mode 100644 index 00000000..808531b0 --- /dev/null +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/domain/HandWavedMemberDto.java @@ -0,0 +1,16 @@ +package org.depromeet.sambad.moring.domain.meeting.handwaving.domain; + +import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMember; + +public record HandWavedMemberDto( + MeetingMember handWavedMember, + HandWaving handWaving +) { + public Long getMemberId() { + return handWavedMember.getId(); + } + + public HandWavingStatus getStatus() { + return handWaving.getStatus(); + } +} diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java index 975aab53..95709d8b 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/handwaving/infrastructure/HandWavingRepositoryImpl.java @@ -1,6 +1,5 @@ package org.depromeet.sambad.moring.domain.meeting.handwaving.infrastructure; -import static org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavingStatus.*; import static org.depromeet.sambad.moring.domain.meeting.handwaving.domain.QHandWaving.*; import static org.depromeet.sambad.moring.domain.meeting.member.domain.QMeetingMember.*; @@ -8,10 +7,11 @@ import java.util.Optional; import org.depromeet.sambad.moring.domain.meeting.handwaving.application.HandWavingRepository; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavedMemberDto; import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWaving; -import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMember; import org.springframework.stereotype.Repository; +import com.querydsl.core.Tuple; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -40,8 +40,8 @@ public Optional findFirstBySenderIdAndReceiverIdOrderByIdDesc(Long s } @Override - public List findHandWavedMembersByMeetingMemberId(Long meetingMemberId) { - return query.select(meetingMember) + public List findHandWavedMembersByMeetingMemberId(Long meetingMemberId) { + List results = query.select(handWaving, meetingMember) .from(handWaving) .join(meetingMember) .on(handWaving.receiver.id.eq(meetingMember.id) @@ -49,10 +49,16 @@ public List findHandWavedMembersByMeetingMemberId(Long meetingMem .where( handWaving.receiver.id.eq(meetingMemberId) .or(handWaving.sender.id.eq(meetingMemberId)), - handWaving.status.eq(ACCEPTED), meetingMember.id.ne(meetingMemberId) ) .fetch(); + + return results.stream() + .map(tuple -> new HandWavedMemberDto( + tuple.get(meetingMember), + tuple.get(handWaving) + )) + .toList(); } @Override diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberRepository.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberRepository.java index a4ecbe63..f6979219 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberRepository.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberRepository.java @@ -14,7 +14,8 @@ public interface MeetingMemberRepository { Optional findByUserIdAndMeetingId(Long userId, Long meetingId); - List findByMeetingIdAndMeetingMemberIdNotOrderByName(Long meetingId, Long loginMeetingMemberId); + List findByMeetingIdAndMeetingMemberIdNotInOrderByName( + Long meetingId, List excludeMemberIds); List findNextTargetsByMeeting(Long meetingId, Long loginMeetingMemberId, List excludeMemberIds); diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberService.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberService.java index a969a935..67aebbaf 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberService.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/application/MeetingMemberService.java @@ -4,9 +4,11 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; import org.depromeet.sambad.moring.domain.event.application.EventService; import org.depromeet.sambad.moring.domain.meeting.handwaving.application.HandWavingRepository; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavedMemberDto; import org.depromeet.sambad.moring.domain.meeting.meeting.application.MeetingRepository; import org.depromeet.sambad.moring.domain.meeting.meeting.domain.Meeting; import org.depromeet.sambad.moring.domain.meeting.meeting.domain.MeetingCode; @@ -92,11 +94,18 @@ public MeetingMemberListResponse getMeetingMembers(Long userId, Long meetingId) meetingMemberValidator.validateUserIsMemberOfMeeting(userId, meetingId); MeetingMember me = getByUserIdAndMeetingId(userId, meetingId); - List members = meetingMemberRepository.findByMeetingIdAndMeetingMemberIdNotOrderByName(meetingId, - me.getId()); - List handWavedMembers = handWavingRepository.findHandWavedMembersByMeetingMemberId(me.getId()); + List handWavedMembers = handWavingRepository.findHandWavedMembersByMeetingMemberId(me.getId()); + List excludeMemberIds = handWavedMembers.stream() + .map(HandWavedMemberDto::getMemberId) + .collect(Collectors.toList()); - return MeetingMemberListResponse.from(members, handWavedMembers); + // 본인은 항상 1순위이기 때문에, 목록 조회 대상에서 제외 + excludeMemberIds.add(me.getId()); + + List notHandWavedMembers = meetingMemberRepository.findByMeetingIdAndMeetingMemberIdNotInOrderByName( + meetingId, excludeMemberIds); + + return MeetingMemberListResponse.from(me, notHandWavedMembers, handWavedMembers); } public MeetingMember getByUserIdAndMeetingId(Long userId, Long meetingId) { diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/domain/MeetingMember.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/domain/MeetingMember.java index 91bcde05..0fb63561 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/domain/MeetingMember.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/domain/MeetingMember.java @@ -1,6 +1,7 @@ package org.depromeet.sambad.moring.domain.meeting.member.domain; import static jakarta.persistence.EnumType.*; +import static org.depromeet.sambad.moring.domain.common.utils.UserIdResolver.*; import java.time.LocalDate; import java.util.ArrayList; @@ -143,6 +144,10 @@ public boolean isOwner() { return role.equals(MeetingMemberRole.OWNER); } + public boolean isMe() { + return Objects.equals(this.user.getId(), resolveRequestedUserId()); + } + @Override public int compareTo(MeetingMember o) { // 지연로딩 객체일 경우, getter를 통해 필드를 가져와야 프록시 객체가 초기화되어 정상적인 비교 수행 가능 diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberJpaRepository.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberJpaRepository.java index d07013eb..448f449d 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberJpaRepository.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberJpaRepository.java @@ -10,7 +10,9 @@ public interface MeetingMemberJpaRepository extends JpaRepository findByUserId(Long userId); - List findByMeetingIdAndIdNotOrderByName(Long meetingId, Long meetingMemberId); + List findByMeetingIdAndIdNotInOrderByName(Long meetingId, List excludeMemberIds); + + List findByMeetingIdOrderByName(Long meetingId); Optional findByUserIdAndMeetingId(Long userId, Long meetingId); } diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberRepositoryImpl.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberRepositoryImpl.java index e8135afa..4b07bb52 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberRepositoryImpl.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/infrastructure/MeetingMemberRepositoryImpl.java @@ -58,10 +58,14 @@ public boolean isOwnerExceedingMaxMeetings(Long meetingId, int maxHostMeetings) return meetingMemberQueryRepository.isOwnerExceedingMaxMeetings(meetingId, maxHostMeetings); } - public List findByMeetingIdAndMeetingMemberIdNotOrderByName(Long meetingId, - Long loginMeetingMemberId) { - return meetingMemberJpaRepository.findByMeetingIdAndIdNotOrderByName(meetingId, - loginMeetingMemberId); + @Override + public List findByMeetingIdAndMeetingMemberIdNotInOrderByName( + Long meetingId, List excludeMemberIds + ) { + if (excludeMemberIds.isEmpty()) { + return meetingMemberJpaRepository.findByMeetingIdOrderByName(meetingId); + } + return meetingMemberJpaRepository.findByMeetingIdAndIdNotInOrderByName(meetingId, excludeMemberIds); } @Override diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/request/MeetingMemberPersistRequest.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/request/MeetingMemberPersistRequest.java index 3ba010b5..fae65607 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/request/MeetingMemberPersistRequest.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/request/MeetingMemberPersistRequest.java @@ -43,7 +43,6 @@ public record MeetingMemberPersistRequest( String location, @Schema(description = "모임원 취미 ID 리스트", example = "[1, 2, 3]", requiredMode = NOT_REQUIRED) - @Size(max = 3) List hobbyIds, @Schema(description = "모임원 MBTI", example = "ISFP", requiredMode = NOT_REQUIRED) diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponse.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponse.java index edb3a297..e9a7b451 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponse.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponse.java @@ -2,8 +2,10 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*; +import java.util.ArrayList; import java.util.List; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavedMemberDto; import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMember; import io.swagger.v3.oas.annotations.media.Schema; @@ -11,18 +13,42 @@ public record MeetingMemberListResponse( @Schema( description = "모임원 목록", - example = "[{\"meetingMemberId\":1,\"name\":\"이한음\",\"profileImageFileUrl\":\"https://example.com\",\"role\":\"OWNER\"}]", requiredMode = REQUIRED ) List contents ) { - public static MeetingMemberListResponse from(List members, List handWavedMembers) { - List memberResponses = members.stream() + public static MeetingMemberListResponse from( + MeetingMember me, List notHandWavedMembers, List handWavedMembers + ) { + List sortedHandWavedMembers = handWavedMembers.stream() + .map(HandWavedMemberDto::handWavedMember) .sorted() + .toList(); + + List sortedNotHandWavedMembers = notHandWavedMembers.stream() + .sorted() + .toList(); + + List mergedMembers = mergeMeetingMembers(me, sortedHandWavedMembers, sortedNotHandWavedMembers); + + List memberResponses = mergedMembers.stream() .map(member -> MeetingMemberListResponseDetail.from(member, handWavedMembers)) .toList(); return new MeetingMemberListResponse(memberResponses); } + + private static List mergeMeetingMembers( + MeetingMember me, List sortedHandWavedMember, List sortedNotHandWavedMembers + ) { + List mergedMembers = new ArrayList<>(); + + // 다음과 같은 순서대로 모임원 목록을 구성 + mergedMembers.add(me); + mergedMembers.addAll(sortedHandWavedMember); + mergedMembers.addAll(sortedNotHandWavedMembers); + + return mergedMembers; + } } diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponseDetail.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponseDetail.java index 4aec1ebf..6bf10d2d 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponseDetail.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/member/presentation/response/MeetingMemberListResponseDetail.java @@ -3,8 +3,12 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*; import java.util.List; +import java.util.Objects; +import java.util.Optional; import org.depromeet.sambad.moring.domain.file.presentation.annotation.FullFileUrl; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavedMemberDto; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavingStatus; import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMember; import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMemberRole; @@ -25,15 +29,40 @@ public record MeetingMemberListResponseDetail( MeetingMemberRole role, @Schema(description = "서로 손 흔들어 인사하기를 수행했는지 여부", example = "true", requiredMode = REQUIRED) - boolean isHandWaved + boolean isHandWaved, + + @Schema(description = "나인지 여부", example = "false", requiredMode = REQUIRED) + boolean isMe, + + @Schema(description = "서로 손 흔들어 인사하기를 수행했는지 여부", example = "REQUESTED", requiredMode = REQUIRED) + HandWavingStatus handWavingStatus ) { - public static MeetingMemberListResponseDetail from(MeetingMember member, List handWavedMembers) { + public static MeetingMemberListResponseDetail from( + MeetingMember member, List handWavedMembers + ) { + + HandWavedMemberDto handWavedMember = getHandWavedMember(member, handWavedMembers); + HandWavingStatus handWavingStatus = Optional.ofNullable(handWavedMember) + .map(HandWavedMemberDto::getStatus) + .orElse(HandWavingStatus.NOT_REQUESTED); + return new MeetingMemberListResponseDetail( member.getId(), member.getName(), member.getProfileImageUrl(), member.getRole(), - handWavedMembers.contains(member) + Objects.nonNull(handWavedMember), + member.isMe(), + handWavingStatus ); } + + private static HandWavedMemberDto getHandWavedMember( + MeetingMember member, List handWavedMembers + ) { + return handWavedMembers.stream() + .filter(handWavedMember -> Objects.equals(handWavedMember.getMemberId(), member.getId())) + .findFirst() + .orElse(null); + } } diff --git a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/question/application/MeetingQuestionService.java b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/question/application/MeetingQuestionService.java index f40eacb0..c5b18080 100644 --- a/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/question/application/MeetingQuestionService.java +++ b/moring-domain/src/main/java/org/depromeet/sambad/moring/domain/meeting/question/application/MeetingQuestionService.java @@ -8,6 +8,7 @@ import org.depromeet.sambad.moring.domain.event.application.EventService; import org.depromeet.sambad.moring.domain.event.domain.EventType; import org.depromeet.sambad.moring.domain.meeting.handwaving.application.HandWavingRepository; +import org.depromeet.sambad.moring.domain.meeting.handwaving.domain.HandWavedMemberDto; import org.depromeet.sambad.moring.domain.meeting.meeting.domain.Meeting; import org.depromeet.sambad.moring.domain.meeting.member.application.MeetingMemberService; import org.depromeet.sambad.moring.domain.meeting.member.domain.MeetingMember; @@ -152,9 +153,10 @@ public MeetingMemberListResponse getMeetingMembersByMeetingQuestionId( meetingQuestion.getId()); MeetingMember me = meetingMemberService.getByUserIdAndMeetingId(userId, meetingId); - List handWavedMembers = handWavingRepository.findHandWavedMembersByMeetingMemberId(me.getId()); + List handWavedMembers = handWavingRepository.findHandWavedMembersByMeetingMemberId( + me.getId()); - return MeetingMemberListResponse.from(members, handWavedMembers); + return MeetingMemberListResponse.from(me, members, handWavedMembers); } private CurrentMeetingQuestionResponse getCurrentMeetingQuestionResponse(