Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/main/java/com/retrip/crew/application/in/CrewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.retrip.crew.domain.vo.IntroductionTitle;
import com.retrip.crew.infra.adapter.in.presentation.rest.common.ScrollPageResponse;
import com.retrip.crew.infra.util.PaginationUtils;
import java.util.List;
import lombok.RequiredArgsConstructor;
import java.util.UUID;
import org.springframework.data.domain.Pageable;
Expand All @@ -40,6 +41,7 @@ public class CrewService implements ManageCrewUseCase, GetCrewUseCase, ManageInt
private final CrewMemberRepository crewMemberRepository;
private final CrewQueryRepository crewQueryRepository;
private final IntroductionRepository introductionRepository;
private final CrewBanMemberRepository crewBanMemberRepository;
private final IntroductionQueryRepository introductionQueryRepository;

@Override
Expand Down Expand Up @@ -154,4 +156,24 @@ public void deleteCrew(UUID crewId, UUID loginMemberId) {
Crew crew = findCrewById(crewId);
crew.softDelete(loginMemberId);
}

@Override
public void expelMember(UUID loginMemberId, UUID crewId, UUID expellerId) {
Crew crew = findCrewById(crewId);
crew.expelMember(loginMemberId, expellerId);
}

@Override
public void banMember(UUID loginMemberId, UUID crewId, UUID bannedMemberId) {
Crew crew = findCrewById(crewId);
crew.banMember(loginMemberId, bannedMemberId);
}
Comment on lines +166 to +170
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

차단 후에 어떤 데이터를 api 응답으로 보내주는게 맞을지 같이 고민해보는게 좋겠어요


@Override
public CrewBanListResponse getBanMembers(UUID loginMemberId, UUID crewId) {
Crew crew = findCrewById(crewId);
crew.validateCrewLeader(loginMemberId);
List<CrewBanMember> crewBanMembers = crewBanMemberRepository.findAllByCrewId(crewId);
return CrewBanListResponse.of(crewBanMembers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.retrip.crew.application.in.request.crew;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import java.util.UUID;

@Schema(description = "크루 회원 차단 Request")
public record CrewMemberBanRequest(

@Schema(description = "차단할 회원 ID")
@NotNull
UUID memberId
) {
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.retrip.crew.application.in.request.crew;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import java.util.UUID;

@Schema(description = "크루 멤버 추방 Request")
public record CrewMemberExpelRequest(

@Schema(description = "추방할 멤버 ID")
@NotNull
UUID memberId
) {
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.retrip.crew.application.in.response.crew;

import com.retrip.crew.domain.entity.CrewBanMember;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Schema(description = "크루 차단 리스트 조회 Response")
public record CrewBanListResponse(
@Schema(description = "차단한 회원 리스트")
List<BanMemberResponse> banMembers
) {
public static CrewBanListResponse of(List<CrewBanMember> crewBanMembers) {
return new CrewBanListResponse(BanMemberResponse.toList(crewBanMembers));
}

public record BanMemberResponse(
@Schema(description = "차단한 회원 ID")
UUID bannedMemberIds
){

public static List<BanMemberResponse> toList(List<CrewBanMember> crewBanMembers) {
return crewBanMembers.stream()
.map(BanMemberResponse::from)
.collect(Collectors.toList());
}

private static BanMemberResponse from(CrewBanMember crewBanMember) {
return new BanMemberResponse(crewBanMember.getMemberId());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.retrip.crew.application.in.request.crew.CrewLeaderDelegateRequest;
import com.retrip.crew.application.in.request.crew.CrewUpdateRequest;
import com.retrip.crew.application.in.request.crew.CrewWithdrawalRequest;
import com.retrip.crew.application.in.response.crew.CrewBanListResponse;
import com.retrip.crew.application.in.response.crew.CrewCreateResponse;
import com.retrip.crew.application.in.response.crew.CrewLeaderDelegateResponse;
import com.retrip.crew.application.in.response.crew.CrewUpdateResponse;
Expand All @@ -20,4 +21,11 @@ public interface ManageCrewUseCase {
CrewLeaderDelegateResponse delegateCrewLeader(UUID crewId, CrewLeaderDelegateRequest request);

void deleteCrew(UUID crewId, UUID loginMemberId);

void expelMember(UUID memberId, UUID crewId, UUID expellerId);

void banMember(UUID memberId, UUID crewId, UUID bannedMemberId);

CrewBanListResponse getBanMembers(UUID memberId, UUID crewId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.retrip.crew.application.out.repository;

import com.retrip.crew.domain.entity.CrewBanMember;
import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CrewBanMemberRepository extends ReadRepository<CrewBanMember, UUID> {
List<CrewBanMember> findAllByCrewId(UUID crewId);
}
23 changes: 23 additions & 0 deletions src/main/java/com/retrip/crew/domain/entity/Crew.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.retrip.crew.domain.entity;

import static com.retrip.crew.domain.exception.common.ErrorCode.CREW_MEMBER_BANNED_CANNOT_APPLY;

import com.retrip.crew.domain.exception.NotCrewLeaderException;
import com.retrip.crew.domain.exception.common.BusinessException;
import com.retrip.crew.domain.vo.CrewDescription;
import com.retrip.crew.domain.vo.CrewTitle;

Expand Down Expand Up @@ -45,6 +48,8 @@ public class Crew extends BaseEntity {

@Embedded private Recruitment recruitment;

@Embedded private CrewBanMembers crewBanMembers;

@Column(name = "is_deleted", nullable = false)
private boolean isDeleted = false;

Expand All @@ -57,6 +62,7 @@ private Crew(String name, String description, int maxMembers, UUID leader, List<
this.posts = new Posts();
this.announcements = new Announcements();
this.introductions = new Introductions();
this.crewBanMembers = new CrewBanMembers();
}

public static Crew create(String title, String description, int maxMembers, UUID leader, List<String> questions) {
Expand Down Expand Up @@ -86,6 +92,7 @@ public void update(CrewTitle title, CrewDescription description) {
}

public Demand demand(UUID memberId) {
validateAddDemand(this.getId(), memberId);
return recruitment.addDemand(memberId, this);
}

Expand Down Expand Up @@ -126,4 +133,20 @@ public void deleteRecruitmentQuestion(UUID memberId, RecruitmentQuestion savedQu
validateCrewLeader(memberId);
recruitment.deleteRecruitmentQuestion(savedQuestion);
}

public void expelMember(UUID loginMemberId, UUID expellerId) {
this.crewMembers.expelMember(loginMemberId, expellerId);
this.crewBanMembers.banMember(this, expellerId);
}

public void banMember(UUID loginMemberId, UUID bannedMemberId) {
validateCrewLeader(loginMemberId);
this.crewBanMembers.banMember(this, bannedMemberId);
}

private void validateAddDemand(UUID crewId, UUID memberId) {
if(this.crewBanMembers.isBan(crewId, memberId)){
throw new BusinessException(CREW_MEMBER_BANNED_CANNOT_APPLY);
}
}
}
41 changes: 41 additions & 0 deletions src/main/java/com/retrip/crew/domain/entity/CrewBanMember.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.retrip.crew.domain.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
@Getter
public class CrewBanMember extends BaseEntity {

@Id
@Column(columnDefinition = "varbinary(16)")
private UUID id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(
name = "crew_id",
nullable = false,
columnDefinition = "varbinary(16)",
foreignKey = @ForeignKey(name = "fk_crew_member_to_crew")
)
private Crew crew;

@Column(nullable = false)
private UUID memberId;

public CrewBanMember(Crew crew, UUID bannedMemberId) {
this.id = UUID.randomUUID();
this.crew = crew;
this.memberId = bannedMemberId;
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/retrip/crew/domain/entity/CrewBanMembers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.retrip.crew.domain.entity;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
@Embeddable
public class CrewBanMembers {

@OneToMany(mappedBy = "crew", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CrewBanMember> values = new ArrayList<>();

public void banMember(Crew crew, UUID bannedMemberId) {
this.values.add(createBanMember(crew, bannedMemberId));
}

private CrewBanMember createBanMember(Crew crew, UUID bannedMemberId) {
return new CrewBanMember(crew, bannedMemberId);
}

public boolean isBan(UUID crewId, UUID memberId) {
return this.values.stream()
.anyMatch(member -> crewId.equals(member.getCrew().getId()) && memberId.equals(member.getMemberId()));
}
}
30 changes: 30 additions & 0 deletions src/main/java/com/retrip/crew/domain/entity/CrewMembers.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.retrip.crew.domain.entity;

import static com.retrip.crew.domain.exception.common.ErrorCode.CREW_MEMBER_NOT_IN_CREW;

import com.retrip.crew.domain.CrewTrip;
import com.retrip.crew.domain.exception.ImpossibleWithdrawCrewException;
import com.retrip.crew.domain.exception.NotCrewLeaderException;
import com.retrip.crew.domain.exception.common.BusinessException;
import com.retrip.crew.domain.exception.common.IllegalStateException;
import com.retrip.crew.domain.exception.common.InvalidValueException;
import jakarta.persistence.CascadeType;
Expand Down Expand Up @@ -107,4 +110,31 @@ private void validatePossibleDelegate(CrewMember leader) {
throw new NotCrewLeaderException();
}
}

public void expelMember(UUID loginMemberId, UUID expellerId) {
validateCrewLeader(loginMemberId);
validateExistCrewMembers(expellerId);

CrewMember crewMemberToExpel = values.stream()
.filter(member -> expellerId.equals(member.getMemberId()))
.findFirst()
.orElseThrow(() -> new BusinessException(CREW_MEMBER_NOT_IN_CREW));

values.remove(crewMemberToExpel);
}

private void validateCrewLeader(UUID loginMemberId) {
if(!isLeader(loginMemberId)) {
throw new NotCrewLeaderException();
}
}

private void validateExistCrewMembers(UUID expellerId) {
boolean isExist = values.stream()
.anyMatch(member -> expellerId.equals(member.getMemberId()));

if(!isExist) {
throw new BusinessException(CREW_MEMBER_NOT_IN_CREW);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ public enum ErrorCode {
POST_DELETE_FAIL(FORBIDDEN, "Crew-011", "자유 게시글을 삭제할 권한이 없습니다."),
QUESTION_UPDATE_FAIL(FORBIDDEN, "Crew-012", "질문 수정 권한이 없습니다."),
QUESTION_DELETE_FAIL(FORBIDDEN, "Crew-013", "질문 삭제 권한이 없습니다."),
QUESTION_NOT_FOUND(BAD_REQUEST, "Crew-014", "질문을 찾을 수 없습니다.");

QUESTION_NOT_FOUND(BAD_REQUEST, "Crew-014", "질문을 찾을 수 없습니다."),
CREW_MEMBER_NOT_IN_CREW(BAD_REQUEST, "Crew-015","차단 대상 멤버가 해당 크루에 포함되어 있지 않습니다."),
CREW_MEMBER_BANNED_CANNOT_APPLY(HttpStatus.BAD_REQUEST, "Crew-016", "차단된 사용자는 해당 크루에 참가 신청할 수 없습니다."),
;

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,30 @@ public ApiResponse<?> deleteCrew(
manageCrewUseCase.deleteCrew(crewId, loginMemberId);
return ApiResponse.noContent();
}

@Schema(description = "크루 멤버 추방")
@DeleteMapping("/{crewId}/members/exile")
public ApiResponse<?> expelMember(@RequestParam("memberId") UUID memberId, //TODO: 추후 로그인 구현되면 이부분은 바뀔 에정
@PathVariable("crewId") UUID crewId,
@RequestBody CrewMemberExpelRequest request) {
manageCrewUseCase.expelMember(memberId, crewId, request.memberId());
return ApiResponse.noContent();
}

@Schema(description = "크루에서 회원 차단")
@PostMapping("/{crewId}/members/ban")
public ApiResponse<?> banMember(@RequestParam("memberId") UUID memberId, //TODO: 추후 로그인 구현되면 이부분은 바뀔 에정
@PathVariable("crewId") UUID crewId,
@RequestBody CrewMemberBanRequest request) {
manageCrewUseCase.banMember(memberId, crewId, request.memberId());
return ApiResponse.noContent();
}

@Schema(description = "크루 멤버 차단 목록 조회")
@GetMapping("/{crewId}/members/ban")
public ApiResponse<CrewBanListResponse> banMember(@RequestParam("memberId") UUID memberId, //TODO: 추후 로그인 구현되면 이부분은 바뀔 에정
@PathVariable("crewId") UUID crewId) {
CrewBanListResponse banMembers = manageCrewUseCase.getBanMembers(memberId, crewId);
return ApiResponse.ok(banMembers);
}
}
Loading