Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public enum ErrorCode {
EMPTY_RESULT(400, "C012", "조회 결과가 없습니다."),
DUPLICATED_STUDENT_NO(400, "C013", "이미 등록된 학번입니다."),
SEND_EMAIL_FAIL(400, "C014", "이메일 전송에 실패하였습니다."),
MAIL_TYPE_NOT_VALID(400, "C015", "메일 타입이 올바르지 않습니다.")
MAIL_TYPE_NOT_VALID(400, "C015", "메일 타입이 올바르지 않습니다."),
INVALID_DATETIME_FORMAT(400, "C016", "날짜 형식이 올바르지 않습니다."),
INVALID_TIME_FORMAT(400, "C017", "시간 형식이 올바르지 않습니다.")
;

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.RecruitConfigResponseDto;
import dmu.dasom.api.domain.recruit.service.RecruitService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
Expand All @@ -12,17 +14,17 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/recruit")
@RequiredArgsConstructor
public class RecruitController {

private final ApplicantService applicantService;
private final RecruitService recruitService;

// 지원하기
@Operation(summary = "부원 지원하기")
Expand All @@ -42,4 +44,12 @@ public ResponseEntity<Void> apply(@Valid @RequestBody final ApplicantCreateReque
return ResponseEntity.ok().build();
}

// 모집 일정 조회
@Operation(summary = "모집 일정 조회")
@ApiResponse(responseCode = "200", description = "모집 일정 조회 성공")
@GetMapping
public ResponseEntity<List<RecruitConfigResponseDto>> getRecruitSchedule() {
return ResponseEntity.ok(recruitService.getRecruitSchedule());
}

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

import dmu.dasom.api.domain.recruit.enums.ConfigKey;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@Schema(name = "RecruitConfigResponseDto", description = "모집 설정 응답 DTO")
public class RecruitConfigResponseDto {

@Schema(description = "모집 설정 키", example = "RECRUITMENT_PERIOD_START")
private ConfigKey key;

@Schema(description = "모집 설정 값 (날짜 혹은 시간 값)", example = "2024-10-01T10:00:00 || 10:00:00")
private String value;

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

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

@Getter
@Schema(name = "RecruitScheduleModifyRequestDto", description = "모집 일정 수정 요청 DTO")
public class RecruitScheduleModifyRequestDto {

@NotNull
@Schema(description = "모집 설정 키", example = "key Enum 확인")
ConfigKey key;

@NotNull
@Schema(description = "모집 설정 값 (날짜 혹은 시간 값)", example = "2024-10-01T10:00:00 || 10:00:00")
String value;

}
56 changes: 56 additions & 0 deletions src/main/java/dmu/dasom/api/domain/recruit/entity/Recruit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dmu.dasom.api.domain.recruit.entity;

import dmu.dasom.api.domain.recruit.dto.RecruitConfigResponseDto;
import dmu.dasom.api.domain.recruit.enums.ConfigKey;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.DynamicUpdate;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

@AllArgsConstructor
@Builder
@DynamicUpdate
@Entity
@Getter
@NoArgsConstructor
public class Recruit {

private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

@Enumerated(EnumType.STRING)
@Column(name = "key", length = 64, nullable = false, unique = true)
@Id
private ConfigKey key;

@Column(name = "value")
private String value;

public void updateDateTime(final LocalDateTime dateTime) {
this.value = dateTime.format(DATE_TIME_FORMATTER);
}

public void updateTime(final LocalTime time) {
this.value = time.format(TIME_FORMATTER);
}

public RecruitConfigResponseDto toResponse() {
LocalDateTime dateTime = LocalDateTime.parse(this.value, DATE_TIME_FORMATTER);
return RecruitConfigResponseDto.builder()
.key(key)
.value(dateTime.format(DATE_TIME_FORMATTER))
.build();
}

public RecruitConfigResponseDto toTimeResponse() {
LocalTime time = LocalTime.parse(this.value, TIME_FORMATTER);
return RecruitConfigResponseDto.builder()
.key(key)
.value(time.format(TIME_FORMATTER))
.build();
}

}
23 changes: 23 additions & 0 deletions src/main/java/dmu/dasom/api/domain/recruit/enums/ConfigKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dmu.dasom.api.domain.recruit.enums;

public enum ConfigKey {

// 모집 기간(시작일, 종료일 - 시간 포함)
RECRUITMENT_PERIOD_START, // 모집 시작일
RECRUITMENT_PERIOD_END, // 모집 종료일

// 1차 합격 발표일 (시간 포함)
DOCUMENT_PASS_ANNOUNCEMENT, // 1차 합격 발표일

// 면접 기간 (시작일, 종료일)
INTERVIEW_PERIOD_START, // 면접 기간 시작일
INTERVIEW_PERIOD_END, // 면접 기간 종료일

// 면접 시간 (시작 시간, 종료 시간)
INTERVIEW_TIME_START, // 면접 시작 시간
INTERVIEW_TIME_END, // 면접 종료 시간

// 2차 합격 발표일 (시간 포함)
INTERVIEW_PASS_ANNOUNCEMENT // 2차 합격 발표일

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

import dmu.dasom.api.domain.recruit.entity.Recruit;
import dmu.dasom.api.domain.recruit.enums.ConfigKey;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface RecruitRepository extends JpaRepository<Recruit, Long> {

Optional<Recruit> findByKey(final ConfigKey key);

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

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

import java.util.List;

public interface RecruitService {

List<RecruitConfigResponseDto> getRecruitSchedule();

void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto requestDto);

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

import dmu.dasom.api.domain.common.exception.CustomException;
import dmu.dasom.api.domain.common.exception.ErrorCode;
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.repository.RecruitRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class RecruitServiceImpl implements RecruitService {

private final RecruitRepository recruitRepository;

// 모집 일정 설정 조회
@Override
public List<RecruitConfigResponseDto> getRecruitSchedule() {
return findAll().stream()
.map(config -> config.getKey() == ConfigKey.INTERVIEW_TIME_START || config.getKey() == ConfigKey.INTERVIEW_TIME_END
? config.toTimeResponse() : config.toResponse())
.toList();
}

// 모집 일정 설정 수정
@Override
@Transactional
public void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto request) {
final Recruit config = findByKey(request.getKey());

if (request.getKey().equals(ConfigKey.INTERVIEW_TIME_START) || request.getKey().equals(ConfigKey.INTERVIEW_TIME_END)) {
final LocalTime time = parseTimeFormat(request.getValue());
config.updateTime(time);
return;
}

final LocalDateTime dateTime = parseDateTimeFormat(request.getValue());
config.updateDateTime(dateTime);
}

// DB에 저장된 모든 Recruit 객체를 찾아 반환
private List<Recruit> findAll() {
return recruitRepository.findAll();
}

// DB에서 key에 해당하는 Recruit 객체를 찾아 반환
private Recruit findByKey(final ConfigKey key) {
return recruitRepository.findByKey(key)
.orElseThrow(() -> new CustomException(ErrorCode.ARGUMENT_NOT_VALID));

}

// 시간 형식 변환 및 검증
private LocalTime parseTimeFormat(String value) {
try {
return LocalTime.parse(value, DateTimeFormatter.ofPattern("HH:mm:ss"));
} catch (DateTimeParseException e) {
throw new CustomException(ErrorCode.INVALID_TIME_FORMAT);
}
}

// 날짜 및 시간 형식 변환 및 검증
private LocalDateTime parseDateTimeFormat(String value) {
try {
return LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));
} catch (DateTimeParseException e) {
throw new CustomException(ErrorCode.INVALID_DATETIME_FORMAT);
}
}

}
Loading