diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/api/query/FriendQueryApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/api/query/FriendQueryApi.java index 7fe063959..345a98c22 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/api/query/FriendQueryApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/api/query/FriendQueryApi.java @@ -66,10 +66,10 @@ ResponseEntity> findFriendsBeforeGroupInvite( @Operation( summary = "소셜 친구 요청 받은 목록 조회", description = """ - 사용자가 소셜 친구 요청을 받은 목록을 보여준다. -
- 수락 대기 중인 요청만 해당한다. - """, + 사용자가 소셜 친구 요청을 받은 목록을 보여준다. +
+ 수락 대기 중인 요청만 해당한다. + """, security = {@SecurityRequirement(name = "user_token")}, tags = {"friend"} ) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepository.java index de7021d81..73a9bb6d4 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepository.java @@ -30,7 +30,7 @@ Optional findFriendsByTag( List findFriendIdsByOwnerId(final Long memberId); - Slice findFriendsBeforeGroupInvite( + Slice findFriends( final FriendBeforeGroupInviteRequest request); List findFriendIds(final List groupMemberIds, final Long memberId); diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepositoryImpl.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepositoryImpl.java index 63cb8d93f..f4d70e495 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepositoryImpl.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/repository/member_friend/MemberFriendQueryRepositoryImpl.java @@ -1,10 +1,7 @@ package site.timecapsulearchive.core.domain.friend.repository.member_friend; -import static com.querydsl.jpa.JPAExpressions.select; -import static site.timecapsulearchive.core.domain.friend.entity.QFriendInvite.friendInvite; import static site.timecapsulearchive.core.domain.friend.entity.QMemberFriend.memberFriend; import static site.timecapsulearchive.core.domain.member.entity.QMember.member; -import static site.timecapsulearchive.core.domain.member_group.entity.QMemberGroup.memberGroup; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; @@ -73,8 +70,9 @@ private Slice getFriendSummaryDtos(final int size, return new SliceImpl<>(friendSummaryDtos, Pageable.ofSize(size), hasNext); } - public Slice findFriendsBeforeGroupInvite( - final FriendBeforeGroupInviteRequest request) { + public Slice findFriends( + final FriendBeforeGroupInviteRequest request + ) { final List friends = jpaQueryFactory .select( Projections.constructor( @@ -86,15 +84,8 @@ public Slice findFriendsBeforeGroupInvite( ) ) .from(memberFriend) - .innerJoin(member).on(memberFriend.owner.id.eq(member.id)) - .innerJoin(member).on(memberFriend.friend.id.eq(member.id)) .where(memberFriend.owner.id.eq(request.memberId()) .and(memberFriend.createdAt.lt(request.createdAt())) - .and(memberFriend.friend.id.notIn( - select(memberGroup.member.id) - .from(memberGroup) - .where(memberGroup.group.id.eq(request.groupId())) - )) ) .limit(request.size() + 1) .fetch(); diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryService.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryService.java index 2e0ecc5e8..15e711f91 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryService.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryService.java @@ -2,8 +2,10 @@ import java.time.ZonedDateTime; import java.util.List; +import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import site.timecapsulearchive.core.domain.friend.data.dto.FriendSummaryDto; @@ -13,6 +15,8 @@ import site.timecapsulearchive.core.domain.friend.exception.FriendNotFoundException; import site.timecapsulearchive.core.domain.friend.repository.friend_invite.FriendInviteRepository; import site.timecapsulearchive.core.domain.friend.repository.member_friend.MemberFriendRepository; +import site.timecapsulearchive.core.domain.member_group.repository.group_invite_repository.GroupInviteRepository; +import site.timecapsulearchive.core.domain.member_group.repository.member_group_repository.MemberGroupRepository; import site.timecapsulearchive.core.global.common.wrapper.ByteArrayWrapper; @Service @@ -21,6 +25,8 @@ public class FriendQueryService { private final MemberFriendRepository memberFriendRepository; + private final MemberGroupRepository memberGroupRepository; + private final GroupInviteRepository groupInviteRepository; private final FriendInviteRepository friendInviteRepository; public Slice findFriendsSlice( @@ -33,7 +39,36 @@ public Slice findFriendsSlice( public Slice findFriendsBeforeGroupInviteSlice( final FriendBeforeGroupInviteRequest request) { - return memberFriendRepository.findFriendsBeforeGroupInvite(request); + final Slice friendSummaryDtos = memberFriendRepository.findFriends( + request); + + final List groupMemberIdsToExcludeBeforeGroupInvite = getGroupMemberIdsToExcludeBeforeGroupInvite( + request); + + final List friendSummaryBeforeGroupInvitedDtos = getFriendSummaryBeforeGroupInvitedDtos( + friendSummaryDtos, groupMemberIdsToExcludeBeforeGroupInvite); + + return new SliceImpl<>(friendSummaryBeforeGroupInvitedDtos, friendSummaryDtos.getPageable(), + friendSummaryDtos.hasNext()); + } + + private List getGroupMemberIdsToExcludeBeforeGroupInvite( + final FriendBeforeGroupInviteRequest request) { + return Stream.concat( + memberGroupRepository.findGroupMemberIdsByGroupId(request.groupId()).stream(), + groupInviteRepository.findGroupMemberIdsByGroupIdAndGroupOwnerId(request.groupId(), + request.memberId()).stream()) + .distinct() + .toList(); + } + + private List getFriendSummaryBeforeGroupInvitedDtos( + final Slice friendSummaryDtos, + final List groupMemberIdsToExcludeBeforeGroupInvite + ) { + return friendSummaryDtos.getContent() + .stream() + .filter(dto -> !groupMemberIdsToExcludeBeforeGroupInvite.contains(dto.id())).toList(); } public Slice findFriendReceivingInvitesSlice( diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApi.java index 42695d39b..8cf12d1d5 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApi.java @@ -9,7 +9,6 @@ import java.time.ZonedDateTime; import org.springframework.http.ResponseEntity; import site.timecapsulearchive.core.domain.group.data.response.GroupDetailResponse; -import site.timecapsulearchive.core.domain.group.data.response.GroupMemberInfosResponse; import site.timecapsulearchive.core.domain.group.data.response.GroupsSliceResponse; import site.timecapsulearchive.core.global.common.response.ApiSpec; diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApiController.java index 4eb6a53ce..22349e302 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/api/query/GroupQueryApiController.java @@ -1,7 +1,6 @@ package site.timecapsulearchive.core.domain.group.api.query; import java.time.ZonedDateTime; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Slice; import org.springframework.http.ResponseEntity; @@ -13,9 +12,7 @@ import org.springframework.web.bind.annotation.RestController; import site.timecapsulearchive.core.domain.group.data.dto.CompleteGroupSummaryDto; import site.timecapsulearchive.core.domain.group.data.dto.GroupDetailTotalDto; -import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberDto; import site.timecapsulearchive.core.domain.group.data.response.GroupDetailResponse; -import site.timecapsulearchive.core.domain.group.data.response.GroupMemberInfosResponse; import site.timecapsulearchive.core.domain.group.data.response.GroupsSliceResponse; import site.timecapsulearchive.core.domain.group.service.query.GroupQueryService; import site.timecapsulearchive.core.global.common.response.ApiSpec; @@ -60,7 +57,8 @@ public ResponseEntity> findGroups( @RequestParam(defaultValue = "20", value = "size") final int size, @RequestParam(value = "created_at") final ZonedDateTime createdAt ) { - final Slice groupsSlice = groupQueryService.findGroupsSlice(memberId, + final Slice groupsSlice = groupQueryService.findGroupsSlice( + memberId, size, createdAt); diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/repository/GroupQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/repository/GroupQueryRepository.java index b13299a40..d9d6b63cf 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/repository/GroupQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/group/repository/GroupQueryRepository.java @@ -5,7 +5,6 @@ import java.util.Optional; import org.springframework.data.domain.Slice; import site.timecapsulearchive.core.domain.group.data.dto.GroupDetailDto; -import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberDto; import site.timecapsulearchive.core.domain.group.data.dto.GroupSummaryDto; diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member/repository/MemberRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member/repository/MemberRepository.java index 8efa30cea..02c68c260 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member/repository/MemberRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member/repository/MemberRepository.java @@ -1,6 +1,5 @@ package site.timecapsulearchive.core.domain.member.repository; -import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/data/response/GroupSendingInviteMemberResponse.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/data/response/GroupSendingInviteMemberResponse.java index b4193f30f..a01e1a4fa 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/data/response/GroupSendingInviteMemberResponse.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/data/response/GroupSendingInviteMemberResponse.java @@ -11,9 +11,11 @@ public record GroupSendingInviteMemberResponse( String profileUrl, ZonedDateTime sendingInvitesCreatedAt ) { + public GroupSendingInviteMemberResponse { if (sendingInvitesCreatedAt != null) { - sendingInvitesCreatedAt = sendingInvitesCreatedAt.withZoneSameInstant(ResponseMappingConstant.ZONE_ID); + sendingInvitesCreatedAt = sendingInvitesCreatedAt.withZoneSameInstant( + ResponseMappingConstant.ZONE_ID); } } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepository.java index c9c5c3166..65a8aa3f2 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepository.java @@ -18,6 +18,8 @@ Slice findGroupReceivingInvitesSlice( final ZonedDateTime createdAt ); + List findGroupMemberIdsByGroupIdAndGroupOwnerId(final Long groupId, final Long memberId); + List findGroupSendingInvites( final Long memberId, final Long groupId diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepositoryImpl.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepositoryImpl.java index 7f2b33ec6..abd1b5b4e 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepositoryImpl.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteQueryRepositoryImpl.java @@ -14,9 +14,7 @@ import java.time.ZonedDateTime; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import org.springframework.data.domain.SliceImpl; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @@ -32,8 +30,11 @@ public class GroupInviteQueryRepositoryImpl implements GroupInviteQueryRepositor private final JPAQueryFactory jpaQueryFactory; @Override - public void bulkSave(final Long groupOwnerId, final Long groupId, - final List groupMemberIds) { + public void bulkSave( + final Long groupOwnerId, + final Long groupId, + final List groupMemberIds + ) { jdbcTemplate.batchUpdate( """ INSERT INTO group_invite ( @@ -101,6 +102,19 @@ public Slice findGroupReceivingInvitesSlice( return SliceUtil.makeSlice(size, groupInviteSummaryDtos); } + @Override + public List findGroupMemberIdsByGroupIdAndGroupOwnerId( + final Long groupId, + final Long groupOwnerId + ) { + return jpaQueryFactory + .select(groupInvite.groupMember.id) + .from(groupInvite) + .where(groupInvite.groupOwner.id.eq(groupOwnerId).and(groupInvite.group.id.eq(groupId))) + .fetch(); + } + + @Override public List findGroupSendingInvites( final Long memberId, final Long groupId diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepository.java index f664cc0cc..b11a3eade 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepository.java @@ -18,4 +18,6 @@ public interface MemberGroupQueryRepository { List findGroupMemberInfos(Long memberId, Long groupId); Optional findGroupMembersCount(Long groupId); + + List findGroupMemberIdsByGroupId(final Long groupId); } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepositoryImpl.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepositoryImpl.java index 9eafc40a2..84eb64bfe 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepositoryImpl.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupQueryRepositoryImpl.java @@ -102,4 +102,12 @@ public Optional findGroupMembersCount(final Long groupId) { .fetchOne() ); } + + public List findGroupMemberIdsByGroupId(final Long groupId) { + return jpaQueryFactory + .select(memberGroup.member.id) + .from(memberGroup) + .where(memberGroup.group.id.eq(groupId)) + .fetch(); + } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupRepository.java index 39393cb7b..6f2a9cf28 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/member_group_repository/MemberGroupRepository.java @@ -3,7 +3,6 @@ import java.util.List; import java.util.Optional; import org.springframework.data.repository.Repository; -import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberDto; import site.timecapsulearchive.core.domain.member_group.entity.MemberGroup; public interface MemberGroupRepository extends Repository, diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/global/config/redis/RedissonLockAspect.java b/backend/core/src/main/java/site/timecapsulearchive/core/global/config/redis/RedissonLockAspect.java index f4444c523..5430e1499 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/global/config/redis/RedissonLockAspect.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/global/config/redis/RedissonLockAspect.java @@ -32,7 +32,8 @@ public Object redissonLock(ProceedingJoinPoint joinPoint) throws Throwable { RedissonLock redissonLock = method.getAnnotation(RedissonLock.class); String lockKey = - method.getName() + DIVISION + RedisLockSpELParser.getLockKey(signature.getParameterNames(), + method.getName() + DIVISION + RedisLockSpELParser.getLockKey( + signature.getParameterNames(), joinPoint.getArgs(), redissonLock.value()); long waitTime = redissonLock.waitTime(); diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/FriendDtoFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/FriendDtoFixture.java index 5cf59d72a..4ee3f18b8 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/FriendDtoFixture.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/FriendDtoFixture.java @@ -1,9 +1,16 @@ package site.timecapsulearchive.core.common.fixture.dto; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.List; import java.util.Optional; +import java.util.stream.IntStream; import java.util.stream.LongStream; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; +import site.timecapsulearchive.core.domain.friend.data.dto.FriendSummaryDto; import site.timecapsulearchive.core.domain.friend.data.dto.SearchFriendSummaryDto; import site.timecapsulearchive.core.domain.friend.data.dto.SearchFriendSummaryDtoByTag; import site.timecapsulearchive.core.global.common.wrapper.ByteArrayWrapper; @@ -35,4 +42,18 @@ public static Optional getFriendSummaryDtoByTag() { .build()); } + + public static Slice getFriendSummaryDtoSlice(int count, boolean hasNextPage) { + List dtos = IntStream.range(0, count) + .mapToObj(i -> new FriendSummaryDto( + (long) i, + i + "testProfileUrl", + i + "testNickname", + ZonedDateTime.now(ZoneId.of("UTC")).plusDays(i) + ) + ) + .toList(); + + return new SliceImpl<>(dtos, Pageable.ofSize(count), hasNextPage); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryServiceTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryServiceTest.java index 5d5088689..4596edcc3 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryServiceTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/friend/service/query/FriendQueryServiceTest.java @@ -9,29 +9,43 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; +import org.springframework.data.domain.Slice; import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.dto.FriendDtoFixture; +import site.timecapsulearchive.core.domain.friend.data.dto.FriendSummaryDto; import site.timecapsulearchive.core.domain.friend.data.dto.SearchFriendSummaryDto; import site.timecapsulearchive.core.domain.friend.data.dto.SearchFriendSummaryDtoByTag; +import site.timecapsulearchive.core.domain.friend.data.request.FriendBeforeGroupInviteRequest; import site.timecapsulearchive.core.domain.friend.exception.FriendNotFoundException; import site.timecapsulearchive.core.domain.friend.repository.friend_invite.FriendInviteRepository; import site.timecapsulearchive.core.domain.friend.repository.member_friend.MemberFriendRepository; +import site.timecapsulearchive.core.domain.member_group.repository.group_invite_repository.GroupInviteRepository; +import site.timecapsulearchive.core.domain.member_group.repository.member_group_repository.MemberGroupRepository; import site.timecapsulearchive.core.global.common.wrapper.ByteArrayWrapper; class FriendQueryServiceTest { private final MemberFriendRepository memberFriendRepository = mock( MemberFriendRepository.class); + private final MemberGroupRepository memberGroupRepository = mock(MemberGroupRepository.class); + private final GroupInviteRepository groupInviteRepository = mock(GroupInviteRepository.class); private final FriendInviteRepository friendInviteRepository = mock( FriendInviteRepository.class); private final FriendQueryService friendQueryService = new FriendQueryService( - memberFriendRepository, friendInviteRepository); + memberFriendRepository, + memberGroupRepository, + groupInviteRepository, + friendInviteRepository + ); @Test void 사용자는_주소록_기반_핸드폰_번호로_Ahchive_사용자_리스트를_조회_할_수_있다() { @@ -103,4 +117,66 @@ class FriendQueryServiceTest { assertThatThrownBy(() -> friendQueryService.searchFriend(memberId, tag)) .isInstanceOf(FriendNotFoundException.class); } + + @Test + void 그룹장은_그룹_초대_전_초대_가능한_친구_목록을_조회할_수_있다() { + //given + Long memberId = 1L; + Long groupId = 1L; + int size = 20; + ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")).plusDays(1); + + FriendBeforeGroupInviteRequest request = FriendBeforeGroupInviteRequest.of(memberId, + groupId, + size, now); + given(memberFriendRepository.findFriends(request)).willReturn( + FriendDtoFixture.getFriendSummaryDtoSlice(5, true)); + given(memberGroupRepository.findGroupMemberIdsByGroupId(request.groupId())).willReturn( + List.of(3L)); + given(groupInviteRepository.findGroupMemberIdsByGroupIdAndGroupOwnerId(request.groupId(), + request.memberId())).willReturn(List.of(4L)); + + Slice friendsBeforeGroupInviteSlice = friendQueryService.findFriendsBeforeGroupInviteSlice( + request); + + SoftAssertions.assertSoftly( + softly -> { + assertThat(friendsBeforeGroupInviteSlice.getContent()).isNotEmpty(); + assertThat(friendsBeforeGroupInviteSlice.getContent()).allMatch( + dto -> !dto.profileUrl().isBlank()); + assertThat(friendsBeforeGroupInviteSlice.getContent()).allMatch( + dto -> !dto.nickname().isBlank()); + assertThat(friendsBeforeGroupInviteSlice.getContent()).allMatch( + dto -> Objects.nonNull(dto.id())); + assertThat(friendsBeforeGroupInviteSlice.getContent()).allMatch( + dto -> Objects.nonNull(dto.createdAt())); + assertThat(friendsBeforeGroupInviteSlice.hasNext()).isTrue(); + assertThat(friendsBeforeGroupInviteSlice.getSize()).isEqualTo(5); + } + ); + } + + @Test + void 그룹장은_그룹_초대_전_이미_그룹멤버_혹은_그룹_요청을_보낸_사용자를_제외하고_초대_가능한_사용자를_조회한다() { + //given + Long memberId = 1L; + Long groupId = 1L; + int size = 20; + ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")).plusDays(1); + + FriendBeforeGroupInviteRequest request = FriendBeforeGroupInviteRequest.of(memberId, + groupId, + size, now); + given(memberFriendRepository.findFriends(request)).willReturn( + FriendDtoFixture.getFriendSummaryDtoSlice(5, true)); + given(memberGroupRepository.findGroupMemberIdsByGroupId(request.groupId())).willReturn( + List.of(3L)); + given(groupInviteRepository.findGroupMemberIdsByGroupIdAndGroupOwnerId(request.groupId(), + request.memberId())).willReturn(List.of(4L)); + + Slice friendsBeforeGroupInviteSlice = friendQueryService.findFriendsBeforeGroupInviteSlice( + request); + + assertThat(friendsBeforeGroupInviteSlice.getContent()).isNotIn(3L, 4L); + } } \ No newline at end of file