-
Notifications
You must be signed in to change notification settings - Fork 2
[DDING-91] 지원하기 API 구현 #233
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
Changes from all commits
bb66260
2fb9efc
392b085
237e9dd
0a367c5
17bc0c2
c9d2c6a
a9e4a75
8297adc
178793c
0736cb2
c995843
786d71e
0b071f6
438292b
d0f9d6a
fbefe2b
cfecc45
331668e
0f29123
4aa5d56
05b6525
7701b45
37626bf
8160061
0fe9e37
62b2f00
97b93f0
0c61cdd
22a5063
915c237
91ddb0a
e0f55d5
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,24 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.api; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.controller.dto.request.CreateFormApplicationRequest; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import jakarta.validation.Valid; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@Tag(name = "Form - User", description = "User Form API") | ||
@RequestMapping("/server") | ||
public interface UserFormApi { | ||
|
||
@Operation(summary = "지원하기 API") | ||
@ApiResponse(responseCode = "201", description = "지원하기 성공") | ||
@ResponseStatus(HttpStatus.CREATED) | ||
@PostMapping("/forms/{formId}/applications") | ||
void createFormResponse( | ||
@PathVariable Long formId, | ||
@Valid @RequestBody CreateFormApplicationRequest request | ||
); | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,19 @@ | ||||||||||||||||||||||||||||
package ddingdong.ddingdongBE.domain.formapplicaion.controller; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.api.UserFormApi; | ||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.controller.dto.request.CreateFormApplicationRequest; | ||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.service.FacadeUserFormService; | ||||||||||||||||||||||||||||
import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||
import org.springframework.web.bind.annotation.RestController; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
@RestController | ||||||||||||||||||||||||||||
@RequiredArgsConstructor | ||||||||||||||||||||||||||||
public class UserFormController implements UserFormApi { | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
private final FacadeUserFormService facadeUserFormService; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||
public void createFormResponse(Long formId, CreateFormApplicationRequest createFormApplicationRequest) { | ||||||||||||||||||||||||||||
facadeUserFormService.createFormApplication(formId, createFormApplicationRequest.toCommand()); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
Comment on lines
+15
to
+18
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. 🛠️ Refactor suggestion 응답 타입과 검증 로직이 필요합니다. 컨트롤러에서 다음 사항들을 개선해 주시기 바랍니다:
다음과 같이 개선하는 것을 추천드립니다: -public void createFormResponse(Long formId, CreateFormApplicationRequest createFormApplicationRequest) {
+public ResponseEntity<ApiResponse> createFormResponse(
+ @PathVariable @Positive Long formId,
+ @Valid @RequestBody CreateFormApplicationRequest createFormApplicationRequest
+) {
facadeUserFormService.createFormApplication(formId, createFormApplicationRequest.toCommand());
+ return ResponseEntity.status(HttpStatus.CREATED)
+ .body(ApiResponse.success("폼 신청이 성공적으로 생성되었습니다."));
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,60 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
package ddingdong.ddingdongBE.domain.formapplicaion.controller.dto.request; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormApplicationStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.service.dto.CreateFormApplicationCommand; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.service.dto.CreateFormApplicationCommand.CreateFormAnswerCommand; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import io.swagger.v3.oas.annotations.media.ArraySchema; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import io.swagger.v3.oas.annotations.media.Schema; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import jakarta.validation.constraints.NotNull; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public record CreateFormApplicationRequest( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@NotNull(message = "지원자 이름은 필수 입력 사항입니다.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Schema(description = "지원자 이름", example = "김띵동") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
String name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@NotNull(message = "지원자 학번은 필수 입력 사항입니다.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Schema(description = "학번", example = "60200000") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
String studentNumber, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@NotNull(message = "지원자 학과는 필수 입력 사항입니다.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Schema(description = "학과", example = "융합소프트웨어학부 응용소프트웨어전공") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
String department, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@ArraySchema(schema = @Schema(implementation = CreateFormAnswerRequest.class)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List<CreateFormAnswerRequest> formAnswers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+12
to
+28
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가 누락되었습니다. 폼 신청을 생성하기 위해서는 어떤 폼에 대한 신청인지 식별할 수 있는 formId가 필요합니다. public record CreateFormApplicationRequest(
+ @NotNull(message = "폼 ID는 필수 입력 사항입니다.")
+ @Schema(description = "폼 ID", example = "1")
+ Long formId,
@NotNull(message = "지원자 이름은 필수 입력 사항입니다.")
@Schema(description = "지원자 이름", example = "김띵동")
String name, 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
record CreateFormAnswerRequest( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@NotNull(message = "질문 id는 null이 될 수 없습니다.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Schema(description = "질문 id", example = "1") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Long fieldId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Schema(description = "답변 값") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List<String> value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public CreateFormAnswerCommand toCommand() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return CreateFormAnswerCommand.builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.fieldId(fieldId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.value(value) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public CreateFormApplicationCommand toCommand() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List<CreateFormAnswerCommand> createFormAnswerCommands = formAnswers.stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.map(CreateFormAnswerRequest::toCommand) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.toList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return CreateFormApplicationCommand.builder() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.name(name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.studentNumber(studentNumber) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.department(department) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.status(FormApplicationStatus.SUBMITTED) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.formAnswerCommands(createFormAnswerCommands) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,40 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
package ddingdong.ddingdongBE.domain.formapplicaion.entity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.common.BaseEntity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.common.converter.StringListConverter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.entity.FieldType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.entity.FormField; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import jakarta.persistence.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import lombok.AccessLevel; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import lombok.Builder; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import lombok.Getter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import lombok.NoArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Entity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Getter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public class FormAnswer extends BaseEntity { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private Long id; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Column(nullable = false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Convert(converter = StringListConverter.class) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private List<String> value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@ManyToOne(fetch = FetchType.LAZY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private FormApplication formApplication; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@ManyToOne(fetch = FetchType.LAZY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private FormField formField; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+27
to
+31
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. 연관 관계의 무결성 보장이 필요합니다. FormApplication과 FormField에 대한 null 체크가 누락되어 있습니다. 엔티티 생성 시점에 이를 검증하는 것이 좋습니다. 다음과 같이 생성자에 검증 로직을 추가하는 것을 추천드립니다: @Builder
private FormAnswer(List<String> value, FormApplication formApplication, FormField formField) {
+ validateRelations(formApplication, formField);
this.value = value;
this.formApplication = formApplication;
this.formField = formField;
}
+private void validateRelations(FormApplication formApplication, FormField formField) {
+ if (formApplication == null) {
+ throw new IllegalArgumentException("FormApplication은 null일 수 없습니다.");
+ }
+ if (formField == null) {
+ throw new IllegalArgumentException("FormField는 null일 수 없습니다.");
+ }
+} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Builder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private FormAnswer(List<String> value, FormApplication formApplication, FormField formField) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.value = value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.formApplication = formApplication; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.formField = formField; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.entity; | ||
|
||
import ddingdong.ddingdongBE.common.BaseEntity; | ||
import ddingdong.ddingdongBE.domain.form.entity.Form; | ||
import jakarta.persistence.*; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Getter | ||
public class FormApplication extends BaseEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(nullable = false) | ||
private String name; | ||
|
||
@Column(nullable = false) | ||
private String studentNumber; | ||
|
||
@Column(nullable = false) | ||
private String department; | ||
Comment on lines
+20
to
+27
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. 개인정보 필드에 대한 보안 처리가 필요합니다. name, studentNumber, department 필드에 개인정보가 포함되어 있으므로, 적절한 보안 처리가 필요합니다. 다음과 같은 보안 조치를 추가하는 것을 추천드립니다:
+@Convert(converter = EncryptionConverter.class)
@Column(nullable = false)
private String name;
+@Convert(converter = EncryptionConverter.class)
@Column(nullable = false)
private String studentNumber;
+@Convert(converter = EncryptionConverter.class)
@Column(nullable = false)
private String department;
@Override
public String toString() {
return "FormApplication{" +
"id=" + id +
", name='" + maskPersonalInfo(name) + '\'' +
", studentNumber='" + maskPersonalInfo(studentNumber) + '\'' +
", department='" + department + '\'' +
", status=" + status +
'}';
}
private String maskPersonalInfo(String info) {
if (info == null || info.length() <= 2) return "*".repeat(info.length());
return info.substring(0, 1) + "*".repeat(info.length() - 2) + info.substring(info.length() - 1);
} |
||
|
||
@Enumerated(EnumType.STRING) | ||
@Column(nullable = false, name = "status") | ||
private FormApplicationStatus status; | ||
Comment on lines
+29
to
+31
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. 🛠️ Refactor suggestion 상태 전이 로직이 필요합니다. FormApplicationStatus에 대한 상태 관리 로직이 누락되어 있습니다. 다음과 같은 상태 관리 메서드를 추가하는 것을 추천드립니다: public void approve() {
validateStatusTransition(FormApplicationStatus.APPROVED);
this.status = FormApplicationStatus.APPROVED;
}
public void reject() {
validateStatusTransition(FormApplicationStatus.REJECTED);
this.status = FormApplicationStatus.REJECTED;
}
private void validateStatusTransition(FormApplicationStatus newStatus) {
if (this.status != FormApplicationStatus.PENDING) {
throw new IllegalStateException("이미 처리된 지원서입니다.");
}
} |
||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
private Form form; | ||
|
||
@Builder | ||
private FormApplication(String name, String studentNumber, String department, FormApplicationStatus status, Form form) { | ||
this.name = name; | ||
this.studentNumber = studentNumber; | ||
this.department = department; | ||
this.status = status; | ||
this.form = form; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.entity; | ||
|
||
public enum FormApplicationStatus { | ||
SUBMITTED, | ||
FIRST_PASS, | ||
FINAL_PASS, | ||
FAILURE | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.repository; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormAnswer; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface FormAnswerRepository extends JpaRepository<FormAnswer, Long> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.repository; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormApplication; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface FormApplicationRepository extends JpaRepository<FormApplication, Long> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.service; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.service.dto.CreateFormApplicationCommand; | ||
|
||
public interface FacadeUserFormService { | ||
|
||
void createFormApplication(Long formId, CreateFormApplicationCommand createFormApplicationCommand); | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,46 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
package ddingdong.ddingdongBE.domain.formapplicaion.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.entity.Form; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormAnswer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.entity.FormField; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormApplication; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.service.FormFieldService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.form.service.FormService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.service.dto.CreateFormApplicationCommand; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ddingdong.ddingdongBE.domain.formapplicaion.service.dto.CreateFormApplicationCommand.CreateFormAnswerCommand; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public class FacadeUserFormServiceImpl implements FacadeUserFormService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private final FormApplicationService formApplicationService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private final FormAnswerService formAnswerService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private final FormService formService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private final FormFieldService formFieldService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Transactional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void createFormApplication(Long formId, CreateFormApplicationCommand createFormApplicationCommand) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Form form = formService.getById(formId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FormApplication formApplication = createFormApplicationCommand.toEntity(form); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FormApplication savedFormApplication = formApplicationService.create(formApplication); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List<FormAnswer> formAnswers = toFormAnswers(savedFormApplication, createFormApplicationCommand.formAnswerCommands()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
formAnswerService.createAll(formAnswers); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+29
to
+36
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. 🛠️ Refactor suggestion 비즈니스 검증 로직과 예외 처리가 필요합니다. Facade 서비스에서 다음 사항들을 개선해 주시기 바랍니다:
다음과 같이 개선하는 것을 추천드립니다: @Transactional
@Override
public void createFormApplication(Long formId, CreateFormApplicationCommand createFormApplicationCommand) {
+ try {
Form form = formService.getById(formId);
+ validateFormStatus(form);
+ validateFormAnswers(form, createFormApplicationCommand.formAnswerCommands());
FormApplication formApplication = createFormApplicationCommand.toEntity(form);
FormApplication savedFormApplication = formApplicationService.create(formApplication);
List<FormAnswer> formAnswers = toFormAnswers(savedFormApplication, createFormApplicationCommand.formAnswerCommands());
formAnswerService.createAll(formAnswers);
+ } catch (FormNotFoundException | FormFieldNotFoundException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new FormApplicationException("폼 신청 생성 중 오류가 발생했습니다: " + e.getMessage());
+ }
}
+private void validateFormStatus(Form form) {
+ if (!form.isAcceptingApplications()) {
+ throw new InvalidFormStatusException("현재 신청이 불가능한 폼입니다.");
+ }
+}
+private void validateFormAnswers(Form form, List<CreateFormAnswerCommand> answers) {
+ // 필수 답변 검증
+ Set<Long> requiredFieldIds = form.getRequiredFieldIds();
+ Set<Long> answeredFieldIds = answers.stream()
+ .map(CreateFormAnswerCommand::fieldId)
+ .collect(Collectors.toSet());
+
+ if (!answeredFieldIds.containsAll(requiredFieldIds)) {
+ throw new InvalidFormAnswerException("필수 항목이 모두 답변되지 않았습니다.");
+ }
+} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private List<FormAnswer> toFormAnswers(FormApplication savedFormApplication, List<CreateFormAnswerCommand> createFormAnswerCommands) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return createFormAnswerCommands.stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.map(formAnswerCommand -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FormField formField = formFieldService.getById(formAnswerCommand.fieldId()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return formAnswerCommand.toEntity(savedFormApplication, formField); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.toList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+38
to
+45
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. 🛠️ Refactor suggestion 폼 필드 유효성 검증이 필요합니다. toFormAnswers 메서드에서 폼 필드와 답변 값의 유효성을 검증해야 합니다. 다음과 같이 개선하는 것을 추천드립니다: private List<FormAnswer> toFormAnswers(FormApplication savedFormApplication, List<CreateFormAnswerCommand> createFormAnswerCommands) {
return createFormAnswerCommands.stream()
.map(formAnswerCommand -> {
FormField formField = formFieldService.getById(formAnswerCommand.fieldId());
+ validateAnswerValue(formField, formAnswerCommand.value());
return formAnswerCommand.toEntity(savedFormApplication, formField);
})
.toList();
}
+private void validateAnswerValue(FormField formField, String value) {
+ if (formField.isRequired() && (value == null || value.trim().isEmpty())) {
+ throw new InvalidFormAnswerException("필수 항목에 답변이 누락되었습니다.");
+ }
+
+ if (!formField.isValidValue(value)) {
+ throw new InvalidFormAnswerException("답변 형식이 올바르지 않습니다.");
+ }
+} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.service; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormAnswer; | ||
import java.util.List; | ||
|
||
public interface FormAnswerService { | ||
|
||
void createAll(List<FormAnswer> formAnswers); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.service; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormApplication; | ||
|
||
public interface FormApplicationService { | ||
|
||
FormApplication create(FormApplication formApplication); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package ddingdong.ddingdongBE.domain.formapplicaion.service; | ||
|
||
import ddingdong.ddingdongBE.domain.formapplicaion.entity.FormAnswer; | ||
import ddingdong.ddingdongBE.domain.formapplicaion.repository.FormAnswerRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class GeneralFormAnswerService implements FormAnswerService { | ||
|
||
private final FormAnswerRepository formAnswerRepository; | ||
|
||
@Transactional | ||
@Override | ||
public void createAll(List<FormAnswer> formAnswers) { | ||
formAnswerRepository.saveAll(formAnswers); | ||
} | ||
|
||
} |
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.
🛠️ Refactor suggestion
API 문서화 개선이 필요합니다.
API 문서화와 경로에 대해 다음 사항들을 개선해 주시기 바랍니다:
다음과 같이 개선하는 것을 추천드립니다:
그리고 createFormResponse 메서드에 다음 문서화를 추가해 주세요: