Skip to content

Commit

Permalink
refactor: 리쿠르팅 생성 API 수정 (#452)
Browse files Browse the repository at this point in the history
* refactor: 리쿠르팅 생성 api 수정

* refactor: 검증 로직을 도메인 서비스로 이동

* refactor: 학기 기간을 서버에서 지정하도록 수정

* refactor: 레포지토리 활용 로직을 응용 서비스로 이동

* docs: 주석 추가

* refactor: 검증 로직을 도메인 서비스로 이동

* fix: 학기 시작일과 종료일을 직접 입력할 수 있도록 수정

* remove: 학기 시작일과 종료일결정 로직 제거

* test: given 분리
  • Loading branch information
Sangwook02 authored Jul 15, 2024
1 parent 794bb85 commit f20de72
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.gdschongik.gdsc.domain.recruitment.application;

import static com.gdschongik.gdsc.domain.common.model.SemesterType.*;
import static com.gdschongik.gdsc.global.common.constant.TemporalConstant.*;
import static com.gdschongik.gdsc.global.exception.ErrorCode.*;

import com.gdschongik.gdsc.domain.common.model.SemesterType;
import com.gdschongik.gdsc.domain.common.vo.Money;
import com.gdschongik.gdsc.domain.recruitment.dao.RecruitmentRepository;
import com.gdschongik.gdsc.domain.recruitment.dao.RecruitmentRoundRepository;
import com.gdschongik.gdsc.domain.recruitment.domain.Recruitment;
import com.gdschongik.gdsc.domain.recruitment.domain.RecruitmentRound;
import com.gdschongik.gdsc.domain.recruitment.domain.RecruitmentValidator;
import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period;
import com.gdschongik.gdsc.domain.recruitment.dto.request.RecruitmentCreateRequest;
import com.gdschongik.gdsc.domain.recruitment.dto.request.RecruitmentRoundUpdateRequest;
import com.gdschongik.gdsc.domain.recruitment.dto.response.AdminRecruitmentResponse;
Expand All @@ -28,9 +30,24 @@ public class AdminRecruitmentService {

private final RecruitmentRepository recruitmentRepository;
private final RecruitmentRoundRepository recruitmentRoundRepository;
private final RecruitmentValidator recruitmentValidator;

@Transactional
public void createRecruitment(RecruitmentCreateRequest request) {}
public void createRecruitment(RecruitmentCreateRequest request) {
boolean isRecruitmentOverlap = recruitmentRepository.existsByAcademicYearAndSemesterType(
request.academicYear(), request.semesterType());

recruitmentValidator.validateRecruitmentCreate(isRecruitmentOverlap);

Recruitment recruitment = Recruitment.createRecruitment(
request.academicYear(),
request.semesterType(),
Money.from(request.fee()),
Period.createPeriod(request.semesterStartDate(), request.semesterEndDate()));
recruitmentRepository.save(recruitment);

log.info("[AdminRecruitmentService] 리쿠르팅 생성: recruitmentId={}", recruitment.getId());
}

public List<AdminRecruitmentResponse> getAllRecruitments() {
List<Recruitment> recruitments = recruitmentRepository.findByOrderBySemesterPeriodDesc();
Expand All @@ -47,12 +64,6 @@ public List<AdminRecruitmentRoundResponse> getAllRecruitmentRounds() {
@Transactional
public void updateRecruitmentRound(Long recruitmentRoundId, RecruitmentRoundUpdateRequest request) {}

// private void validateRecruitmentOverlap(Integer academicYear, SemesterType semesterType) {
// if (recruitmentRepository.existsByAcademicYearAndSemesterType(academicYear, semesterType)) {
// throw new CustomException(RECRUITMENT_OVERLAP);
// }
// }

/*
1. 해당 학기에 리쿠르팅이 존재해야 함.
2. 해당 학기의 모든 리쿠르팅이 아직 시작되지 않았어야 함.
Expand All @@ -68,49 +79,6 @@ public void validateRecruitmentNotStarted(Integer academicYear, SemesterType sem
recruitmentRounds.forEach(RecruitmentRound::validatePeriodNotStarted);
}

// // TODO validateRegularRequirement처럼 로직 변경
// private void validatePeriodMatchesAcademicYear(
// LocalDateTime startDate, LocalDateTime endDate, Integer academicYear) {
// if (academicYear.equals(startDate.getYear()) && academicYear.equals(endDate.getYear())) {
// return;
// }
//
// throw new CustomException(RECRUITMENT_PERIOD_MISMATCH_ACADEMIC_YEAR);
// }
//
// // TODO validateRegularRequirement처럼 로직 변경
// private void validatePeriodMatchesSemesterType(
// LocalDateTime startDate, LocalDateTime endDate, SemesterType semesterType) {
// if (getSemesterTypeByStartDateOrEndDate(startDate).equals(semesterType)
// && getSemesterTypeByStartDateOrEndDate(endDate).equals(semesterType)) {
// return;
// }
//
// throw new CustomException(RECRUITMENT_PERIOD_MISMATCH_SEMESTER_TYPE);
// }
//
// private SemesterType getSemesterTypeByStartDateOrEndDate(LocalDateTime dateTime) {
// int year = dateTime.getYear();
// LocalDateTime firstSemesterStartDate = LocalDateTime.of(
// year, FIRST.getStartDate().getMonth(), FIRST.getStartDate().getDayOfMonth(), 0, 0);
// LocalDateTime secondSemesterStartDate = LocalDateTime.of(
// year, SECOND.getStartDate().getMonth(), SECOND.getStartDate().getDayOfMonth(), 0, 0);
//
// /*
// 개강일 기준으로 2주 전까지는 같은 학기로 간주한다.
// */
// if (dateTime.isAfter(firstSemesterStartDate.minusWeeks(PRE_SEMESTER_TERM))
// && dateTime.getMonthValue() < Month.JULY.getValue()) {
// return FIRST;
// }
//
// if (dateTime.isAfter(secondSemesterStartDate.minusWeeks(PRE_SEMESTER_TERM))) {
// return SECOND;
// }
//
// throw new CustomException(RECRUITMENT_PERIOD_SEMESTER_TYPE_UNMAPPED);
// }
//
// private void validatePeriodWithinTwoWeeks(
// LocalDateTime startDate, LocalDateTime endDate, Integer academicYear, SemesterType semesterType) {
// LocalDateTime semesterStartDate = LocalDateTime.of(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.gdschongik.gdsc.domain.recruitment.dao;

import com.gdschongik.gdsc.domain.common.model.SemesterType;
import com.gdschongik.gdsc.domain.recruitment.domain.Recruitment;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RecruitmentRepository extends JpaRepository<Recruitment, Long> {

// boolean existsByAcademicYearAndSemesterType(Integer academicYear, SemesterType semesterType);
boolean existsByAcademicYearAndSemesterType(Integer academicYear, SemesterType semesterType);

List<Recruitment> findByOrderBySemesterPeriodDesc();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.gdschongik.gdsc.domain.recruitment.domain;

import static com.gdschongik.gdsc.global.exception.ErrorCode.*;

import com.gdschongik.gdsc.global.annotation.DomainService;
import com.gdschongik.gdsc.global.exception.CustomException;

@DomainService
public class RecruitmentValidator {

public void validateRecruitmentCreate(boolean isRecruitmentOverlap) {
// 학년도와 학기가 같은 리쿠르팅이 이미 존재하는 경우
if (isRecruitmentOverlap) {
throw new CustomException(RECRUITMENT_OVERLAP);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import java.time.LocalDateTime;

public record RecruitmentCreateRequest(
@Future @Schema(description = "학기 시작일", pattern = DATETIME) LocalDateTime periodStartDate,
@Future @Schema(description = "학기 종료일", pattern = DATETIME) LocalDateTime periodEndDate,
@Future @Schema(description = "학기 시작일", pattern = DATETIME) LocalDateTime semesterStartDate,
@Future @Schema(description = "학기 종료일", pattern = DATETIME) LocalDateTime semesterEndDate,
@NotNull(message = "학년도는 null이 될 수 없습니다.") @Schema(description = "학년도", pattern = ACADEMIC_YEAR)
Integer academicYear,
@NotNull(message = "학기는 null이 될 수 없습니다.") @Schema(description = "학기") SemesterType semesterType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,41 @@
package com.gdschongik.gdsc.domain.recruitment.application;

import static com.gdschongik.gdsc.global.common.constant.RecruitmentConstant.*;
import static com.gdschongik.gdsc.global.common.constant.SemesterConstant.*;
import static com.gdschongik.gdsc.global.exception.ErrorCode.*;
import static org.assertj.core.api.Assertions.*;

import com.gdschongik.gdsc.domain.recruitment.dao.RecruitmentRepository;
import com.gdschongik.gdsc.domain.recruitment.dto.request.RecruitmentCreateRequest;
import com.gdschongik.gdsc.helper.IntegrationTest;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

class AdminRecruitmentServiceTest extends IntegrationTest {

@Autowired
private AdminRecruitmentService adminRecruitmentService;

// todo: test 원복
// @Nested
// class 리쿠르팅_생성시 {
// @Test
// void 학기_시작일과_종료일의_연도가_입력된_학년도와_다르다면_실패한다() {
// // given
// RecruitmentCreateRequest request =
// new RecruitmentCreateRequest(START_DATE, END_DATE, 2025, SEMESTER_TYPE, FEE_AMOUNT);
//
// // when & then
// assertThatThrownBy(() -> adminRecruitmentService.createRecruitment(request))
// .isInstanceOf(CustomException.class)
// .hasMessage(RECRUITMENT_PERIOD_MISMATCH_ACADEMIC_YEAR.getMessage());
// }
//
// @Test
// void 학기_시작일과_종료일의_학기가_입력된_학기와_다르다면_실패한다() {
// // given
// RecruitmentCreateRequest request =
// new RecruitmentCreateRequest(START_DATE, END_DATE, ACADEMIC_YEAR, SemesterType.SECOND,
// FEE_AMOUNT);
//
// // when & then
// assertThatThrownBy(() -> adminRecruitmentService.createRecruitment(request))
// .isInstanceOf(CustomException.class)
// .hasMessage(RECRUITMENT_PERIOD_MISMATCH_SEMESTER_TYPE.getMessage());
// }
//
// @Test
// void 학년도_학기가_모두_중복되는_리쿠르팅이라면_실패한다() {
// // given
// createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE);
// RecruitmentCreateRequest request = new RecruitmentCreateRequest(
// LocalDateTime.of(2024, 3, 12, 0, 0),
// LocalDateTime.of(2024, 3, 13, 0, 0),
// ACADEMIC_YEAR,
// SEMESTER_TYPE,
// FEE_AMOUNT);
//
// // when & then
// assertThatThrownBy(() -> adminRecruitmentService.createRecruitment(request))
// .isInstanceOf(CustomException.class)
// .hasMessage(RECRUITMENT_OVERLAP.getMessage());
// }
// }
@Autowired
private RecruitmentRepository recruitmentRepository;

@Nested
class 리쿠르팅_생성시 {

@Test
void 성공한다() {
// given
RecruitmentCreateRequest request = new RecruitmentCreateRequest(
SEMESTER_START_DATE, SEMESTER_END_DATE, ACADEMIC_YEAR, SEMESTER_TYPE, FEE_AMOUNT);

// when
adminRecruitmentService.createRecruitment(request);

// then
assertThat(recruitmentRepository.findAll()).hasSize(1);
}
}

// todo: test 원복
// @Nested
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.gdschongik.gdsc.domain.recruitment.domain;

import static com.gdschongik.gdsc.global.exception.ErrorCode.*;
import static org.assertj.core.api.Assertions.*;

import com.gdschongik.gdsc.global.exception.CustomException;
import org.junit.jupiter.api.Test;

public class RecruitmentValidatorTest {

RecruitmentValidator recruitmentValidator = new RecruitmentValidator();

@Test
void 학년도_학기가_모두_중복되는_리쿠르팅이라면_실패한다() {
// given
boolean isRecruitmentOverlap = true;

// when & then
assertThatThrownBy(() -> recruitmentValidator.validateRecruitmentCreate(isRecruitmentOverlap))
.isInstanceOf(CustomException.class)
.hasMessage(RECRUITMENT_OVERLAP.getMessage());
}
}

0 comments on commit f20de72

Please sign in to comment.