-
Notifications
You must be signed in to change notification settings - Fork 1
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
[DDING-95] 지원자 상세 조회 API 구현 #240
Changes from all commits
8b40c1a
5ff484b
2d22171
9fb14da
87e44a0
70b7e7f
12d1248
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package ddingdong.ddingdongBE.domain.formapplication.controller.dto.response; | ||
|
||
import ddingdong.ddingdongBE.domain.form.entity.FieldType; | ||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplicationStatus; | ||
import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.FormApplicationQuery; | ||
import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.FormApplicationQuery.FormFieldAnswerListQuery; | ||
|
||
import io.swagger.v3.oas.annotations.media.ArraySchema; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import lombok.Builder; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
@Builder | ||
public record FormApplicationResponse ( | ||
@Schema(description = "제출일시", example = "2025-01-01T00:00") | ||
LocalDateTime submittedAt, | ||
@Schema(description = "지원자 이름", example = "김띵동") | ||
String name, | ||
@Schema(description = "지원자 학번", example = "60201111") | ||
String studentNumber, | ||
@Schema(description = "지원자 학과", example = "융합소프트웨어학부") | ||
String department, | ||
@Schema(description = "status", example = "SUBMITTED") | ||
FormApplicationStatus status, | ||
@ArraySchema(schema = @Schema(implementation = FormFieldAnswerListResponse.class)) | ||
List<FormFieldAnswerListResponse> formFieldAnswers | ||
){ | ||
@Builder | ||
record FormFieldAnswerListResponse ( | ||
@Schema(description = "폼지 질문 ID", example = "1") | ||
Long fieldId, | ||
@Schema(description = "폼지 질문", example = "성별이 무엇입니까??") | ||
String question, | ||
@Schema(description = "폼지 질문 유형", example = "RADIO", allowableValues = {"CHECK_BOX", "RADIO", "TEXT", "LONG_TEXT", "FILE"}) | ||
FieldType type, | ||
@Schema(description = "폼지 지문", example = "[\"여성\", \"남성\"]") | ||
List<String> options, | ||
@Schema(description = "필수 여부", example = "true") | ||
Boolean required, | ||
@Schema(description = "질문 순서", example = "1") | ||
Integer order, | ||
@Schema(description = "섹션", example = "공통") | ||
String section, | ||
@Schema(description = "질문 답변 값", example = "[\"지문1\"]") | ||
List<String> value | ||
) { | ||
public static FormFieldAnswerListResponse from(FormFieldAnswerListQuery formFieldAnswerListQuery) { | ||
return FormFieldAnswerListResponse.builder() | ||
.fieldId(formFieldAnswerListQuery.fieldId()) | ||
.question(formFieldAnswerListQuery.question()) | ||
.type(formFieldAnswerListQuery.type()) | ||
.options(formFieldAnswerListQuery.options()) | ||
.required(formFieldAnswerListQuery.required()) | ||
.order(formFieldAnswerListQuery.order()) | ||
.section(formFieldAnswerListQuery.section()) | ||
.value(formFieldAnswerListQuery.value()) | ||
.build(); | ||
} | ||
} | ||
public static FormApplicationResponse from(FormApplicationQuery formApplicationQuery) { | ||
List<FormFieldAnswerListResponse> responses = formApplicationQuery.formFieldAnswers().stream() | ||
.map(FormFieldAnswerListResponse::from) | ||
.toList(); | ||
|
||
return FormApplicationResponse.builder() | ||
.submittedAt(formApplicationQuery.createdAt()) | ||
.name(formApplicationQuery.name()) | ||
.studentNumber(formApplicationQuery.studentNumber()) | ||
.department(formApplicationQuery.department()) | ||
.status(formApplicationQuery.status()) | ||
.formFieldAnswers(responses) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
package ddingdong.ddingdongBE.domain.formapplication.repository; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormAnswer; | ||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplication; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import java.util.List; | ||
|
||
public interface FormAnswerRepository extends JpaRepository<FormAnswer, Long> { | ||
List<FormAnswer> findAllByFormApplication(FormApplication formApplication); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
package ddingdong.ddingdongBE.domain.formapplication.service; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.FormApplicationQuery; | ||
import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.MyFormApplicationPageQuery; | ||
import ddingdong.ddingdongBE.domain.user.entity.User; | ||
|
||
public interface FacadeCentralFormApplicationService { | ||
|
||
MyFormApplicationPageQuery getMyFormApplicationPage(Long formId, User user, int size, Long currentCursorId); | ||
|
||
FormApplicationQuery getFormApplication(Long formId, Long applicationId, User user); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.club.entity.Club; | ||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.club.service.ClubService; | ||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormAnswer; | ||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.FormApplicationQuery; | ||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.PagingQuery; | ||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.entity.Form; | ||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.service.FormService; | ||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -11,7 +13,6 @@ | |||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.user.entity.User; | ||||||||||||||||||||||||||||||||||||||||||||||
import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||
import org.springframework.data.domain.Slice; | ||||||||||||||||||||||||||||||||||||||||||||||
import org.springframework.security.access.AccessDeniedException; | ||||||||||||||||||||||||||||||||||||||||||||||
import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||
import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -22,17 +23,11 @@ | |||||||||||||||||||||||||||||||||||||||||||||
@Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||||||||||
public class FacadeCentralFormApplicationServiceImpl implements FacadeCentralFormApplicationService { | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
private final ClubService clubService; | ||||||||||||||||||||||||||||||||||||||||||||||
private final FormService formService; | ||||||||||||||||||||||||||||||||||||||||||||||
private final FormApplicationService formApplicationService; | ||||||||||||||||||||||||||||||||||||||||||||||
private final FormAnswerService formAnswerService; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||
public MyFormApplicationPageQuery getMyFormApplicationPage(Long formId, User user, int size, Long currentCursorId) { | ||||||||||||||||||||||||||||||||||||||||||||||
Club club = clubService.getByUserId(user.getId()); | ||||||||||||||||||||||||||||||||||||||||||||||
Form form = formService.getById(formId); | ||||||||||||||||||||||||||||||||||||||||||||||
if (!form.getClub().equals(club)) { | ||||||||||||||||||||||||||||||||||||||||||||||
throw new AccessDeniedException("권한이 없습니다."); | ||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||
Slice<FormApplication> formApplicationPage = formApplicationService.getFormApplicationPageByFormId(formId, size, currentCursorId); | ||||||||||||||||||||||||||||||||||||||||||||||
if (formApplicationPage == null) { | ||||||||||||||||||||||||||||||||||||||||||||||
return MyFormApplicationPageQuery.createEmpty(); | ||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -44,6 +39,12 @@ public MyFormApplicationPageQuery getMyFormApplicationPage(Long formId, User use | |||||||||||||||||||||||||||||||||||||||||||||
PagingQuery pagingQuery = PagingQuery.of(currentCursorId, completeFormApplications, formApplicationPage.hasNext()); | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
return MyFormApplicationPageQuery.of(formApplicationListQueries, pagingQuery); | ||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||
public FormApplicationQuery getFormApplication(Long formId, Long applicationId, User user) { | ||||||||||||||||||||||||||||||||||||||||||||||
FormApplication formApplication = formApplicationService.getById(applicationId); | ||||||||||||||||||||||||||||||||||||||||||||||
List<FormAnswer> formAnswers = formAnswerService.getAllByApplication(formApplication); | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p1) form으로 fields를 찾는 것보다 formAnswer내부의 field를 사용하면 dto내 복잡한 로직을 줄일 수 있을 것 같아요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하...!!! 제가 엔터티가 객체랑 매핑되어 있는 걸 잊었네요... 테이블에 있는 것처럼 id만 있다고 생각 했더니 이렇게 됐습니다. 알려주셔서 감사합니다! dto 재사용이 조심스러워야 한다는 점도 처음 알았습니다. 감사합니다. 수정 완료했습니다! |
||||||||||||||||||||||||||||||||||||||||||||||
return FormApplicationQuery.of(formApplication, formAnswers); | ||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+44
to
49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 필수 유효성 검사가 누락되었습니다!
다음과 같이 수정하는 것을 제안드립니다: @Override
public FormApplicationQuery getFormApplication(Long formId, Long applicationId, User user) {
+ Form form = formService.getById(formId);
+ if (!form.getClub().equals(user.getClub())) {
+ throw new AccessDeniedException("해당 폼에 대한 접근 권한이 없습니다.");
+ }
FormApplication formApplication = formApplicationService.getById(applicationId);
+ if (formApplication == null) {
+ throw new EntityNotFoundException("지원서를 찾을 수 없습니다.");
+ }
+ if (!formApplication.getForm().getId().equals(formId)) {
+ throw new InvalidArgumentException("지원서가 해당 폼에 속하지 않습니다.");
+ }
List<FormAnswer> formAnswers = formAnswerService.getAllByApplication(formApplication);
return FormApplicationQuery.of(formApplication, formAnswers);
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,14 @@ | ||
package ddingdong.ddingdongBE.domain.formapplication.service; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormAnswer; | ||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplication; | ||
|
||
import java.util.List; | ||
|
||
public interface FormAnswerService { | ||
|
||
void createAll(List<FormAnswer> formAnswers); | ||
|
||
List<FormAnswer> getAllByApplication(FormApplication formApplication); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package ddingdong.ddingdongBE.domain.formapplication.service.dto.query; | ||
|
||
import ddingdong.ddingdongBE.domain.form.entity.FieldType; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormAnswer; | ||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplication; | ||
import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplicationStatus; | ||
|
||
import lombok.Builder; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
@Builder | ||
public record FormApplicationQuery ( | ||
LocalDateTime createdAt, | ||
String name, | ||
String studentNumber, | ||
String department, | ||
FormApplicationStatus status, | ||
List<FormFieldAnswerListQuery> formFieldAnswers | ||
) { | ||
@Builder | ||
public record FormFieldAnswerListQuery ( | ||
Long fieldId, | ||
String question, | ||
FieldType type, | ||
List<String> options, | ||
Boolean required, | ||
Integer order, | ||
String section, | ||
List<String> value | ||
) { | ||
public static FormFieldAnswerListQuery from(FormAnswer formAnswer) { | ||
return FormFieldAnswerListQuery.builder() | ||
.fieldId(formAnswer.getFormField().getId()) | ||
.question(formAnswer.getFormField().getQuestion()) | ||
.type(formAnswer.getFormField().getFieldType()) | ||
.options(formAnswer.getFormField().getOptions()) | ||
.required(formAnswer.getFormField().isRequired()) | ||
.order(formAnswer.getFormField().getFieldOrder()) | ||
.section(formAnswer.getFormField().getSection()) | ||
.value(formAnswer.getValue()) | ||
.build(); | ||
} | ||
} | ||
public static FormApplicationQuery of(FormApplication formApplication, List<FormAnswer> formAnswers) { | ||
List<FormFieldAnswerListQuery> formFieldAnswerListQueries = formAnswers.stream() | ||
.map(FormFieldAnswerListQuery::from) | ||
.toList(); | ||
return FormApplicationQuery.builder() | ||
.createdAt(formApplication.getCreatedAt()) | ||
.name(formApplication.getName()) | ||
.studentNumber(formApplication.getStudentNumber()) | ||
.department(formApplication.getDepartment()) | ||
.status(formApplication.getStatus()) | ||
.formFieldAnswers(formFieldAnswerListQueries) | ||
.build(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3)
formId, user 파라미터는 해당 메서드에서 사용을 안하는데 따로 받는 이유가 있을까요?
없다면 제거해도 괜찮을거 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추후 해당 폼이 로그인한 사용자 소유의 폼인지 유효성 검사를 해야 할 것 같아서 받아왔는데 일단 삭제해두는 게 맞을까요?