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
40 changes: 38 additions & 2 deletions src/main/java/com/retrip/crew/application/in/CrewService.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,60 @@
package com.retrip.crew.application.in;

import com.retrip.crew.application.in.request.CrewCreateRequest;
import com.retrip.crew.application.in.request.CrewOrder;
import com.retrip.crew.application.in.response.CrewCreateResponse;
import com.retrip.crew.application.in.response.CrewDetailResponse;
import com.retrip.crew.application.in.response.CrewListResponse;
import com.retrip.crew.application.in.usecase.CreateCrewUseCase;
import com.retrip.crew.application.in.usecase.GetCrewUseCase;
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 jakarta.transaction.Transactional;
import com.retrip.crew.domain.exception.CrewNotFoundException;
import com.retrip.crew.infra.adapter.in.presentation.rest.common.ScrollPageResponse;
import com.retrip.crew.infra.util.PaginationUtils;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class CrewService implements CreateCrewUseCase {
public class CrewService implements CreateCrewUseCase, GetCrewUseCase {
private final CrewRepository crewRepository;
private final CrewMemberRepository crewMemberRepository;
private final CrewQueryRepository crewQueryRepository;

@Override
public CrewCreateResponse createCrew(CrewCreateRequest request) {
Crew crew = crewRepository.save(request.to(request.leader()));

return CrewCreateResponse.of(crew);
}

@Override
@Transactional(readOnly = true)
public ScrollPageResponse<CrewListResponse> getCrews(Pageable pageable, String keyword, CrewOrder order, String sort) {
Pageable orderPageable = PaginationUtils.createPageRequest(pageable, order.getField(), sort);
Slice<CrewListResponse> result = crewQueryRepository.getCrews(orderPageable, keyword);
Long totalCount = crewQueryRepository.getCrewCount(keyword);
return ScrollPageResponse.of(totalCount, result.hasNext(), result.getContent());
}

@Override
@Transactional(readOnly = true)
public CrewDetailResponse getCrewDetail(UUID crewId) {
Crew crew = findById(crewId);
int memberCount = crewMemberRepository.countByCrewId(crewId);
return CrewDetailResponse.of(crew, memberCount);
}

private Crew findById(UUID crewId){
return crewRepository.findById(crewId)
.orElseThrow(CrewNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.retrip.crew.domain.entity.Crew;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;

import java.util.UUID;
Expand All @@ -15,10 +16,13 @@ public record CrewCreateRequest(
String title,
@Schema(description = "크루 설명")
@Size(min = 1, max = 500)
String description
String description,
@Schema(description = "크루 최대 인원")
@Min(1)
int maxMembers
){

public Crew to(UUID leader) {
return Crew.create(this.title, this.description, leader);
return Crew.create(this.title, this.description, this.maxMembers, leader);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.retrip.crew.application.in.request;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum CrewOrder {
DATE("createdAt");

private final String field;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static CrewCreateResponse of(Crew crew) {
return new CrewCreateResponse(
crew.getId(),
crew.getTitle().getValue(),
crew.getDescription().getValue(),
crew.getDescription(),
crew.getLeader().getId()
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.retrip.crew.application.in.response;

import com.retrip.crew.domain.entity.Crew;
import com.retrip.crew.domain.entity.CrewMember;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import java.util.UUID;
import lombok.Builder;

@Schema
@Builder
public record CrewDetailResponse(
@Schema(description = "크루 ID")
UUID id,

@Schema(description = "크루 타이틀")
String title,

@Schema(description = "크루 설명")
String description,

@Schema(description = "크루 리더 ID")
UUID leaderId,

@Schema(description = "크루원 현재 인원수")
Integer memberCount,

@Schema(description = "크루원 수용가능한 최대 인원수")
Integer maxMemberCount,

@Schema(description = "크루원 리스트")
List<CrewMemberResponse> members
) {

public static CrewDetailResponse of(Crew crew, int memberCount){
return CrewDetailResponse.builder()
.id(crew.getId())
.title(crew.getTitle().getValue())
.description(crew.getDescription())
.leaderId(crew.getLeader().getMemberId())
.memberCount(memberCount)
.maxMemberCount(crew.getMaxMembers())
.members(toList(crew.getCrewMembers().getValues()))
.build();
}

public static List<CrewMemberResponse> toList(List<CrewMember> crewMembers){
return crewMembers.stream()
.map(CrewMemberResponse::from)
.toList();
}

@Schema
public record CrewMemberResponse(

@Schema(description = "크루 멤버 고유 ID")
UUID id,

@Schema(description = "크루원 ID")
UUID memberId,

@Schema(description = "크루원 역할코드")
String roleCode,

@Schema(description = "크루원 역할명")
String roleName
){
public static CrewMemberResponse from(CrewMember crewMember){
return new CrewMemberResponse(
crewMember.getId(),
crewMember.getMemberId(),
crewMember.getCrewMemberRole().getCode(),
crewMember.getCrewMemberRole().getViewName()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.retrip.crew.application.in.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.UUID;

@Schema(description = "크루 리스트 조회 Response")
public record CrewListResponse(
@Schema(description = "크루 ID")
UUID id,

@Schema(description = "크루 타이틀")
String title,

@Schema(description = "크루 리더 ID")
UUID leaderId,

@Schema(description = "크루원 현재 인원수")
Long memberCount,

@Schema(description = "크루원 수용가능한 최대 인원수")
Integer maxMemberCount
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.retrip.crew.application.in.usecase;

import com.retrip.crew.application.in.request.CrewOrder;
import com.retrip.crew.application.in.response.CrewDetailResponse;
import com.retrip.crew.application.in.response.CrewListResponse;
import com.retrip.crew.infra.adapter.in.presentation.rest.common.ScrollPageResponse;
import java.util.UUID;
import org.springframework.data.domain.Pageable;

public interface GetCrewUseCase {
ScrollPageResponse<CrewListResponse> getCrews(Pageable pageable, String keyword, CrewOrder order, String sort);

CrewDetailResponse getCrewDetail(UUID crewId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.retrip.crew.application.out.repository;

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

public interface CrewMemberRepository extends JpaRepository<CrewMember, UUID> {
int countByCrewId(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.application.in.response.CrewListResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

public interface CrewQueryRepository {
Slice<CrewListResponse> getCrews(Pageable pageable, String keyword);
Long getCrewCount(String keyword);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.retrip.crew.application.out.repository;


import com.retrip.crew.domain.entity.Crew;
import org.springframework.data.jpa.repository.JpaRepository;

Expand Down
19 changes: 11 additions & 8 deletions src/main/java/com/retrip/crew/domain/entity/Crew.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,24 @@
import java.util.UUID;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Crew extends BaseEntity {
@Id
@Column(columnDefinition = "varbinary(16)")
@Getter
private UUID id;

@Getter
@Embedded
private CrewTitle title;

@Embedded
@Getter
private CrewDescription description;


@Embedded
private CrewMembers crewMembers;

@Column(name = "max_members", nullable = false)
private int maxMembers;
Copy link
Collaborator

Choose a reason for hiding this comment

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

해당 필드를 이 이슈에서 추가한 이유가 있을까요??
작업 내용에는 없는것 같아서.. 만약 추가된다면 작업 내용에 스토리 적는게 좋을거 같습니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

크루도 최대 받을수 있는 인원이 정해져있는데 크루 리스트 조회할때 사용자가 최대인원과 현재 가입되어있는 인원 ex ) 2/10 이렇게 보여야하기에 필요해서 추가했습니다


@Embedded
private Posts posts;
Expand All @@ -39,26 +38,30 @@ public class Crew extends BaseEntity {
@Embedded
private Introductions introductions;


@Version
private long version;

private Crew(String name, String description, UUID leader) {
private Crew(String name, String description, int maxMembers, UUID leader) {
this.id = UUID.randomUUID();
this.title = new CrewTitle(name);
this.description = new CrewDescription(description);
this.maxMembers = maxMembers;
this.crewMembers = new CrewMembers(this, leader);
this.posts = new Posts();
this.announcements = new Announcements();
this.introductions = new Introductions();
}

public static Crew create(String title, String description, UUID leader) {
return new Crew(title, description, leader);
public static Crew create(String title, String description, int maxMembers, UUID leader) {
return new Crew(title, description, maxMembers, leader);
}

public CrewMember getLeader() {
return crewMembers.getLeader();
}

public String getDescription(){
return description.getValue();
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
package com.retrip.crew.infra.adapter.in.presentation.rest;

import com.retrip.crew.application.in.request.CrewCreateRequest;
import com.retrip.crew.application.in.request.CrewOrder;
import com.retrip.crew.application.in.response.CrewCreateResponse;
import com.retrip.crew.application.in.response.CrewDetailResponse;
import com.retrip.crew.application.in.response.CrewListResponse;
import com.retrip.crew.application.in.usecase.CreateCrewUseCase;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.retrip.crew.application.in.usecase.GetCrewUseCase;
import com.retrip.crew.infra.adapter.in.presentation.rest.common.ApiResponse;
import com.retrip.crew.infra.adapter.in.presentation.rest.common.ScrollPageResponse;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand All @@ -17,11 +27,33 @@
@Tag(name = "Crew", description = "크루 서비스")
public class CrewController {
private final CreateCrewUseCase createCrewUseCase;
private final GetCrewUseCase getCrewUseCase;

@PostMapping
@Schema(description = "크루 생성")
public ResponseEntity<CrewCreateResponse> createCrew(@RequestBody CrewCreateRequest request) {
CrewCreateResponse crew = createCrewUseCase.createCrew(request);
return ResponseEntity.created(URI.create("/crews/" + crew.id())).body(crew);
}

@GetMapping
@Schema(description = "크루 리스트 조회")
public ResponseEntity<ApiResponse<ScrollPageResponse<CrewListResponse>>> getCrews(
@RequestParam(name = "keyword", required = false) String keyword,
@RequestParam(name = "order", defaultValue = "DATE") CrewOrder order,
@RequestParam(name = "sort", defaultValue = "asc") String sort,
@PageableDefault(size = 10) Pageable pageable
) {
ScrollPageResponse<CrewListResponse> response = getCrewUseCase.getCrews(pageable, keyword, order, sort);
return ResponseEntity.ok().body(ApiResponse.ok(response));
}

@GetMapping("/{crewId}")
@Schema(description = "크루 상세 조회")
public ResponseEntity<ApiResponse<CrewDetailResponse>> getCrewDetail(
@PathVariable("crewId") UUID crewId
) {
CrewDetailResponse response = getCrewUseCase.getCrewDetail(crewId);
return ResponseEntity.ok().body(ApiResponse.ok(response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.retrip.crew.infra.adapter.in.presentation.rest.common;

import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ScrollPageResponse<T> {
private Long totalCount;
private boolean hasNext;
private List<T> list;

public static <T> ScrollPageResponse<T> of(Long totalCount, boolean hasNext, List<T> list) {
return new ScrollPageResponse<>(totalCount, hasNext, list);
}
}
Loading