From d30d15a7f09b8330b459317d341ccd40ab93ae38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Sat, 23 Dec 2023 16:44:36 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[FEAT]=20=EC=B4=88=EB=8C=80=20=EC=8A=B9?= =?UTF-8?q?=EB=9D=BD=20=EC=82=AD=EC=A0=9C=20api=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B4=88=EB=8C=80=20=EC=A4=91=EB=B3=B5=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/group.adoc | 3 + backend/src/docs/plan.adoc | 6 ++ .../group/controller/GroupController.java | 21 ++--- .../dto/request/DeleteGroupInviteRequest.java | 14 +++ .../backend/domain/group/entity/Group.java | 19 +++- .../domain/group/entity/GroupMember.java | 4 + .../domain/group/service/GroupService.java | 13 ++- .../plan/controller/PlanController.java | 16 +++- .../twtw/backend/domain/plan/entity/Plan.java | 41 ++++---- .../domain/plan/entity/PlanInviteCode.java | 12 +++ .../domain/plan/entity/PlanMember.java | 24 +++-- .../domain/plan/service/PlanService.java | 17 +++- .../group/controller/GroupControllerTest.java | 55 +++++++---- .../group/repository/GroupRepositoryTest.java | 7 +- .../group/service/GroupServiceTest.java | 11 +-- .../plan/controller/PlanControllerTest.java | 94 +++++++++++++------ .../domain/plan/service/PlanServiceTest.java | 9 +- 17 files changed, 256 insertions(+), 110 deletions(-) create mode 100644 backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java create mode 100644 backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java diff --git a/backend/src/docs/group.adoc b/backend/src/docs/group.adoc index 56fc5e95..6e2a7422 100644 --- a/backend/src/docs/group.adoc +++ b/backend/src/docs/group.adoc @@ -17,6 +17,9 @@ operation::post join group[snippets='http-request,http-response'] === 그룹 초대 operation::post invite group[snippets='http-request,http-response'] +=== 그룹 초대 삭제 +operation::delete group invite[snippets='http-request,http-response'] + === 위치 공유 ON operation::post share location[snippets='http-request,http-response'] diff --git a/backend/src/docs/plan.adoc b/backend/src/docs/plan.adoc index 2b7dd926..1a3d5474 100644 --- a/backend/src/docs/plan.adoc +++ b/backend/src/docs/plan.adoc @@ -17,9 +17,15 @@ operation::get plan[snippets='http-request,http-response'] === 계획 삭제 operation::delete plan[snippets='http-request,http-response'] +=== 계획 초대 +operation::post invite plan[snippets='http-request,http-response'] + === 계획 참여 operation::post join plan[snippets='http-request,http-response'] +=== 계획 초대 삭제 +operation::delete plan invite[snippets='http-request,http-response'] + === 계획 탈퇴 operation::post out plan[snippets='http-request,http-response'] diff --git a/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java b/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java index 59deab5f..7ca3f5cf 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java @@ -1,22 +1,13 @@ package com.twtw.backend.domain.group.controller; -import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; -import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; -import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; -import com.twtw.backend.domain.group.dto.request.OutGroupRequest; -import com.twtw.backend.domain.group.dto.request.UpdateLocationRequest; +import com.twtw.backend.domain.group.dto.request.DeleteGroupInviteRequest; +import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; import com.twtw.backend.domain.group.service.GroupService; - import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.UUID; @@ -53,6 +44,12 @@ public ResponseEntity inviteGroup( return ResponseEntity.ok(groupService.inviteGroup(inviteGroupRequest)); } + @DeleteMapping("/invite") + public ResponseEntity deleteInvite(@RequestBody DeleteGroupInviteRequest deleteGroupInviteRequest) { + groupService.deleteInvite(deleteGroupInviteRequest); + return ResponseEntity.noContent().build(); + } + @PostMapping("/share/{id}") public ResponseEntity shareLocation(@PathVariable UUID id) { groupService.shareLocation(id); diff --git a/backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java b/backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java new file mode 100644 index 00000000..a35e3614 --- /dev/null +++ b/backend/src/main/java/com/twtw/backend/domain/group/dto/request/DeleteGroupInviteRequest.java @@ -0,0 +1,14 @@ +package com.twtw.backend.domain.group.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class DeleteGroupInviteRequest { + private UUID groupId; +} diff --git a/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java b/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java index f6db95ff..07f01d59 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java @@ -73,8 +73,19 @@ public void inviteAll(final List friends) { friends.forEach(friend -> addGroupMember(new GroupMember(this, friend))); } - private boolean addGroupMember(final GroupMember groupMember) { - return this.groupMembers.add(groupMember); + public List getGroupMembers() { + return this.groupMembers.stream().filter(GroupMember::isAccepted).toList(); + } + + private void addGroupMember(final GroupMember groupMember) { + if (hasSameMember(groupMember)) { + return; + } + this.groupMembers.add(groupMember); + } + + private boolean hasSameMember(final GroupMember groupMember) { + return this.groupMembers.stream().map(GroupMember::getMember).anyMatch(groupMember::isSameMember); } public void updateMemberLocation( @@ -100,4 +111,8 @@ public void outGroup(final Member member) { private boolean hasNoLeader() { return this.groupMembers.stream().noneMatch(GroupMember::isLeader); } + + public void deleteInvite(final Member member) { + this.groupMembers.removeIf(groupMember -> groupMember.isSameMember(member)); + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java b/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java index 7050dbff..8eef93fb 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/entity/GroupMember.java @@ -102,4 +102,8 @@ public boolean isSameMember(final Member member) { public boolean isLeader() { return this.group.getLeaderId().equals(this.member.getId()); } + + public boolean isAccepted() { + return this.groupInviteCode == GroupInviteCode.ACCEPTED; + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java b/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java index c96f7bcd..a4e86f4e 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/service/GroupService.java @@ -1,10 +1,6 @@ package com.twtw.backend.domain.group.service; -import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; -import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; -import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; -import com.twtw.backend.domain.group.dto.request.OutGroupRequest; -import com.twtw.backend.domain.group.dto.request.UpdateLocationRequest; +import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; @@ -148,4 +144,11 @@ public void outGroup(final OutGroupRequest outGroupRequest) { final Group group = getGroupEntity(outGroupRequest.getGroupId()); group.outGroup(member); } + + @Transactional + public void deleteInvite(final DeleteGroupInviteRequest deleteGroupInviteRequest) { + final Member member = authService.getMemberByJwt(); + final Group group = getGroupEntity(deleteGroupInviteRequest.getGroupId()); + group.deleteInvite(member); + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java b/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java index 9ef58f56..62eb5acb 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/controller/PlanController.java @@ -53,9 +53,21 @@ public ResponseEntity deletePlanById(@PathVariable UUID id) { return ResponseEntity.noContent().build(); } + @PostMapping("/invite") + public ResponseEntity invitePlan(@RequestBody PlanMemberRequest request) { + return ResponseEntity.ok(planService.invitePlan(request)); + } + + @DeleteMapping("/invite") + public ResponseEntity deleteInvite(@RequestBody PlanMemberRequest request) { + planService.deleteInvite(request); + return ResponseEntity.noContent().build(); + } + @PostMapping("/join") - public ResponseEntity joinPlan(@RequestBody PlanMemberRequest request) { - return ResponseEntity.ok(planService.joinPlan(request)); + public ResponseEntity joinPlan(@RequestBody PlanMemberRequest request) { + planService.joinPlan(request); + return ResponseEntity.noContent().build(); } @PostMapping("/out") diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java index 0dc6094a..644cc708 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java @@ -8,31 +8,18 @@ import com.twtw.backend.global.audit.AuditListener; import com.twtw.backend.global.audit.Auditable; import com.twtw.backend.global.audit.BaseTime; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; - +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; - import org.hibernate.annotations.Where; import java.time.LocalDateTime; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; @Getter @Entity @@ -74,11 +61,22 @@ public Plan(Member member, Place place, Group group, LocalDateTime planDay) { } public void addMember(final Member member) { + if (hasSameMember(member)) { + return; + } this.planMembers.add(new PlanMember(this, member, false)); } + private boolean hasSameMember(final Member member) { + return this.planMembers.stream().anyMatch(planMember -> planMember.isSameMember(member)); + } + + public Set getPlanMembers() { + return this.planMembers.stream().filter(PlanMember::isAccepted).collect(Collectors.toSet()); + } + public void deleteMember(final Member member) { - this.planMembers.removeIf(planMember -> planMember.hasSameMember(member)); + this.planMembers.removeIf(planMember -> planMember.isSameMember(member)); if (hasNoPlanMaker()) { this.planMembers.stream().findFirst().ifPresent(PlanMember::updateToPlanMaker); @@ -126,4 +124,15 @@ public UUID getPlanMakerId() { .getMember() .getId(); } + + public void acceptInvite(final Member member) { + this.planMembers.stream() + .filter(planMember -> planMember.isSameMember(member)) + .findFirst() + .ifPresent(PlanMember::acceptInvite); + } + + public void deleteInvite(final Member member) { + this.planMembers.removeIf(planMember -> planMember.isSameMember(member)); + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java new file mode 100644 index 00000000..d742ef0e --- /dev/null +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanInviteCode.java @@ -0,0 +1,12 @@ +package com.twtw.backend.domain.plan.entity; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum PlanInviteCode { + REQUESTED("요청"), + ACCEPTED("승인"), + DENIED("거절"); + + private final String toKorean; +} diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java index 4f31feff..1937c651 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/PlanMember.java @@ -5,15 +5,7 @@ import com.twtw.backend.global.audit.Auditable; import com.twtw.backend.global.audit.BaseTime; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -44,6 +36,9 @@ public class PlanMember implements Auditable { @ManyToOne(fetch = FetchType.LAZY) private Member member; + @Enumerated(EnumType.STRING) + private PlanInviteCode planInviteCode; + private Boolean isPlanMaker; @Setter @@ -56,13 +51,22 @@ public PlanMember(final Plan plan, final Member member, final Boolean isPlanMake this.plan = plan; this.member = member; this.isPlanMaker = isPlanMaker; + this.planInviteCode = PlanInviteCode.REQUESTED; } - public boolean hasSameMember(final Member member) { + public boolean isSameMember(final Member member) { return this.member.equals(member); } public void updateToPlanMaker() { this.isPlanMaker = true; } + + public boolean isAccepted() { + return this.planInviteCode == PlanInviteCode.ACCEPTED; + } + + public void acceptInvite() { + this.planInviteCode = PlanInviteCode.ACCEPTED; + } } diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java b/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java index 2fb04e1a..1177410c 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/service/PlanService.java @@ -84,7 +84,8 @@ public PlanResponse savePlan(final SavePlanRequest request) { return planMapper.toPlanResponse(planRepository.save(plan)); } - public PlanResponse joinPlan(PlanMemberRequest request) { + @Transactional + public PlanResponse invitePlan(PlanMemberRequest request) { Member member = authService.getMemberByJwt(); Plan plan = getPlanEntity(request.getPlanId()); plan.addMember(member); @@ -149,4 +150,18 @@ public void updatePlanDay(final UpdatePlanDayRequest request) { final Plan plan = getPlanEntity(request.getPlanId()); plan.updatePlanDay(request.getChangeDay()); } + + @Transactional + public void joinPlan(final PlanMemberRequest request) { + Member member = authService.getMemberByJwt(); + Plan plan = getPlanEntity(request.getPlanId()); + plan.acceptInvite(member); + } + + @Transactional + public void deleteInvite(final PlanMemberRequest request) { + Member member = authService.getMemberByJwt(); + Plan plan = getPlanEntity(request.getPlanId()); + plan.deleteInvite(member); + } } diff --git a/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java b/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java index 0b0a5ebc..113134d0 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java @@ -1,30 +1,12 @@ package com.twtw.backend.domain.group.controller; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; -import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; -import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; -import com.twtw.backend.domain.group.dto.request.OutGroupRequest; -import com.twtw.backend.domain.group.dto.request.UpdateLocationRequest; +import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; import com.twtw.backend.domain.group.service.GroupService; import com.twtw.backend.domain.member.dto.response.MemberResponse; import com.twtw.backend.support.docs.RestDocsTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -36,6 +18,17 @@ import java.util.List; import java.util.UUID; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @DisplayName("GroupController의") @WebMvcTest(GroupController.class) class GroupControllerTest extends RestDocsTest { @@ -168,6 +161,30 @@ void inviteGroup() throws Exception { .andDo(document("post invite group", getDocumentRequest(), getDocumentResponse())); } + @Test + @DisplayName("그룹 초대 삭제 API가 수행되는가") + void deleteInvite() throws Exception { + // given + willDoNothing().given(groupService).deleteInvite(any()); + + // when + final ResultActions perform = + mockMvc.perform( + delete("/group/invite") + .contentType(MediaType.APPLICATION_JSON) + .content(toRequestBody(new DeleteGroupInviteRequest(UUID.randomUUID()))) + .header( + "Authorization", + "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); + + // then + perform.andExpect(status().isNoContent()); + + // docs + perform.andDo(print()) + .andDo(document("delete group invite", getDocumentRequest(), getDocumentResponse())); + } + @Test @DisplayName("위치 공유 수정 API가 수행되는가") void shareLocation() throws Exception { diff --git a/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java b/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java index f0d0a7b9..1a59a6a5 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java @@ -1,7 +1,5 @@ package com.twtw.backend.domain.group.repository; -import static org.assertj.core.api.Assertions.assertThat; - import com.twtw.backend.domain.group.entity.Group; import com.twtw.backend.domain.group.entity.GroupMember; import com.twtw.backend.domain.member.entity.Member; @@ -12,7 +10,6 @@ import com.twtw.backend.fixture.member.MemberEntityFixture; import com.twtw.backend.fixture.place.PlaceEntityFixture; import com.twtw.backend.support.repository.RepositoryTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,6 +17,8 @@ import java.time.LocalDateTime; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("GroupRepository의") class GroupRepositoryTest extends RepositoryTest { @@ -49,7 +48,7 @@ void makeGroup() { final Group saveGroup = groupRepository.save(group); // then - assertThat(saveGroup.getGroupMembers()).hasSize(2); + assertThat(saveGroup.getGroupMembers()).hasSize(1); } @Test diff --git a/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java b/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java index 68e8df64..ab352cc6 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java @@ -1,7 +1,5 @@ package com.twtw.backend.domain.group.service; -import static org.assertj.core.api.Assertions.assertThat; - import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; @@ -15,13 +13,14 @@ import com.twtw.backend.domain.member.entity.Member; import com.twtw.backend.fixture.member.MemberEntityFixture; import com.twtw.backend.support.service.LoginTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("GroupService의") class GroupServiceTest extends LoginTest { @Autowired private GroupService groupService; @@ -158,9 +157,7 @@ void getGroupById() { Group group1 = new Group("BABY_MONSTER", "YG_OFFICIAL_IMAGE", leader); - GroupMember groupMember1 = new GroupMember(group1, loginUser); - - group1.getGroupMembers().add(groupMember1); + group1.inviteAll(List.of(loginUser)); Group saveGroup1 = groupRepository.save(group1); // when @@ -168,6 +165,6 @@ void getGroupById() { GroupInfoResponse response = groupService.getGroupById(saveGroup1.getId()); // then - assertThat(response.getGroupMembers()).hasSize(2); + assertThat(response.getGroupMembers()).hasSize(1); } } diff --git a/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java b/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java index 343aca67..2eae1dad 100644 --- a/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java @@ -1,17 +1,5 @@ package com.twtw.backend.domain.plan.controller; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.member.dto.response.MemberResponse; import com.twtw.backend.domain.place.entity.CategoryGroupCode; @@ -25,7 +13,6 @@ import com.twtw.backend.domain.plan.dto.response.PlanResponse; import com.twtw.backend.domain.plan.service.PlanService; import com.twtw.backend.support.docs.RestDocsTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -37,6 +24,17 @@ import java.util.List; import java.util.UUID; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @DisplayName("PlanController의") @WebMvcTest(PlanController.class) class PlanControllerTest extends RestDocsTest { @@ -196,11 +194,10 @@ void deletePlanById() throws Exception { } @Test - @DisplayName("계획 참여 API가 수행되는가") + @DisplayName("계획 초대 API가 수행되는가") void joinPlan() throws Exception { // given - final PlanResponse expected = new PlanResponse(UUID.randomUUID(), UUID.randomUUID()); - given(planService.joinPlan(any())).willReturn(expected); + willDoNothing().given(planService).joinPlan(any()); // when final ResultActions perform = @@ -209,28 +206,69 @@ void joinPlan() throws Exception { .contentType(MediaType.APPLICATION_JSON) .content( toRequestBody( - new SavePlanRequest( - UUID.randomUUID(), - LocalDateTime.of(2023, 12, 25, 13, 30), - new PlaceDetails( - "이디야커피 안성죽산점", - "http://place.map.kakao.com/1562566188", - "경기 안성시 죽산면 죽주로 287-1", - 127.426865189637, - 37.0764635355795)))) + new PlanMemberRequest(UUID.randomUUID()))) .header( "Authorization", "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); // then - perform.andExpect(status().isOk()) - .andExpect(jsonPath("$.planId").isString()) - .andExpect(jsonPath("$.groupId").isString()); + perform.andExpect(status().isNoContent()); // docs perform.andDo(print()) .andDo(document("post join plan", getDocumentRequest(), getDocumentResponse())); } + @Test + @DisplayName("계획 참여 API가 수행되는가") + void invitePlan() throws Exception { + // given + final PlanResponse expected = new PlanResponse(UUID.randomUUID(), UUID.randomUUID()); + given(planService.invitePlan(any())).willReturn(expected); + + // when + final ResultActions perform = + mockMvc.perform( + post("/plans/invite") + .contentType(MediaType.APPLICATION_JSON) + .content( + toRequestBody( + new PlanMemberRequest(UUID.randomUUID()))) + .header( + "Authorization", + "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); + // then + perform.andExpect(status().isOk()); + + // docs + perform.andDo(print()) + .andDo(document("post invite plan", getDocumentRequest(), getDocumentResponse())); + } + + @Test + @DisplayName("계획 초대 삭제 API가 수행되는가") + void deleteInvite() throws Exception { + // given + willDoNothing().given(planService).deletePlan(any()); + + // when + final ResultActions perform = + mockMvc.perform( + delete("/plans/invite") + .contentType(MediaType.APPLICATION_JSON) + .content( + toRequestBody( + new PlanMemberRequest(UUID.randomUUID()))) + .header( + "Authorization", + "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); + // then + perform.andExpect(status().isNoContent()); + + // docs + perform.andDo(print()) + .andDo(document("delete plan invite", getDocumentRequest(), getDocumentResponse())); + } + @Test @DisplayName("계획 탈퇴 API가 수행되는가") void outPlan() throws Exception { diff --git a/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java b/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java index 5b731f78..209c1bba 100644 --- a/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java @@ -1,7 +1,5 @@ package com.twtw.backend.domain.plan.service; -import static org.assertj.core.api.Assertions.assertThat; - import com.twtw.backend.domain.group.repository.GroupRepository; import com.twtw.backend.domain.member.entity.Member; import com.twtw.backend.domain.place.entity.CategoryGroupCode; @@ -18,7 +16,6 @@ import com.twtw.backend.fixture.place.PlaceEntityFixture; import com.twtw.backend.fixture.plan.PlanEntityFixture; import com.twtw.backend.support.service.LoginTest; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +24,8 @@ import java.util.Optional; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("PlanService의") class PlanServiceTest extends LoginTest { @@ -83,7 +82,9 @@ void joinPlan() { final UUID planId = plan.getId(); // when - planService.joinPlan(new PlanMemberRequest(planId)); + planService.invitePlan(new PlanMemberRequest(planId)); + plan.acceptInvite(loginUser); + plan.acceptInvite(member); // then final Plan result = planRepository.findById(planId).orElseThrow(); From a1b1cb680c377584230cdf1dd364d98b2c0fb5ef Mon Sep 17 00:00:00 2001 From: github-actions <> Date: Sat, 23 Dec 2023 07:44:52 +0000 Subject: [PATCH 2/2] Google Java Format --- .../group/controller/GroupController.java | 6 ++-- .../backend/domain/group/entity/Group.java | 4 ++- .../twtw/backend/domain/plan/entity/Plan.java | 3 ++ .../group/controller/GroupControllerTest.java | 34 +++++++++++------- .../group/repository/GroupRepositoryTest.java | 5 +-- .../group/service/GroupServiceTest.java | 5 +-- .../plan/controller/PlanControllerTest.java | 36 +++++++++---------- .../domain/plan/service/PlanServiceTest.java | 5 +-- 8 files changed, 56 insertions(+), 42 deletions(-) diff --git a/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java b/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java index 7ca3f5cf..c95b2a9e 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/controller/GroupController.java @@ -1,11 +1,12 @@ package com.twtw.backend.domain.group.controller; -import com.twtw.backend.domain.group.dto.request.DeleteGroupInviteRequest; import com.twtw.backend.domain.group.dto.request.*; +import com.twtw.backend.domain.group.dto.request.DeleteGroupInviteRequest; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; import com.twtw.backend.domain.group.dto.response.SimpleGroupInfoResponse; import com.twtw.backend.domain.group.service.GroupService; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -45,7 +46,8 @@ public ResponseEntity inviteGroup( } @DeleteMapping("/invite") - public ResponseEntity deleteInvite(@RequestBody DeleteGroupInviteRequest deleteGroupInviteRequest) { + public ResponseEntity deleteInvite( + @RequestBody DeleteGroupInviteRequest deleteGroupInviteRequest) { groupService.deleteInvite(deleteGroupInviteRequest); return ResponseEntity.noContent().build(); } diff --git a/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java b/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java index 07f01d59..06be1c91 100644 --- a/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java +++ b/backend/src/main/java/com/twtw/backend/domain/group/entity/Group.java @@ -85,7 +85,9 @@ private void addGroupMember(final GroupMember groupMember) { } private boolean hasSameMember(final GroupMember groupMember) { - return this.groupMembers.stream().map(GroupMember::getMember).anyMatch(groupMember::isSameMember); + return this.groupMembers.stream() + .map(GroupMember::getMember) + .anyMatch(groupMember::isSameMember); } public void updateMemberLocation( diff --git a/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java b/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java index 644cc708..8a39db9a 100644 --- a/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java +++ b/backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java @@ -8,11 +8,14 @@ import com.twtw.backend.global.audit.AuditListener; import com.twtw.backend.global.audit.Auditable; import com.twtw.backend.global.audit.BaseTime; + import jakarta.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; + import org.hibernate.annotations.Where; import java.time.LocalDateTime; diff --git a/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java b/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java index 113134d0..b54f0da0 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/controller/GroupControllerTest.java @@ -1,5 +1,17 @@ package com.twtw.backend.domain.group.controller; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import com.twtw.backend.domain.group.dto.request.*; import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.group.dto.response.ShareInfoResponse; @@ -7,6 +19,7 @@ import com.twtw.backend.domain.group.service.GroupService; import com.twtw.backend.domain.member.dto.response.MemberResponse; import com.twtw.backend.support.docs.RestDocsTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -18,17 +31,6 @@ import java.util.List; import java.util.UUID; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @DisplayName("GroupController의") @WebMvcTest(GroupController.class) class GroupControllerTest extends RestDocsTest { @@ -172,7 +174,9 @@ void deleteInvite() throws Exception { mockMvc.perform( delete("/group/invite") .contentType(MediaType.APPLICATION_JSON) - .content(toRequestBody(new DeleteGroupInviteRequest(UUID.randomUUID()))) + .content( + toRequestBody( + new DeleteGroupInviteRequest(UUID.randomUUID()))) .header( "Authorization", "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); @@ -182,7 +186,11 @@ void deleteInvite() throws Exception { // docs perform.andDo(print()) - .andDo(document("delete group invite", getDocumentRequest(), getDocumentResponse())); + .andDo( + document( + "delete group invite", + getDocumentRequest(), + getDocumentResponse())); } @Test diff --git a/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java b/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java index 1a59a6a5..19e1efdc 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/repository/GroupRepositoryTest.java @@ -1,5 +1,7 @@ package com.twtw.backend.domain.group.repository; +import static org.assertj.core.api.Assertions.assertThat; + import com.twtw.backend.domain.group.entity.Group; import com.twtw.backend.domain.group.entity.GroupMember; import com.twtw.backend.domain.member.entity.Member; @@ -10,6 +12,7 @@ import com.twtw.backend.fixture.member.MemberEntityFixture; import com.twtw.backend.fixture.place.PlaceEntityFixture; import com.twtw.backend.support.repository.RepositoryTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -17,8 +20,6 @@ import java.time.LocalDateTime; import java.util.List; -import static org.assertj.core.api.Assertions.assertThat; - @DisplayName("GroupRepository의") class GroupRepositoryTest extends RepositoryTest { diff --git a/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java b/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java index ab352cc6..335d50b5 100644 --- a/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/group/service/GroupServiceTest.java @@ -1,5 +1,7 @@ package com.twtw.backend.domain.group.service; +import static org.assertj.core.api.Assertions.assertThat; + import com.twtw.backend.domain.group.dto.request.InviteGroupRequest; import com.twtw.backend.domain.group.dto.request.JoinGroupRequest; import com.twtw.backend.domain.group.dto.request.MakeGroupRequest; @@ -13,14 +15,13 @@ import com.twtw.backend.domain.member.entity.Member; import com.twtw.backend.fixture.member.MemberEntityFixture; import com.twtw.backend.support.service.LoginTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; -import static org.assertj.core.api.Assertions.assertThat; - @DisplayName("GroupService의") class GroupServiceTest extends LoginTest { @Autowired private GroupService groupService; diff --git a/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java b/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java index 2eae1dad..0f2ef619 100644 --- a/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/plan/controller/PlanControllerTest.java @@ -1,5 +1,17 @@ package com.twtw.backend.domain.plan.controller; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; +import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import com.twtw.backend.domain.group.dto.response.GroupInfoResponse; import com.twtw.backend.domain.member.dto.response.MemberResponse; import com.twtw.backend.domain.place.entity.CategoryGroupCode; @@ -13,6 +25,7 @@ import com.twtw.backend.domain.plan.dto.response.PlanResponse; import com.twtw.backend.domain.plan.service.PlanService; import com.twtw.backend.support.docs.RestDocsTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -24,17 +37,6 @@ import java.util.List; import java.util.UUID; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentRequest; -import static com.twtw.backend.support.docs.ApiDocsUtils.getDocumentResponse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @DisplayName("PlanController의") @WebMvcTest(PlanController.class) class PlanControllerTest extends RestDocsTest { @@ -204,9 +206,7 @@ void joinPlan() throws Exception { mockMvc.perform( post("/plans/join") .contentType(MediaType.APPLICATION_JSON) - .content( - toRequestBody( - new PlanMemberRequest(UUID.randomUUID()))) + .content(toRequestBody(new PlanMemberRequest(UUID.randomUUID()))) .header( "Authorization", "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); @@ -230,9 +230,7 @@ void invitePlan() throws Exception { mockMvc.perform( post("/plans/invite") .contentType(MediaType.APPLICATION_JSON) - .content( - toRequestBody( - new PlanMemberRequest(UUID.randomUUID()))) + .content(toRequestBody(new PlanMemberRequest(UUID.randomUUID()))) .header( "Authorization", "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); @@ -255,9 +253,7 @@ void deleteInvite() throws Exception { mockMvc.perform( delete("/plans/invite") .contentType(MediaType.APPLICATION_JSON) - .content( - toRequestBody( - new PlanMemberRequest(UUID.randomUUID()))) + .content(toRequestBody(new PlanMemberRequest(UUID.randomUUID()))) .header( "Authorization", "Bearer wefa3fsdczf32.gaoiuergf92.gb5hsa2jgh")); diff --git a/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java b/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java index 209c1bba..daf668fe 100644 --- a/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java +++ b/backend/src/test/java/com/twtw/backend/domain/plan/service/PlanServiceTest.java @@ -1,5 +1,7 @@ package com.twtw.backend.domain.plan.service; +import static org.assertj.core.api.Assertions.assertThat; + import com.twtw.backend.domain.group.repository.GroupRepository; import com.twtw.backend.domain.member.entity.Member; import com.twtw.backend.domain.place.entity.CategoryGroupCode; @@ -16,6 +18,7 @@ import com.twtw.backend.fixture.place.PlaceEntityFixture; import com.twtw.backend.fixture.plan.PlanEntityFixture; import com.twtw.backend.support.service.LoginTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -24,8 +27,6 @@ import java.util.Optional; import java.util.UUID; -import static org.assertj.core.api.Assertions.assertThat; - @DisplayName("PlanService의") class PlanServiceTest extends LoginTest {