diff --git a/backend/src/main/java/reviewme/question/domain/OptionGroup.java b/backend/src/main/java/reviewme/question/domain/OptionGroup.java index 330ff963a..4cab80b43 100644 --- a/backend/src/main/java/reviewme/question/domain/OptionGroup.java +++ b/backend/src/main/java/reviewme/question/domain/OptionGroup.java @@ -28,4 +28,10 @@ public class OptionGroup { @Column(name = "max_selection_count", nullable = false) private int maxSelectionCount; + + public OptionGroup(long questionId, int minSelectionCount, int maxSelectionCount) { + this.questionId = questionId; + this.minSelectionCount = minSelectionCount; + this.maxSelectionCount = maxSelectionCount; + } } diff --git a/backend/src/main/java/reviewme/question/domain/OptionItem.java b/backend/src/main/java/reviewme/question/domain/OptionItem.java index bd318b945..eac0f58fd 100644 --- a/backend/src/main/java/reviewme/question/domain/OptionItem.java +++ b/backend/src/main/java/reviewme/question/domain/OptionItem.java @@ -2,6 +2,8 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -28,4 +30,15 @@ public class OptionItem { @Column(name = "position", nullable = false) private int position; + + @Column(name = "option_type", nullable = false) + @Enumerated(EnumType.STRING) + private OptionType optionType; + + public OptionItem(String content, long optionGroupId, int position, OptionType optionType) { + this.content = content; + this.optionGroupId = optionGroupId; + this.position = position; + this.optionType = optionType; + } } diff --git a/backend/src/main/java/reviewme/question/domain/OptionType.java b/backend/src/main/java/reviewme/question/domain/OptionType.java new file mode 100644 index 000000000..dfa86920b --- /dev/null +++ b/backend/src/main/java/reviewme/question/domain/OptionType.java @@ -0,0 +1,6 @@ +package reviewme.question.domain; + +public enum OptionType { + CATEGORY, + KEYWORD, +} diff --git a/backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java b/backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java new file mode 100644 index 000000000..8042be186 --- /dev/null +++ b/backend/src/main/java/reviewme/question/repository/OptionGroupRepository.java @@ -0,0 +1,9 @@ +package reviewme.question.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import reviewme.question.domain.OptionGroup; + +@Repository +public interface OptionGroupRepository extends JpaRepository { +} diff --git a/backend/src/main/java/reviewme/question/repository/OptionItemRepository.java b/backend/src/main/java/reviewme/question/repository/OptionItemRepository.java new file mode 100644 index 000000000..a0ce20c9c --- /dev/null +++ b/backend/src/main/java/reviewme/question/repository/OptionItemRepository.java @@ -0,0 +1,15 @@ +package reviewme.question.repository; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import reviewme.question.domain.OptionItem; +import reviewme.question.domain.OptionType; + +@Repository +public interface OptionItemRepository extends JpaRepository { + + List findAllByOptionType(OptionType optionType); + + boolean existsByOptionTypeAndId(OptionType optionType, long id); +} diff --git a/backend/src/main/java/reviewme/review/controller/ReviewController.java b/backend/src/main/java/reviewme/review/controller/ReviewController.java index 00bdf9917..0e6561c09 100644 --- a/backend/src/main/java/reviewme/review/controller/ReviewController.java +++ b/backend/src/main/java/reviewme/review/controller/ReviewController.java @@ -13,6 +13,7 @@ import reviewme.global.HeaderProperty; import reviewme.review.dto.request.CreateReviewRequest; import reviewme.review.dto.response.ReceivedReviewsResponse; +import reviewme.review.dto.response.ReceivedReviewsResponse2; import reviewme.review.dto.response.ReviewDetailResponse; import reviewme.review.dto.response.ReviewSetupResponse; import reviewme.review.service.ReviewService; @@ -45,6 +46,14 @@ public ResponseEntity findReceivedReviews( return ResponseEntity.ok(response); } + @GetMapping("/v2/reviews") + public ResponseEntity findReceivedReviews2( + @HeaderProperty(GROUP_ACCESS_CODE_HEADER) String groupAccessCode + ) { + ReceivedReviewsResponse2 response = reviewService.findReceivedReviews2(groupAccessCode); + return ResponseEntity.ok(response); + } + @GetMapping("/reviews/{id}") public ResponseEntity findReceivedReviewDetail( @PathVariable long id, diff --git a/backend/src/main/java/reviewme/review/domain/CheckboxAnswer.java b/backend/src/main/java/reviewme/review/domain/CheckboxAnswer.java index ae8ce51fb..60067fa68 100644 --- a/backend/src/main/java/reviewme/review/domain/CheckboxAnswer.java +++ b/backend/src/main/java/reviewme/review/domain/CheckboxAnswer.java @@ -29,4 +29,9 @@ public class CheckboxAnswer { @ElementCollection @CollectionTable(name = "selected_option_ids") private List selectedOptionIds; + + public CheckboxAnswer(long questionId, List selectedOptionIds) { + this.questionId = questionId; + this.selectedOptionIds = selectedOptionIds; + } } diff --git a/backend/src/main/java/reviewme/review/domain/Review2.java b/backend/src/main/java/reviewme/review/domain/Review2.java index c01612fe1..d860a89d4 100644 --- a/backend/src/main/java/reviewme/review/domain/Review2.java +++ b/backend/src/main/java/reviewme/review/domain/Review2.java @@ -9,6 +9,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import java.time.LocalDateTime; import java.util.List; import lombok.AccessLevel; import lombok.Getter; @@ -37,4 +38,17 @@ public class Review2 { @OneToMany(cascade = CascadeType.PERSIST) @JoinColumn(name = "review_id", nullable = false, updatable = false) private List checkboxAnswers; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + public Review2(long templateId, long reviewGroupId, + List textAnswers, List checkboxAnswers, + LocalDateTime createdAt) { + this.templateId = templateId; + this.reviewGroupId = reviewGroupId; + this.textAnswers = textAnswers; + this.checkboxAnswers = checkboxAnswers; + this.createdAt = createdAt; + } } diff --git a/backend/src/main/java/reviewme/review/domain/TextAnswer.java b/backend/src/main/java/reviewme/review/domain/TextAnswer.java index 32894645c..d356f1900 100644 --- a/backend/src/main/java/reviewme/review/domain/TextAnswer.java +++ b/backend/src/main/java/reviewme/review/domain/TextAnswer.java @@ -25,4 +25,9 @@ public class TextAnswer { @Column(name = "text", nullable = false, length = 1_000) private String text; + + public TextAnswer(long questionId, String text) { + this.questionId = questionId; + this.text = text; + } } diff --git a/backend/src/main/java/reviewme/review/domain/exception/CategoryOptionByReviewNotFoundException.java b/backend/src/main/java/reviewme/review/domain/exception/CategoryOptionByReviewNotFoundException.java new file mode 100644 index 000000000..fb44adea0 --- /dev/null +++ b/backend/src/main/java/reviewme/review/domain/exception/CategoryOptionByReviewNotFoundException.java @@ -0,0 +1,13 @@ +package reviewme.review.domain.exception; + +import lombok.extern.slf4j.Slf4j; +import reviewme.global.exception.NotFoundException; + +@Slf4j +public class CategoryOptionByReviewNotFoundException extends NotFoundException { + + public CategoryOptionByReviewNotFoundException(long reviewId) { + super("리뷰에 선택한 카테고리가 없어요."); + log.warn("CategoryOptionNotFoundException is occured - reviewId: {}", reviewId); + } +} diff --git a/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewCategoryResponse.java b/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewCategoryResponse.java new file mode 100644 index 000000000..2077a8e57 --- /dev/null +++ b/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewCategoryResponse.java @@ -0,0 +1,14 @@ +package reviewme.review.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(name = "선택된 카테고리 응답") +public record ReceivedReviewCategoryResponse( + + @Schema(description = "카테고리 ID") + long optionId, + + @Schema(description = "카테고리 내용") + String content +) { +} diff --git a/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewResponse2.java b/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewResponse2.java new file mode 100644 index 000000000..0cf779cc3 --- /dev/null +++ b/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewResponse2.java @@ -0,0 +1,22 @@ +package reviewme.review.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDate; +import java.util.List; + +@Schema(name = "리뷰 내용 응답") +public record ReceivedReviewResponse2( + + @Schema(description = "리뷰 ID") + long id, + + @Schema(description = "리뷰 작성일") + LocalDate createdAt, + + @Schema(description = "응답 내용 미리보기") + String contentPreview, + + @Schema(description = "선택된 카테고리 목록") + List categories +) { +} diff --git a/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewsResponse2.java b/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewsResponse2.java new file mode 100644 index 000000000..5649e4d75 --- /dev/null +++ b/backend/src/main/java/reviewme/review/dto/response/ReceivedReviewsResponse2.java @@ -0,0 +1,18 @@ +package reviewme.review.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +@Schema(name = "내가 받은 리뷰 목록 응답") +public record ReceivedReviewsResponse2( + + @Schema(description = "리뷰이 이름") + String revieweeName, + + @Schema(description = "프로젝트 이름") + String projectName, + + @Schema(description = "받은 리뷰 미리보기 목록") + List reviews +) { +} diff --git a/backend/src/main/java/reviewme/review/repository/CheckboxAnswerRepository.java b/backend/src/main/java/reviewme/review/repository/CheckboxAnswerRepository.java new file mode 100644 index 000000000..30ce44014 --- /dev/null +++ b/backend/src/main/java/reviewme/review/repository/CheckboxAnswerRepository.java @@ -0,0 +1,9 @@ +package reviewme.review.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import reviewme.review.domain.CheckboxAnswer; + +@Repository +public interface CheckboxAnswerRepository extends JpaRepository { +} diff --git a/backend/src/main/java/reviewme/review/repository/Review2Repository.java b/backend/src/main/java/reviewme/review/repository/Review2Repository.java new file mode 100644 index 000000000..d5639b5d9 --- /dev/null +++ b/backend/src/main/java/reviewme/review/repository/Review2Repository.java @@ -0,0 +1,14 @@ +package reviewme.review.repository; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import reviewme.review.domain.Review2; + +@Repository +public interface Review2Repository extends JpaRepository { + + @Query("SELECT r FROM Review2 r WHERE r.reviewGroupId=:reviewGroupId ORDER BY r.createdAt DESC") + List findReceivedReviewsByGroupId(long reviewGroupId); +} diff --git a/backend/src/main/java/reviewme/review/service/ReviewPreviewGenerator.java b/backend/src/main/java/reviewme/review/service/ReviewPreviewGenerator.java index ef145ce9a..1f434fe03 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewPreviewGenerator.java +++ b/backend/src/main/java/reviewme/review/service/ReviewPreviewGenerator.java @@ -2,6 +2,7 @@ import java.util.List; import reviewme.review.domain.ReviewContent; +import reviewme.review.domain.TextAnswer; public class ReviewPreviewGenerator { @@ -17,4 +18,15 @@ public String generatePreview(List reviewContents) { } return answer; } + + public String generatePreview2(List reviewTextAnswers) { + if (reviewTextAnswers.isEmpty()) { + return ""; + } + String answer = reviewTextAnswers.get(0).getText(); + if (answer.length() > PREVIEW_LENGTH) { + return answer.substring(0, PREVIEW_LENGTH); + } + return answer; + } } diff --git a/backend/src/main/java/reviewme/review/service/ReviewService.java b/backend/src/main/java/reviewme/review/service/ReviewService.java index 3b34adebd..e32ebad4c 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewService.java +++ b/backend/src/main/java/reviewme/review/service/ReviewService.java @@ -6,10 +6,15 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reviewme.keyword.repository.KeywordRepository; +import reviewme.question.domain.OptionType; import reviewme.question.domain.Question; +import reviewme.question.repository.OptionItemRepository; +import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; +import reviewme.review.domain.Review2; import reviewme.review.domain.ReviewContent; import reviewme.review.domain.ReviewKeyword; +import reviewme.review.domain.exception.CategoryOptionByReviewNotFoundException; import reviewme.review.domain.exception.ReviewGroupNotFoundByGroupAccessCodeException; import reviewme.review.domain.exception.ReviewGroupNotFoundByRequestReviewCodeException; import reviewme.review.domain.exception.ReviewIsNotInReviewGroupException; @@ -17,13 +22,17 @@ import reviewme.review.dto.request.CreateReviewRequest; import reviewme.review.dto.response.KeywordResponse; import reviewme.review.dto.response.QuestionSetupResponse; +import reviewme.review.dto.response.ReceivedReviewCategoryResponse; import reviewme.review.dto.response.ReceivedReviewKeywordsResponse; import reviewme.review.dto.response.ReceivedReviewResponse; +import reviewme.review.dto.response.ReceivedReviewResponse2; import reviewme.review.dto.response.ReceivedReviewsResponse; +import reviewme.review.dto.response.ReceivedReviewsResponse2; import reviewme.review.dto.response.ReviewContentResponse; import reviewme.review.dto.response.ReviewDetailResponse; import reviewme.review.dto.response.ReviewSetupResponse; import reviewme.review.repository.QuestionRepository; +import reviewme.review.repository.Review2Repository; import reviewme.review.repository.ReviewKeywordRepository; import reviewme.review.repository.ReviewRepository; import reviewme.reviewgroup.domain.ReviewGroup; @@ -38,6 +47,8 @@ public class ReviewService { private final ReviewGroupRepository reviewGroupRepository; private final QuestionRepository questionRepository; private final KeywordRepository keywordRepository; + private final OptionItemRepository optionItemRepository; + private final Review2Repository review2Repository; private final ReviewCreationQuestionValidator reviewCreationQuestionValidator; private final ReviewCreationKeywordValidator reviewCreationKeywordValidator; @@ -143,6 +154,45 @@ private ReviewDetailResponse createReviewDetailResponse(Review review, ReviewGro ); } + @Transactional(readOnly = true) + public ReceivedReviewsResponse2 findReceivedReviews2(String groupAccessCode) { + ReviewGroup reviewGroup = reviewGroupRepository.findByGroupAccessCode(groupAccessCode) + .orElseThrow(() -> new ReviewGroupNotFoundByGroupAccessCodeException(groupAccessCode)); + + List reviewResponses = + review2Repository.findReceivedReviewsByGroupId(reviewGroup.getId()) + .stream() + .map(this::createReceivedReviewResponse2) + .toList(); + + return new ReceivedReviewsResponse2(reviewGroup.getReviewee(), reviewGroup.getProjectName(), reviewResponses); + } + + private ReceivedReviewResponse2 createReceivedReviewResponse2(Review2 review) { + CheckboxAnswer checkboxAnswer = review.getCheckboxAnswers() + .stream() + .filter(answer -> optionItemRepository.existsByOptionTypeAndId( + OptionType.CATEGORY, answer.getSelectedOptionIds().get(0) + )) + .findFirst() + .orElseThrow(() -> new CategoryOptionByReviewNotFoundException(review.getId())); + + List categoryResponses = + optionItemRepository.findAllById(checkboxAnswer.getSelectedOptionIds()) + .stream() + .map(optionItem -> new ReceivedReviewCategoryResponse( + optionItem.getId(), optionItem.getContent() + )) + .toList(); + + return new ReceivedReviewResponse2( + review.getId(), + review.getCreatedAt().toLocalDate(), + reviewPreviewGenerator.generatePreview2(review.getTextAnswers()), + categoryResponses + ); + } + @Transactional(readOnly = true) public ReceivedReviewsResponse findReceivedReviews(String groupAccessCode) { ReviewGroup reviewGroup = reviewGroupRepository.findByGroupAccessCode(groupAccessCode) diff --git a/backend/src/main/java/reviewme/template/domain/Section.java b/backend/src/main/java/reviewme/template/domain/Section.java index fec4f84d6..14eafd910 100644 --- a/backend/src/main/java/reviewme/template/domain/Section.java +++ b/backend/src/main/java/reviewme/template/domain/Section.java @@ -42,4 +42,13 @@ public class Section { @Column(name = "position", nullable = false) private int position; + + public Section(VisibleType visibleType, List questionIds, + Long onSelectedOptionId, String header, int position) { + this.visibleType = visibleType; + this.questionIds = questionIds; + this.onSelectedOptionId = onSelectedOptionId; + this.header = header; + this.position = position; + } } diff --git a/backend/src/main/java/reviewme/template/domain/Template.java b/backend/src/main/java/reviewme/template/domain/Template.java index 310e51ced..3a8c733b1 100644 --- a/backend/src/main/java/reviewme/template/domain/Template.java +++ b/backend/src/main/java/reviewme/template/domain/Template.java @@ -26,4 +26,8 @@ public class Template { @ElementCollection @CollectionTable(name = "section_ids", joinColumns = @JoinColumn(name = "template_id")) List sectionIds; + + public Template(List sectionIds) { + this.sectionIds = sectionIds; + } } diff --git a/backend/src/main/java/reviewme/template/repository/SectionRepository.java b/backend/src/main/java/reviewme/template/repository/SectionRepository.java new file mode 100644 index 000000000..6d03990d1 --- /dev/null +++ b/backend/src/main/java/reviewme/template/repository/SectionRepository.java @@ -0,0 +1,9 @@ +package reviewme.template.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import reviewme.template.domain.Section; + +@Repository +public interface SectionRepository extends JpaRepository { +} diff --git a/backend/src/main/java/reviewme/template/repository/TemplateRepository.java b/backend/src/main/java/reviewme/template/repository/TemplateRepository.java new file mode 100644 index 000000000..e336a4a09 --- /dev/null +++ b/backend/src/main/java/reviewme/template/repository/TemplateRepository.java @@ -0,0 +1,9 @@ +package reviewme.template.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import reviewme.template.domain.Template; + +@Repository +public interface TemplateRepository extends JpaRepository { +} diff --git a/backend/src/test/java/reviewme/review/service/ReviewPreviewGeneratorTest.java b/backend/src/test/java/reviewme/review/service/ReviewPreviewGeneratorTest.java index c962f1216..9ec649852 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewPreviewGeneratorTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewPreviewGeneratorTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import reviewme.review.domain.ReviewContent; +import reviewme.review.domain.TextAnswer; class ReviewPreviewGeneratorTest { @@ -15,10 +15,10 @@ class ReviewPreviewGeneratorTest { // given ReviewPreviewGenerator reviewPreviewGenerator = new ReviewPreviewGenerator(); String answer = "*".repeat(151); - ReviewContent reviewContent = new ReviewContent(1L, answer); + TextAnswer textAnswer = new TextAnswer(1, answer); // when - String actual = reviewPreviewGenerator.generatePreview(List.of(reviewContent)); + String actual = reviewPreviewGenerator.generatePreview2(List.of(textAnswer)); // then assertThat(actual).hasSize(150); @@ -30,10 +30,10 @@ class ReviewPreviewGeneratorTest { // given ReviewPreviewGenerator reviewPreviewGenerator = new ReviewPreviewGenerator(); String answer = "*".repeat(length); - ReviewContent reviewContent = new ReviewContent(1L, answer); + TextAnswer textAnswer = new TextAnswer(1, answer); // when - String actual = reviewPreviewGenerator.generatePreview(List.of(reviewContent)); + String actual = reviewPreviewGenerator.generatePreview2(List.of(textAnswer)); // then assertThat(actual).hasSize(length); diff --git a/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java index b8186c80a..f5a8df1e2 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; -import static reviewme.fixture.KeywordFixture.꼼꼼하게_기록해요; import static reviewme.fixture.KeywordFixture.추진력이_좋아요; import static reviewme.fixture.KeywordFixture.회의를_이끌어요; import static reviewme.fixture.QuestionFixure.기술역량이_어떤가요; @@ -16,25 +15,38 @@ import org.springframework.beans.factory.annotation.Autowired; import reviewme.keyword.domain.Keyword; import reviewme.keyword.repository.KeywordRepository; +import reviewme.question.domain.OptionGroup; +import reviewme.question.domain.OptionItem; +import reviewme.question.domain.OptionType; import reviewme.question.domain.Question; +import reviewme.question.repository.OptionGroupRepository; +import reviewme.question.repository.OptionItemRepository; +import reviewme.review.domain.CheckboxAnswer; import reviewme.review.domain.Review; -import reviewme.review.domain.ReviewContent; -import reviewme.review.domain.ReviewKeyword; +import reviewme.review.domain.Review2; import reviewme.review.domain.exception.ReviewGroupNotFoundByGroupAccessCodeException; import reviewme.review.domain.exception.ReviewIsNotInReviewGroupException; import reviewme.review.dto.request.CreateReviewContentRequest; import reviewme.review.dto.request.CreateReviewRequest; import reviewme.review.dto.response.QuestionSetupResponse; -import reviewme.review.dto.response.ReceivedReviewsResponse; +import reviewme.review.dto.response.ReceivedReviewCategoryResponse; +import reviewme.review.dto.response.ReceivedReviewsResponse2; import reviewme.review.dto.response.ReviewDetailResponse; import reviewme.review.dto.response.ReviewSetupResponse; +import reviewme.review.repository.CheckboxAnswerRepository; import reviewme.review.repository.QuestionRepository; +import reviewme.review.repository.Review2Repository; import reviewme.review.repository.ReviewContentRepository; import reviewme.review.repository.ReviewKeywordRepository; import reviewme.review.repository.ReviewRepository; import reviewme.reviewgroup.domain.ReviewGroup; import reviewme.reviewgroup.repository.ReviewGroupRepository; import reviewme.support.ServiceTest; +import reviewme.template.domain.Section; +import reviewme.template.domain.Template; +import reviewme.template.domain.VisibleType; +import reviewme.template.repository.SectionRepository; +import reviewme.template.repository.TemplateRepository; @ServiceTest class ReviewServiceTest { @@ -60,6 +72,24 @@ class ReviewServiceTest { @Autowired ReviewKeywordRepository reviewKeywordRepository; + @Autowired + OptionItemRepository optionItemRepository; + + @Autowired + OptionGroupRepository optionGroupRepository; + + @Autowired + SectionRepository secionRepository; + + @Autowired + TemplateRepository templateRepository; + + @Autowired + CheckboxAnswerRepository checkboxAnswerRepository; + + @Autowired + Review2Repository review2Repository; + @Test void 리뷰를_생성한다() { // given @@ -118,34 +148,33 @@ class ReviewServiceTest { @Test void 확인_코드에_해당하는_그룹이_없는_경우_예외가_발생한다() { - assertThatThrownBy(() -> reviewService.findReceivedReviews("abc")) + assertThatThrownBy(() -> reviewService.findReceivedReviews2("abc")) .isInstanceOf(ReviewGroupNotFoundByGroupAccessCodeException.class); } @Test void 확인_코드에_해당하는_그룹이_존재하면_리뷰_리스트를_반환한다() { // given - String groupAccessCode = "5678"; - ReviewGroup reviewGroup = reviewGroupRepository.save(new ReviewGroup("산초", "리뷰미", "1234", groupAccessCode)); - Question question = questionRepository.save(기술역량이_어떤가요.create()); - Keyword keyword = keywordRepository.save(꼼꼼하게_기록해요.create()); - ReviewContent reviewContent1 = new ReviewContent(question.getId(), "기술역량 최고입니다 최고예요 !!!!!"); - ReviewContent reviewContent2 = new ReviewContent(question.getId(), "기술역량은 별로라고 생각해요 !!!!!"); - - Review review1 = reviewRepository.save( - new Review(reviewGroup.getId(), List.of(reviewContent1), LocalDateTime.now()) - ); - Review review2 = reviewRepository.save( - new Review(reviewGroup.getId(), List.of(reviewContent2), LocalDateTime.now()) - ); + String groupAccessCode = "groupAccessCode"; + Question question1 = questionRepository.save(new Question("프로젝트 기간 동안, 팀원의 강점이 드러났던 순간을 선택해주세요. (1~2개)")); + OptionGroup categoryOptionGroup = optionGroupRepository.save(new OptionGroup(question1.getId(), 1, 2)); + OptionItem categoryOption1 = new OptionItem("커뮤니케이션 능력 ", categoryOptionGroup.getId(), 1, OptionType.CATEGORY); + OptionItem categoryOption2 = new OptionItem("시간 관리 능력", categoryOptionGroup.getId(), 2, OptionType.CATEGORY); + optionItemRepository.saveAll(List.of(categoryOption1, categoryOption2)); + + Template template = templateRepository.save(new Template(List.of())); - reviewKeywordRepository.saveAll(List.of( - new ReviewKeyword(review1.getId(), keyword.getId()), - new ReviewKeyword(review2.getId(), keyword.getId()) - )); + ReviewGroup reviewGroup = reviewGroupRepository.save( + new ReviewGroup("커비", "리뷰미", "reviewRequestCode", groupAccessCode) + ); + CheckboxAnswer categoryAnswer1 = new CheckboxAnswer(question1.getId(), List.of(categoryOption1.getId())); + CheckboxAnswer categoryAnswer2 = new CheckboxAnswer(question1.getId(), List.of(categoryOption2.getId())); + Review2 review1 = new Review2(template.getId(), reviewGroup.getId(), List.of(), List.of(categoryAnswer1), LocalDateTime.now()); + Review2 review2 = new Review2(template.getId(), reviewGroup.getId(), List.of(), List.of(categoryAnswer2), LocalDateTime.now()); + review2Repository.saveAll(List.of(review1, review2)); // when - ReceivedReviewsResponse response = reviewService.findReceivedReviews(groupAccessCode); + ReceivedReviewsResponse2 response = reviewService.findReceivedReviews2(groupAccessCode); // then assertThat(response.reviews()).hasSize(2); @@ -212,4 +241,54 @@ class ReviewServiceTest { // then assertThat(questionResponse.content()).contains("에프이"); } + + @Test + void 리뷰_목록을_반환할때_선택한_카테고리만_함께_반환한다() { + // given + String groupAccessCode = "groupAccessCode"; + Question question1 = questionRepository.save(new Question("프로젝트 기간 동안, 팀원의 강점이 드러났던 순간을 선택해주세요. (1~2개)")); + Question question2 = questionRepository.save(new Question("커뮤니케이션, 협업 능력에서 어떤 부분이 인상 깊었는지 선택해주세요. (1개 이상)")); + + OptionGroup categoryOptionGroup = optionGroupRepository.save(new OptionGroup(question1.getId(), 1, 2)); + OptionGroup keywordOptionGroup = optionGroupRepository.save(new OptionGroup(question2.getId(), 1, 10)); + + OptionItem categoryOption1 = new OptionItem("커뮤니케이션 능력 ", categoryOptionGroup.getId(), 1, OptionType.CATEGORY); + OptionItem categoryOption2 = new OptionItem("시간 관리 능력", categoryOptionGroup.getId(), 2, OptionType.CATEGORY); + OptionItem keywordOption = new OptionItem("얘기를 잘 들어줘요", keywordOptionGroup.getId(), 2, OptionType.KEYWORD); + optionItemRepository.saveAll(List.of(categoryOption1, categoryOption2, keywordOption)); + + Section section1 = secionRepository.save( + new Section(VisibleType.ALWAYS, List.of(question1.getId()), null, "팀원과 함께 한 기억을 떠올려볼게요.", 1) + ); + Section section2 = secionRepository.save( + new Section(VisibleType.CONDITIONAL, List.of(question2.getId()), null, "선택한 순간들을 바탕으로 리뷰를 작성해볼게요.", 1) + ); + Template template = templateRepository.save(new Template(List.of(section1.getId(), section2.getId()))); + + ReviewGroup reviewGroup = reviewGroupRepository.save( + new ReviewGroup("커비", "리뷰미", "reviewRequestCode", groupAccessCode) + ); + CheckboxAnswer categoryAnswer = new CheckboxAnswer(question1.getId(), List.of(categoryOption1.getId())); + CheckboxAnswer keywordAnswer = new CheckboxAnswer(question2.getId(), List.of(keywordOption.getId())); + review2Repository.save( + new Review2(template.getId(), reviewGroup.getId(), List.of(), List.of(categoryAnswer, keywordAnswer), + LocalDateTime.now()) + ); + + // when + ReceivedReviewsResponse2 response = reviewService.findReceivedReviews2(groupAccessCode); + + // then + List categoryContents = optionItemRepository.findAllByOptionType(OptionType.CATEGORY) + .stream() + .map(OptionItem::getContent) + .toList(); + + assertThat(response.reviews()) + .map(review -> review.categories() + .stream() + .map(ReceivedReviewCategoryResponse::content) + .toList()) + .allSatisfy(content -> assertThat(categoryContents).containsAll(content)); + } }