Skip to content
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
@@ -1,5 +1,8 @@
package dmu.dasom.api.domain.applicant.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import dmu.dasom.api.domain.applicant.entity.Applicant;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
Expand All @@ -9,6 +12,11 @@
@Schema(name = "ApplicantCreateRequestDto", description = "지원자 생성 요청 DTO")
public class ApplicantCreateRequestDto {

@NotNull
@Size(max = 16)
@Schema(description = "이름", example = "홍길동")
private String name;

@NotNull
@Pattern(regexp = "^[0-9]{8}$")
@Size(min = 8, max = 8)
Expand Down Expand Up @@ -39,13 +47,18 @@ public class ApplicantCreateRequestDto {
private String reasonForApply;

@Size(max = 200)
@Schema(description = "활동 희망사항", example = "동아리 활동 참여")
@Schema(description = "활동 희망사항", example = "동아리 활동 참여", nullable = true)
private String activityWish;

@NotNull
@Schema(description = "개인정보 처리방침 동의 여부", example = "true")
private Boolean isPrivacyPolicyAgreed;

@JsonProperty(defaultValue = "false")
@JsonSetter(nulls = Nulls.SKIP)
@Schema(description = "지원서 덮어쓰기 확인 여부", example = "false", defaultValue = "false", nullable = true)
private Boolean isOverwriteConfirmed = false;

public Applicant toEntity() {
return Applicant.builder()
.studentNo(this.studentNo)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dmu.dasom.api.domain.applicant.entity;

import dmu.dasom.api.domain.applicant.dto.ApplicantCreateRequestDto;
import dmu.dasom.api.domain.applicant.dto.ApplicantDetailsResponseDto;
import dmu.dasom.api.domain.applicant.dto.ApplicantResponseDto;
import dmu.dasom.api.domain.applicant.enums.ApplicantStatus;
Expand All @@ -9,6 +10,7 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
Expand All @@ -17,6 +19,7 @@

@AllArgsConstructor
@Builder
@DynamicUpdate
@Entity
@EntityListeners(AuditingEntityListener.class)
@Getter
Expand All @@ -32,7 +35,7 @@ public class Applicant {
@Size(max = 16)
private String name;

@Column(name = "student_no", nullable = false, length = 8)
@Column(name = "student_no", nullable = false, unique = true, length = 8)
@Pattern(regexp = "^[0-9]{8}$")
@Size(min = 8, max = 8)
private String studentNo;
Expand Down Expand Up @@ -105,4 +108,14 @@ public ApplicantDetailsResponseDto toApplicantDetailsResponse() {
.build();
}

public void overwrite(final ApplicantCreateRequestDto request) {
this.name = request.getName();
this.contact = request.getContact();
this.email = request.getEmail();
this.grade = request.getGrade();
this.reasonForApply = request.getReasonForApply();
this.activityWish = request.getActivityWish();
this.isPrivacyPolicyAgreed = request.getIsPrivacyPolicyAgreed();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.Optional;

public interface ApplicantRepository extends JpaRepository<Applicant, Long> {

@Query("SELECT a FROM Applicant a ORDER BY a.id DESC")
Page<Applicant> findAllWithPageRequest(final Pageable pageable);

Optional<Applicant> findByStudentNo(final String studentNo);

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@RequiredArgsConstructor
@Service
@Transactional
public class ApplicantServiceImpl implements ApplicantService {

private final static int DEFAULT_PAGE_SIZE = 20;
Expand All @@ -25,6 +29,20 @@ public class ApplicantServiceImpl implements ApplicantService {
// 지원자 저장
@Override
public void apply(final ApplicantCreateRequestDto request) {
final Optional<Applicant> applicant = findByStudentNo(request.getStudentNo());

// 이미 지원한 학번이 존재할 경우
if (applicant.isPresent()) {
// 덮어쓰기 확인 여부가 false일 경우 예외 발생
if (!request.getIsOverwriteConfirmed())
throw new CustomException(ErrorCode.DUPLICATED_STUDENT_NO);

// 기존 지원자 정보 갱신 수행
applicant.get().overwrite(request);
return;
}

// 새로운 지원자일 경우 저장
applicantRepository.save(request.toEntity());
}

Expand Down Expand Up @@ -61,4 +79,9 @@ private Applicant findById(final Long id) {
.orElseThrow(() -> new CustomException(ErrorCode.EMPTY_RESULT));
}

// 학번으로 지원자 존재 여부 확인
private Optional<Applicant> findByStudentNo(final String studentNo) {
return applicantRepository.findByStudentNo(studentNo);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public enum ErrorCode {
INTERNAL_SERVER_ERROR(500, "C009", "서버에 문제가 발생하였습니다."),
NOT_FOUND(404, "C010", "해당 리소스를 찾을 수 없습니다."),
WRITE_FAIL(400, "C011", "데이터를 쓰는데 실패하였습니다."),
EMPTY_RESULT(400, "C012", "조회 결과가 없습니다.")
EMPTY_RESULT(400, "C012", "조회 결과가 없습니다."),
DUPLICATED_STUDENT_NO(400, "C013", "이미 등록된 학번입니다."),
;

private final int status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import dmu.dasom.api.domain.applicant.dto.ApplicantCreateRequestDto;
import dmu.dasom.api.domain.applicant.service.ApplicantService;
import dmu.dasom.api.domain.common.exception.ErrorResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
Expand All @@ -23,8 +27,15 @@ public class RecruitController {
// 지원하기
@Operation(summary = "부원 지원하기")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "지원 성공")
})
@ApiResponse(responseCode = "200", description = "지원 성공"),
@ApiResponse(responseCode = "400", description = "실패 케이스",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(
name = "학번 중복",
value = "{ \"code\": \"C013\", \"message\": \"이미 등록된 학번입니다.\" }")}))})
@PostMapping("/apply")
public ResponseEntity<Void> apply(@Valid @RequestBody final ApplicantCreateRequestDto request) {
applicantService.apply(request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.springframework.data.domain.PageRequest;

import java.util.Collections;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
Expand All @@ -37,6 +38,8 @@ class ApplicantServiceTest {
void apply_success() {
// given
ApplicantCreateRequestDto request = mock(ApplicantCreateRequestDto.class);
when(request.getStudentNo()).thenReturn("20210000");
when(applicantRepository.findByStudentNo("20210000")).thenReturn(Optional.empty());

// when
applicantService.apply(request);
Expand All @@ -48,6 +51,38 @@ void apply_success() {
@Test
@DisplayName("지원자 저장 - 실패")
void apply_fail() {
// given
ApplicantCreateRequestDto request = mock(ApplicantCreateRequestDto.class);
when(request.getStudentNo()).thenReturn("20210000");
when(applicantRepository.findByStudentNo("20210000")).thenReturn(Optional.of(mock(Applicant.class)));
when(request.getIsOverwriteConfirmed()).thenReturn(false);

// when
CustomException exception = assertThrows(CustomException.class, () -> {
applicantService.apply(request);
});

// then
verify(applicantRepository).findByStudentNo("20210000");
assertEquals(ErrorCode.DUPLICATED_STUDENT_NO, exception.getErrorCode());
}

@Test
@DisplayName("지원자 저장 - 덮어쓰기")
void apply_overwrite() {
// given
ApplicantCreateRequestDto request = mock(ApplicantCreateRequestDto.class);
when(request.getStudentNo()).thenReturn("20210000");
Applicant applicant = mock(Applicant.class);
when(applicantRepository.findByStudentNo("20210000")).thenReturn(Optional.of(applicant));
when(request.getIsOverwriteConfirmed()).thenReturn(true);

// when
applicantService.apply(request);

// then
verify(applicantRepository).findByStudentNo("20210000");
verify(applicant).overwrite(request);
}

@Test
Expand Down