Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public interface ApplicantService {

void sendEmailsToApplicants(MailType mailType);

ApplicantDetailsResponseDto getApplicantByStudentNo(final String studentNo);

}
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ public void sendEmailsToApplicants(MailType mailType) {
}
}

// 학번으로 지원자 조회
@Override
public ApplicantDetailsResponseDto getApplicantByStudentNo(final String studentNo) {
return findByStudentNo(studentNo)
.map(Applicant::toApplicantDetailsResponse)
.orElseThrow(() -> new CustomException(ErrorCode.ARGUMENT_NOT_VALID));
}

// Repository에서 ID로 지원자 조회
private Applicant findById(final Long id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public enum ErrorCode {
SEND_EMAIL_FAIL(400, "C014", "이메일 전송에 실패하였습니다."),
MAIL_TYPE_NOT_VALID(400, "C015", "메일 타입이 올바르지 않습니다."),
INVALID_DATETIME_FORMAT(400, "C016", "날짜 형식이 올바르지 않습니다."),
INVALID_TIME_FORMAT(400, "C017", "시간 형식이 올바르지 않습니다.")
INVALID_TIME_FORMAT(400, "C017", "시간 형식이 올바르지 않습니다."),
INVALID_INQUIRY_PERIOD(400, "C018", "조회 기간이 아닙니다.")
;

private final int status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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 dmu.dasom.api.domain.recruit.dto.ResultCheckRequestDto;
import dmu.dasom.api.domain.recruit.dto.ResultCheckResponseDto;
import dmu.dasom.api.domain.recruit.dto.RecruitConfigResponseDto;
import dmu.dasom.api.domain.recruit.service.RecruitService;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -29,19 +31,22 @@ public class RecruitController {
// 지원하기
@Operation(summary = "부원 지원하기")
@ApiResponses(value = {
@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\": \"이미 등록된 학번입니다.\" }")}))})
@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);
return ResponseEntity.ok().build();
return ResponseEntity.ok()
.build();
}

// 모집 일정 조회
Expand All @@ -52,4 +57,23 @@ public ResponseEntity<List<RecruitConfigResponseDto>> getRecruitSchedule() {
return ResponseEntity.ok(recruitService.getRecruitSchedule());
}

// 합격 결과 확인
@Operation(summary = "합격 결과 확인")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "합격 결과 확인 성공"),
@ApiResponse(responseCode = "400", description = "실패 케이스",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class),
examples = {
@ExampleObject(
name = "학번 조회 실패 혹은 전화번호 뒷자리 일치하지 않음",
value = "{ \"code\": \"C007\", \"message\": \"요청한 값이 올바르지 않습니다.\" }")
}))
})
@GetMapping("/result")
public ResponseEntity<ResultCheckResponseDto> checkResult(@ModelAttribute final ResultCheckRequestDto request) {
return ResponseEntity.ok(recruitService.checkResult(request));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dmu.dasom.api.domain.recruit.dto;

import dmu.dasom.api.domain.recruit.enums.ResultCheckType;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;

@AllArgsConstructor
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ParameterObject
@Schema(name = "ResultCheckRequestDto", description = "지원 결과 확인 요청 DTO")
public class ResultCheckRequestDto {

@NotNull
@Parameter(description = "지원 결과 조회 타입")
@Schema(example = "DOCUMENT_PASS")
private ResultCheckType type;

@NotNull
@Parameter(description = "학번")
@Schema(example = "20210000")
private String studentNo;

@NotNull
@Parameter(description = "전화번호 뒷자리")
@Schema(example = "6789")
private String contactLastDigit;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dmu.dasom.api.domain.recruit.dto;

import dmu.dasom.api.domain.recruit.enums.ResultCheckType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@Schema(name = "ResultCheckResponseDto", description = "지원 결과 확인 응답 DTO")
public class ResultCheckResponseDto {

@NotNull
@Schema(description = "지원 결과 확인 타입", example = "DOCUMENT_PASS")
ResultCheckType type;

@NotNull
@Schema(description = "학번", example = "20210000")
@Size(min = 8, max = 8)
String studentNo;

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

@NotNull
@Schema(description = "결과", example = "true")
Boolean isPassed;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dmu.dasom.api.domain.recruit.enums;

public enum ResultCheckType {
DOCUMENT_PASS,
INTERVIEW_PASS
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dmu.dasom.api.domain.recruit.service;

import dmu.dasom.api.domain.recruit.dto.ResultCheckRequestDto;
import dmu.dasom.api.domain.recruit.dto.ResultCheckResponseDto;
import dmu.dasom.api.domain.recruit.dto.RecruitConfigResponseDto;
import dmu.dasom.api.domain.recruit.dto.RecruitScheduleModifyRequestDto;

Expand All @@ -11,4 +13,6 @@ public interface RecruitService {

void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto requestDto);

ResultCheckResponseDto checkResult(final ResultCheckRequestDto request);

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package dmu.dasom.api.domain.recruit.service;

import dmu.dasom.api.domain.applicant.dto.ApplicantDetailsResponseDto;
import dmu.dasom.api.domain.applicant.enums.ApplicantStatus;
import dmu.dasom.api.domain.applicant.service.ApplicantService;
import dmu.dasom.api.domain.common.exception.CustomException;
import dmu.dasom.api.domain.common.exception.ErrorCode;
import dmu.dasom.api.domain.recruit.dto.ResultCheckRequestDto;
import dmu.dasom.api.domain.recruit.dto.ResultCheckResponseDto;
import dmu.dasom.api.domain.recruit.dto.RecruitConfigResponseDto;
import dmu.dasom.api.domain.recruit.dto.RecruitScheduleModifyRequestDto;
import dmu.dasom.api.domain.recruit.entity.Recruit;
import dmu.dasom.api.domain.recruit.enums.ConfigKey;
import dmu.dasom.api.domain.recruit.enums.ResultCheckType;
import dmu.dasom.api.domain.recruit.repository.RecruitRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -23,6 +29,7 @@
public class RecruitServiceImpl implements RecruitService {

private final RecruitRepository recruitRepository;
private final ApplicantService applicantService;

// 모집 일정 설정 조회
@Override
Expand All @@ -49,6 +56,39 @@ public void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto request)
config.updateDateTime(dateTime);
}

// 합격 결과 확인
@Override
public ResultCheckResponseDto checkResult(final ResultCheckRequestDto request) {
final Recruit recruit = switch (request.getType()) {
case DOCUMENT_PASS -> findByKey(ConfigKey.DOCUMENT_PASS_ANNOUNCEMENT);
case INTERVIEW_PASS -> findByKey(ConfigKey.INTERVIEW_PASS_ANNOUNCEMENT);
};
final LocalDateTime parsedTime = parseDateTimeFormat(recruit.getValue());

// 설정 된 시간이 현재 시간보다 이전인 경우 예외 발생
final LocalDateTime now = LocalDateTime.now();
if (now.isBefore(parsedTime))
throw new CustomException(ErrorCode.INVALID_INQUIRY_PERIOD);

final ApplicantDetailsResponseDto applicant = applicantService.getApplicantByStudentNo(request.getStudentNo());

// 연락처 뒷자리가 일치하지 않을 경우 예외 발생
if (!applicant.getContact().split("-")[2].equals(request.getContactLastDigit()))
throw new CustomException(ErrorCode.ARGUMENT_NOT_VALID);

// 합격 여부 반환
return ResultCheckResponseDto.builder()
.type(request.getType())
.studentNo(applicant.getStudentNo())
.name(applicant.getName())
.isPassed(request.getType().equals(ResultCheckType.DOCUMENT_PASS) ?
applicant.getStatus()
.equals(ApplicantStatus.DOCUMENT_PASSED) :
applicant.getStatus()
.equals(ApplicantStatus.INTERVIEW_PASSED))
.build();
}

// DB에 저장된 모든 Recruit 객체를 찾아 반환
private List<Recruit> findAll() {
return recruitRepository.findAll();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dmu.dasom.api.domain.applicant;

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.entity.Applicant;
import dmu.dasom.api.domain.applicant.enums.ApplicantStatus;
Expand Down Expand Up @@ -176,4 +177,39 @@ void sendEmailsToApplicants_finalResult() throws MessagingException {
verify(emailService).sendEmail("[email protected]", "합격자", mailType);
verify(emailService).sendEmail("[email protected]", "불합격자", mailType);
}

@Test
@DisplayName("학번으로 지원자 조회 - 성공")
void getApplicantByStudentNo_success() {
// given
String studentNo = "20210000";
Applicant applicant = mock(Applicant.class);
when(applicantRepository.findByStudentNo(studentNo)).thenReturn(Optional.of(applicant));
when(applicant.toApplicantDetailsResponse()).thenReturn(mock(ApplicantDetailsResponseDto.class));

// when
ApplicantDetailsResponseDto applicantByStudentNo = applicantService.getApplicantByStudentNo(studentNo);

// then
assertNotNull(applicantByStudentNo);
verify(applicantRepository).findByStudentNo(studentNo);
}

@Test
@DisplayName("학번으로 지원자 조회 - 실패 (결과 없음)")
void getApplicantByStudentNo_fail() {
// given
String studentNo = "20210000";
when(applicantRepository.findByStudentNo(studentNo)).thenReturn(Optional.empty());

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

// then
verify(applicantRepository).findByStudentNo(studentNo);
assertEquals(ErrorCode.ARGUMENT_NOT_VALID, exception.getErrorCode());
}

}
Loading