diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApi.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApi.java index 9b9d85e67..39b8e8daa 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApi.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApi.java @@ -107,6 +107,30 @@ ResponseEntity> acceptGroupInvitation( Long groupId ); + @Operation( + summary = "보낸 그룹 초대 삭제 ", + description = "그룹장이 보낸 그룹 초대를 삭제한다. 그룹장만 그룹 초대를 삭제할 수 있다.", + security = {@SecurityRequirement(name = "user_token")}, + tags = {"member group"} + ) + @ApiResponses(value = { + @ApiResponse( + responseCode = "200", + description = "처리 완료" + ), + @ApiResponse( + responseCode = "404", + description = "그룹 초대를 찾을 수 없는 경우 발생한다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) + ) + }) + ResponseEntity> deleteGroupInvite( + Long memberId, + + @Parameter(in = ParameterIn.PATH, description = "보낸 그룹 초대 아이디", required = true) + Long groupInviteId + ); + @Operation( summary = "그룹 요청 거부", description = "특정 그룹으로부터 초대 요청을 거부한다.", diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApiController.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApiController.java index 1c6434a44..7577c6635 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApiController.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/api/command/MemberGroupCommandApiController.java @@ -64,6 +64,20 @@ public ResponseEntity> acceptGroupInvitation( ); } + @DeleteMapping(value = "/sending-invites/{group_invite_id}") + public ResponseEntity> deleteGroupInvite( + @AuthenticationPrincipal final Long memberId, + @PathVariable("group_invite_id") final Long groupInviteId + ) { + memberGroupCommandService.deleteGroupInvite(memberId, groupInviteId); + + return ResponseEntity.ok( + ApiSpec.empty( + SuccessCode.SUCCESS + ) + ); + } + @DeleteMapping(value = "/{group_id}/member/{target_id}/reject") public ResponseEntity> rejectGroupInvitation( @AuthenticationPrincipal final Long memberId, diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/entity/GroupInvite.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/entity/GroupInvite.java index dc67cce81..95473cef4 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/entity/GroupInvite.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/entity/GroupInvite.java @@ -14,6 +14,7 @@ import lombok.NoArgsConstructor; 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.global.entity.BaseEntity; @Entity @@ -48,5 +49,4 @@ private GroupInvite(Group group, Member groupOwner, Member groupMember) { public static GroupInvite createOf(Group group, Member groupOwner, Member groupMember) { return new GroupInvite(group, groupOwner, groupMember); } - } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteRepository.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteRepository.java index b882c940d..64cddd3a8 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteRepository.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/repository/group_invite_repository/GroupInviteRepository.java @@ -1,6 +1,7 @@ package site.timecapsulearchive.core.domain.member_group.repository.group_invite_repository; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; @@ -12,6 +13,8 @@ public interface GroupInviteRepository extends Repository, void save(GroupInvite groupInvite); + void delete(GroupInvite groupInvite); + @Query("delete from GroupInvite gi " + "where gi.group.id =:groupId " + "and gi.groupOwner.id =:groupOwnerId " @@ -27,5 +30,7 @@ int deleteGroupInviteByGroupIdAndGroupOwnerIdAndGroupMemberId( @Query("delete from GroupInvite gi where gi.id in :groupInviteIds") @Modifying void bulkDelete(@Param("groupInviteIds") List groupInviteIds); + + Optional findGroupInviteByIdAndGroupOwnerId(Long groupInviteId, Long groupOwnerId); } diff --git a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandService.java b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandService.java index 35dc7b94c..a1fedde35 100644 --- a/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandService.java +++ b/backend/core/src/main/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandService.java @@ -14,6 +14,7 @@ import site.timecapsulearchive.core.domain.member_group.data.dto.GroupAcceptNotificationDto; import site.timecapsulearchive.core.domain.member_group.data.dto.GroupOwnerSummaryDto; import site.timecapsulearchive.core.domain.member_group.data.request.SendGroupRequest; +import site.timecapsulearchive.core.domain.member_group.entity.GroupInvite; import site.timecapsulearchive.core.domain.member_group.entity.MemberGroup; import site.timecapsulearchive.core.domain.member_group.exception.GroupInviteNotFoundException; import site.timecapsulearchive.core.domain.member_group.exception.GroupMemberCountLimitException; @@ -105,6 +106,16 @@ private void deleteGroupInvite(final Long memberId, final Long groupId, } } + @Transactional + public void deleteGroupInvite(final Long memberId, final Long groupInviteId) { + final GroupInvite groupInvite = groupInviteRepository.findGroupInviteByIdAndGroupOwnerId( + groupInviteId, + memberId) + .orElseThrow(GroupInviteNotFoundException::new); + + groupInviteRepository.delete(groupInvite); + } + /** * 사용자는 사용자가 속한 그룹을 탈퇴한다. *
주의 - 그룹 탈퇴 시 아래 조건에 해당하면 예외가 발생한다. diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupInviteFixture.java b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupInviteFixture.java new file mode 100644 index 000000000..7b31b2300 --- /dev/null +++ b/backend/core/src/test/java/site/timecapsulearchive/core/common/fixture/domain/GroupInviteFixture.java @@ -0,0 +1,14 @@ +package site.timecapsulearchive.core.common.fixture.domain; + +import java.util.Optional; +import site.timecapsulearchive.core.domain.group.entity.Group; +import site.timecapsulearchive.core.domain.member.entity.Member; +import site.timecapsulearchive.core.domain.member_group.entity.GroupInvite; + +public class GroupInviteFixture { + + public static Optional groupInvite(Group group, Member groupOwner, + Member groupMember) { + return Optional.of(GroupInvite.createOf(group, groupOwner, groupMember)); + } +} diff --git a/backend/core/src/test/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandServiceTest.java b/backend/core/src/test/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandServiceTest.java index 955a6eaf4..9aa2299a3 100644 --- a/backend/core/src/test/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandServiceTest.java +++ b/backend/core/src/test/java/site/timecapsulearchive/core/domain/member_group/service/MemberGroupCommandServiceTest.java @@ -19,6 +19,7 @@ import org.springframework.transaction.support.TransactionTemplate; import site.timecapsulearchive.core.common.dependency.TestTransactionTemplate; import site.timecapsulearchive.core.common.fixture.domain.GroupFixture; +import site.timecapsulearchive.core.common.fixture.domain.GroupInviteFixture; import site.timecapsulearchive.core.common.fixture.domain.MemberFixture; import site.timecapsulearchive.core.common.fixture.domain.MemberGroupFixture; import site.timecapsulearchive.core.common.fixture.dto.GroupDtoFixture; @@ -30,6 +31,7 @@ import site.timecapsulearchive.core.domain.member_group.data.dto.GroupAcceptNotificationDto; import site.timecapsulearchive.core.domain.member_group.data.dto.GroupOwnerSummaryDto; import site.timecapsulearchive.core.domain.member_group.data.request.SendGroupRequest; +import site.timecapsulearchive.core.domain.member_group.entity.GroupInvite; import site.timecapsulearchive.core.domain.member_group.entity.MemberGroup; import site.timecapsulearchive.core.domain.member_group.exception.GroupInviteNotFoundException; import site.timecapsulearchive.core.domain.member_group.exception.GroupMemberCountLimitException; @@ -303,6 +305,42 @@ class MemberGroupCommandServiceTest { verify(memberGroupRepository, times(1)).delete(any(MemberGroup.class)); } + @Test + void 그룹장인_사람이_그룹_초대를_삭제하면_삭제된다() { + //given + Long groupOwnerId = 1L; + Long groupMemberId = 2L; + Long groupInviteId = 1L; + given(groupInviteRepository.findGroupInviteByIdAndGroupOwnerId(anyLong(), + anyLong())) + .willReturn(GroupInviteFixture.groupInvite(GroupFixture.group(), + MemberFixture.memberWithMemberId(groupOwnerId), + MemberFixture.memberWithMemberId(groupMemberId)) + ); + + //when + groupMemberCommandService.deleteGroupInvite(groupOwnerId, groupInviteId); + + //then + verify(groupInviteRepository, times(1)).delete(any(GroupInvite.class)); + } + + @Test + void 그룹_초대가_존재하지_않는_경우_예외가_발생한다() { + //given + Long groupOwnerId = 1L; + Long groupInviteId = 1L; + given(groupInviteRepository.findGroupInviteByIdAndGroupOwnerId(anyLong(), + anyLong())).willReturn(Optional.empty()); + + //when + //then + assertThatThrownBy( + () -> groupMemberCommandService.deleteGroupInvite(groupOwnerId, groupInviteId)) + .isInstanceOf(GroupInviteNotFoundException.class) + .hasMessageContaining(ErrorCode.GROUP_INVITATION_NOT_FOUND_ERROR.getMessage()); + } + @Test void 나_자신을_그룹에서_삭제하려하면_예외가_발생한다() { //given