From 50dbae3121347b3985da10c9c100711244039064 Mon Sep 17 00:00:00 2001 From: Mingyu Song <100754581+mikekks@users.noreply.github.com> Date: Sun, 14 Jul 2024 00:00:11 +0900 Subject: [PATCH] =?UTF-8?q?feat/LS-18:=20=ED=9A=8C=EA=B3=A0=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84=20(#2?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 컨벤션 수정 * docs: 머지 전략 리드미 수정 * chore: 사용하지 않는 어노테이션 삭제 * docs: add 컨벤션 추가 * add: 예외 클래스 및 예외 타입 추가 * feat: 회고 응답 관련 로직을 위해 일급컬렉션 구현 * del: 사용하지 않는 코드 삭제 * docs: del 관련 컨벤션 추가 * chore: Space 연관관계 추가 * feat: 1. 팀 관련 로직을 위한 일급컬렉션 생성 2. 스페이스 내 회원인지 검증 로직 추가 3. 팀 멤버 수 계산 로직 추가 * feat: 회고 목록 조회 컨트롤러 구현 및 스웨거 문서화 * add: 회고 목록 조회를 위한 Dto 추가 * style: dto 위치 변경 * chore: 연관 관계 수정으로 인한 코드 변경 * feat: 회고 목록 조회 서비스 로직 구현 * docs: 협업관련 컨벤션 추가 * docs: 쿼리 관련 컨벤션 추가 * del: 팀원 수 데이터 삭제 * chore: 검증 로직 변경 --- .github/pull_request_template.md | 3 +- README.md | 6 ++- .../auth/controller/AuthController.java | 4 +- .../auth/controller/dto/SignInRequest.java | 3 +- .../auth/controller/dto/SignUpRequest.java | 3 -- .../retrospect/controller/RetrospectApi.java | 11 +++-- .../controller/RetrospectController.java | 45 +++++++++++++++---- .../dto/response/RetrospectGetResponse.java | 25 +++++++++++ .../response/RetrospectListGetResponse.java | 18 ++++++++ .../retrospect/service/RetrospectService.java | 38 +++++++++++++++- .../RetrospectCreateServiceRequest.java | 2 +- .../RetrospectGetServiceResponse.java | 16 +++++++ .../RetrospectListGetServiceResponse.java | 13 ++++++ .../domain/space/service/SpaceService.java | 11 +++-- .../MemberSpaceRelationExceptionType.java | 28 ++++++++++++ .../common/exception/SpaceExceptionType.java | 22 +++++++++ .../layer/domain/answer/entity/Answers.java | 19 ++++++++ .../answer/repository/AnswerRepository.java | 4 +- .../member/exception/MemberException.java | 10 +++++ .../member/repository/MemberRepository.java | 1 - .../repository/RetrospectRepository.java | 4 +- .../space/entity/MemberSpaceRelation.java | 9 +++- .../org/layer/domain/space/entity/Team.java | 25 +++++++++++ .../MemberSpaceRelationException.java | 10 +++++ .../space/exception/SpaceException.java | 10 +++++ .../MemberSpaceRelationRepository.java | 5 +++ .../space/repository/SpaceRepository.java | 11 ++++- 27 files changed, 322 insertions(+), 34 deletions(-) create mode 100644 layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectGetResponse.java create mode 100644 layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectListGetResponse.java rename layer-api/src/main/java/org/layer/domain/retrospect/service/dto/{ => request}/RetrospectCreateServiceRequest.java (72%) create mode 100644 layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectGetServiceResponse.java create mode 100644 layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectListGetServiceResponse.java create mode 100644 layer-common/src/main/java/org/layer/common/exception/MemberSpaceRelationExceptionType.java create mode 100644 layer-common/src/main/java/org/layer/common/exception/SpaceExceptionType.java create mode 100644 layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java create mode 100644 layer-domain/src/main/java/org/layer/domain/member/exception/MemberException.java create mode 100644 layer-domain/src/main/java/org/layer/domain/space/entity/Team.java create mode 100644 layer-domain/src/main/java/org/layer/domain/space/exception/MemberSpaceRelationException.java create mode 100644 layer-domain/src/main/java/org/layer/domain/space/exception/SpaceException.java diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f972dc01..c4463621 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -17,9 +17,10 @@ ## ⚙️ 테스트 결과 +### 발생한 쿼리 첨부 ## 👉 반영 브랜치 -- feat/# +- feat/ - closed # diff --git a/README.md b/README.md index 88d1af1b..2f1660c8 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ 3. 브랜치를 생성한 후에 작업을 진행한다. 4. 진행한 후에 커밋을 한다. 5. 작업이 완료되면 PR을 생성한다. -6. PR을 생성한 후에 팀원들에게 리뷰를 요청한다. 리뷰는 나머지 2명 모두에게 요청하되, 1명의 승인을 받으면 머지 가능한 상태가 된다. +6. PR을 생성한 후에 팀원들에게 리뷰를 요청한다. 리뷰는 PR 올린 시간 기준으로 24시간 내로는 2명의 승인, 그 이후로는 1명의 승인이 필요하다. 7. 리뷰를 받은 후에 PR을 default branch에 merge한다. 8. merge된 후, 배포를 진행한다. @@ -57,12 +57,15 @@ - issue는 노션에 생성한다. - 노션에 생성된 issue 번호를 기반으로 branch 생성 - ex) feat/#{노션이슈번호} +- dev 브랜치에 머지할 때는 브랜치 간소화 및 revert 용이성을 위해 스쿼시 머지를 진행한다. ## 🙏 Commit Convention - 유다시티 컨벤션 ``` feat: 새로운 기능 구현 +add: 기능구현까지는 아니지만 새로운 파일이 추가된 경우 +del: 기존 코드를 삭제한 경우 fix: 버그, 오류 해결 docs: README나 WIKI 등의 문서 작업 style: 코드가 아닌 스타일 변경을 하는 경우 @@ -89,6 +92,7 @@ chore: 코드 수정, 내부 파일 수정 - Controller에서 요청/응답하는 DTO와 Service에서 사용하는 DTO를 분리합니다. - Layered Architecture를 엄격하게 준수합니다. - 확장/번경에 용이하게 합니다. + - 매개변수가 5개 미만일 경우 controller-service간 Dto를 사용하지 않습니다. - 네이밍은 아래와 같이 정의합니다. - Controller DTO: `${Entity명}${복수형일 경우 List 추가}${행위 또는 상태}${Request/Response}` - Service DTO: `${Entity명}${복수형일 경우 List 추가}${행위 또는 상태}Service${Request/Response}` diff --git a/layer-api/src/main/java/org/layer/domain/auth/controller/AuthController.java b/layer-api/src/main/java/org/layer/domain/auth/controller/AuthController.java index c0d522f5..7b53b290 100644 --- a/layer-api/src/main/java/org/layer/domain/auth/controller/AuthController.java +++ b/layer-api/src/main/java/org/layer/domain/auth/controller/AuthController.java @@ -67,14 +67,14 @@ public ResponseEntity reissueToken(ReissueTokenRequest rei @DisableSwaggerSecurity //== google OAuth2 test용 API 액세스 토큰 발급 ==// - @GetMapping("oauth2/google") + @GetMapping("/oauth2/google") public String googleTest(@RequestParam("code") String code) { return googleService.getToken(code); } @DisableSwaggerSecurity //== kakao OAuth2 test용 API 액세스 토큰 발급 ==// - @GetMapping("oauth2/kakao") + @GetMapping("/oauth2/kakao") public Object kakaoLogin(@RequestParam(value = "code", required = false) String code) { return kakaoService.getToken(code); } diff --git a/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignInRequest.java b/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignInRequest.java index 2f6f149d..04c07adf 100644 --- a/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignInRequest.java +++ b/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignInRequest.java @@ -1,7 +1,6 @@ package org.layer.domain.auth.controller.dto; -import com.fasterxml.jackson.annotation.JsonProperty; import org.layer.domain.member.entity.SocialType; -public record SignInRequest(@JsonProperty("social_type") SocialType socialType) { +public record SignInRequest(SocialType socialType) { } diff --git a/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignUpRequest.java b/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignUpRequest.java index dabb82b6..8247cca7 100644 --- a/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignUpRequest.java +++ b/layer-api/src/main/java/org/layer/domain/auth/controller/dto/SignUpRequest.java @@ -1,9 +1,6 @@ package org.layer.domain.auth.controller.dto; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; import org.layer.domain.member.entity.SocialType; -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public record SignUpRequest(SocialType socialType, String name) { } diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectApi.java b/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectApi.java index 2fbc25b4..d9cbe3df 100644 --- a/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectApi.java +++ b/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectApi.java @@ -1,6 +1,8 @@ package org.layer.domain.retrospect.controller; +import org.layer.common.annotation.MemberId; import org.layer.domain.retrospect.controller.dto.request.RetrospectCreateRequest; +import org.layer.domain.retrospect.controller.dto.response.RetrospectListGetResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -12,7 +14,10 @@ @Tag(name = "회고", description = "회고 관련 API") public interface RetrospectApi { - @Operation(summary = "회고 생성", description = "") - ResponseEntity createRetrospect(@PathVariable("spaceId") Long spaceId, - @RequestBody @Valid RetrospectCreateRequest request); + @Operation(summary = "회고 생성", description = "") + ResponseEntity createRetrospect(@PathVariable("spaceId") Long spaceId, + @RequestBody @Valid RetrospectCreateRequest request, @MemberId Long memberId); + + @Operation(summary = "회고 목록 조회", description = "특정 팀 스페이스에서 작성했던 회고 목록을 보는 기능입니다.") + ResponseEntity getRetrospects(@PathVariable("spaceId") Long spaceId, @MemberId Long memberId); } diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectController.java b/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectController.java index bceab944..109c347f 100644 --- a/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectController.java +++ b/layer-api/src/main/java/org/layer/domain/retrospect/controller/RetrospectController.java @@ -1,8 +1,16 @@ package org.layer.domain.retrospect.controller; +import java.util.List; + +import org.layer.common.annotation.MemberId; +import org.layer.domain.retrospect.controller.dto.response.RetrospectGetResponse; +import org.layer.domain.retrospect.controller.dto.response.RetrospectListGetResponse; import org.layer.domain.retrospect.service.RetrospectService; import org.layer.domain.retrospect.controller.dto.request.RetrospectCreateRequest; +import org.layer.domain.retrospect.service.dto.response.RetrospectListGetServiceResponse; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +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; @@ -17,14 +25,35 @@ @RequestMapping("/space/{spaceId}/retrospect") public class RetrospectController implements RetrospectApi { - private final RetrospectService retrospectService; + private final RetrospectService retrospectService; + + @Override + @PostMapping + @PreAuthorize("isAuthenticated()") + public ResponseEntity createRetrospect( + @PathVariable("spaceId") Long spaceId, + @RequestBody @Valid RetrospectCreateRequest request, + @MemberId Long memberId) { + + retrospectService.create(spaceId, request.formId(), request.title(), request.introduction()); + return ResponseEntity.ok(null); + } + + @Override + @GetMapping + @PreAuthorize("isAuthenticated()") + public ResponseEntity getRetrospects(@PathVariable("spaceId") Long spaceId, + @MemberId Long memberId) { + + RetrospectListGetServiceResponse serviceResponse = retrospectService.getRetrospects(spaceId, memberId); + + List retrospectGetResponses = serviceResponse.retrospects().stream() + .map(r -> RetrospectGetResponse.of(r.title(), r.introduction(), r.isWrite(), r.retrospectStatus(), + r.writeCount())) + .toList(); - @Override - @PostMapping - public ResponseEntity createRetrospect(@PathVariable("spaceId") Long spaceId, - @RequestBody @Valid RetrospectCreateRequest request) { + return ResponseEntity.ok() + .body(RetrospectListGetResponse.of(serviceResponse.layerCount(), retrospectGetResponses)); + } - retrospectService.create(spaceId, request.formId(), request.title(), request.introduction()); - return ResponseEntity.ok(null); - } } diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectGetResponse.java b/layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectGetResponse.java new file mode 100644 index 00000000..4d3d04b8 --- /dev/null +++ b/layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectGetResponse.java @@ -0,0 +1,25 @@ +package org.layer.domain.retrospect.controller.dto.response; + +import org.layer.domain.retrospect.entity.RetrospectStatus; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(name = "RetrospectGetResponse", description = "특정 회고 조회 Dto") +public record RetrospectGetResponse( + @Schema(description = "회고 이름", example = "중간 발표 이후") + String title, + @Schema(description = "회고 설명", example = "중간 발표 관련해서 KPT 회고를 해봅시다.") + String introduction, + @Schema(description = "회고 작성 여부", example = "false") + boolean isWrite, + @Schema(description = "회고 상태 : PROCEEDING 나 DONE 중에 하나입니다.", example = "PROCEEDING") + RetrospectStatus retrospectStatus, + @Schema(description = "해당 회고 응답 수", example = "4") + int writeCount +) { + public static RetrospectGetResponse of(String title, String introduction, boolean isWrite, RetrospectStatus retrospectStatus, + int writeCount){ + + return new RetrospectGetResponse(title, introduction, isWrite, retrospectStatus, writeCount); + } +} diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectListGetResponse.java b/layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectListGetResponse.java new file mode 100644 index 00000000..50a71469 --- /dev/null +++ b/layer-api/src/main/java/org/layer/domain/retrospect/controller/dto/response/RetrospectListGetResponse.java @@ -0,0 +1,18 @@ +package org.layer.domain.retrospect.controller.dto.response; + +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(name = "RetrospectListGetResponse", description = "회고 목록 조회 Dto") +public record RetrospectListGetResponse( + @Schema(description = "쌓인 레이어 수", example = "3") + int layerCount, + @Schema(description = "회고 객체 목록", example = "") + List retrospects + +) { + public static RetrospectListGetResponse of(int layerCount, List retrospects){ + return new RetrospectListGetResponse(layerCount, retrospects); + } +} diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java b/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java index 0470774a..cc393c8f 100644 --- a/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java +++ b/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java @@ -1,19 +1,36 @@ package org.layer.domain.retrospect.service; +import static org.layer.common.exception.MemberSpaceRelationExceptionType.*; + +import java.util.List; +import java.util.Optional; + +import org.layer.domain.answer.entity.Answers; +import org.layer.domain.answer.repository.AnswerRepository; import org.layer.domain.retrospect.entity.Retrospect; import org.layer.domain.retrospect.entity.RetrospectStatus; import org.layer.domain.retrospect.repository.RetrospectRepository; +import org.layer.domain.retrospect.service.dto.response.RetrospectGetServiceResponse; +import org.layer.domain.retrospect.service.dto.response.RetrospectListGetServiceResponse; +import org.layer.domain.space.entity.MemberSpaceRelation; +import org.layer.domain.space.exception.MemberSpaceRelationException; +import org.layer.domain.space.repository.MemberSpaceRelationRepository; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class RetrospectService { private final RetrospectRepository retrospectRepository; + private final MemberSpaceRelationRepository memberSpaceRelationRepository; + private final AnswerRepository answerRepository; - public void create(Long spaceId, Long formId, String title, String introduction){ + @Transactional + public void create(Long spaceId, Long formId, String title, String introduction) { Retrospect retrospect = Retrospect.builder() .title(title) .formId(formId) @@ -24,4 +41,23 @@ public void create(Long spaceId, Long formId, String title, String introduction) retrospectRepository.save(retrospect); } + + public RetrospectListGetServiceResponse getRetrospects(Long spaceId, Long memberId) { + Optional team = memberSpaceRelationRepository.findBySpaceIdAndMemberId( + spaceId, memberId); + if (team.isEmpty()) { // 해당 멤버가 요청한 스페이스 소속 여부 확인 + throw new MemberSpaceRelationException(NOT_FOUND_MEMBER_SPACE_RELATION); + } + + List retrospects = retrospectRepository.findAllBySpaceId(spaceId); + List retrospectIds = retrospects.stream().map(Retrospect::getId).toList(); + Answers answers = new Answers(answerRepository.findAllByRetrospectIdIn(retrospectIds)); + + List retrospectDtos = retrospects.stream() + .map(r -> RetrospectGetServiceResponse.of(r.getTitle(), r.getIntroduction(), + answers.hasRetrospectAnswer(memberId), r.getRetrospectStatus(), answers.getWriteCount())) + .toList(); + + return RetrospectListGetServiceResponse.of(retrospects.size(), retrospectDtos); + } } diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/RetrospectCreateServiceRequest.java b/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/request/RetrospectCreateServiceRequest.java similarity index 72% rename from layer-api/src/main/java/org/layer/domain/retrospect/service/dto/RetrospectCreateServiceRequest.java rename to layer-api/src/main/java/org/layer/domain/retrospect/service/dto/request/RetrospectCreateServiceRequest.java index 223f8ece..edd2eba4 100644 --- a/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/RetrospectCreateServiceRequest.java +++ b/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/request/RetrospectCreateServiceRequest.java @@ -1,4 +1,4 @@ -package org.layer.domain.retrospect.service.dto; +package org.layer.domain.retrospect.service.dto.request; import java.util.List; diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectGetServiceResponse.java b/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectGetServiceResponse.java new file mode 100644 index 00000000..0690ce3a --- /dev/null +++ b/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectGetServiceResponse.java @@ -0,0 +1,16 @@ +package org.layer.domain.retrospect.service.dto.response; + +import org.layer.domain.retrospect.entity.RetrospectStatus; + +public record RetrospectGetServiceResponse( + String title, + String introduction, + boolean isWrite, + RetrospectStatus retrospectStatus, + int writeCount +) { + public static RetrospectGetServiceResponse of(String title, String introduction, boolean isWrite, + RetrospectStatus retrospectStatus, int writeCount){ + return new RetrospectGetServiceResponse(title, introduction, isWrite, retrospectStatus, writeCount); + } +} diff --git a/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectListGetServiceResponse.java b/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectListGetServiceResponse.java new file mode 100644 index 00000000..008e030c --- /dev/null +++ b/layer-api/src/main/java/org/layer/domain/retrospect/service/dto/response/RetrospectListGetServiceResponse.java @@ -0,0 +1,13 @@ +package org.layer.domain.retrospect.service.dto.response; + +import java.util.List; + + +public record RetrospectListGetServiceResponse( + int layerCount, + List retrospects +) { + public static RetrospectListGetServiceResponse of(int layerCount, List retrospects){ + return new RetrospectListGetServiceResponse(layerCount, retrospects); + } +} diff --git a/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java b/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java index 56d7b764..91faea1b 100644 --- a/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java +++ b/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java @@ -1,17 +1,18 @@ package org.layer.domain.space.service; - +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.layer.common.dto.Meta; -import org.layer.common.exception.BaseCustomException; import org.layer.domain.space.dto.SpaceRequest; import org.layer.domain.space.dto.SpaceResponse; +import org.layer.domain.space.dto.SpaceWithMemberCount; import org.layer.domain.space.entity.MemberSpaceRelation; +import org.layer.domain.space.entity.Space; import org.layer.domain.space.repository.MemberSpaceRelationRepository; import org.layer.domain.space.repository.SpaceRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.util.stream.Collectors; @@ -62,6 +63,4 @@ public SpaceResponse.SpaceWithUserCountInfo getSpaceById(Long memberId, Long spa return SpaceResponse.SpaceWithUserCountInfo.toResponse(foundSpace); } - } - diff --git a/layer-common/src/main/java/org/layer/common/exception/MemberSpaceRelationExceptionType.java b/layer-common/src/main/java/org/layer/common/exception/MemberSpaceRelationExceptionType.java new file mode 100644 index 00000000..724fd3ef --- /dev/null +++ b/layer-common/src/main/java/org/layer/common/exception/MemberSpaceRelationExceptionType.java @@ -0,0 +1,28 @@ +package org.layer.common.exception; + +import org.springframework.http.HttpStatus; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum MemberSpaceRelationExceptionType implements ExceptionType { + /** + * 400 + */ + + NOT_FOUND_MEMBER_SPACE_RELATION(HttpStatus.NOT_FOUND, "해당 스페이스에 소속되지 않은 멤버입니다."); + + private final HttpStatus status; + private final String message; + + @Override + public HttpStatus httpStatus() { + return status; + } + + @Override + public String message() { + return message; + } + +} diff --git a/layer-common/src/main/java/org/layer/common/exception/SpaceExceptionType.java b/layer-common/src/main/java/org/layer/common/exception/SpaceExceptionType.java new file mode 100644 index 00000000..cd8d37ef --- /dev/null +++ b/layer-common/src/main/java/org/layer/common/exception/SpaceExceptionType.java @@ -0,0 +1,22 @@ +package org.layer.common.exception; + +import org.springframework.http.HttpStatus; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum SpaceExceptionType implements ExceptionType{ + NOT_FOUND_SPACE(HttpStatus.NOT_FOUND, "유효하지 않은 스페이스 id 입니다."); + + private final HttpStatus status; + private final String message; + @Override + public HttpStatus httpStatus() { + return status; + } + + @Override + public String message() { + return message; + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java b/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java new file mode 100644 index 00000000..3eb4ac5c --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java @@ -0,0 +1,19 @@ +package org.layer.domain.answer.entity; + +import java.util.List; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class Answers { + private final List answers; + + public boolean hasRetrospectAnswer(Long memberId) { + return answers.stream() + .anyMatch(answer -> answer.getMemberId().equals(memberId)); + } + + public int getWriteCount() { + return answers.size(); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/answer/repository/AnswerRepository.java b/layer-domain/src/main/java/org/layer/domain/answer/repository/AnswerRepository.java index 5cf4eed5..4a43c28e 100644 --- a/layer-domain/src/main/java/org/layer/domain/answer/repository/AnswerRepository.java +++ b/layer-domain/src/main/java/org/layer/domain/answer/repository/AnswerRepository.java @@ -1,8 +1,10 @@ package org.layer.domain.answer.repository; +import java.util.List; + import org.layer.domain.answer.entity.Answer; import org.springframework.data.jpa.repository.JpaRepository; public interface AnswerRepository extends JpaRepository { - + List findAllByRetrospectIdIn(List retrospectIds); } diff --git a/layer-domain/src/main/java/org/layer/domain/member/exception/MemberException.java b/layer-domain/src/main/java/org/layer/domain/member/exception/MemberException.java new file mode 100644 index 00000000..7a01ddf3 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/member/exception/MemberException.java @@ -0,0 +1,10 @@ +package org.layer.domain.member.exception; + +import org.layer.common.exception.BaseCustomException; +import org.layer.common.exception.ExceptionType; + +public class MemberException extends BaseCustomException { + public MemberException(ExceptionType exceptionType) { + super(exceptionType); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/member/repository/MemberRepository.java b/layer-domain/src/main/java/org/layer/domain/member/repository/MemberRepository.java index cfe66374..94d045cb 100644 --- a/layer-domain/src/main/java/org/layer/domain/member/repository/MemberRepository.java +++ b/layer-domain/src/main/java/org/layer/domain/member/repository/MemberRepository.java @@ -7,6 +7,5 @@ import java.util.Optional; public interface MemberRepository extends JpaRepository { - // SELECT * FROM MEMBER WHERE socialId = ? AND socialType = ?; Optional findBySocialIdAndSocialType(String socialId, SocialType socialType); } diff --git a/layer-domain/src/main/java/org/layer/domain/retrospect/repository/RetrospectRepository.java b/layer-domain/src/main/java/org/layer/domain/retrospect/repository/RetrospectRepository.java index 2a259c5e..44a69497 100644 --- a/layer-domain/src/main/java/org/layer/domain/retrospect/repository/RetrospectRepository.java +++ b/layer-domain/src/main/java/org/layer/domain/retrospect/repository/RetrospectRepository.java @@ -1,8 +1,10 @@ package org.layer.domain.retrospect.repository; +import java.util.List; + import org.layer.domain.retrospect.entity.Retrospect; import org.springframework.data.jpa.repository.JpaRepository; public interface RetrospectRepository extends JpaRepository { - + List findAllBySpaceId(Long spaceId); } diff --git a/layer-domain/src/main/java/org/layer/domain/space/entity/MemberSpaceRelation.java b/layer-domain/src/main/java/org/layer/domain/space/entity/MemberSpaceRelation.java index 36280558..0fd90f57 100644 --- a/layer-domain/src/main/java/org/layer/domain/space/entity/MemberSpaceRelation.java +++ b/layer-domain/src/main/java/org/layer/domain/space/entity/MemberSpaceRelation.java @@ -1,6 +1,9 @@ package org.layer.domain.space.entity; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -18,6 +21,8 @@ public class MemberSpaceRelation extends BaseEntity { @NotNull private Long memberId; - @NotNull - private Long spaceId; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "space_id") + private Space space; + } diff --git a/layer-domain/src/main/java/org/layer/domain/space/entity/Team.java b/layer-domain/src/main/java/org/layer/domain/space/entity/Team.java new file mode 100644 index 00000000..580ea533 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/space/entity/Team.java @@ -0,0 +1,25 @@ +package org.layer.domain.space.entity; + +import static org.layer.common.exception.MemberSpaceRelationExceptionType.*; + +import java.util.List; + +import org.layer.domain.space.exception.MemberSpaceRelationException; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class Team { + private final List memberSpaceRelations; + + public void validateTeamMembership(Long memberId){ + memberSpaceRelations.stream() + .filter(memberSpaceRelation -> memberSpaceRelation.getMemberId().equals(memberId)) + .findAny() + .orElseThrow(() -> new MemberSpaceRelationException(NOT_FOUND_MEMBER_SPACE_RELATION)); + } + + public int getTeamMemberCount(){ + return memberSpaceRelations.size(); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/space/exception/MemberSpaceRelationException.java b/layer-domain/src/main/java/org/layer/domain/space/exception/MemberSpaceRelationException.java new file mode 100644 index 00000000..253fab63 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/space/exception/MemberSpaceRelationException.java @@ -0,0 +1,10 @@ +package org.layer.domain.space.exception; + +import org.layer.common.exception.BaseCustomException; +import org.layer.common.exception.ExceptionType; + +public class MemberSpaceRelationException extends BaseCustomException { + public MemberSpaceRelationException(ExceptionType exceptionType) { + super(exceptionType); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/space/exception/SpaceException.java b/layer-domain/src/main/java/org/layer/domain/space/exception/SpaceException.java new file mode 100644 index 00000000..a8993eb5 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/space/exception/SpaceException.java @@ -0,0 +1,10 @@ +package org.layer.domain.space.exception; + +import org.layer.common.exception.BaseCustomException; +import org.layer.common.exception.ExceptionType; + +public class SpaceException extends BaseCustomException { + public SpaceException(ExceptionType exceptionType) { + super(exceptionType); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/space/repository/MemberSpaceRelationRepository.java b/layer-domain/src/main/java/org/layer/domain/space/repository/MemberSpaceRelationRepository.java index 912f7307..7345704b 100644 --- a/layer-domain/src/main/java/org/layer/domain/space/repository/MemberSpaceRelationRepository.java +++ b/layer-domain/src/main/java/org/layer/domain/space/repository/MemberSpaceRelationRepository.java @@ -1,7 +1,12 @@ package org.layer.domain.space.repository; + +import java.util.Optional; + import org.layer.domain.space.entity.MemberSpaceRelation; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberSpaceRelationRepository extends JpaRepository { + + Optional findBySpaceIdAndMemberId(Long spaceId, Long memberId); } diff --git a/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepository.java b/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepository.java index 18d0aa8f..7c28c57b 100644 --- a/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepository.java +++ b/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepository.java @@ -1,8 +1,17 @@ package org.layer.domain.space.repository; +import org.layer.domain.space.dto.SpaceWithMemberCount; import org.layer.domain.space.entity.Space; +import org.layer.domain.space.entity.SpaceCategory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; -public interface SpaceRepository extends JpaRepository, SpaceCustomRepository { +public interface SpaceRepository extends JpaRepository { + default Space findByIdOrThrow(Long spaceId){ + return findById(spaceId) + .orElseThrow(() -> new SpaceException(NOT_FOUND_SPACE)); + } }