-
Notifications
You must be signed in to change notification settings - Fork 2
feat: 크루 참여 요청 수락 및 거절 기능 추가 #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
48bc215
324b72a
f635476
8426fcb
5a9e34a
de4ec16
f6ea90e
6dba95b
8d8dc62
3088aad
958b4a4
3616265
751e3d0
7dc18be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,37 @@ | ||
| package com.retrip.crew.application.in; | ||
|
|
||
| import com.retrip.crew.application.in.request.CreateDemandRequest; | ||
| import com.retrip.crew.application.in.request.CrewCreateRequest; | ||
| import com.retrip.crew.application.in.request.CrewOrder; | ||
| import com.retrip.crew.application.in.request.CrewUpdateRequest; | ||
| import com.retrip.crew.application.in.response.*; | ||
| import com.retrip.crew.application.in.request.crew.CrewCreateRequest; | ||
| import com.retrip.crew.application.in.request.crew.CrewOrder; | ||
| import com.retrip.crew.application.in.request.crew.CrewUpdateRequest; | ||
| import com.retrip.crew.application.in.request.demand.CreateDemandRequest; | ||
| import com.retrip.crew.application.in.request.demand.DemandOrder; | ||
| import com.retrip.crew.application.in.response.crew.CrewCreateResponse; | ||
| import com.retrip.crew.application.in.response.crew.CrewDetailResponse; | ||
| import com.retrip.crew.application.in.response.crew.CrewListResponse; | ||
| import com.retrip.crew.application.in.response.crew.CrewUpdateResponse; | ||
| import com.retrip.crew.application.in.response.demand.*; | ||
| import com.retrip.crew.application.in.usecase.GetCrewUseCase; | ||
| import com.retrip.crew.application.in.usecase.ManageCrewUseCase; | ||
| import com.retrip.crew.application.in.usecase.ManageDemandUseCase; | ||
| import com.retrip.crew.application.in.usecase.UpdateRecruitmentUseCase; | ||
| import com.retrip.crew.application.out.repository.CrewDemandRepository; | ||
| import com.retrip.crew.application.out.repository.CrewMemberRepository; | ||
| import com.retrip.crew.application.out.repository.CrewQueryRepository; | ||
| import com.retrip.crew.application.out.repository.CrewRepository; | ||
| import com.retrip.crew.domain.entity.Crew; | ||
| import com.retrip.crew.domain.entity.Demand; | ||
| import com.retrip.crew.domain.entity.Recruitment; | ||
| import com.retrip.crew.domain.exception.CrewNotFoundException; | ||
| import com.retrip.crew.domain.exception.NotCrewLeaderException; | ||
| import com.retrip.crew.domain.exception.common.BusinessException; | ||
| import com.retrip.crew.domain.exception.common.EntityNotFoundException; | ||
| import com.retrip.crew.domain.vo.CrewDescription; | ||
| import com.retrip.crew.domain.vo.CrewTitle; | ||
| import com.retrip.crew.domain.vo.DemandStatus; | ||
| import com.retrip.crew.infra.adapter.in.presentation.rest.common.ScrollPageResponse; | ||
| import com.retrip.crew.infra.util.PaginationUtils; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.data.domain.Pageable; | ||
| import org.springframework.data.domain.Slice; | ||
| import org.springframework.stereotype.Service; | ||
|
|
@@ -35,6 +46,7 @@ public class CrewService implements ManageCrewUseCase, UpdateRecruitmentUseCase, | |
| private final CrewRepository crewRepository; | ||
| private final CrewMemberRepository crewMemberRepository; | ||
| private final CrewQueryRepository crewQueryRepository; | ||
| private final CrewDemandRepository demandRepository; | ||
|
|
||
| @Override | ||
| public CrewCreateResponse createCrew(CrewCreateRequest request) { | ||
|
|
@@ -75,6 +87,59 @@ public CreateDemandResponse createDemand(UUID crewId, CreateDemandRequest reques | |
| return CreateDemandResponse.of(crew.getId(), demand); | ||
| } | ||
|
|
||
| @Override | ||
| public Page<DemandsResponse> getDemands( | ||
| UUID crewId, UUID memberId, String status, Pageable pageable, DemandOrder order, String sort) { | ||
| Crew crew = findById(crewId); | ||
| throwIfNotLeader(crew, memberId, new NotCrewLeaderException()); | ||
| Page<Demand> demands = demandRepository.findByCrewIdAndStatus( | ||
| crewId, DemandStatus.valueOf(status), PaginationUtils.createPageRequest(pageable, order.getField(), sort)); | ||
| return demands.map(d -> DemandsResponse.of(crewId, d)); | ||
| } | ||
|
|
||
| @Override | ||
| public Page<CrewsOfDemandResponse> getCrewsOfDemand( | ||
| UUID crewId, UUID demandId, UUID memberId, Pageable pageable, CrewOrder order, String sort) { | ||
| Crew crew = findById(crewId); | ||
| throwIfNotLeader(crew, memberId, new NotCrewLeaderException()); | ||
| Demand demand = findDemandByIdAndCrewId(demandId, crewId); | ||
| return crewQueryRepository.findAllContainsMember(pageable, demand.getMemberId()); | ||
| } | ||
|
|
||
| private static void throwIfNotLeader(Crew crew, UUID memberId, BusinessException exception) { | ||
| if (!crew.getCrewMembers().isLeader(memberId)) { | ||
| throw exception; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void cancelDemand(UUID crewId, UUID demandId, UUID memberId) { | ||
| Demand demand = findDemandByIdAndCrewId(demandId, crewId); | ||
| Crew crew = demand.getCrew(); | ||
| crew.cancelDemand(demand); | ||
| } | ||
|
|
||
| @Override | ||
| public RejectDemandResponse rejectDemand(UUID crewId, UUID demandId, UUID memberId) { | ||
| Demand demand = findDemandByIdAndCrewId(demandId, crewId); | ||
| Crew crew = demand.getCrew(); | ||
| crew.rejectDemand(demand); | ||
| return RejectDemandResponse.of(demand); | ||
| } | ||
|
|
||
| @Override | ||
| public ApproveDemandResponse approveDemand(UUID crewId, UUID demandId, UUID memberId) { | ||
| Demand demand = findDemandByIdAndCrewId(demandId, crewId); | ||
| Crew crew = demand.getCrew(); | ||
| crew.approveDemand(demand); | ||
| return ApproveDemandResponse.of(demand); | ||
| } | ||
|
|
||
| private Demand findDemandByIdAndCrewId(UUID demandId, UUID crewId) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CrewId까지 Join한 이유가 궁금합니다~
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. crew는 approveDemand를 호출하기 위해 필요하고 demand를 조회할때 crewId를 파라미터로 사용한 이유는 크루에 해당하는 demand를 안전하게 조회하기 위함입니다. 또한 demand에서 crewId는 외래키이기 때문에 조인은 되지 않습니다.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2테이블을 Join 조회 한 후, Demand에 대한 정보만 조회한다면, Query 1번 만으로 가능할 거 같아서요!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이해했습니다. crew를 조회할때 demand도 함께 가져오는게 좋겠네요. |
||
| return demandRepository.findCrewByIdAndCrewId(demandId, crewId) | ||
| .orElseThrow(() -> new EntityNotFoundException("참여 요청 엔티티를 찾을 수 없습니다.")); | ||
| } | ||
|
|
||
| @Override | ||
| @Transactional(readOnly = true) | ||
| public ScrollPageResponse<CrewListResponse> getCrews(Pageable pageable, String keyword, CrewOrder order, String sort) { | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.retrip.crew.application.in.request.demand; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| @Schema(description = "크루 참여 요청 생성 Request") | ||
| public record CreateDemandRequest( | ||
| UUID memberId | ||
| ) { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.retrip.crew.application.in.request.demand; | ||
|
|
||
| import lombok.Getter; | ||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| @Getter | ||
| @RequiredArgsConstructor | ||
| public enum DemandOrder { | ||
| DATE("createdAt"); | ||
|
|
||
| private final String field; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package com.retrip.crew.application.in.response.demand; | ||
|
|
||
| import com.retrip.crew.domain.entity.Demand; | ||
| import com.retrip.crew.domain.vo.DemandStatus; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| @Schema(description = "크루 참여 요청 승인 Response") | ||
| public record ApproveDemandResponse( | ||
| @Schema(description = "크루 ID") | ||
| UUID crewId, | ||
|
|
||
| @Schema(description = "참여 요청 ID") | ||
| UUID demandId, | ||
|
|
||
| @Schema(description = "참여 요청자 ID") | ||
| UUID memberId, | ||
|
|
||
| @Schema(description = "참여 요청 상태") | ||
| DemandStatus status | ||
| ) { | ||
| public static ApproveDemandResponse of(Demand demand) { | ||
| return new ApproveDemandResponse(demand.getCrew().getId(), demand.getId(), demand.getMemberId(), demand.getStatus()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.retrip.crew.application.in.response.demand; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| @Schema(description = "참여자가 속한 크루 목록 조회 Response") | ||
| public record CrewsOfDemandResponse( | ||
| @Schema(description = "참여 요청자 ID") | ||
| UUID memberId, | ||
|
|
||
| @Schema(description = "크루 ID") | ||
| UUID id, | ||
|
|
||
| @Schema(description = "크루 타이틀") | ||
| String title, | ||
|
|
||
| @Schema(description = "크루 리더 ID") | ||
| UUID leaderId, | ||
|
|
||
| @Schema(description = "크루원 현재 인원수") | ||
| long memberCount, | ||
|
|
||
| @Schema(description = "크루원 최대 인원수") | ||
| int maxMemberCount | ||
| ) { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package com.retrip.crew.application.in.response.demand; | ||
|
|
||
| import com.retrip.crew.domain.entity.Demand; | ||
| import com.retrip.crew.domain.vo.DemandStatus; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| @Schema(description = "참여 요청 목록 조회 Response") | ||
| public record DemandsResponse( | ||
| @Schema(description = "크루 ID") | ||
| UUID crewId, | ||
|
|
||
| @Schema(description = "참여 요청 ID") | ||
| UUID demandId, | ||
|
|
||
| @Schema(description = "참여 요청자 ID") | ||
| UUID memberId, | ||
|
|
||
| @Schema(description = "참여 요청 상태") | ||
| DemandStatus status | ||
| ) { | ||
| public static DemandsResponse of(UUID crewId, Demand demand) { | ||
| return new DemandsResponse(crewId, demand.getId(), demand.getMemberId(), demand.getStatus()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package com.retrip.crew.application.in.response.demand; | ||
|
|
||
| import com.retrip.crew.domain.entity.Demand; | ||
| import com.retrip.crew.domain.vo.DemandStatus; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| @Schema(description = "크루 참여 요청 거절 Response") | ||
| public record RejectDemandResponse( | ||
| @Schema(description = "크루 ID") | ||
| UUID crewId, | ||
|
|
||
| @Schema(description = "참여 요청 ID") | ||
| UUID demandId, | ||
|
|
||
| @Schema(description = "참여 요청자 ID") | ||
| UUID memberId, | ||
|
|
||
| @Schema(description = "참여 요청 상태") | ||
| DemandStatus status | ||
| ) { | ||
| public static RejectDemandResponse of(Demand demand) { | ||
| return new RejectDemandResponse(demand.getCrew().getId(), demand.getId(), demand.getMemberId(), demand.getStatus()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,25 @@ | ||
| package com.retrip.crew.application.in.usecase; | ||
|
|
||
| import com.retrip.crew.application.in.request.CreateDemandRequest; | ||
| import com.retrip.crew.application.in.response.CreateDemandResponse; | ||
| import com.retrip.crew.application.in.request.demand.CreateDemandRequest; | ||
| import com.retrip.crew.application.in.request.crew.CrewOrder; | ||
| import com.retrip.crew.application.in.request.demand.DemandOrder; | ||
| import com.retrip.crew.application.in.response.demand.*; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.data.domain.Pageable; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| public interface ManageDemandUseCase { | ||
| CreateDemandResponse createDemand(UUID crewId, CreateDemandRequest request); | ||
|
|
||
| Page<DemandsResponse> getDemands( | ||
| UUID crewId, UUID memberId, String status, Pageable pageable, DemandOrder order, String sort); | ||
|
|
||
| Page<CrewsOfDemandResponse> getCrewsOfDemand(UUID crewId, UUID demandId, UUID memberId, Pageable pageable, CrewOrder order, String sort); | ||
|
|
||
| void cancelDemand(UUID crewId, UUID demandId, UUID memberId); | ||
|
|
||
| RejectDemandResponse rejectDemand(UUID crewId, UUID demandId, UUID memberId); | ||
|
|
||
| ApproveDemandResponse approveDemand(UUID crewId, UUID demandId, UUID memberId); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 코드가 서비스 로직에 있는것이 맞는걸까요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
조회를 위한 검증이라 entity로 옮기긴 애매할것 같아요. 생각나는 좋은 방법 있으신가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
엔티티에 있으면 좋을 것 같다고 생각하긴 했는데.. 말씀주신대로 조회를 위한 검증이라 서비스에 있는것이 좋을 것 같습니다.
추가로 Crew 조회 시, Crew Member와 같이 Fetch 조인하면, Query를 1번만 호출할 거 같네요!