Skip to content
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

Feat(#24): 답변 작성 API 구현 #55

Merged
merged 5 commits into from
Feb 5, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ public class CustomException extends RuntimeException {
new CustomException(ErrorType.INCORRECT_TOKEN_FORMAT);
public static final CustomException INVALID_APPLE_ID_TOKEN =
new CustomException(ErrorType.INVALID_APPLE_ID_TOKEN);
public static final CustomException MEMBER_NOT_FOUND =
new CustomException(ErrorType.MEMBER_NOT_FOUND);
public static final CustomException SURVEY_OPTION_NOT_FOUND =
new CustomException(ErrorType.SURVEY_OPTION_NOT_FOUND);
public static final CustomException SURVEY_NOT_FOUND =
new CustomException(ErrorType.SURVEY_NOT_FOUND);
public static final CustomException NOT_READY_FOR_NEXT_BUNDLE =
new CustomException(ErrorType.NOT_READY_FOR_NEXT_BUNDLE);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public enum ErrorType {
INVALID_APPLE_ID_TOKEN(
HttpStatus.BAD_REQUEST, ErrorCode.E400, "유효하지 않은 애플로그인입니다.", LogLevel.WARN),

SURVEY_OPTION_NOT_FOUND(HttpStatus.NOT_FOUND, ErrorCode.E404, "존재하지 않는 설문 옵션입니다.", LogLevel.WARN),

SURVEY_NOT_FOUND(HttpStatus.NOT_FOUND, ErrorCode.E404, "존재하지 않는 설문입니다.", LogLevel.WARN),

// survey
NOT_READY_FOR_NEXT_BUNDLE(
HttpStatus.BAD_REQUEST, ErrorCode.E400, "다음 번들을 진행할 준비가 되지 않았습니다.", LogLevel.WARN),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.nexters.jaknaesocore.domain.survey.dto;

public record SurveySubmissionCommand(Long optionId, String comment) {}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.nexters.jaknaesocore.common.model.BaseTimeEntity;
import org.nexters.jaknaesocore.common.support.error.CustomException;

@Getter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
Expand Down Expand Up @@ -34,4 +35,11 @@ public void addOption(final SurveyOption option) {
}

public abstract SurveyType getSurveyType();

public SurveyOption getOptionById(final Long optionId) {
return options.stream()
.filter(option -> option.getId().equals(optionId))
.findFirst()
.orElseThrow(() -> CustomException.SURVEY_OPTION_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,30 @@ public class SurveySubmission extends BaseTimeEntity {
@JoinColumn(name = "option_id")
private SurveyOption selectedOption;

private String comment;
private String retrospective;

@Builder
private SurveySubmission(
Member member, Survey survey, SurveyOption selectedOption, String comment) {
final Member member,
final Survey survey,
final SurveyOption selectedOption,
final String retrospective) {
this.member = member;
this.survey = survey;
this.selectedOption = selectedOption;
this.comment = comment;
this.retrospective = retrospective;
}

public static SurveySubmission create(
final Member member,
final Survey survey,
final SurveyOption selectedOption,
final String retrospective) {
return SurveySubmission.builder()
.member(member)
.survey(survey)
.selectedOption(selectedOption)
.retrospective(retrospective)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.nexters.jaknaesocore.common.support.error.CustomException;
import org.nexters.jaknaesocore.domain.member.model.Member;
import org.nexters.jaknaesocore.domain.member.repository.MemberRepository;
import org.nexters.jaknaesocore.domain.survey.dto.SurveyHistoryDetailResponse;
import org.nexters.jaknaesocore.domain.survey.dto.SurveyHistoryResponse;
import org.nexters.jaknaesocore.domain.survey.dto.SurveyResponse;
import org.nexters.jaknaesocore.domain.survey.model.Survey;
import org.nexters.jaknaesocore.domain.survey.model.SurveyBundle;
import org.nexters.jaknaesocore.domain.survey.model.SurveySubmission;
import org.nexters.jaknaesocore.domain.survey.model.SurveySubscriptions;
import org.nexters.jaknaesocore.domain.survey.dto.SurveySubmissionCommand;
import org.nexters.jaknaesocore.domain.survey.model.*;
import org.nexters.jaknaesocore.domain.survey.repository.SurveyBundleRepository;
import org.nexters.jaknaesocore.domain.survey.repository.SurveyRepository;
import org.nexters.jaknaesocore.domain.survey.repository.SurveySubmissionRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,8 +20,10 @@
@Service
public class SurveyService {

private final MemberRepository memberRepository;
private final SurveyBundleRepository surveyBundleRepository;
private final SurveySubmissionRepository surveySubmissionRepository;
private final SurveyRepository surveyRepository;

@Transactional(readOnly = true)
public SurveyResponse getNextSurvey(final Long bundleId, final Long memberId) {
Expand Down Expand Up @@ -89,4 +92,20 @@ private SurveyHistoryResponse createCurrentBundleSurveyHistory(

return new SurveyHistoryResponse(bundleId, historyDetails, submissions.size() + 1);
}

@Transactional
public void submitSurvey(Long surveyId, Long memberId, SurveySubmissionCommand request) {
Survey survey =
surveyRepository.findById(surveyId).orElseThrow(() -> CustomException.SURVEY_NOT_FOUND);
SurveyOption surveyOption = survey.getOptionById(request.optionId());
Member member =
memberRepository
.findByIdAndDeletedAtIsNull(memberId)
.orElseThrow(() -> CustomException.MEMBER_NOT_FOUND);

SurveySubmission surveySubmission =
SurveySubmission.create(member, survey, surveyOption, request.comment());

surveySubmissionRepository.save(surveySubmission);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE survey_submission
RENAME COLUMN comment TO retrospective;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.nexters.jaknaesocore.domain.survey.model;

import static org.junit.jupiter.api.Assertions.*;

import org.assertj.core.api.BDDAssertions;
import org.junit.jupiter.api.Test;
import org.nexters.jaknaesocore.common.support.error.CustomException;
import org.springframework.test.util.ReflectionTestUtils;

class SurveyTest {

@Test
void 설문의_선택지를_ID를_통해_찾는다() {
// given
SurveyBundle surveyBundle = new SurveyBundle();
BalanceSurvey survey = new BalanceSurvey("설문", surveyBundle);

SurveyOption option1 = createSurveyOptionWithId(survey, "옵션1", 1L);
SurveyOption option2 = createSurveyOptionWithId(survey, "옵션2", 2L);
SurveyOption option3 = createSurveyOptionWithId(survey, "옵션3", 3L);

// when
SurveyOption foundOption = survey.getOptionById(2L);

// then
BDDAssertions.then(foundOption).extracting("id", "content").containsExactly(2L, "옵션2");
}

@Test
void 설문의_선택지를_ID를_통해_찾을_수_없을_때_예외를_발생한다() {
// given
SurveyBundle surveyBundle = new SurveyBundle();
BalanceSurvey survey = new BalanceSurvey("설문", surveyBundle);

SurveyOption option1 = createSurveyOptionWithId(survey, "옵션1", 1L);
SurveyOption option2 = createSurveyOptionWithId(survey, "옵션2", 2L);
SurveyOption option3 = createSurveyOptionWithId(survey, "옵션3", 3L);
// when
// then
BDDAssertions.thenThrownBy(() -> survey.getOptionById(4L))
.isInstanceOf(CustomException.class)
.isEqualTo(CustomException.SURVEY_OPTION_NOT_FOUND);
}

private SurveyOption createSurveyOptionWithId(Survey survey, String content, Long id) {
SurveyOption option = SurveyOption.builder().survey(survey).content(content).build();
ReflectionTestUtils.setField(option, "id", id);
return option;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@
import org.nexters.jaknaesocore.common.support.IntegrationTest;
import org.nexters.jaknaesocore.domain.member.model.Member;
import org.nexters.jaknaesocore.domain.member.repository.MemberRepository;
import org.nexters.jaknaesocore.domain.survey.model.BalanceSurvey;
import org.nexters.jaknaesocore.domain.survey.model.Keyword;
import org.nexters.jaknaesocore.domain.survey.model.KeywordScore;
import org.nexters.jaknaesocore.domain.survey.model.SurveyBundle;
import org.nexters.jaknaesocore.domain.survey.model.SurveyOption;
import org.nexters.jaknaesocore.domain.survey.model.SurveySubmission;
import org.nexters.jaknaesocore.domain.survey.model.*;
import org.springframework.beans.factory.annotation.Autowired;

class SurveySubmissionRepositoryTest extends IntegrationTest {
Expand Down Expand Up @@ -76,7 +71,7 @@ void findByMember_IdAndDeletedAtIsNull() {
@Test
void 회원이_제출한_가장_마지막_설문을_조회한다() {
// given
Member member = Member.create();
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
Expand Down Expand Up @@ -125,7 +120,7 @@ void findByMember_IdAndDeletedAtIsNull() {
@Test
void 번들에서_제출한_설문을_조회한다() {
// given
Member member = Member.create();
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package org.nexters.jaknaesocore.domain.survey.service;

import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.BDDAssertions.tuple;
import static org.assertj.core.api.BDDAssertions.*;

import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.nexters.jaknaesocore.common.support.IntegrationTest;
import org.nexters.jaknaesocore.common.support.error.CustomException;
import org.nexters.jaknaesocore.domain.member.model.Member;
import org.nexters.jaknaesocore.domain.member.repository.MemberRepository;
import org.nexters.jaknaesocore.domain.survey.dto.SurveyHistoryResponse;
import org.nexters.jaknaesocore.domain.survey.dto.SurveyResponse;
import org.nexters.jaknaesocore.domain.survey.dto.SurveySubmissionCommand;
import org.nexters.jaknaesocore.domain.survey.model.*;
import org.nexters.jaknaesocore.domain.survey.model.BalanceSurvey;
import org.nexters.jaknaesocore.domain.survey.model.Keyword;
import org.nexters.jaknaesocore.domain.survey.model.KeywordScore;
Expand All @@ -30,10 +32,10 @@ class SurveyServiceTest extends IntegrationTest {
@Autowired private SurveyService surveyService;

@Autowired private MemberRepository memberRepository;
@Autowired private SurveySubmissionRepository surveySubmissionRepository;
@Autowired private SurveyBundleRepository surveyBundleRepository;
@Autowired private SurveyRepository surveyRepository;
@Autowired private SurveyOptionRepository surveyOptionRepository;
@Autowired private SurveySubmissionRepository surveySubmissionRepository;

@AfterEach
void tearDown() {
Expand Down Expand Up @@ -73,10 +75,111 @@ void getNextSurvey() {
.containsExactly(tuple(option.getId(), "질문 옵션 내용"));
}

@DisplayName("submitSurvey 메서드는")
@Nested
class submitSurvey {

@DisplayName("회원이 존재하지 않으면")
@Nested
class whenMemberNotFound {
@Test
@DisplayName("예외를 발생시킨다")
void throwMemberNotFoundException() {
// given
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
BalanceSurvey balanceSurvey = new BalanceSurvey("질문내용", surveyBundle);
surveyRepository.save(balanceSurvey);
List<KeywordScore> scores =
List.of(
KeywordScore.builder().keyword(Keyword.ACHIEVEMENT).score(BigDecimal.ONE).build(),
KeywordScore.builder().keyword(Keyword.BENEVOLENCE).score(BigDecimal.TWO).build());
SurveyOption option =
SurveyOption.builder().survey(balanceSurvey).scores(scores).content("질문 옵션 내용").build();
surveyOptionRepository.save(option);

SurveySubmissionCommand request =
new SurveySubmissionCommand(option.getId(), "나는 행복한게 좋으니까");

// when
// then
thenThrownBy(() -> surveyService.submitSurvey(balanceSurvey.getId(), 0L, request))
.isEqualTo(CustomException.MEMBER_NOT_FOUND);
}
}

@DisplayName("설문을 저장한다")
@Nested
class shouldSubmitted {
@Test
void 설문에_응답을_제출한다() {
// given
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
BalanceSurvey balanceSurvey = new BalanceSurvey("질문내용", surveyBundle);
surveyRepository.save(balanceSurvey);
List<KeywordScore> scores =
List.of(
KeywordScore.builder().keyword(Keyword.ACHIEVEMENT).score(BigDecimal.ONE).build(),
KeywordScore.builder().keyword(Keyword.BENEVOLENCE).score(BigDecimal.TWO).build());
SurveyOption option =
SurveyOption.builder().survey(balanceSurvey).scores(scores).content("질문 옵션 내용").build();
surveyOptionRepository.save(option);

SurveySubmissionCommand request =
new SurveySubmissionCommand(option.getId(), "나는 행복한게 좋으니까");

// when
surveyService.submitSurvey(balanceSurvey.getId(), member.getId(), request);
// then
List<SurveySubmission> submissions = surveySubmissionRepository.findAll();
then(submissions).hasSize(1);
then(submissions.getFirst())
.extracting("member.id", "survey.id", "selectedOption.id", "retrospective")
.containsExactly(member.getId(), balanceSurvey.getId(), option.getId(), "나는 행복한게 좋으니까");
}
}

@DisplayName("설문이 존재하지 않으면")
@Nested
class whenSurveyNotFound {
@Test
@DisplayName("예외를 발생시킨다")
void throwSurveyNotFoundException() {
// given
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
BalanceSurvey balanceSurvey = new BalanceSurvey("질문내용", surveyBundle);
surveyRepository.save(balanceSurvey);
List<KeywordScore> scores =
List.of(
KeywordScore.builder().keyword(Keyword.ACHIEVEMENT).score(BigDecimal.ONE).build(),
KeywordScore.builder().keyword(Keyword.BENEVOLENCE).score(BigDecimal.TWO).build());
SurveyOption option =
SurveyOption.builder().survey(balanceSurvey).scores(scores).content("질문 옵션 내용").build();
surveyOptionRepository.save(option);

SurveySubmissionCommand request =
new SurveySubmissionCommand(option.getId(), "나는 행복한게 좋으니까");

// when
// then
Comment on lines +171 to +172
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
Member Author

Choose a reason for hiding this comment

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

제가 템플릿을 쓰고있어서 test 를 치면 자동으로

@DisplayName("")
@Test
void test() {
//given

//when

//then

}

이렇게 생성되게 사용하고있어요... 손에 너무 습관이 들어서 안지운것 같습니다

thenThrownBy(() -> surveyService.submitSurvey(0L, member.getId(), request))
.isEqualTo(CustomException.SURVEY_NOT_FOUND);
}
}
}

@Test
void 설문_기록이_없으면_1번_번들을_제공한다() {
// given
Member member = Member.create();
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
Expand Down Expand Up @@ -115,7 +218,7 @@ void getNextSurvey() {
@Test
void 설문_기록이_일정_개수_이하이면_기록과_함께_번들ID를_제공한다() {
// given
Member member = Member.create();
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();
surveyBundleRepository.save(surveyBundle);
Expand Down Expand Up @@ -164,7 +267,7 @@ void getNextSurvey() {
@Test
void 설문_기록이_번들_크기만큼_있으면_다음_번들ID를_제공한다() {
// given
Member member = Member.create();
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle1 = new SurveyBundle();
SurveyBundle surveyBundle2 = new SurveyBundle();
Expand Down Expand Up @@ -217,7 +320,7 @@ void getNextSurvey() {
@Test
void 진행할_다음_설문_번들이_존재하지_않으면_예외를_발생한다() {
// given
Member member = Member.create();
Member member = Member.create("나민혁", "[email protected]");
memberRepository.save(member);
SurveyBundle surveyBundle = new SurveyBundle();

Expand Down
Loading