Skip to content

Commit

Permalink
Merge pull request #81 from HongDam-org/feat/plan-group-invite
Browse files Browse the repository at this point in the history
[FEAT] 그룹, 계획 초대 중복 제거 및 초대 승락/삭제 api 추가
  • Loading branch information
ohksj77 authored Dec 23, 2023
2 parents 1bc638d + a1b1cb6 commit b75b054
Show file tree
Hide file tree
Showing 17 changed files with 234 additions and 74 deletions.
3 changes: 3 additions & 0 deletions backend/src/docs/group.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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']

Expand Down
6 changes: 6 additions & 0 deletions backend/src/docs/plan.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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']

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
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.*;
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.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;
Expand Down Expand Up @@ -53,6 +45,13 @@ public ResponseEntity<GroupInfoResponse> inviteGroup(
return ResponseEntity.ok(groupService.inviteGroup(inviteGroupRequest));
}

@DeleteMapping("/invite")
public ResponseEntity<Void> deleteInvite(
@RequestBody DeleteGroupInviteRequest deleteGroupInviteRequest) {
groupService.deleteInvite(deleteGroupInviteRequest);
return ResponseEntity.noContent().build();
}

@PostMapping("/share/{id}")
public ResponseEntity<Void> shareLocation(@PathVariable UUID id) {
groupService.shareLocation(id);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,21 @@ public void inviteAll(final List<Member> friends) {
friends.forEach(friend -> addGroupMember(new GroupMember(this, friend)));
}

private boolean addGroupMember(final GroupMember groupMember) {
return this.groupMembers.add(groupMember);
public List<GroupMember> 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(
Expand All @@ -100,4 +113,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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -155,4 +151,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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,21 @@ public ResponseEntity<Void> deletePlanById(@PathVariable UUID id) {
return ResponseEntity.noContent().build();
}

@PostMapping("/invite")
public ResponseEntity<PlanResponse> invitePlan(@RequestBody PlanMemberRequest request) {
return ResponseEntity.ok(planService.invitePlan(request));
}

@DeleteMapping("/invite")
public ResponseEntity<Void> deleteInvite(@RequestBody PlanMemberRequest request) {
planService.deleteInvite(request);
return ResponseEntity.noContent().build();
}

@PostMapping("/join")
public ResponseEntity<PlanResponse> joinPlan(@RequestBody PlanMemberRequest request) {
return ResponseEntity.ok(planService.joinPlan(request));
public ResponseEntity<Void> joinPlan(@RequestBody PlanMemberRequest request) {
planService.joinPlan(request);
return ResponseEntity.noContent().build();
}

@PostMapping("/out")
Expand Down
38 changes: 25 additions & 13 deletions backend/src/main/java/com/twtw/backend/domain/plan/entity/Plan.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,7 @@
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;
Expand All @@ -33,6 +22,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

@Getter
@Entity
Expand Down Expand Up @@ -74,11 +64,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<PlanMember> 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);
Expand Down Expand Up @@ -126,4 +127,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));
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,12 @@
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.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.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;
Expand Down Expand Up @@ -168,6 +163,36 @@ 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void makeGroup() {
final Group saveGroup = groupRepository.save(group);

// then
assertThat(saveGroup.getGroupMembers()).hasSize(2);
assertThat(saveGroup.getGroupMembers()).hasSize(1);
}

@Test
Expand Down
Loading

0 comments on commit b75b054

Please sign in to comment.