From e418fcc325894dcebc32183a6ba7be5a35d1ec3f Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sat, 8 Jun 2024 16:39:48 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat=20:=20=EA=B7=B8=EB=A3=B9=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group_capsule/api/GroupCapsuleApi.java | 18 ++++++++---------- .../api/GroupCapsuleApiController.java | 11 +++++++++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java index 06fb9b364..4baec2440 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java @@ -116,19 +116,17 @@ ResponseEntity> getGroupCapsuleSummaryByCap description = "처리 완료" ) }) - @GetMapping( - value = "/groups/{group_id}/capsules", - produces = {"application/json"} - ) ResponseEntity getGroupCapsules( - @Parameter(in = ParameterIn.PATH, description = "그룹 아이디", required = true, schema = @Schema()) - @PathVariable("group_id") Long groupId, + Long memberId, - @Parameter(in = ParameterIn.QUERY, description = "페이지 크기", required = true, schema = @Schema()) - @NotNull @Valid @RequestParam(value = "size") Long size, + @Parameter(in = ParameterIn.QUERY, description = "그룹 아이디", required = true) + Long groupId, + + @Parameter(in = ParameterIn.QUERY, description = "페이지 크기", required = true) + Long size, - @Parameter(in = ParameterIn.QUERY, description = "마지막 캡슐 아이디", required = true, schema = @Schema()) - @NotNull @Valid @RequestParam(value = "capsule_id") Long capsuleId + @Parameter(in = ParameterIn.QUERY, description = "마지막 캡슐 아이디", required = true) + Long capsuleId ); @Operation( diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java index 824421e0b..34faac0cc 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java @@ -108,9 +108,16 @@ public ResponseEntity> getGroupCapsuleSumma ); } + @GetMapping( + produces = {"application/json"} + ) @Override - public ResponseEntity getGroupCapsules(Long groupId, Long size, - Long capsuleId) { + public ResponseEntity getGroupCapsules( + @AuthenticationPrincipal final Long memberId, + @RequestParam("group_id") final Long groupId, + @RequestParam("size") final Long size, + @RequestParam("capsuleId") final Long capsuleId + ) { return null; } From 3241e461af2d6bfa2655cdc3c2bb877f9a51a2cb Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sat, 8 Jun 2024 17:24:22 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat=20:=20=EA=B7=B8=EB=A3=B9=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group_capsule/api/GroupCapsuleApi.java | 10 +++--- .../api/GroupCapsuleApiController.java | 19 ++++++++--- .../data/dto/GroupCapsuleSliceRequestDto.java | 18 ++++++++++ .../GroupCapsuleQueryRepository.java | 33 +++++++++++++++++++ .../service/GroupCapsuleService.java | 5 +++ .../GroupCapsuleQueryRepositoryTest.java | 4 +-- 6 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java index 4baec2440..3c2d9ec8a 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java @@ -9,21 +9,19 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; import java.time.ZonedDateTime; import org.hibernate.validator.constraints.Range; +import org.springframework.data.domain.Slice; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; +import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleCreateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleUpdateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleDetailResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleOpenStateResponse; -import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsulePageResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSummaryResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.MyGroupCapsuleSliceResponse; import site.timecapsulearchive.core.global.common.response.ApiSpec; @@ -116,14 +114,14 @@ ResponseEntity> getGroupCapsuleSummaryByCap description = "처리 완료" ) }) - ResponseEntity getGroupCapsules( + ResponseEntity>> getGroupCapsules( Long memberId, @Parameter(in = ParameterIn.QUERY, description = "그룹 아이디", required = true) Long groupId, @Parameter(in = ParameterIn.QUERY, description = "페이지 크기", required = true) - Long size, + int size, @Parameter(in = ParameterIn.QUERY, description = "마지막 캡슐 아이디", required = true) Long capsuleId diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java index 34faac0cc..093ca6915 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java @@ -16,12 +16,12 @@ import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleOpenStateDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleCreateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleUpdateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleDetailResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleOpenStateResponse; -import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsulePageResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSummaryResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.MyGroupCapsuleSliceResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.facade.GroupCapsuleFacade; @@ -112,13 +112,24 @@ public ResponseEntity> getGroupCapsuleSumma produces = {"application/json"} ) @Override - public ResponseEntity getGroupCapsules( + public ResponseEntity>> getGroupCapsules( @AuthenticationPrincipal final Long memberId, @RequestParam("group_id") final Long groupId, - @RequestParam("size") final Long size, + @RequestParam("size") final int size, @RequestParam("capsuleId") final Long capsuleId ) { - return null; + final GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(memberId, groupId, + size, capsuleId); + + final Slice groupCapsuleSlice = groupCapsuleService.findGroupCapsuleSlice( + dto); + + return ResponseEntity.ok( + ApiSpec.success( + SuccessCode.SUCCESS, + groupCapsuleSlice + ) + ); } @GetMapping(value = "/my", produces = {"application/json"}) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java new file mode 100644 index 000000000..b6bcabb8b --- /dev/null +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java @@ -0,0 +1,18 @@ +package site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto; + +public record GroupCapsuleSliceRequestDto( + Long memberId, + Long groupId, + int size, + Long capsuleId +) { + + public static GroupCapsuleSliceRequestDto createOf( + final Long memberId, + final Long groupId, + final int size, + final Long capsuleId + ) { + return new GroupCapsuleSliceRequestDto(memberId, groupId, size, capsuleId); + } +} diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java index 90c01c9d7..7efb70699 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java @@ -10,6 +10,7 @@ import static site.timecapsulearchive.core.domain.member.entity.QMember.member; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -24,6 +25,7 @@ import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; import site.timecapsulearchive.core.domain.member.entity.QMember; @@ -177,4 +179,35 @@ public Long findGroupCapsuleCount(final Long groupId) { .where(capsule.group.id.eq(groupId)) .fetchOne(); } + + public Slice findGroupCapsuleSlice(final GroupCapsuleSliceRequestDto dto) { + final List groupCapsuleDtos = jpaQueryFactory + .select( + Projections.constructor( + CapsuleBasicInfoDto.class, + capsule.id, + capsuleSkin.imageUrl, + capsule.dueDate, + capsule.createdAt, + capsule.title, + capsule.isOpened, + capsule.type + ) + ) + .from(capsule) + .where(capsule.group.id.eq(dto.groupId()) + .and(capsuleIdPagingCursorCondition(dto.capsuleId()))) + .limit(dto.size() + 1) + .fetch(); + + return SliceUtil.makeSlice(dto.size(), groupCapsuleDtos); + } + + private BooleanExpression capsuleIdPagingCursorCondition(final Long capsuleId) { + if (capsuleId == null) { + return null; + } + + return capsule.id.lt(capsuleId); + } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java index 396e808a3..f3124102f 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java @@ -14,6 +14,7 @@ import site.timecapsulearchive.core.domain.capsule.generic_capsule.repository.CapsuleRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleCreateRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleOpenStateDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; @@ -119,5 +120,9 @@ public GroupCapsuleOpenStateDto openGroupCapsule(final Long memberId, final Long groupCapsule.open(); return GroupCapsuleOpenStateDto.opened(); } + + public Slice findGroupCapsuleSlice(final GroupCapsuleSliceRequestDto dto) { + return groupCapsuleQueryRepository.findGroupCapsuleSlice(dto); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java index 47f1036fa..ab77d69a4 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java @@ -22,6 +22,7 @@ import site.timecapsulearchive.core.common.fixture.domain.GroupFixture; import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.domain.MemberGroupFixture; +import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; import site.timecapsulearchive.core.domain.capsule.entity.CapsuleType; import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; @@ -29,7 +30,6 @@ import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; -import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.MyGroupCapsuleDto; import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; import site.timecapsulearchive.core.domain.group.entity.Group; @@ -187,7 +187,7 @@ void setup(@Autowired EntityManager entityManager) { ZonedDateTime now = ZonedDateTime.now().plusDays(1); //when - Slice groupCapsules = groupCapsuleQueryRepository.findMyGroupCapsuleSlice( + Slice groupCapsules = groupCapsuleQueryRepository.findMyGroupCapsuleSlice( groupLeaderId, size, now); //then From c3aaa3aa82e468eb036dd20227d9849d61cf10ab Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sat, 8 Jun 2024 19:36:38 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat=20:=20=EA=B7=B8=EB=A3=B9=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../capsule/group_capsule/api/GroupCapsuleApi.java | 5 +++++ .../group_capsule/service/GroupCapsuleService.java | 9 +++++++++ .../MemberGroupQueryRepository.java | 2 ++ .../MemberGroupQueryRepositoryImpl.java | 10 ++++++++++ 4 files changed, 26 insertions(+) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java index 3c2d9ec8a..4d4bfbafb 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java @@ -112,6 +112,11 @@ ResponseEntity> getGroupCapsuleSummaryByCap @ApiResponse( responseCode = "200", description = "처리 완료" + ), + @ApiResponse( + responseCode = "403", + description = "그룹에 대한 권한이 없는 경우 발생한다", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) ) }) ResponseEntity>> getGroupCapsules( diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java index f3124102f..461a9ded9 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java @@ -21,6 +21,8 @@ import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; import site.timecapsulearchive.core.domain.group.entity.Group; import site.timecapsulearchive.core.domain.member.entity.Member; +import site.timecapsulearchive.core.domain.member_group.exception.NoGroupAuthorityException; +import site.timecapsulearchive.core.domain.member_group.repository.member_group_repository.MemberGroupRepository; @Service @Transactional(readOnly = true) @@ -29,6 +31,7 @@ public class GroupCapsuleService { private final CapsuleRepository capsuleRepository; private final GroupCapsuleQueryRepository groupCapsuleQueryRepository; + private final MemberGroupRepository memberGroupRepository; @Transactional public Capsule saveGroupCapsule( @@ -122,6 +125,12 @@ public GroupCapsuleOpenStateDto openGroupCapsule(final Long memberId, final Long } public Slice findGroupCapsuleSlice(final GroupCapsuleSliceRequestDto dto) { + boolean isGroupMember = memberGroupRepository.existMemberGroupByMemberIdAndGroupId(dto.memberId(), + dto.groupId()); + if (!isGroupMember) { + throw new NoGroupAuthorityException(); + } + return groupCapsuleQueryRepository.findGroupCapsuleSlice(dto); } } 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 b11a3eade..c8aebdf57 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 @@ -20,4 +20,6 @@ public interface MemberGroupQueryRepository { Optional findGroupMembersCount(Long groupId); List findGroupMemberIdsByGroupId(final Long groupId); + + boolean existMemberGroupByMemberIdAndGroupId(Long memberId, 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 84eb64bfe..2f08ca343 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 @@ -110,4 +110,14 @@ public List findGroupMemberIdsByGroupId(final Long groupId) { .where(memberGroup.group.id.eq(groupId)) .fetch(); } + + @Override + public boolean existMemberGroupByMemberIdAndGroupId(Long memberId, Long groupId) { + final Integer count = jpaQueryFactory.selectOne() + .from(memberGroup) + .where(memberGroup.member.id.eq(memberId).and(memberGroup.group.id.eq(groupId))) + .fetchFirst(); + + return count != null; + } } From 36f62c96c0216b11b2bb0c7c09fbb83ba51b5265 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sat, 8 Jun 2024 19:51:23 +0900 Subject: [PATCH 4/8] =?UTF-8?q?fix=20:=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/capsule/group_capsule/api/GroupCapsuleApi.java | 2 +- .../group_capsule/api/GroupCapsuleApiController.java | 4 ++-- .../group_capsule/data/dto/GroupCapsuleSliceRequestDto.java | 6 +++--- .../repository/GroupCapsuleQueryRepository.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java index 4d4bfbafb..cd84a1cde 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java @@ -129,7 +129,7 @@ ResponseEntity>> getGroupCapsules( int size, @Parameter(in = ParameterIn.QUERY, description = "마지막 캡슐 아이디", required = true) - Long capsuleId + Long lastCapsuleId ); @Operation( diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java index 093ca6915..d001b2cb7 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java @@ -116,10 +116,10 @@ public ResponseEntity>> getGroupCapsules( @AuthenticationPrincipal final Long memberId, @RequestParam("group_id") final Long groupId, @RequestParam("size") final int size, - @RequestParam("capsuleId") final Long capsuleId + @RequestParam("last_capsule_id") final Long lastCapsuleId ) { final GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(memberId, groupId, - size, capsuleId); + size, lastCapsuleId); final Slice groupCapsuleSlice = groupCapsuleService.findGroupCapsuleSlice( dto); diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java index b6bcabb8b..5b61f89de 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleSliceRequestDto.java @@ -4,15 +4,15 @@ public record GroupCapsuleSliceRequestDto( Long memberId, Long groupId, int size, - Long capsuleId + Long lastCapsuleId ) { public static GroupCapsuleSliceRequestDto createOf( final Long memberId, final Long groupId, final int size, - final Long capsuleId + final Long lastCapsuleId ) { - return new GroupCapsuleSliceRequestDto(memberId, groupId, size, capsuleId); + return new GroupCapsuleSliceRequestDto(memberId, groupId, size, lastCapsuleId); } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java index 7efb70699..deda44822 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java @@ -196,7 +196,7 @@ public Slice findGroupCapsuleSlice(final GroupCapsuleSliceR ) .from(capsule) .where(capsule.group.id.eq(dto.groupId()) - .and(capsuleIdPagingCursorCondition(dto.capsuleId()))) + .and(capsuleIdPagingCursorCondition(dto.lastCapsuleId()))) .limit(dto.size() + 1) .fetch(); From e09db1c7d5fac0c4942e4e681831be77947d8146 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sat, 8 Jun 2024 20:19:34 +0900 Subject: [PATCH 5/8] =?UTF-8?q?fix=20:=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EC=8B=B1=20=EC=BF=BC=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - order by를 써 id가 역순으로 나오게 수정 --- .../group_capsule/repository/GroupCapsuleQueryRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java index deda44822..92f3b8b23 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepository.java @@ -197,6 +197,7 @@ public Slice findGroupCapsuleSlice(final GroupCapsuleSliceR .from(capsule) .where(capsule.group.id.eq(dto.groupId()) .and(capsuleIdPagingCursorCondition(dto.lastCapsuleId()))) + .orderBy(capsule.id.desc()) .limit(dto.size() + 1) .fetch(); From f13662a84d310e1f6950a3ecded355af53dd22a5 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sat, 8 Jun 2024 20:46:52 +0900 Subject: [PATCH 6/8] =?UTF-8?q?test=20:=20=EA=B7=B8=EB=A3=B9=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fixture/domain/CapsuleFixture.java | 16 +++- .../dto/CapsuleBasicInfoDtoFixture.java | 21 +++++ .../GroupCapsuleQueryRepositoryTest.java | 94 +++++++++++++++---- .../service/GroupCapsuleServiceTest.java | 75 +++++++++++++-- 4 files changed, 177 insertions(+), 29 deletions(-) create mode 100644 backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/CapsuleBasicInfoDtoFixture.java diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java index c9fdb0112..837de4c1a 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java @@ -1,8 +1,8 @@ package site.timecapsulearchive.core.common.fixture.domain; import java.lang.reflect.Field; -import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.IntStream; @@ -217,4 +217,18 @@ public static Optional groupCapsuleAlreadyOpen(Long memberId, Long caps return Optional.ofNullable(capsule); } + + public static List groupCapsules( + Member owner, + CapsuleSkin capsuleSkin, + Group group, + int maxCount + ) { + List result = new ArrayList<>(); + for (int count = 0; count < maxCount; count++) { + result.add(groupCapsule(owner, capsuleSkin, group)); + } + + return result; + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/CapsuleBasicInfoDtoFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/CapsuleBasicInfoDtoFixture.java new file mode 100644 index 000000000..ad15d3ef6 --- /dev/null +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/dto/CapsuleBasicInfoDtoFixture.java @@ -0,0 +1,21 @@ +package site.timecapsulearchive.core.common.fixture.dto; + +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; +import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; +import site.timecapsulearchive.core.domain.capsule.entity.CapsuleType; + +public class CapsuleBasicInfoDtoFixture { + + public static List capsuleBasicInfoDtos(Long capsuleId, int size) { + List result = new ArrayList<>(); + for (long count = capsuleId; count < size; count++) { + result.add(new CapsuleBasicInfoDto(count, count + "test-url", ZonedDateTime.now(), + ZonedDateTime.now(), count + "test-title", false, CapsuleType.GROUP)); + } + + return result; + } + +} diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java index ab77d69a4..044ea11d5 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java @@ -1,13 +1,13 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.repository; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import java.time.ZonedDateTime; import java.util.List; import java.util.Optional; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -29,6 +29,7 @@ import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; @@ -39,10 +40,12 @@ @TestConstructor(autowireMode = AutowireMode.ALL) class GroupCapsuleQueryRepositoryTest extends RepositoryTest { + private static final int MAX_COUNT = 20; private final GroupCapsuleQueryRepository groupCapsuleQueryRepository; private Long groupLeaderId; - private Long capsuleId; + private Long lastCapsuleId; + private Long groupId; private Capsule capsule; GroupCapsuleQueryRepositoryTest(JPAQueryFactory jpaQueryFactory) { @@ -65,20 +68,24 @@ void setup(@Autowired EntityManager entityManager) { //그룹 Group group = GroupFixture.group(); entityManager.persist(group); + groupId = group.getId(); //그룹 구성 List memberGroups = MemberGroupFixture.memberGroups(groupMember, group); memberGroups.forEach(entityManager::persist); //그룹 캡슐 - capsule = CapsuleFixture.groupCapsule(owner, capsuleSkin, group); - entityManager.persist(capsule); - capsuleId = capsule.getId(); - - //그룹 캡슐 오픈 여부 - List groupCapsuleOpens = GroupCapsuleOpenFixture.groupCapsuleOpens(false, - capsule, groupMember); - groupCapsuleOpens.forEach(entityManager::persist); + List capsules = CapsuleFixture.groupCapsules(owner, capsuleSkin, group, MAX_COUNT); + for (Capsule c : capsules) { + entityManager.persist(c); + + List groupCapsuleOpens = GroupCapsuleOpenFixture.groupCapsuleOpens( + false, + c, groupMember); + groupCapsuleOpens.forEach(entityManager::persist); + } + capsule = capsules.get(0); + lastCapsuleId = capsules.get(capsules.size() - 1).getId(); } @Test @@ -86,11 +93,11 @@ void setup(@Autowired EntityManager entityManager) { // given //when GroupCapsuleDetailDto groupCapsuleDetailDto = groupCapsuleQueryRepository.findGroupCapsuleDetailDtoByCapsuleId( - capsuleId).orElseThrow(); + capsule.getId()).orElseThrow(); CapsuleDetailDto capsuleDetailDto = groupCapsuleDetailDto.capsuleDetailDto(); //then - SoftAssertions.assertSoftly( + assertSoftly( softly -> { softly.assertThat(capsuleDetailDto).isNotNull(); softly.assertThat(capsuleDetailDto.capsuleType()).isEqualTo(capsule.getType()); @@ -106,11 +113,11 @@ void setup(@Autowired EntityManager entityManager) { //given //when GroupCapsuleDetailDto detailDto = groupCapsuleQueryRepository.findGroupCapsuleDetailDtoByCapsuleId( - capsuleId).orElseThrow(); + capsule.getId()).orElseThrow(); List summaryDto = detailDto.members(); //then - SoftAssertions.assertSoftly( + assertSoftly( softly -> { softly.assertThat(summaryDto).isNotEmpty(); softly.assertThat(summaryDto).allMatch(dto -> !dto.isOpened()); @@ -137,11 +144,11 @@ void setup(@Autowired EntityManager entityManager) { // given //when GroupCapsuleSummaryDto detailDto = groupCapsuleQueryRepository.findGroupCapsuleSummaryDtoByCapsuleId( - capsuleId).orElseThrow(); + capsule.getId()).orElseThrow(); CapsuleSummaryDto capsuleSummaryDto = detailDto.capsuleSummaryDto(); //then - SoftAssertions.assertSoftly( + assertSoftly( softly -> { softly.assertThat(capsuleSummaryDto).isNotNull(); softly.assertThat(capsuleSummaryDto.title()).isEqualTo(capsule.getTitle()); @@ -155,11 +162,11 @@ void setup(@Autowired EntityManager entityManager) { // given //when GroupCapsuleSummaryDto detailDto = groupCapsuleQueryRepository.findGroupCapsuleSummaryDtoByCapsuleId( - capsuleId).orElseThrow(); + capsule.getId()).orElseThrow(); List summaryDto = detailDto.members(); //then - SoftAssertions.assertSoftly( + assertSoftly( softly -> { softly.assertThat(summaryDto).isNotEmpty(); softly.assertThat(summaryDto).allMatch(dto -> !dto.isOpened()); @@ -191,11 +198,60 @@ void setup(@Autowired EntityManager entityManager) { groupLeaderId, size, now); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { assertThat(groupCapsules.hasContent()).isTrue(); assertThat(groupCapsules).allMatch( capsule -> capsule.capsuleType().equals(CapsuleType.GROUP)); assertThat(groupCapsules).allMatch(capsule -> capsule.createdAt().isBefore(now)); }); } + + @Test + void 사용자가_그룹_캡슐_목록을_조회하면_해당_그룹의_그룹캡슐이_나온다() { + //then + int size = 20; + GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(groupLeaderId, + groupId, size, lastCapsuleId); + + //when + Slice groupCapsuleSlice = groupCapsuleQueryRepository.findGroupCapsuleSlice( + dto); + + //then + assertSoftly(softly -> { + softly.assertThat(groupCapsuleSlice.hasContent()).isTrue(); + softly.assertThat(groupCapsuleSlice.getContent()).allMatch(c -> c.capsuleId() != null); + softly.assertThat(groupCapsuleSlice.getContent()) + .allMatch(c -> c.capsuleType().equals(CapsuleType.GROUP)); + softly.assertThat(groupCapsuleSlice.getContent()).allMatch(c -> c.isOpened() != null); + softly.assertThat(groupCapsuleSlice.getContent()).allMatch(c -> c.dueDate() != null); + softly.assertThat(groupCapsuleSlice.getContent()).allMatch(c -> c.createdAt() != null); + softly.assertThat(groupCapsuleSlice.getContent()) + .allMatch(c -> c.skinUrl() != null && !c.skinUrl().isBlank()); + softly.assertThat(groupCapsuleSlice.getContent()) + .allMatch(c -> c.title() != null && !c.title().isBlank()); + }); + } + + @Test + void 사용자가_그룹_캡슐_목록의_첫_페이지_이후_다음_페이지를_조회하면_다음_페이지의_그룹캡슐이_나온다() { + //then + int size = 10; + GroupCapsuleSliceRequestDto firstSliceDto = GroupCapsuleSliceRequestDto.createOf( + groupLeaderId, + groupId, size, null); + Slice firstGroupCapsuleSlice = groupCapsuleQueryRepository.findGroupCapsuleSlice( + firstSliceDto); + CapsuleBasicInfoDto capsuleBasicInfoDto = firstGroupCapsuleSlice.getContent() + .get(0); + + //when + GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(groupLeaderId, + groupId, size, capsuleBasicInfoDto.capsuleId()); + Slice groupCapsuleSlice = groupCapsuleQueryRepository.findGroupCapsuleSlice( + dto); + + //then + assertThat(groupCapsuleSlice.hasContent()).isTrue(); + } } \ No newline at end of file diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java index 31e5d2ca5..fe50a5f7c 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java @@ -1,7 +1,9 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.service; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.SoftAssertions.assertSoftly; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -11,9 +13,13 @@ import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Test; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; import site.timecapsulearchive.core.common.fixture.domain.CapsuleFixture; import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; +import site.timecapsulearchive.core.common.fixture.dto.CapsuleBasicInfoDtoFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleDtoFixture; +import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; import site.timecapsulearchive.core.domain.capsule.exception.CapsuleNotFondException; import site.timecapsulearchive.core.domain.capsule.exception.GroupCapsuleOpenNotFoundException; @@ -22,9 +28,12 @@ import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.CapsuleOpenStatus; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleOpenStateDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; import site.timecapsulearchive.core.domain.member.entity.Member; +import site.timecapsulearchive.core.domain.member_group.exception.NoGroupAuthorityException; +import site.timecapsulearchive.core.domain.member_group.repository.member_group_repository.MemberGroupRepository; import site.timecapsulearchive.core.global.error.ErrorCode; class GroupCapsuleServiceTest { @@ -36,9 +45,10 @@ class GroupCapsuleServiceTest { private final CapsuleRepository capsuleRepository = mock(CapsuleRepository.class); private final GroupCapsuleQueryRepository groupCapsuleQueryRepository = mock( GroupCapsuleQueryRepository.class); + private final MemberGroupRepository memberGroupRepository = mock(MemberGroupRepository.class); private final GroupCapsuleService groupCapsuleService = new GroupCapsuleService( - capsuleRepository, groupCapsuleQueryRepository); + capsuleRepository, groupCapsuleQueryRepository, memberGroupRepository); @Test void 개봉된_그룹_캡슐의_상세_내용을_볼_수_있다() { @@ -196,7 +206,8 @@ class GroupCapsuleServiceTest { @Test void 그룹_캡슐이_없는_경우_그룹_캡슐_개봉_시_예외가_발생한다() { //given - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(Optional.empty()); //when @@ -212,7 +223,8 @@ class GroupCapsuleServiceTest { ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")); Optional groupCapsule = CapsuleFixture.groupCapsuleSpecificTime(memberId, capsuleId, now.plusYears(5)); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -232,7 +244,8 @@ class GroupCapsuleServiceTest { //given Optional groupCapsule = CapsuleFixture.groupCapsuleSpecificTime(memberId, capsuleId, null); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -254,7 +267,8 @@ class GroupCapsuleServiceTest { Optional groupCapsule = CapsuleFixture.groupCapsuleNotAllMemberOpen(memberId, capsuleId, groupMembers); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -276,7 +290,8 @@ class GroupCapsuleServiceTest { Optional groupCapsule = CapsuleFixture.groupCapsuleHalfMemberOpen(memberId, capsuleId, groupMembers); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -295,7 +310,8 @@ class GroupCapsuleServiceTest { void 그룹_캡슐_개봉이_없는_경우_예외가_발생한다() { //given Optional groupCapsule = CapsuleFixture.groupCapsuleEmptyOpen(memberId, capsuleId); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -312,7 +328,8 @@ class GroupCapsuleServiceTest { Optional groupCapsule = CapsuleFixture.groupCapsuleAllMemberOpen(memberId, capsuleId, groupMembers); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -334,7 +351,8 @@ class GroupCapsuleServiceTest { Optional groupCapsule = CapsuleFixture.groupCapsuleExcludeSpecificMember(memberId, capsuleId, groupMembers); - given(capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + given( + capsuleRepository.findNotOpenedGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); //when @@ -348,4 +366,43 @@ class GroupCapsuleServiceTest { CapsuleOpenStatus.OPEN); }); } + + @Test + void 사용자가_그룹원이_아니면_그룹_캡슐_목록_조회_시_예외가_발생한다() { + //given + Long groupId = 1L; + int size = 20; + GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(memberId, groupId, + size, capsuleId); + given(memberGroupRepository.existMemberGroupByMemberIdAndGroupId(memberId, groupId)) + .willReturn(false); + + //when + //then + assertThatThrownBy(() -> groupCapsuleService.findGroupCapsuleSlice(dto)) + .isInstanceOf(NoGroupAuthorityException.class) + .hasMessageContaining(ErrorCode.NO_GROUP_AUTHORITY_ERROR.getMessage()); + } + + @Test + void 사용자가_그룹원이면_그룹_캡슐_목록_조회_시_그룹_캡슐_목록이_조회된다() { + //given + Long groupId = 1L; + int size = 20; + GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(memberId, groupId, + size, capsuleId); + given(memberGroupRepository.existMemberGroupByMemberIdAndGroupId(memberId, groupId)) + .willReturn(true); + given(groupCapsuleQueryRepository.findGroupCapsuleSlice( + any(GroupCapsuleSliceRequestDto.class))) + .willReturn( + new SliceImpl<>(CapsuleBasicInfoDtoFixture.capsuleBasicInfoDtos(capsuleId, size))); + + //when + Slice groupCapsuleSlice = groupCapsuleService.findGroupCapsuleSlice( + dto); + + //then + assertThat(groupCapsuleSlice.hasContent()).isTrue(); + } } From 72657010c2f558358d6fa23327021e6ff829c540 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Sun, 9 Jun 2024 15:06:12 +0900 Subject: [PATCH 7/8] =?UTF-8?q?fix=20:=20=EC=9D=91=EB=8B=B5=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - slice를 wrapping하는 응답 객체 수정 --- .../group_capsule/api/GroupCapsuleApi.java | 5 ++-- .../api/GroupCapsuleApiController.java | 14 ++++++--- .../response/GroupCapsuleSliceResponse.java | 30 +++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleSliceResponse.java diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java index cd84a1cde..1c22c4317 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java @@ -11,17 +11,16 @@ import jakarta.validation.Valid; import java.time.ZonedDateTime; import org.hibernate.validator.constraints.Range; -import org.springframework.data.domain.Slice; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; -import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleCreateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleUpdateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleDetailResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleOpenStateResponse; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSliceResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSummaryResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.MyGroupCapsuleSliceResponse; import site.timecapsulearchive.core.global.common.response.ApiSpec; @@ -119,7 +118,7 @@ ResponseEntity> getGroupCapsuleSummaryByCap content = @Content(schema = @Schema(implementation = ErrorResponse.class)) ) }) - ResponseEntity>> getGroupCapsules( + ResponseEntity> getGroupCapsules( Long memberId, @Parameter(in = ParameterIn.QUERY, description = "그룹 아이디", required = true) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java index d001b2cb7..1467541c2 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java @@ -22,6 +22,7 @@ import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleUpdateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleDetailResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleOpenStateResponse; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSliceResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSummaryResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.MyGroupCapsuleSliceResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.facade.GroupCapsuleFacade; @@ -112,13 +113,14 @@ public ResponseEntity> getGroupCapsuleSumma produces = {"application/json"} ) @Override - public ResponseEntity>> getGroupCapsules( + public ResponseEntity> getGroupCapsules( @AuthenticationPrincipal final Long memberId, @RequestParam("group_id") final Long groupId, @RequestParam("size") final int size, - @RequestParam("last_capsule_id") final Long lastCapsuleId + @RequestParam(value = "last_capsule_id", required = false) final Long lastCapsuleId ) { - final GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(memberId, groupId, + final GroupCapsuleSliceRequestDto dto = GroupCapsuleSliceRequestDto.createOf(memberId, + groupId, size, lastCapsuleId); final Slice groupCapsuleSlice = groupCapsuleService.findGroupCapsuleSlice( @@ -127,7 +129,11 @@ public ResponseEntity>> getGroupCapsules( return ResponseEntity.ok( ApiSpec.success( SuccessCode.SUCCESS, - groupCapsuleSlice + GroupCapsuleSliceResponse.create( + groupCapsuleSlice.getContent(), + groupCapsuleSlice.hasNext(), + s3PreSignedUrlManager::getS3PreSignedUrlForGet + ) ) ); } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleSliceResponse.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleSliceResponse.java new file mode 100644 index 000000000..fc80eaa90 --- /dev/null +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleSliceResponse.java @@ -0,0 +1,30 @@ +package site.timecapsulearchive.core.domain.capsule.group_capsule.data.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; +import java.util.function.UnaryOperator; +import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; +import site.timecapsulearchive.core.domain.capsule.data.response.CapsuleBasicInfoResponse; + +@Schema(description = "그룹 캡슐 목록 응답") +public record GroupCapsuleSliceResponse( + + @Schema(description = "캡슐 기본 정보 목록") + List capsuleBasicInfos, + + @Schema(description = "다음 페이지 유무") + boolean hasNext +) { + + public static GroupCapsuleSliceResponse create( + final List dtos, + final boolean hasNext, + final UnaryOperator preSignUrlFunction + ) { + List capsuleBasicInfoResponses = dtos.stream() + .map(dto -> dto.toResponse(preSignUrlFunction)) + .toList(); + + return new GroupCapsuleSliceResponse(capsuleBasicInfoResponses, hasNext); + } +} From c8944f85fce7c4d6bfbcfc5f417e572ed5b03a27 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Tue, 11 Jun 2024 23:18:23 +0900 Subject: [PATCH 8/8] =?UTF-8?q?fix=20:=20=EB=A8=B8=EC=A7=80=20=EC=B6=A9?= =?UTF-8?q?=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/capsule/group_capsule/api/GroupCapsuleApi.java | 1 + .../capsule/group_capsule/api/GroupCapsuleApiController.java | 1 - .../capsule/group_capsule/service/GroupCapsuleService.java | 2 ++ .../core/common/fixture/domain/CapsuleFixture.java | 1 + .../repository/GroupCapsuleQueryRepositoryTest.java | 1 + .../capsule/group_capsule/service/GroupCapsuleServiceTest.java | 2 ++ 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java index 10b481aca..4ea78b58d 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApi.java @@ -22,6 +22,7 @@ import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleOpenStateResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSliceResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleSummaryResponse; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupMemberCapsuleOpenStatusListResponse; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.MyGroupCapsuleSliceResponse; import site.timecapsulearchive.core.global.common.response.ApiSpec; import site.timecapsulearchive.core.global.error.ErrorResponse; diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java index 3e86dcfac..f2d701514 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/api/GroupCapsuleApiController.java @@ -20,7 +20,6 @@ import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupMemberCapsuleOpenStatusDto; -import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.MyGroupCapsuleDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleCreateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.reqeust.GroupCapsuleUpdateRequest; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleDetailResponse; diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java index 825396413..23bb7f30a 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleService.java @@ -2,6 +2,7 @@ import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.util.List; import lombok.RequiredArgsConstructor; import org.locationtech.jts.geom.Point; import org.springframework.data.domain.Slice; @@ -17,6 +18,7 @@ import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSummaryDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleOpenStateDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupMemberCapsuleOpenStatusDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenQueryRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java index 3519e6eb8..f2ea71594 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/CapsuleFixture.java @@ -2,6 +2,7 @@ import java.lang.reflect.Field; import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.IntStream; diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java index 6ced89814..94f0a09ae 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleQueryRepositoryTest.java @@ -80,6 +80,7 @@ void setup(@Autowired EntityManager entityManager) { entityManager.persist(c); List groupCapsuleOpens = GroupCapsuleOpenFixture.groupCapsuleOpens( + group, false, c, groupMember); groupCapsuleOpens.forEach(entityManager::persist); diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java index 76a4ad71c..bead22b6f 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/service/GroupCapsuleServiceTest.java @@ -19,6 +19,7 @@ import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleBasicInfoDtoFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleDtoFixture; +import site.timecapsulearchive.core.common.fixture.dto.GroupMemberCapsuleOpenStatusDtoFixture; import site.timecapsulearchive.core.domain.capsule.data.dto.CapsuleBasicInfoDto; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; import site.timecapsulearchive.core.domain.capsule.exception.CapsuleNotFondException; @@ -28,6 +29,7 @@ import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.CapsuleOpenStatus; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleOpenStateDto; +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupMemberCapsuleOpenStatusDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenQueryRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleSliceRequestDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository;