diff --git a/src/main/java/ddingdong/ddingdongBE/domain/form/service/dto/query/FormQuery.java b/src/main/java/ddingdong/ddingdongBE/domain/form/service/dto/query/FormQuery.java index 00fe510c..1bdb2946 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/form/service/dto/query/FormQuery.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/form/service/dto/query/FormQuery.java @@ -20,6 +20,7 @@ public record FormQuery( @Builder public record FormFieldListQuery( + Long id, String question, FieldType type, List options, @@ -29,6 +30,7 @@ public record FormFieldListQuery( ) { public static FormFieldListQuery from(FormField formField) { return FormFieldListQuery.builder() + .id(formField.getId()) .question(formField.getQuestion()) .type(formField.getFieldType()) .options(formField.getOptions()) diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/CentralFormApplicationApi.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/CentralFormApplicationApi.java index cc95479f..f31d1e1a 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/CentralFormApplicationApi.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/CentralFormApplicationApi.java @@ -2,6 +2,8 @@ import ddingdong.ddingdongBE.auth.PrincipalDetails; import ddingdong.ddingdongBE.domain.formapplication.controller.dto.response.FormApplicationResponse; +import ddingdong.ddingdongBE.domain.formapplication.controller.dto.request.UpdateFormApplicationStatusRequest; +import ddingdong.ddingdongBE.domain.formapplication.controller.dto.response.FormApplicationResponse; import ddingdong.ddingdongBE.domain.formapplication.controller.dto.response.MyFormApplicationPageResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -10,6 +12,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; @@ -44,4 +47,14 @@ FormApplicationResponse getFormApplication( @AuthenticationPrincipal PrincipalDetails principalDetails ); + @Operation(summary = "지원자 상태 수정 API") + @ApiResponse(responseCode = "204", description = "지원자 상태 수정 성공") + @ResponseStatus(HttpStatus.NO_CONTENT) + @SecurityRequirement(name = "AccessToken") + @PatchMapping("/my/forms/{formId}/applications") + void updateFormApplicationStatus( + @PathVariable("formId") Long formId, + @AuthenticationPrincipal PrincipalDetails principalDetails, + @Valid @RequestBody UpdateFormApplicationStatusRequest request + ); } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/UserFormApplicationApi.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/UserFormApplicationApi.java index 39f989af..253d5069 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/UserFormApplicationApi.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/api/UserFormApplicationApi.java @@ -16,7 +16,7 @@ public interface UserFormApplicationApi { @ApiResponse(responseCode = "201", description = "지원하기 성공") @ResponseStatus(HttpStatus.CREATED) @PostMapping("/forms/{formId}/applications") - void createFormResponse( + void createFormApplication( @PathVariable Long formId, @Valid @RequestBody CreateFormApplicationRequest request ); diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/CentralFormApplicationController.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/CentralFormApplicationController.java index 8160c7db..38b950b9 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/CentralFormApplicationController.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/CentralFormApplicationController.java @@ -1,6 +1,7 @@ package ddingdong.ddingdongBE.domain.formapplication.controller; import ddingdong.ddingdongBE.auth.PrincipalDetails; +import ddingdong.ddingdongBE.domain.formapplication.controller.dto.request.UpdateFormApplicationStatusRequest; import ddingdong.ddingdongBE.domain.formapplication.controller.dto.response.FormApplicationResponse; import ddingdong.ddingdongBE.domain.formapplication.service.FacadeCentralFormApplicationService; import ddingdong.ddingdongBE.domain.formapplication.api.CentralFormApplicationApi; @@ -15,19 +16,25 @@ @RequiredArgsConstructor public class CentralFormApplicationController implements CentralFormApplicationApi { - private final FacadeCentralFormApplicationService facadeCentralFormService; + private final FacadeCentralFormApplicationService facadeCentralFormApplicationService; @Override public MyFormApplicationPageResponse getMyFormApplicationPage(Long formId, int size, Long currentCursorId, PrincipalDetails principalDetails) { User user = principalDetails.getUser(); - MyFormApplicationPageQuery query = facadeCentralFormService.getMyFormApplicationPage(formId, user, size, currentCursorId); + MyFormApplicationPageQuery query = facadeCentralFormApplicationService.getMyFormApplicationPage(formId, user, size, currentCursorId); return MyFormApplicationPageResponse.from(query); } @Override public FormApplicationResponse getFormApplication(Long formId, Long applicationId, PrincipalDetails principalDetails) { User user = principalDetails.getUser(); - FormApplicationQuery query = facadeCentralFormService.getFormApplication(formId, applicationId, user); + FormApplicationQuery query = facadeCentralFormApplicationService.getFormApplication(formId, applicationId, user); return FormApplicationResponse.from(query); } + + @Override + public void updateFormApplicationStatus(Long formId, PrincipalDetails principalDetails, UpdateFormApplicationStatusRequest request) { + User user = principalDetails.getUser(); + facadeCentralFormApplicationService.updateStatus(request.toCommand(formId, user)); + } } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/UserFormApplicationController.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/UserFormApplicationController.java index 9359b927..1c987805 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/UserFormApplicationController.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/UserFormApplicationController.java @@ -13,7 +13,7 @@ public class UserFormApplicationController implements UserFormApplicationApi { private final FacadeUserFormService facadeUserFormService; @Override - public void createFormResponse(Long formId, CreateFormApplicationRequest createFormApplicationRequest) { + public void createFormApplication(Long formId, CreateFormApplicationRequest createFormApplicationRequest) { facadeUserFormService.createFormApplication(createFormApplicationRequest.toCommand(formId)); } } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/dto/request/UpdateFormApplicationStatusRequest.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/dto/request/UpdateFormApplicationStatusRequest.java new file mode 100644 index 00000000..b3d793e5 --- /dev/null +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/controller/dto/request/UpdateFormApplicationStatusRequest.java @@ -0,0 +1,28 @@ +package ddingdong.ddingdongBE.domain.formapplication.controller.dto.request; + +import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplicationStatus; +import ddingdong.ddingdongBE.domain.formapplication.service.dto.command.UpdateFormApplicationStatusCommand; +import ddingdong.ddingdongBE.domain.user.entity.User; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; + +import java.util.List; + +public record UpdateFormApplicationStatusRequest( + @NotNull(message = "지원자 id 리스트는 필수 입력 사항입니다.") + @Schema(description = "수정할 지원자 id 리스트", example = "[1, 2, 3]") + List applicationIds, + + @NotNull(message = "지원자 상태는 필수 입력 사항입니다.") + @Schema(description = "수정할 지원자 상태", example = "FIRST_PASS") + String status +) { + public UpdateFormApplicationStatusCommand toCommand(Long formId, User user) { + return UpdateFormApplicationStatusCommand.builder() + .formId(formId) + .applicationIds(applicationIds) + .status(FormApplicationStatus.findStatus(status)) + .user(user) + .build(); + } +} diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplication.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplication.java index 7fa2f192..92de2761 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplication.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplication.java @@ -41,4 +41,8 @@ private FormApplication(String name, String studentNumber, String department, Fo this.status = status; this.form = form; } + + public void updateStatus(FormApplicationStatus status) { + this.status = status; + } } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplicationStatus.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplicationStatus.java index 2cf62598..3bcc1ff9 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplicationStatus.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/entity/FormApplicationStatus.java @@ -1,9 +1,19 @@ package ddingdong.ddingdongBE.domain.formapplication.entity; +import ddingdong.ddingdongBE.common.exception.InvalidatedMappingException.InvalidatedEnumValue; +import java.util.Arrays; + public enum FormApplicationStatus { SUBMITTED, FIRST_PASS, FINAL_PASS, FIRST_FAIL, - FINAL_FAIL + FINAL_FAIL; + + public static FormApplicationStatus findStatus(String status) { + return Arrays.stream(values()) + .filter(findStatus -> findStatus.name().equals(status)) + .findFirst() + .orElseThrow(() -> new InvalidatedEnumValue("FormApplicationStatus (status=" + status + ")를 찾을 수 없습니다.")); + } } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationService.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationService.java index 5cbb528a..ea642ac7 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationService.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationService.java @@ -1,5 +1,6 @@ package ddingdong.ddingdongBE.domain.formapplication.service; +import ddingdong.ddingdongBE.domain.formapplication.service.dto.command.UpdateFormApplicationStatusCommand; 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; @@ -9,4 +10,6 @@ public interface FacadeCentralFormApplicationService { MyFormApplicationPageQuery getMyFormApplicationPage(Long formId, User user, int size, Long currentCursorId); FormApplicationQuery getFormApplication(Long formId, Long applicationId, User user); + + void updateStatus(UpdateFormApplicationStatusCommand command); } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationServiceImpl.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationServiceImpl.java index 5c28a9bc..1dc8566f 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationServiceImpl.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FacadeCentralFormApplicationServiceImpl.java @@ -1,12 +1,9 @@ package ddingdong.ddingdongBE.domain.formapplication.service; -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.command.UpdateFormApplicationStatusCommand; 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; import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplication; import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.MyFormApplicationPageQuery; import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.MyFormApplicationPageQuery.FormApplicationListQuery; @@ -47,4 +44,11 @@ public FormApplicationQuery getFormApplication(Long formId, Long applicationId, List formAnswers = formAnswerService.getAllByApplication(formApplication); return FormApplicationQuery.of(formApplication, formAnswers); } + + @Transactional + @Override + public void updateStatus(UpdateFormApplicationStatusCommand command) { + List formApplications = formApplicationService.getAllById(command.applicationIds()); + formApplications.forEach(formApplication -> formApplication.updateStatus(command.status())); + } } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FormApplicationService.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FormApplicationService.java index 8aa459fe..fd9d3691 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FormApplicationService.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/FormApplicationService.java @@ -3,6 +3,8 @@ import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplication; import org.springframework.data.domain.Slice; +import java.util.List; + public interface FormApplicationService { FormApplication create(FormApplication formApplication); @@ -10,4 +12,6 @@ public interface FormApplicationService { Slice getFormApplicationPageByFormId(Long formId, int size, Long currentCursorId); FormApplication getById(Long applicationId); + + List getAllById(List applicationIds); } diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/GeneralFormApplicationService.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/GeneralFormApplicationService.java index a856d1fa..ae7543a2 100644 --- a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/GeneralFormApplicationService.java +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/GeneralFormApplicationService.java @@ -32,6 +32,11 @@ public Slice getFormApplicationPageByFormId(Long formId, int si return buildSlice(formApplicationPages, size); } + @Override + public List getAllById(List applicationIds) { + return formApplicationRepository.findAllById(applicationIds); + } + @Override public FormApplication getById(Long applicationId) { return formApplicationRepository.findById(applicationId) diff --git a/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/dto/command/UpdateFormApplicationStatusCommand.java b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/dto/command/UpdateFormApplicationStatusCommand.java new file mode 100644 index 00000000..fc5e9473 --- /dev/null +++ b/src/main/java/ddingdong/ddingdongBE/domain/formapplication/service/dto/command/UpdateFormApplicationStatusCommand.java @@ -0,0 +1,16 @@ +package ddingdong.ddingdongBE.domain.formapplication.service.dto.command; + +import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplicationStatus; +import ddingdong.ddingdongBE.domain.user.entity.User; +import lombok.Builder; + +import java.util.List; + +@Builder +public record UpdateFormApplicationStatusCommand( + Long formId, + List applicationIds, + FormApplicationStatus status, + User user +) { +} diff --git a/src/test/java/ddingdong/ddingdongBE/domain/form/service/FacadeCentralFormApplicationServiceImplTest.java b/src/test/java/ddingdong/ddingdongBE/domain/form/service/FacadeCentralFormApplicationServiceImplTest.java index 63ecd96d..80c2baee 100644 --- a/src/test/java/ddingdong/ddingdongBE/domain/form/service/FacadeCentralFormApplicationServiceImplTest.java +++ b/src/test/java/ddingdong/ddingdongBE/domain/form/service/FacadeCentralFormApplicationServiceImplTest.java @@ -11,6 +11,7 @@ import ddingdong.ddingdongBE.domain.formapplication.entity.FormApplicationStatus; import ddingdong.ddingdongBE.domain.formapplication.service.FacadeCentralFormApplicationService; import ddingdong.ddingdongBE.domain.formapplication.service.FormApplicationService; +import ddingdong.ddingdongBE.domain.formapplication.service.dto.command.UpdateFormApplicationStatusCommand; import ddingdong.ddingdongBE.domain.formapplication.service.dto.query.FormApplicationQuery; import ddingdong.ddingdongBE.domain.user.entity.Role; import ddingdong.ddingdongBE.domain.user.entity.User; @@ -20,8 +21,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import java.util.ArrayList; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; @SpringBootTest class FacadeCentralFormApplicationServiceImplTest extends TestContainerSupport { @@ -80,4 +83,63 @@ void getFormApplication() { // then assertThat(formApplicationQuery.name()).isEqualTo("지원자1"); } + + @DisplayName("동아리는 지원자의 상태를 수정할 수 있다.") + @Test + void updateFormApplicationStatus() { + // given + User user = fixture.giveMeBuilder(User.class) + .set("id", 1L) + .set("Role", Role.CLUB) + .set("deletedAt", null) + .sample(); + User savedUser = userRepository.saveAndFlush(user); + Club club = fixture.giveMeBuilder(Club.class) + .set("id", 1L) + .set("user", savedUser) + .set("score", null) + .set("clubMembers", null) + .set("deletedAt", null) + .sample(); + Club savedClub = clubRepository.saveAndFlush(club); + Form form = fixture.giveMeBuilder(Form.class) + .set("id", 1L) + .set("title", "제목1") + .set("club", savedClub) + .sample(); + Form savedForm = formRepository.saveAndFlush(form); + FormApplication formApplication1 = FormApplication.builder() + .name("지원자1") + .studentNumber("60201115") + .department("융합소프트웨어학부") + .status(FormApplicationStatus.SUBMITTED) + .form(savedForm) + .build(); + FormApplication formApplication2 = FormApplication.builder() + .name("지원자2") + .studentNumber("602011156") + .department("디지털콘텐츠디자인학과") + .status(FormApplicationStatus.SUBMITTED) + .form(savedForm) + .build(); + FormApplication savedApplication1 = formApplicationService.create(formApplication1); + FormApplication savedApplication2 = formApplicationService.create(formApplication2); + List applicationIds = new ArrayList<>(); + applicationIds.add(savedApplication1.getId()); + applicationIds.add(savedApplication2.getId()); + UpdateFormApplicationStatusCommand command = fixture.giveMeBuilder(UpdateFormApplicationStatusCommand.class) + .set("formId", savedForm.getId()) + .set("applicationIds", applicationIds) + .set("status", FormApplicationStatus.FIRST_PASS) + .set("user", savedUser) + .sample(); + // when + facadeCentralFormApplicationService.updateStatus(command); + // then + assertThat(formApplication1.getName()).isEqualTo("지원자1"); + assertThat(formApplication1.getStatus()).isEqualTo(FormApplicationStatus.FIRST_PASS); + assertThat(formApplication2.getName()).isEqualTo("지원자2"); + assertThat(formApplication2.getStatus()).isEqualTo(FormApplicationStatus.FIRST_PASS); + } + } \ No newline at end of file