Skip to content

Commit

Permalink
refactor: applicant 관련 기능에 mapper 도입
Browse files Browse the repository at this point in the history
  • Loading branch information
jongmee committed Aug 27, 2024
1 parent 8446c90 commit e444238
Show file tree
Hide file tree
Showing 15 changed files with 201 additions and 189 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.server.crews.applicant.application;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

import com.server.crews.applicant.domain.Application;
Expand All @@ -13,6 +10,7 @@
import com.server.crews.applicant.dto.request.EvaluationRequest;
import com.server.crews.applicant.dto.response.ApplicationDetailsResponse;
import com.server.crews.applicant.dto.response.ApplicationsResponse;
import com.server.crews.applicant.mapper.ApplicationMapper;
import com.server.crews.applicant.repository.ApplicationRepository;
import com.server.crews.applicant.repository.NarrativeAnswerRepository;
import com.server.crews.applicant.repository.SelectiveAnswerRepository;
Expand All @@ -31,7 +29,6 @@
import com.server.crews.recruitment.repository.SelectiveQuestionRepository;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -58,39 +55,24 @@ public ApplicationDetailsResponse saveApplication(Long applicantId, ApplicationS
Applicant applicant = applicantRepository.findById(applicantId)
.orElseThrow(() -> new CrewsException(ErrorCode.USER_NOT_FOUND));

List<NarrativeAnswer> narrativeAnswers = extractNarrativeAnswers(request);
List<SelectiveAnswer> selectiveAnswers = extractSelectiveAnswers(request);

Application application = new Application(request.id(), recruitment, applicant, request.studentNumber(),
request.major(), request.name(), narrativeAnswers, selectiveAnswers);
validateNarrativeQuestions(request);
validateSelectiveQuestions(request);

Application application = ApplicationMapper.applicationSaveRequestToApplication(request, recruitment,
applicant);
Application savedApplication = applicationRepository.save(application);

return ApplicationDetailsResponse.of(savedApplication, narrativeAnswers,
collectSelectiveAnswersByQuestion(selectiveAnswers));
return ApplicationMapper.applicationToApplicationDetailsResponse(savedApplication);
}

private List<NarrativeAnswer> extractNarrativeAnswers(ApplicationSaveRequest request) {
private void validateNarrativeQuestions(ApplicationSaveRequest request) {
List<AnswerSaveRequest> narrativeAnswerSaveRequests = filterByQuestionType(QuestionType.NARRATIVE, request);
Set<Long> narrativeQuestionIds = extractQuestionIds(narrativeAnswerSaveRequests);
if (narrativeQuestionIds.size() != narrativeAnswerSaveRequests.size()) {
throw new CrewsException(ErrorCode.DUPLICATE_NARRATIVE_ANSWERS);
}
List<NarrativeQuestion> savedNarrativeQuestions = narrativeQuestionRepository.findAllByIdIn(
narrativeQuestionIds);
validateQuestionIds(savedNarrativeQuestions, narrativeQuestionIds);

Map<Long, NarrativeQuestion> savedNarrativeQuestionsById = savedNarrativeQuestions.stream()
.collect(toMap(NarrativeQuestion::getId, identity()));

return narrativeAnswerSaveRequests.stream()
.map(narrativeQuestionAnswerRequest -> new NarrativeAnswer(narrativeQuestionAnswerRequest.answerId(),
savedNarrativeQuestionsById.get(narrativeQuestionAnswerRequest.questionId()),
narrativeQuestionAnswerRequest.content()))
.toList();
}

private List<SelectiveAnswer> extractSelectiveAnswers(ApplicationSaveRequest request) {
private void validateSelectiveQuestions(ApplicationSaveRequest request) {
List<AnswerSaveRequest> selectiveAnswerSaveRequests = filterByQuestionType(QuestionType.SELECTIVE, request);
Set<Long> selectiveQuestionIds = extractQuestionIds(selectiveAnswerSaveRequests);
List<SelectiveQuestion> savedSelectiveQuestions = selectiveQuestionRepository.findAllByIdIn(
Expand All @@ -104,16 +86,6 @@ private List<SelectiveAnswer> extractSelectiveAnswers(ApplicationSaveRequest req
if (savedChoices.size() != choiceIds.size()) {
throw new CrewsException(ErrorCode.CHOICE_NOT_FOUND);
}

Map<Long, Choice> savedChoicesById = savedChoices.stream()
.collect(toMap(Choice::getId, identity()));
Map<Long, SelectiveQuestion> savedSelectiveQuestionsById = savedSelectiveQuestions.stream()
.collect(toMap(SelectiveQuestion::getId, identity()));

return selectiveAnswerSaveRequests.stream()
.map(selectiveQuestionAnswerRequest -> new SelectiveAnswer(selectiveQuestionAnswerRequest.answerId(),
savedChoicesById.get(selectiveQuestionAnswerRequest.choiceId()),
savedSelectiveQuestionsById.get(selectiveQuestionAnswerRequest.questionId()))).toList();
}

private List<AnswerSaveRequest> filterByQuestionType(QuestionType questionType,
Expand All @@ -138,7 +110,7 @@ private void validateQuestionIds(List<?> savedQuestions, Set<Long> questionIds)
public List<ApplicationsResponse> findAllApplicationsByRecruitment(Long publisherId) {
List<Application> applications = applicationRepository.findAllWithApplicantByPublisherId(publisherId);
return applications.stream()
.map(ApplicationsResponse::from)
.map(ApplicationMapper::applicationToApplicationsResponse)
.toList();
}

Expand All @@ -147,18 +119,10 @@ public ApplicationDetailsResponse findApplicationDetails(Long applicationId, Lon
.orElseThrow(() -> new CrewsException(ErrorCode.APPLICATION_NOT_FOUND));
checkPermission(application, publisherId);
List<NarrativeAnswer> narrativeAnswers = narrativeAnswerRepository.findAllByApplication(application);
Map<Long, List<SelectiveAnswer>> selectiveAnswers = collectSelectiveAnswersByQuestion(
selectiveAnswerRepository.findAllByApplication(application));
return ApplicationDetailsResponse.of(application, narrativeAnswers, selectiveAnswers);
}

public ApplicationDetailsResponse findMyApplicationDetails(Long applicantId, String code) {
Application application = applicationRepository.findByApplicantIdAndRecruitmentCode(applicantId, code)
.orElseThrow(() -> new CrewsException(ErrorCode.APPLICATION_NOT_FOUND));
List<NarrativeAnswer> narrativeAnswers = narrativeAnswerRepository.findAllByApplication(application);
Map<Long, List<SelectiveAnswer>> selectiveAnswers = collectSelectiveAnswersByQuestion(
selectiveAnswerRepository.findAllByApplication(application));
return ApplicationDetailsResponse.of(application, narrativeAnswers, selectiveAnswers);
List<SelectiveAnswer> selectiveAnswers = selectiveAnswerRepository.findAllByApplication(application);
application.replaceNarrativeAnswers(narrativeAnswers);
application.replaceSelectiveAnswers(selectiveAnswers);
return ApplicationMapper.applicationToApplicationDetailsResponse(application);
}

private void checkPermission(Application application, Long publisherId) {
Expand All @@ -167,9 +131,14 @@ private void checkPermission(Application application, Long publisherId) {
}
}

private Map<Long, List<SelectiveAnswer>> collectSelectiveAnswersByQuestion(List<SelectiveAnswer> selectiveAnswers) {
return selectiveAnswers.stream()
.collect(groupingBy(selectiveAnswer -> selectiveAnswer.getSelectiveQuestion().getId()));
public ApplicationDetailsResponse findMyApplicationDetails(Long applicantId, String code) {
Application application = applicationRepository.findByApplicantIdAndRecruitmentCode(applicantId, code)
.orElseThrow(() -> new CrewsException(ErrorCode.APPLICATION_NOT_FOUND));
List<NarrativeAnswer> narrativeAnswers = narrativeAnswerRepository.findAllByApplication(application);
List<SelectiveAnswer> selectiveAnswers = selectiveAnswerRepository.findAllByApplication(application);
application.replaceNarrativeAnswers(narrativeAnswers);
application.replaceSelectiveAnswers(selectiveAnswers);
return ApplicationMapper.applicationToApplicationDetailsResponse(application);
}

@Transactional
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/com/server/crews/applicant/domain/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public class Application {
private String name;

@OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
private List<NarrativeAnswer> narrativeAnswers = new ArrayList<>();
private List<NarrativeAnswer> narrativeAnswers;

@OneToMany(mappedBy = "application", cascade = CascadeType.ALL, orphanRemoval = true)
private List<SelectiveAnswer> selectiveAnswers = new ArrayList<>();
private List<SelectiveAnswer> selectiveAnswers;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false, name = "recruitment_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
Expand All @@ -72,19 +72,19 @@ public Application(Long id,
this.studentNumber = studentNumber;
this.major = major;
this.name = name;
updateNarrativeAnswers(narrativeAnswers);
updateSelectiveAnswers(selectiveAnswers);
this.outcome = Outcome.PENDING;
replaceNarrativeAnswers(narrativeAnswers);
replaceSelectiveAnswers(selectiveAnswers);
}

public void updateNarrativeAnswers(List<NarrativeAnswer> narrativeAnswers) {
this.narrativeAnswers.addAll(narrativeAnswers);
public void replaceNarrativeAnswers(List<NarrativeAnswer> narrativeAnswers) {
narrativeAnswers.forEach(narrativeAnswer -> narrativeAnswer.updateApplication(this));
this.narrativeAnswers = new ArrayList<>(narrativeAnswers);
}

public void updateSelectiveAnswers(List<SelectiveAnswer> selectiveAnswers) {
this.selectiveAnswers.addAll(selectiveAnswers);
public void replaceSelectiveAnswers(List<SelectiveAnswer> selectiveAnswers) {
selectiveAnswers.forEach(selectiveAnswer -> selectiveAnswer.updateApplication(this));
this.selectiveAnswers = new ArrayList<>(selectiveAnswers);
}

public void pass() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.server.crews.applicant.dto.response;

import com.server.crews.recruitment.dto.request.QuestionType;
import lombok.Builder;

@Builder
public record AnswerResponse(
Long answerId,
Long questionId,
String content,
Long choiceId,
QuestionType type
) {
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
package com.server.crews.applicant.dto.response;

import com.server.crews.applicant.domain.Application;
import com.server.crews.applicant.domain.NarrativeAnswer;
import com.server.crews.applicant.domain.SelectiveAnswer;
import java.util.List;
import java.util.Map;
import lombok.Builder;

@Builder
public record ApplicationDetailsResponse(Long id, String studentNumber, String major, String name,
List<SelectiveAnswerResponse> selectiveAnswers,
List<NarrativeAnswerResponse> narrativeAnswers) {

public static ApplicationDetailsResponse of(Application application, List<NarrativeAnswer> narrativeAnswers,
Map<Long, List<SelectiveAnswer>> selectiveAnswers) {
return ApplicationDetailsResponse.builder()
.id(application.getId())
.studentNumber(application.getStudentNumber())
.major(application.getMajor())
.name(application.getName())
.narrativeAnswers(from(narrativeAnswers))
.selectiveAnswers(from(selectiveAnswers))
.build();
}

private static List<NarrativeAnswerResponse> from(List<NarrativeAnswer> narrativeAnswers) {
return narrativeAnswers.stream()
.map(NarrativeAnswerResponse::from)
.toList();
}

private static List<SelectiveAnswerResponse> from(Map<Long, List<SelectiveAnswer>> selectiveAnswers) {
return selectiveAnswers.entrySet()
.stream()
.map(entry -> SelectiveAnswerResponse.from(entry.getKey(), entry.getValue()))
.toList();
}
public record ApplicationDetailsResponse(
Long id,
String studentNumber,
String major,
String name,
List<AnswerResponse> answers
) {
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package com.server.crews.applicant.dto.response;

import com.server.crews.applicant.domain.Application;
import com.server.crews.applicant.domain.Outcome;
import lombok.Builder;

@Builder
public record ApplicationsResponse(Long id, String studentNumber, String name, String major, Outcome outcome) {
public static ApplicationsResponse from(final Application application) {
return ApplicationsResponse.builder()
.id(application.getId())
.studentNumber(application.getStudentNumber())
.name(application.getName())
.major(application.getMajor())
.outcome(application.getOutcome())
.build();
}
public record ApplicationsResponse(
Long id,
String studentNumber,
String name,
String major,
Outcome outcome
) {
}

This file was deleted.

This file was deleted.

This file was deleted.

45 changes: 45 additions & 0 deletions src/main/java/com/server/crews/applicant/mapper/AnswerMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.server.crews.applicant.mapper;

import com.server.crews.applicant.domain.NarrativeAnswer;
import com.server.crews.applicant.domain.SelectiveAnswer;
import com.server.crews.applicant.dto.request.AnswerSaveRequest;
import com.server.crews.applicant.dto.response.AnswerResponse;
import com.server.crews.recruitment.domain.Choice;
import com.server.crews.recruitment.domain.NarrativeQuestion;
import com.server.crews.recruitment.domain.SelectiveQuestion;
import com.server.crews.recruitment.dto.request.QuestionType;
import java.util.List;

public class AnswerMapper {

public static AnswerResponse selectiveAnswerToAnswerResponse(SelectiveAnswer selectiveAnswer) {
return AnswerResponse.builder()
.answerId(selectiveAnswer.getId())
.questionId(selectiveAnswer.getSelectiveQuestion().getId())
.choiceId(selectiveAnswer.getChoice().getId())
.type(QuestionType.SELECTIVE)
.build();
}

public static AnswerResponse narrativeAnswerToAnswerResponse(NarrativeAnswer narrativeAnswer) {
return AnswerResponse.builder()
.answerId(narrativeAnswer.getId())
.questionId(narrativeAnswer.getNarrativeQuestion().getId())
.content(narrativeAnswer.getContent())
.type(QuestionType.NARRATIVE)
.build();
}

public static SelectiveAnswer answerSaveRequestToSelectiveAnswer(AnswerSaveRequest answerSaveRequest) {
return new SelectiveAnswer(
answerSaveRequest.answerId(),
new Choice(answerSaveRequest.choiceId(), null),
new SelectiveQuestion(answerSaveRequest.questionId(), List.of(), null, null, null, null, null));
}

public static NarrativeAnswer answerSaveRequestToNarrativeAnswer(AnswerSaveRequest answerSaveRequest) {
return new NarrativeAnswer(answerSaveRequest.answerId(),
new NarrativeQuestion(answerSaveRequest.questionId(), null, null, null, null),
answerSaveRequest.content());
}
}
Loading

0 comments on commit e444238

Please sign in to comment.