From 6bfdb4e787f73200f87b25b5d3797d3144142b06 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 14:26:17 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat=20:=20=EA=B7=B8=EB=A3=B9=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=20=EC=A1=B0=ED=9A=8C,=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=BA=A1=EC=8A=90=20=EA=B0=9C=EB=B4=89=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=BF=BC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/CapsuleRepository.java | 9 +++++++++ .../GroupCapsuleOpenQueryRepository.java | 16 +++------------- .../repository/GroupCapsuleOpenRepository.java | 3 +++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/generic_capsule/repository/CapsuleRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/generic_capsule/repository/CapsuleRepository.java index 03908bba4..f50bfd7ef 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/generic_capsule/repository/CapsuleRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/generic_capsule/repository/CapsuleRepository.java @@ -23,4 +23,13 @@ int updateIsOpenedTrue( @Param("memberId") Long memberId, @Param("capsuleId") Long capsuleId ); + + @Query("select c " + + "from Capsule c" + + " where c.id = :capsuleId and c.member.id = :memberId " + + "and c.type = 'GROUP' and c.group.id is not null") + Optional findGroupCapsuleByMemberIdAndCapsuleId( + @Param("memberId") Long memberId, + @Param("capsuleId") Long capsuleId + ); } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepository.java index d6e6d03f2..218d84b9b 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepository.java @@ -1,8 +1,5 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.repository; -import static site.timecapsulearchive.core.domain.capsule.entity.QGroupCapsuleOpen.groupCapsuleOpen; - -import com.querydsl.jpa.impl.JPAQueryFactory; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; @@ -20,7 +17,6 @@ public class GroupCapsuleOpenQueryRepository { private final JdbcTemplate jdbcTemplate; - private final JPAQueryFactory jpaQueryFactory; public void bulkSave(final List groupMemberIds, final Capsule capsule) { jdbcTemplate.batchUpdate( @@ -32,8 +28,10 @@ INSERT INTO group_capsule_open ( new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { + boolean isOpened = capsule.getDueDate() == null; + ps.setNull(1, Types.BIGINT); - ps.setBoolean(2, false); + ps.setBoolean(2, isOpened); ps.setLong(3, groupMemberIds.get(i)); ps.setLong(4, capsule.getId()); ps.setTimestamp(5, Timestamp.valueOf(ZonedDateTime.now().toLocalDateTime())); @@ -47,12 +45,4 @@ public int getBatchSize() { } ); } - - public List findIsOpenedByCapsuleId(final Long capsuleId) { - return jpaQueryFactory - .select(groupCapsuleOpen.isOpened) - .from(groupCapsuleOpen) - .where(groupCapsuleOpen.capsule.id.eq(capsuleId)) - .fetch(); - } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenRepository.java index ce02c9eee..4450d78bb 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenRepository.java @@ -1,5 +1,6 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.repository; +import java.util.List; import java.util.Optional; import org.springframework.data.repository.Repository; import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; @@ -9,4 +10,6 @@ public interface GroupCapsuleOpenRepository extends Repository findByMemberIdAndCapsuleId(Long memberId, Long capsuleId); + + List findByCapsuleId(Long capsuleId); } From 29ccb7d88d8fb792679a5d65fcef2a485a2e9027 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 14:44:13 +0900 Subject: [PATCH 2/9] =?UTF-8?q?fix=20:=20=EA=B7=B8=EB=A3=B9=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=20=EA=B0=9C=EB=B4=89=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/capsule/entity/Capsule.java | 4 +++ .../capsule/entity/GroupCapsuleOpen.java | 4 +++ .../service/GroupCapsuleService.java | 31 +++++++++++++------ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java index feab13c7b..e220714b1 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java @@ -111,4 +111,8 @@ public boolean isNotCapsuleOpened() { return dueDate.isAfter(ZonedDateTime.now()); } + + public void open() { + this.isOpened = Boolean.TRUE; + } } \ No newline at end of file diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/GroupCapsuleOpen.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/GroupCapsuleOpen.java index d1e94f550..809d9dc64 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/GroupCapsuleOpen.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/GroupCapsuleOpen.java @@ -53,4 +53,8 @@ public static GroupCapsuleOpen createOf(Member member, Capsule capsule, Boolean public void open() { this.isOpened = Boolean.TRUE; } + + public boolean matched(Long capsuleId, Long memberId) { + return capsule.getId().equals(capsuleId) && member.getId().equals(memberId); + } } 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 d40189ad3..4ed4d368f 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 @@ -33,7 +33,6 @@ public class GroupCapsuleService { private final CapsuleRepository capsuleRepository; private final GroupCapsuleQueryRepository groupCapsuleQueryRepository; private final GroupCapsuleOpenRepository groupCapsuleOpenRepository; - private final GroupCapsuleOpenQueryRepository groupCapsuleOpenQueryRepository; @Transactional public Capsule saveGroupCapsule( @@ -104,19 +103,31 @@ public Slice findMyGroupCapsuleSlice( */ @Transactional public void openGroupCapsule(final Long memberId, final Long capsuleId) { - GroupCapsuleOpen groupCapsuleOpen = groupCapsuleOpenRepository.findByMemberIdAndCapsuleId( - memberId, - capsuleId) - .orElseThrow(GroupCapsuleOpenNotFoundException::new); - groupCapsuleOpen.open(); + Capsule groupCapsule = capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(memberId, capsuleId) + .orElseThrow(CapsuleNotFondException::new); + + if (groupCapsule.getDueDate() == null) { + groupCapsule.open(); + return; + } - List capsuleOpens = groupCapsuleOpenQueryRepository.findIsOpenedByCapsuleId( + List groupCapsuleOpens = groupCapsuleOpenRepository.findByCapsuleId( capsuleId); + if (groupCapsuleOpens.isEmpty()) { + throw new GroupCapsuleOpenNotFoundException(); + } + + boolean allGroupMemberOpened = groupCapsuleOpens.stream() + .allMatch(groupCapsuleOpen -> { + if (groupCapsuleOpen.matched(capsuleId, memberId)) { + groupCapsuleOpen.open(); + } + + return groupCapsuleOpen.getIsOpened(); + }); - boolean allGroupMemberOpened = capsuleOpens.stream() - .allMatch(isOpened -> isOpened.equals(Boolean.TRUE)); if (allGroupMemberOpened) { - capsuleRepository.updateIsOpenedTrue(memberId, capsuleId); + groupCapsule.open(); } } } From 06bf21ac74ac11951b9897876f74cf5c0015c3e5 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 14:44:21 +0900 Subject: [PATCH 3/9] =?UTF-8?q?test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=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 | 24 ++++ .../domain/GroupCapsuleOpenFixture.java | 18 +++ .../GroupCapsuleOpenQueryRepositoryTest.java | 4 +- .../service/GroupCapsuleServiceTest.java | 112 ++++++++++++++---- 4 files changed, 133 insertions(+), 25 deletions(-) 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 386ed7a1e..1c07fff4e 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,5 +1,6 @@ package site.timecapsulearchive.core.common.fixture.domain; +import java.lang.reflect.Field; import java.time.ZonedDateTime; import java.util.List; import java.util.stream.IntStream; @@ -91,4 +92,27 @@ public static Capsule groupCapsule(Member member, CapsuleSkin capsuleSkin, Group .group(group) .build(); } + + public static Capsule groupCapsuleWithCapsuleId( + Member member, + CapsuleSkin capsuleSkin, + Group group, + Long capsuleId + ) { + try { + Capsule capsule = groupCapsule(member, capsuleSkin, group); + + setFieldValue(capsule, "id", capsuleId); + return capsule; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void setFieldValue(Object instance, String fieldName, Object value) + throws NoSuchFieldException, IllegalAccessException { + Field field = instance.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(instance, value); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java index 795913fd7..7b0c0c6bc 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupCapsuleOpenFixture.java @@ -1,7 +1,10 @@ package site.timecapsulearchive.core.common.fixture.domain; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.stream.Stream; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; import site.timecapsulearchive.core.domain.capsule.entity.CapsuleType; import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; @@ -33,4 +36,19 @@ public static Optional groupCapsuleOpen(int dataPrefix) { ) ); } + + public static List groupCapsuleOpensNotAllOpened( + Capsule capsule, + List groupMembers + ) { + int mid = groupMembers.size() / 2; + List opened = groupCapsuleOpens(true, capsule, + groupMembers.subList(0, mid)); + List notOpened = groupCapsuleOpens(false, capsule, + groupMembers.subList(mid, groupMembers.size() - 1)); + + return Stream.of(opened, notOpened) + .flatMap(Collection::stream) + .toList(); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java index e7f245f2d..4a9c6c10d 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/group_capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java @@ -37,13 +37,11 @@ class GroupCapsuleOpenQueryRepositoryTest extends RepositoryTest { private List groupCapsuleOpens; public GroupCapsuleOpenQueryRepositoryTest( - JPAQueryFactory jpaQueryFactory, JdbcTemplate jdbcTemplate, DataSource dataSource ) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - this.groupCapsuleOpenRepository = new GroupCapsuleOpenQueryRepository(jdbcTemplate, - jpaQueryFactory); + this.groupCapsuleOpenRepository = new GroupCapsuleOpenQueryRepository(jdbcTemplate); } @Transactional 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 c6caa072a..20a6ffb87 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,28 +1,34 @@ 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.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import java.time.ZonedDateTime; +import java.util.Collections; import java.util.List; import java.util.Optional; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; +import site.timecapsulearchive.core.common.fixture.domain.CapsuleFixture; +import site.timecapsulearchive.core.common.fixture.domain.CapsuleSkinFixture; import site.timecapsulearchive.core.common.fixture.domain.GroupCapsuleOpenFixture; +import site.timecapsulearchive.core.common.fixture.domain.GroupFixture; +import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleDtoFixture; +import site.timecapsulearchive.core.domain.capsule.entity.Capsule; +import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; +import site.timecapsulearchive.core.domain.capsule.exception.CapsuleNotFondException; import site.timecapsulearchive.core.domain.capsule.exception.GroupCapsuleOpenNotFoundException; import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.generic_capsule.repository.CapsuleRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.GroupCapsuleDetailDto; -import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenQueryRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenRepository; 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.global.error.ErrorCode; class GroupCapsuleServiceTest { @@ -35,13 +41,9 @@ class GroupCapsuleServiceTest { GroupCapsuleQueryRepository.class); private final GroupCapsuleOpenRepository groupCapsuleOpenRepository = mock( GroupCapsuleOpenRepository.class); - private final GroupCapsuleOpenQueryRepository groupCapsuleOpenQueryRepository = mock( - GroupCapsuleOpenQueryRepository.class); private final GroupCapsuleService groupCapsuleService = new GroupCapsuleService( - capsuleRepository, groupCapsuleQueryRepository, groupCapsuleOpenRepository, - groupCapsuleOpenQueryRepository - ); + capsuleRepository, groupCapsuleQueryRepository, groupCapsuleOpenRepository); @Test void 개봉된_그룹_캡슐의_상세_내용을_볼_수_있다() { @@ -201,14 +203,14 @@ class GroupCapsuleServiceTest { //given Long memberId = 1L; Long capsuleId = 1L; - given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(Optional.empty()); //when //then assertThatThrownBy(() -> groupCapsuleService.openGroupCapsule(memberId, capsuleId)) - .isInstanceOf(GroupCapsuleOpenNotFoundException.class) - .hasMessageContaining(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR.getMessage()); + .isInstanceOf(CapsuleNotFondException.class) + .hasMessageContaining(ErrorCode.CAPSULE_NOT_FOUND_ERROR.getMessage()); } @Test @@ -216,17 +218,35 @@ class GroupCapsuleServiceTest { //given Long memberId = 1L; Long capsuleId = 1L; - given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) - .willReturn(GroupCapsuleOpenFixture.groupCapsuleOpen(memberId.intValue())); - given(groupCapsuleOpenQueryRepository.findIsOpenedByCapsuleId(anyLong())) - .willReturn(List.of(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE)); + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpens(false, groupCapsule.get(), groupMembers) + ); //when groupCapsuleService.openGroupCapsule(memberId, capsuleId); //then - verifyNoInteractions(capsuleRepository); + assertThat(groupCapsule.get().getIsOpened()).isFalse(); + } + + private Optional getGroupCapsule(Long memberId, Long capsuleId) { + Member member = MemberFixture.memberWithMemberId(memberId); + + return Optional.ofNullable( + CapsuleFixture.groupCapsuleWithCapsuleId( + member, + CapsuleSkinFixture.capsuleSkin(member), + GroupFixture.group(), + capsuleId + ) + ); } @Test @@ -234,15 +254,63 @@ class GroupCapsuleServiceTest { //given Long memberId = 1L; Long capsuleId = 1L; - given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) - .willReturn(GroupCapsuleOpenFixture.groupCapsuleOpen(memberId.intValue())); - given(groupCapsuleOpenQueryRepository.findIsOpenedByCapsuleId(anyLong())) - .willReturn(List.of(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)); + + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpens(true, groupCapsule.get(), groupMembers) + ); //when groupCapsuleService.openGroupCapsule(memberId, capsuleId); //then - verify(capsuleRepository, times(1)).updateIsOpenedTrue(anyLong(), anyLong()); + assertThat(groupCapsule.get().getIsOpened()).isTrue(); + } + + @Test + void 일부_그룹원이_캡슐을_개봉한_경우_캡슐은_개봉되지_않는다() { + //given + Long memberId = 1L; + Long capsuleId = 1L; + + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpensNotAllOpened(groupCapsule.get(), groupMembers) + ); + + //when + groupCapsuleService.openGroupCapsule(memberId, capsuleId); + + //then + assertThat(groupCapsule.get().getIsOpened()).isFalse(); + } + + @Test + void 모든_그룹원이_캡슐을_개봉이_없는_경우_예외가_발생한다() { + //given + Long memberId = 1L; + Long capsuleId = 1L; + + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)).willReturn( + Collections.emptyList()); + + //when + //then + assertThatThrownBy(() -> groupCapsuleService.openGroupCapsule(memberId, capsuleId)) + .isInstanceOf(GroupCapsuleOpenNotFoundException.class) + .hasMessageContaining(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR.getMessage()); } } From 0127f95d04cf51da5b26cdea7b61fdee0ff512e9 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 19:37:49 +0900 Subject: [PATCH 4/9] =?UTF-8?q?fix=20:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 객체가 직접 판단하도록 함수 이동 --- .../core/domain/capsule/entity/Capsule.java | 4 ++++ .../capsule/group_capsule/service/GroupCapsuleService.java | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java index e220714b1..094d43ace 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java @@ -115,4 +115,8 @@ public boolean isNotCapsuleOpened() { public void open() { this.isOpened = Boolean.TRUE; } + + public boolean isTimeCapsule() { + return dueDate != null; + } } \ No newline at end of file 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 4ed4d368f..d41693ff4 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 @@ -18,7 +18,6 @@ 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.capsule.group_capsule.repository.GroupCapsuleOpenQueryRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; @@ -106,7 +105,7 @@ public void openGroupCapsule(final Long memberId, final Long capsuleId) { Capsule groupCapsule = capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(memberId, capsuleId) .orElseThrow(CapsuleNotFondException::new); - if (groupCapsule.getDueDate() == null) { + if (!groupCapsule.isTimeCapsule()) { groupCapsule.open(); return; } From 2c5355e1c457dea45490d88b8cd46214e5a88235 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 21:07:24 +0900 Subject: [PATCH 5/9] =?UTF-8?q?fix=20:=20=EA=B0=9C=EB=B4=89=EC=9D=BC?= =?UTF-8?q?=EC=9D=B4=20=EC=95=88=EB=90=9C=20=EC=BA=A1=EC=8A=90=20=EC=97=B4?= =?UTF-8?q?=EC=A7=80=20=EB=AA=BB=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/capsule/entity/Capsule.java | 7 ++++- .../group_capsule/api/GroupCapsuleApi.java | 3 ++- .../api/GroupCapsuleApiController.java | 14 +++++++--- .../data/dto/CapsuleOpenStatus.java | 14 ++++++++++ .../data/dto/GroupCapsuleOpenStateDto.java | 23 ++++++++++++++++ .../GroupCapsuleOpenStateResponse.java | 10 +++++++ .../service/GroupCapsuleService.java | 27 +++++++++++++------ .../core/global/error/ErrorCode.java | 1 + 8 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/CapsuleOpenStatus.java create mode 100644 backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleOpenStateDto.java create mode 100644 backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleOpenStateResponse.java diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java index 094d43ace..0325fd7ba 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java @@ -14,6 +14,7 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.List; import lombok.AccessLevel; @@ -109,7 +110,7 @@ public boolean isNotCapsuleOpened() { return false; } - return dueDate.isAfter(ZonedDateTime.now()); + return dueDate.isAfter(ZonedDateTime.now(ZoneId.of("UTC"))); } public void open() { @@ -119,4 +120,8 @@ public void open() { public boolean isTimeCapsule() { return dueDate != null; } + + public boolean canOpen() { + return dueDate == null || dueDate.isBefore(ZonedDateTime.now(ZoneId.of("UTC"))); + } } \ No newline at end of file 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 7a5371a4f..06fb9b364 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.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; @@ -172,7 +173,7 @@ ResponseEntity> getMyGroupCapsules( content = @Content(schema = @Schema(implementation = ErrorResponse.class)) ) }) - ResponseEntity> openCapsule( + ResponseEntity> openCapsule( Long memberId, @Parameter(in = ParameterIn.PATH, 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 9b6089e3a..63f19c19a 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 @@ -14,11 +14,13 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; 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.GroupCapsuleSummaryDto; 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; +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; @@ -139,13 +141,19 @@ public ResponseEntity> getMyGroupCapsules( @PostMapping("/{capsule_id}/open") @Override - public ResponseEntity> openCapsule( + public ResponseEntity> openCapsule( @AuthenticationPrincipal final Long memberId, @PathVariable(value = "capsule_id") final Long capsuleId ) { - groupCapsuleService.openGroupCapsule(memberId, capsuleId); + GroupCapsuleOpenStateDto groupCapsuleOpenStateDto = groupCapsuleService.openGroupCapsule( + memberId, capsuleId); - return ResponseEntity.ok(ApiSpec.empty(SuccessCode.SUCCESS)); + return ResponseEntity.ok( + ApiSpec.success( + SuccessCode.SUCCESS, + groupCapsuleOpenStateDto.toResponse() + ) + ); } @Override diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/CapsuleOpenStatus.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/CapsuleOpenStatus.java new file mode 100644 index 000000000..750a8fb14 --- /dev/null +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/CapsuleOpenStatus.java @@ -0,0 +1,14 @@ +package site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto; + +import lombok.Getter; + +@Getter +public enum CapsuleOpenStatus { + OPEN("캡슐이 개봉되었습니다."), NOT_OPEN("캡슐이 개봉되지 않았습니다."); + + private final String statusMessage; + + CapsuleOpenStatus(String statusMessage) { + this.statusMessage = statusMessage; + } +} diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleOpenStateDto.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleOpenStateDto.java new file mode 100644 index 000000000..56fd18e2a --- /dev/null +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/dto/GroupCapsuleOpenStateDto.java @@ -0,0 +1,23 @@ +package site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto; + +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.response.GroupCapsuleOpenStateResponse; + +public record GroupCapsuleOpenStateDto( + CapsuleOpenStatus capsuleOpenStatus +) { + + public static GroupCapsuleOpenStateDto opened() { + return new GroupCapsuleOpenStateDto(CapsuleOpenStatus.OPEN); + } + + public static GroupCapsuleOpenStateDto notOpened() { + return new GroupCapsuleOpenStateDto(CapsuleOpenStatus.NOT_OPEN); + } + + public GroupCapsuleOpenStateResponse toResponse() { + return new GroupCapsuleOpenStateResponse( + capsuleOpenStatus, + capsuleOpenStatus.getStatusMessage() + ); + } +} diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleOpenStateResponse.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleOpenStateResponse.java new file mode 100644 index 000000000..e77ec5c3a --- /dev/null +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/group_capsule/data/response/GroupCapsuleOpenStateResponse.java @@ -0,0 +1,10 @@ +package site.timecapsulearchive.core.domain.capsule.group_capsule.data.response; + +import site.timecapsulearchive.core.domain.capsule.group_capsule.data.dto.CapsuleOpenStatus; + +public record GroupCapsuleOpenStateResponse( + CapsuleOpenStatus capsuleOpenStatus, + String statusMessage +) { + +} 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 d41693ff4..7ed593728 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 @@ -18,6 +18,7 @@ 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.capsule.group_capsule.data.dto.GroupCapsuleOpenStateDto; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleOpenRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; @@ -101,22 +102,36 @@ public Slice findMyGroupCapsuleSlice( * @param capsuleId 개봉할 캡슐 아이디 */ @Transactional - public void openGroupCapsule(final Long memberId, final Long capsuleId) { - Capsule groupCapsule = capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(memberId, capsuleId) + public GroupCapsuleOpenStateDto openGroupCapsule(final Long memberId, final Long capsuleId) { + Capsule groupCapsule = capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(memberId, + capsuleId) .orElseThrow(CapsuleNotFondException::new); + if (!groupCapsule.canOpen()) { + return GroupCapsuleOpenStateDto.notOpened(); + } + if (!groupCapsule.isTimeCapsule()) { groupCapsule.open(); - return; + return GroupCapsuleOpenStateDto.opened(); + } + + boolean allGroupMemberOpened = isAllGroupMemberOpened(memberId, capsuleId); + if (allGroupMemberOpened) { + groupCapsule.open(); } + return GroupCapsuleOpenStateDto.opened(); + } + + private boolean isAllGroupMemberOpened(Long memberId, Long capsuleId) { List groupCapsuleOpens = groupCapsuleOpenRepository.findByCapsuleId( capsuleId); if (groupCapsuleOpens.isEmpty()) { throw new GroupCapsuleOpenNotFoundException(); } - boolean allGroupMemberOpened = groupCapsuleOpens.stream() + return groupCapsuleOpens.stream() .allMatch(groupCapsuleOpen -> { if (groupCapsuleOpen.matched(capsuleId, memberId)) { groupCapsuleOpen.open(); @@ -124,10 +139,6 @@ public void openGroupCapsule(final Long memberId, final Long capsuleId) { return groupCapsuleOpen.getIsOpened(); }); - - if (allGroupMemberOpened) { - groupCapsule.open(); - } } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/global/error/ErrorCode.java b/backend/core/src/main/java/site/timecapsulearchive/core/global/error/ErrorCode.java index f29833617..f4ef1f2ca 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/global/error/ErrorCode.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/global/error/ErrorCode.java @@ -57,6 +57,7 @@ public enum ErrorCode { CAPSULE_NOT_FOUND_ERROR(404, "CAPSULE-001", "캡슐을 찾지 못하였습니다."), NO_CAPSULE_AUTHORITY_ERROR(403, "CAPSULE-002", "캡슐에 접근 권한이 없습니다."), GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR(404, "CAPSULE-003", "그룹 캡슐 개봉상태를 찾을 수 없습니다."), + CAPSULE_OPEN_STATE_ERROR(400, "CAPSULE-004", "캡슐을 개봉할 수 없는 상태입니다."), //friend FRIEND_NOT_FOUND_ERROR(404, "FRIEND-001", "친구를 찾지 못하였습니다"), From 248e9d005cd37c6acd07a10371b29be2ca8a1ed4 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 21:07:32 +0900 Subject: [PATCH 6/9] =?UTF-8?q?test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=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 | 27 ++++ .../service/GroupCapsuleServiceTest.java | 150 +++++++++++++----- 2 files changed, 133 insertions(+), 44 deletions(-) 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 1c07fff4e..83f029ad3 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 @@ -115,4 +115,31 @@ private static void setFieldValue(Object instance, String fieldName, Object valu field.setAccessible(true); field.set(instance, value); } + + public static Capsule notGroupTimeCapsuleWithCapsuleId( + Member member, + CapsuleSkin capsuleSkin, + Group group, + Long capsuleId, + ZonedDateTime now + ) { + Capsule capsule = Capsule.builder() + .dueDate(now) + .title("testTitle") + .content("testContent") + .type(CapsuleType.GROUP) + .address(getTestAddress()) + .point(geoTransformManager.changePoint4326To3857(TEST_LATITUDE, TEST_LONGITUDE)) + .member(member) + .capsuleSkin(capsuleSkin) + .group(group) + .build(); + + try { + setFieldValue(capsule, "id", capsuleId); + return capsule; + } catch (Exception e) { + throw new RuntimeException(e); + } + } } 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 20a6ffb87..bb8b5333f 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,16 +1,16 @@ 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.anyLong; 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.Optional; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import site.timecapsulearchive.core.common.fixture.domain.CapsuleFixture; import site.timecapsulearchive.core.common.fixture.domain.CapsuleSkinFixture; @@ -19,12 +19,13 @@ import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleDtoFixture; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; -import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; import site.timecapsulearchive.core.domain.capsule.exception.CapsuleNotFondException; import site.timecapsulearchive.core.domain.capsule.exception.GroupCapsuleOpenNotFoundException; import site.timecapsulearchive.core.domain.capsule.generic_capsule.data.dto.CapsuleDetailDto; import site.timecapsulearchive.core.domain.capsule.generic_capsule.repository.CapsuleRepository; +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.repository.GroupCapsuleOpenRepository; import site.timecapsulearchive.core.domain.capsule.group_capsule.repository.GroupCapsuleQueryRepository; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; @@ -34,6 +35,7 @@ class GroupCapsuleServiceTest { private final Long capsuleId = 1L; + private final Long memberId = 1L; private final int groupMemberCount = 3; private final CapsuleRepository capsuleRepository = mock(CapsuleRepository.class); @@ -58,7 +60,7 @@ class GroupCapsuleServiceTest { capsuleId); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); List members = response.members(); softly.assertThat(response).isNotNull(); @@ -84,7 +86,7 @@ class GroupCapsuleServiceTest { capsuleId); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); List members = response.members(); softly.assertThat(response).isNotNull(); @@ -110,7 +112,7 @@ class GroupCapsuleServiceTest { capsuleId); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); List members = response.members(); softly.assertThat(response).isNotNull(); @@ -137,7 +139,7 @@ class GroupCapsuleServiceTest { capsuleId); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); List members = response.members(); softly.assertThat(response).isNotNull(); @@ -162,7 +164,7 @@ class GroupCapsuleServiceTest { capsuleId); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); List members = response.members(); softly.assertThat(response).isNotNull(); @@ -187,7 +189,7 @@ class GroupCapsuleServiceTest { capsuleId); //then - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); List members = response.members(); softly.assertThat(response).isNotNull(); @@ -199,10 +201,8 @@ class GroupCapsuleServiceTest { } @Test - void 그룹_캡슐_개봉이_없는_캡슐을_개봉하려는_경우_예외가_발생한다() { + void 그룹_캡슐이_없는_경우_그룹_캡슐_개봉_시_예외가_발생한다() { //given - Long memberId = 1L; - Long capsuleId = 1L; given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(Optional.empty()); @@ -214,47 +214,66 @@ class GroupCapsuleServiceTest { } @Test - void 모든_그룹원이_캡슐을_개봉하지_않은_경우_캡슐은_개봉되지_않는다() { + void 개봉일이_지나지_않아_그룹_캡슐을_열_수_없는_경우_캡슐은_개봉되지_않는다() { //given - Long memberId = 1L; - Long capsuleId = 1L; - - Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")); + Optional groupCapsule = getGroupCapsuleSpecificTime(memberId, capsuleId, + now.plusYears(5)); given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); - List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); - given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) - .willReturn( - GroupCapsuleOpenFixture.groupCapsuleOpens(false, groupCapsule.get(), groupMembers) - ); + //when + GroupCapsuleOpenStateDto groupCapsuleOpenStateDto = groupCapsuleService.openGroupCapsule( + memberId, capsuleId); + + //then + assertSoftly(softly -> { + softly.assertThat(groupCapsule.get().getIsOpened()).isFalse(); + softly.assertThat(groupCapsuleOpenStateDto.capsuleOpenStatus()) + .isEqualTo(CapsuleOpenStatus.NOT_OPEN); + }); + } + + @Test + void 타임캡슐이_아닌_경우_그룹_캡슐_개봉_시_그룹_캡슐은_개봉된다() { + //given + Optional groupCapsule = getGroupCapsuleSpecificTime(memberId, capsuleId, null); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); //when - groupCapsuleService.openGroupCapsule(memberId, capsuleId); + GroupCapsuleOpenStateDto groupCapsuleOpenStateDto = groupCapsuleService.openGroupCapsule( + memberId, capsuleId); //then - assertThat(groupCapsule.get().getIsOpened()).isFalse(); + assertSoftly(softly -> { + softly.assertThat(groupCapsule.get().getIsOpened()).isTrue(); + softly.assertThat(groupCapsuleOpenStateDto.capsuleOpenStatus()) + .isEqualTo(CapsuleOpenStatus.OPEN); + }); } - private Optional getGroupCapsule(Long memberId, Long capsuleId) { + private Optional getGroupCapsuleSpecificTime( + Long memberId, + Long capsuleId, + ZonedDateTime now + ) { Member member = MemberFixture.memberWithMemberId(memberId); return Optional.ofNullable( - CapsuleFixture.groupCapsuleWithCapsuleId( + CapsuleFixture.notGroupTimeCapsuleWithCapsuleId( member, CapsuleSkinFixture.capsuleSkin(member), GroupFixture.group(), - capsuleId + capsuleId, + now ) ); } @Test - void 모든_그룹원이_캡슐을_개봉한_경우_캡슐은_개봉된다() { + void 모든_그룹원이_캡슐을_개봉하지_않은_경우_캡슐은_개봉되지_않는다() { //given - Long memberId = 1L; - Long capsuleId = 1L; - Optional groupCapsule = getGroupCapsule(memberId, capsuleId); given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); @@ -262,22 +281,37 @@ private Optional getGroupCapsule(Long memberId, Long capsuleId) { List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) .willReturn( - GroupCapsuleOpenFixture.groupCapsuleOpens(true, groupCapsule.get(), groupMembers) + GroupCapsuleOpenFixture.groupCapsuleOpens(false, groupCapsule.get(), groupMembers) ); //when - groupCapsuleService.openGroupCapsule(memberId, capsuleId); + GroupCapsuleOpenStateDto groupCapsuleOpenStateDto = groupCapsuleService.openGroupCapsule( + memberId, capsuleId); //then - assertThat(groupCapsule.get().getIsOpened()).isTrue(); + assertSoftly(softly -> { + softly.assertThat(groupCapsule.get().getIsOpened()).isFalse(); + softly.assertThat(groupCapsuleOpenStateDto.capsuleOpenStatus()).isEqualTo( + CapsuleOpenStatus.OPEN); + }); + } + + private Optional getGroupCapsule(Long memberId, Long capsuleId) { + Member member = MemberFixture.memberWithMemberId(memberId); + + return Optional.ofNullable( + CapsuleFixture.groupCapsuleWithCapsuleId( + member, + CapsuleSkinFixture.capsuleSkin(member), + GroupFixture.group(), + capsuleId + ) + ); } @Test void 일부_그룹원이_캡슐을_개봉한_경우_캡슐은_개봉되지_않는다() { //given - Long memberId = 1L; - Long capsuleId = 1L; - Optional groupCapsule = getGroupCapsule(memberId, capsuleId); given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); @@ -285,22 +319,25 @@ private Optional getGroupCapsule(Long memberId, Long capsuleId) { List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) .willReturn( - GroupCapsuleOpenFixture.groupCapsuleOpensNotAllOpened(groupCapsule.get(), groupMembers) + GroupCapsuleOpenFixture.groupCapsuleOpensNotAllOpened(groupCapsule.get(), + groupMembers) ); //when - groupCapsuleService.openGroupCapsule(memberId, capsuleId); + GroupCapsuleOpenStateDto groupCapsuleOpenStateDto = groupCapsuleService.openGroupCapsule( + memberId, capsuleId); //then - assertThat(groupCapsule.get().getIsOpened()).isFalse(); + assertSoftly(softly -> { + softly.assertThat(groupCapsule.get().getIsOpened()).isFalse(); + softly.assertThat(groupCapsuleOpenStateDto.capsuleOpenStatus()).isEqualTo( + CapsuleOpenStatus.OPEN); + }); } @Test - void 모든_그룹원이_캡슐을_개봉이_없는_경우_예외가_발생한다() { + void 그룹_캡슐_개봉이_없는_경우_예외가_발생한다() { //given - Long memberId = 1L; - Long capsuleId = 1L; - Optional groupCapsule = getGroupCapsule(memberId, capsuleId); given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) .willReturn(groupCapsule); @@ -313,4 +350,29 @@ private Optional getGroupCapsule(Long memberId, Long capsuleId) { .isInstanceOf(GroupCapsuleOpenNotFoundException.class) .hasMessageContaining(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR.getMessage()); } + + @Test + void 모든_그룹원이_캡슐을_개봉한_경우_캡슐은_개봉된다() { + //given + Optional groupCapsule = getGroupCapsule(memberId, capsuleId); + given(capsuleRepository.findGroupCapsuleByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(groupCapsule); + + List groupMembers = MemberFixture.membersWithMemberId(memberId.intValue() + 2, 4); + given(groupCapsuleOpenRepository.findByCapsuleId(capsuleId)) + .willReturn( + GroupCapsuleOpenFixture.groupCapsuleOpens(true, groupCapsule.get(), groupMembers) + ); + + //when + GroupCapsuleOpenStateDto groupCapsuleOpenStateDto = groupCapsuleService.openGroupCapsule( + memberId, capsuleId); + + //then + assertSoftly(softly -> { + softly.assertThat(groupCapsule.get().getIsOpened()).isTrue(); + softly.assertThat(groupCapsuleOpenStateDto.capsuleOpenStatus()).isEqualTo( + CapsuleOpenStatus.OPEN); + }); + } } From 091815b96532a219b265074b0388fef15e9dec38 Mon Sep 17 00:00:00 2001 From: hong seokho Date: Thu, 6 Jun 2024 22:29:13 +0900 Subject: [PATCH 7/9] =?UTF-8?q?fix=20:=20=EA=B7=B8=EB=A3=B9=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=20=EA=B0=9C=EB=B4=89=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 객체지향적으로 변경 --- .../core/domain/capsule/entity/Capsule.java | 23 ++++++++++++-- .../repository/CapsuleRepository.java | 9 +++--- .../GroupCapsuleOpenRepository.java | 6 ---- .../service/GroupCapsuleService.java | 31 +++---------------- 4 files changed, 30 insertions(+), 39 deletions(-) diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java index 0325fd7ba..ba19b34e7 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/entity/Capsule.java @@ -16,12 +16,14 @@ import jakarta.persistence.Table; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.locationtech.jts.geom.Point; +import site.timecapsulearchive.core.domain.capsule.exception.GroupCapsuleOpenNotFoundException; import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; import site.timecapsulearchive.core.domain.group.entity.Group; import site.timecapsulearchive.core.domain.member.entity.Member; @@ -61,13 +63,13 @@ public class Capsule extends BaseEntity { private Address address; @OneToMany(mappedBy = "capsule", cascade = CascadeType.ALL, orphanRemoval = true) - private List images; + private List images = new ArrayList<>(); @OneToMany(mappedBy = "capsule", cascade = CascadeType.ALL, orphanRemoval = true) - private List