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 b2c08a19e..d1e94f550 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 @@ -45,4 +45,12 @@ private GroupCapsuleOpen(Boolean isOpened, Capsule capsule, Member member) { this.capsule = Objects.requireNonNull(capsule); this.member = Objects.requireNonNull(member); } + + public static GroupCapsuleOpen createOf(Member member, Capsule capsule, Boolean isOpened) { + return new GroupCapsuleOpen(isOpened, capsule, member); + } + + public void open() { + this.isOpened = Boolean.TRUE; + } } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/exception/GroupCapsuleOpenNotFoundException.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/exception/GroupCapsuleOpenNotFoundException.java new file mode 100644 index 000000000..fe59e10c2 --- /dev/null +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/capsule/exception/GroupCapsuleOpenNotFoundException.java @@ -0,0 +1,11 @@ +package site.timecapsulearchive.core.domain.capsule.exception; + +import site.timecapsulearchive.core.global.error.ErrorCode; +import site.timecapsulearchive.core.global.error.exception.BusinessException; + +public class GroupCapsuleOpenNotFoundException extends BusinessException { + + public GroupCapsuleOpenNotFoundException() { + super(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR); + } +} 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 38a4fa382..d1647f8d7 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 @@ -153,6 +153,32 @@ ResponseEntity> getMyGroupCapsules( ZonedDateTime createAt ); + @Operation( + summary = "그룹 캡슐 개봉", + description = """ + 그룹원이 그룹 캡슐을 개봉한다.
캡슐을 만들 때의 그룹원 모두가 캡슐을 개봉해야만 캡슐이 개봉된다. + """, + security = {@SecurityRequirement(name = "user_token")}, + tags = {"group capsule"} + ) + @ApiResponses(value = { + @ApiResponse( + responseCode = "200", + description = "처리 완료" + ), + @ApiResponse( + responseCode = "404", + description = "그룹 캡슐의 개봉 상태를 찾을 수 없는 경우 예외가 발생한다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) + ) + }) + ResponseEntity> openCapsule( + Long memberId, + + @Parameter(in = ParameterIn.PATH, description = "개봉할 그룹 캡슐 아이디", required = true) + @PathVariable("capsule_id") Long capsuleId + ); + @Operation( summary = "그룹 캡슐 24시간 이내 수정", description = "사용자가 생성한 그룹 캡슐의 생성 시간이 24시간 이내라면 수정한다.", 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 c7e7f6af1..9b6089e3a 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 @@ -30,7 +30,7 @@ import site.timecapsulearchive.core.infra.s3.manager.S3PreSignedUrlManager; @RestController -@RequestMapping("/groups-capsules") +@RequestMapping("/group-capsules") @RequiredArgsConstructor public class GroupCapsuleApiController implements GroupCapsuleApi { @@ -137,6 +137,17 @@ public ResponseEntity> getMyGroupCapsules( ); } + @PostMapping("/{capsule_id}/open") + @Override + public ResponseEntity> openCapsule( + @AuthenticationPrincipal final Long memberId, + @PathVariable(value = "capsule_id") final Long capsuleId + ) { + groupCapsuleService.openGroupCapsule(memberId, capsuleId); + + return ResponseEntity.ok(ApiSpec.empty(SuccessCode.SUCCESS)); + } + @Override public ResponseEntity updateGroupCapsuleByIdAndGroupId( Long groupId, Long capsuleId, GroupCapsuleUpdateRequest request) { 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 5a9bacd2b..d6e6d03f2 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,5 +1,8 @@ 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; @@ -17,6 +20,7 @@ public class GroupCapsuleOpenQueryRepository { private final JdbcTemplate jdbcTemplate; + private final JPAQueryFactory jpaQueryFactory; public void bulkSave(final List groupMemberIds, final Capsule capsule) { jdbcTemplate.batchUpdate( @@ -43,4 +47,12 @@ 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 a46f6209c..ce02c9eee 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,8 +1,12 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.repository; +import java.util.Optional; import org.springframework.data.repository.Repository; import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; public interface GroupCapsuleOpenRepository extends Repository { + void save(GroupCapsuleOpen groupCapsuleOpen); + + Optional findByMemberIdAndCapsuleId(Long memberId, Long 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 fa264165a..e074314b5 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; @@ -9,12 +10,16 @@ import org.springframework.transaction.annotation.Transactional; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; import site.timecapsulearchive.core.domain.capsule.entity.CapsuleType; +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.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.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; import site.timecapsulearchive.core.domain.group.entity.Group; @@ -27,6 +32,8 @@ public class GroupCapsuleService { private final CapsuleRepository capsuleRepository; private final GroupCapsuleQueryRepository groupCapsuleQueryRepository; + private final GroupCapsuleOpenRepository groupCapsuleOpenRepository; + private final GroupCapsuleOpenQueryRepository groupCapsuleOpenQueryRepository; @Transactional public Capsule saveGroupCapsule( @@ -88,5 +95,29 @@ public Slice findMyGroupCapsuleSlice( ) { return groupCapsuleQueryRepository.findMyGroupCapsuleSlice(memberId, size, createdAt); } + + /** + * 해당 그룹원이 그룹 캡슐을 개봉한다. 모든 그룹원이 개봉하면 캡슐이 개봉된다. + * + * @param memberId 캡슐을 개봉할 그룹원 + * @param capsuleId 개봉할 캡슐 아이디 + */ + @Transactional + public void openGroupCapsule(final Long memberId, final Long capsuleId) { + GroupCapsuleOpen groupCapsuleOpen = groupCapsuleOpenRepository.findByMemberIdAndCapsuleId( + memberId, + capsuleId) + .orElseThrow(GroupCapsuleOpenNotFoundException::new); + groupCapsuleOpen.open(); + + List capsuleOpens = groupCapsuleOpenQueryRepository.findIsOpenedByCapsuleId( + capsuleId); + + boolean allGroupMemberOpened = capsuleOpens.stream() + .allMatch(isOpened -> isOpened.equals(Boolean.TRUE)); + if (allGroupMemberOpened) { + capsuleRepository.updateIsOpenedTrue(memberId, capsuleId); + } + } } 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 21b9da6e9..299bec8c1 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 @@ -52,6 +52,7 @@ public enum ErrorCode { //capsule CAPSULE_NOT_FOUND_ERROR(404, "CAPSULE-001", "캡슐을 찾지 못하였습니다."), NO_CAPSULE_AUTHORITY_ERROR(403, "CAPSULE-002", "캡슐에 접근 권한이 없습니다."), + GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR(404, "CAPSULE-003", "그룹 캡슐 개봉상태를 찾을 수 없습니다."), //friend FRIEND_NOT_FOUND_ERROR(404, "FRIEND-001", "친구를 찾지 못하였습니다"), 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 7ee3e0029..795913fd7 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,8 +1,11 @@ package site.timecapsulearchive.core.common.fixture.domain; import java.util.List; +import java.util.Optional; import site.timecapsulearchive.core.domain.capsule.entity.Capsule; +import site.timecapsulearchive.core.domain.capsule.entity.CapsuleType; import site.timecapsulearchive.core.domain.capsule.entity.GroupCapsuleOpen; +import site.timecapsulearchive.core.domain.capsuleskin.entity.CapsuleSkin; import site.timecapsulearchive.core.domain.member.entity.Member; public class GroupCapsuleOpenFixture { @@ -18,4 +21,16 @@ public static List groupCapsuleOpens(Boolean isOpened, Capsule ).toList(); } + public static Optional groupCapsuleOpen(int dataPrefix) { + Member member = MemberFixture.member(dataPrefix); + CapsuleSkin capsuleSkin = CapsuleSkinFixture.capsuleSkin(member); + + return Optional.of( + GroupCapsuleOpen.createOf( + MemberFixture.member(dataPrefix), + CapsuleFixture.capsule(member, capsuleSkin, CapsuleType.GROUP), + Boolean.FALSE + ) + ); + } } 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 83864e475..c6caa072a 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,34 +1,47 @@ package site.timecapsulearchive.core.domain.capsule.group_capsule.service; +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.List; +import java.util.Optional; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; +import site.timecapsulearchive.core.common.fixture.domain.GroupCapsuleOpenFixture; import site.timecapsulearchive.core.common.fixture.dto.CapsuleDtoFixture; +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.capsule.group_capsule.service.GroupCapsuleService; import site.timecapsulearchive.core.domain.group.data.dto.GroupMemberSummaryDto; +import site.timecapsulearchive.core.global.error.ErrorCode; class GroupCapsuleServiceTest { private final Long capsuleId = 1L; private final int groupMemberCount = 3; + private final CapsuleRepository capsuleRepository = mock(CapsuleRepository.class); private final GroupCapsuleQueryRepository groupCapsuleQueryRepository = mock( GroupCapsuleQueryRepository.class); - private final GroupCapsuleService groupCapsuleService; + private final GroupCapsuleOpenRepository groupCapsuleOpenRepository = mock( + GroupCapsuleOpenRepository.class); + private final GroupCapsuleOpenQueryRepository groupCapsuleOpenQueryRepository = mock( + GroupCapsuleOpenQueryRepository.class); - public GroupCapsuleServiceTest() { - CapsuleRepository capsuleRepository = mock(CapsuleRepository.class); - this.groupCapsuleService = new GroupCapsuleService(capsuleRepository, groupCapsuleQueryRepository); - } + private final GroupCapsuleService groupCapsuleService = new GroupCapsuleService( + capsuleRepository, groupCapsuleQueryRepository, groupCapsuleOpenRepository, + groupCapsuleOpenQueryRepository + ); @Test void 개봉된_그룹_캡슐의_상세_내용을_볼_수_있다() { @@ -42,7 +55,6 @@ public GroupCapsuleServiceTest() { GroupCapsuleDetailDto response = groupCapsuleService.findGroupCapsuleDetailByGroupIdAndCapsuleId( capsuleId); - //then SoftAssertions.assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); @@ -69,7 +81,6 @@ public GroupCapsuleServiceTest() { GroupCapsuleDetailDto response = groupCapsuleService.findGroupCapsuleDetailByGroupIdAndCapsuleId( capsuleId); - //then SoftAssertions.assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); @@ -96,7 +107,6 @@ public GroupCapsuleServiceTest() { GroupCapsuleDetailDto response = groupCapsuleService.findGroupCapsuleDetailByGroupIdAndCapsuleId( capsuleId); - //then SoftAssertions.assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); @@ -116,14 +126,14 @@ public GroupCapsuleServiceTest() { //given given( groupCapsuleQueryRepository.findGroupCapsuleDetailDtoByCapsuleId(anyLong())).willReturn( - CapsuleDtoFixture.getGroupCapsuleDetailDto(capsuleId, false, ZonedDateTime.now().minusDays(5), 3) + CapsuleDtoFixture.getGroupCapsuleDetailDto(capsuleId, false, + ZonedDateTime.now().minusDays(5), 3) ); //when GroupCapsuleDetailDto response = groupCapsuleService.findGroupCapsuleDetailByGroupIdAndCapsuleId( capsuleId); - //then SoftAssertions.assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); @@ -141,14 +151,14 @@ public GroupCapsuleServiceTest() { //given given( groupCapsuleQueryRepository.findGroupCapsuleDetailDtoByCapsuleId(anyLong())).willReturn( - CapsuleDtoFixture.getGroupCapsuleDetailDto(capsuleId, false, ZonedDateTime.now().plusDays(5), 3) + CapsuleDtoFixture.getGroupCapsuleDetailDto(capsuleId, false, + ZonedDateTime.now().plusDays(5), 3) ); //when GroupCapsuleDetailDto response = groupCapsuleService.findGroupCapsuleDetailByGroupIdAndCapsuleId( capsuleId); - //then SoftAssertions.assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); @@ -166,14 +176,14 @@ public GroupCapsuleServiceTest() { //given given( groupCapsuleQueryRepository.findGroupCapsuleDetailDtoByCapsuleId(anyLong())).willReturn( - CapsuleDtoFixture.getGroupCapsuleDetailDto(capsuleId, true, ZonedDateTime.now().plusDays(5), 3) + CapsuleDtoFixture.getGroupCapsuleDetailDto(capsuleId, true, + ZonedDateTime.now().plusDays(5), 3) ); //when GroupCapsuleDetailDto response = groupCapsuleService.findGroupCapsuleDetailByGroupIdAndCapsuleId( capsuleId); - //then SoftAssertions.assertSoftly(softly -> { CapsuleDetailDto detailDto = response.capsuleDetailDto(); @@ -186,4 +196,53 @@ public GroupCapsuleServiceTest() { }); } + @Test + void 그룹_캡슐_개봉이_없는_캡슐을_개봉하려는_경우_예외가_발생한다() { + //given + Long memberId = 1L; + Long capsuleId = 1L; + given(groupCapsuleOpenRepository.findByMemberIdAndCapsuleId(anyLong(), anyLong())) + .willReturn(Optional.empty()); + + //when + //then + assertThatThrownBy(() -> groupCapsuleService.openGroupCapsule(memberId, capsuleId)) + .isInstanceOf(GroupCapsuleOpenNotFoundException.class) + .hasMessageContaining(ErrorCode.GROUP_CAPSULE_OPEN_NOT_FOUND_ERROR.getMessage()); + } + + @Test + void 모든_그룹원이_캡슐을_개봉하지_않은_경우_캡슐은_개봉되지_않는다() { + //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)); + + //when + groupCapsuleService.openGroupCapsule(memberId, capsuleId); + + //then + verifyNoInteractions(capsuleRepository); + } + + @Test + void 모든_그룹원이_캡슐을_개봉한_경우_캡슐은_개봉된다() { + //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)); + + //when + groupCapsuleService.openGroupCapsule(memberId, capsuleId); + + //then + verify(capsuleRepository, times(1)).updateIsOpenedTrue(anyLong(), anyLong()); + } } diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java index ccb33429c..f9dd6ed0b 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/capsule/repository/GroupCapsuleOpenQueryRepositoryTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import java.util.List; import javax.sql.DataSource; @@ -36,11 +37,12 @@ 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); + this.groupCapsuleOpenRepository = new GroupCapsuleOpenQueryRepository(jdbcTemplate, jpaQueryFactory); } @Transactional