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
Expand Up @@ -38,7 +38,8 @@ public enum ErrorCode {
RECRUITMENT_NOT_ACTIVE(400, "C029", "모집 기간이 아닙니다."),
NOT_FOUND_PARTICIPANT(400, "C030", "참가자를 찾을 수 없습니다."),
EXECUTIVE_NOT_FOUND(400, "C031", "임원진을 찾을 수 없습니다."),
;
GENERATION_NOT_FOUND(400, "C032", "저장된 기수를 찾을 수 없습니다."),
INVALID_GENERATION_FORMAT(400, "C033", "유효하지 않은 기수 형식입니다. (예: '1기')");

private final int status;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ public class SignupRequestDto {
@Schema(description = "비밀번호", example = "password", minLength = 8, maxLength = 128)
private String password;

public Member toEntity(final String password) {
@Length(max = 4)
@Schema(description = "기수 (선택)", example = "34기", nullable = true)
private String generation;

public Member toEntity(final String password, final String generation) {
return Member.builder()
.email(this.email)
.password(password)
.generation(generation)
.build();
}
}
5 changes: 4 additions & 1 deletion src/main/java/dmu/dasom/api/domain/member/entity/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ public class Member extends BaseEntity {
@Enumerated(EnumType.STRING)
private Role role = Role.ROLE_MEMBER;

}
// 기수 정보를 저장할 필드 추가
@Column(name = "generation", length = 4, nullable = false)
private String generation;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import dmu.dasom.api.domain.common.exception.CustomException;
import dmu.dasom.api.domain.common.exception.ErrorCode;
import dmu.dasom.api.domain.recruit.service.RecruitService;
import dmu.dasom.api.domain.member.dto.SignupRequestDto;
import dmu.dasom.api.domain.member.entity.Member;
import dmu.dasom.api.domain.member.repository.MemberRepository;
Expand All @@ -24,6 +25,7 @@ public class MemberServiceImpl implements MemberService {

private final BCryptPasswordEncoder encoder;
private final MemberRepository memberRepository;
private final RecruitService recruitService;
private final JwtUtil jwtUtil;

// 이메일로 사용자 조회
Expand All @@ -45,9 +47,13 @@ public void signUp(final SignupRequestDto request) {
// 이미 가입된 이메일인지 확인
if (checkByEmail(request.getEmail()))
throw new CustomException(ErrorCode.SIGNUP_FAILED);
//기수는 선택적으로 가져오며, 없을 경우 신입 부붠 처리하여, 모집일정의 기수 사용
String generation = (request.getGeneration() != null && !request.getGeneration().isEmpty())
? request.getGeneration()
: recruitService.getCurrentGeneration();

// 비밀번호 암호화 후 저장
memberRepository.save(request.toEntity(encoder.encode(request.getPassword())));
// 비밀번호 암호화 후 저장, 기수도 같이 기입
memberRepository.save(request.toEntity(encoder.encode(request.getPassword()), generation));
}

// 토큰 갱신
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/dmu/dasom/api/domain/recruit/entity/Recruit.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,19 @@ public void updateTime(final LocalTime time) {
this.value = time.format(TIME_FORMATTER);
}


// 기수 업데이트
public void updateGeneration(final String generation) {
this.value = generation; // ex. "34기"
}

public RecruitConfigResponseDto toResponse() {
if(this.key == ConfigKey.GENERATION){
return RecruitConfigResponseDto.builder()
.key(key)
.value(value)
.build();
}
LocalDateTime dateTime = LocalDateTime.parse(this.value, DATE_TIME_FORMATTER);
return RecruitConfigResponseDto.builder()
.key(key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public enum ConfigKey {
INTERVIEW_TIME_END, // 면접 종료 시간

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

GENERATION //현재 모집중인 기수 정보
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public interface RecruitService {

void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto requestDto);

void modifyGeneration(String newGeneration);

String getCurrentGeneration();

String generateReservationCode(String studentNo, String contactLastDigits);

LocalDateTime getResultAnnouncementSchedule(ResultCheckType type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ 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();
.map(config -> config.getKey() == ConfigKey.INTERVIEW_TIME_START || config.getKey() == ConfigKey.INTERVIEW_TIME_END
? config.toTimeResponse() : config.toResponse())
.toList();
}

// 모집 일정 설정 수정
Expand All @@ -50,6 +50,20 @@ public void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto request)
config.updateDateTime(dateTime);
}


//기수 수정
@Override
@Transactional
public void modifyGeneration(String newGeneration) {
final Recruit config = findByKey(ConfigKey.GENERATION);
config.updateGeneration(newGeneration);
}
// 기수 조회
@Override
public String getCurrentGeneration() {
Recruit generationConfig = findByKey(ConfigKey.GENERATION);
return generationConfig.getValue();
}
// 모집 기간 여부 확인
@Override
public boolean isRecruitmentActive() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ public ResponseEntity<Void> modifyRecruitSchedule(@Valid @RequestBody final Recr
.build();
}

@Operation(summary = "모집 기수 변경")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "모집 기수 수정 성공"),
@ApiResponse(responseCode = "400", description = "잘못된 요청")
})
@PatchMapping("/generation")
public ResponseEntity<Void> modifyGeneration(@Valid @RequestBody String request) {
recruitService.modifyGeneration(request);
return ResponseEntity.ok()
.build();
}


@Operation(summary = "면접 일정 생성", description = "새로운 면접 일정을 생성합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "면접 일정 생성 성공"),
Expand Down
49 changes: 40 additions & 9 deletions src/test/java/dmu/dasom/api/domain/member/MemberServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
import dmu.dasom.api.domain.member.entity.Member;
import dmu.dasom.api.domain.member.repository.MemberRepository;
import dmu.dasom.api.domain.member.service.MemberServiceImpl;
import dmu.dasom.api.domain.recruit.service.RecruitService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.Optional;

Expand All @@ -28,6 +30,9 @@ class MemberServiceTest {
@Mock
MemberRepository memberRepository;

@Mock
RecruitService recruitService; // RecruitService 주입

@InjectMocks
private MemberServiceImpl memberService;

Expand Down Expand Up @@ -92,23 +97,49 @@ void checkByEmail_false() {
assertFalse(result);
}


@Test
@DisplayName("회원가입 - 성공")
void signUp_success() {
// given
SignupRequestDto request = mock(SignupRequestDto.class);
when(request.getEmail()).thenReturn("[email protected]");
when(request.getPassword()).thenReturn("password");
@DisplayName("회원가입 - 기수 선택값 전달 시 사용")
void signUp_withGenerationProvided() {
// 실제 DTO 객체 사용
SignupRequestDto request = new SignupRequestDto();
// Reflection 또는 생성자/Setter로 값 설정
ReflectionTestUtils.setField(request, "email", "[email protected]");
ReflectionTestUtils.setField(request, "password", "password");
ReflectionTestUtils.setField(request, "generation", "35기");

when(encoder.encode("password")).thenReturn("encodedPassword");
when(memberRepository.existsByEmail("[email protected]")).thenReturn(false);

// when
memberService.signUp(request);

// then
verify(memberRepository, times(1)).save(any());
verify(memberRepository, times(1)).save(argThat(member ->
"35기".equals(member.getGeneration())
));
verify(recruitService, never()).getCurrentGeneration();
}

@Test
@DisplayName("회원가입 - 기수 선택값 없으면 기본값 사용")
void signUp_withGenerationDefault() {
SignupRequestDto request = new SignupRequestDto();
ReflectionTestUtils.setField(request, "email", "[email protected]");
ReflectionTestUtils.setField(request, "password", "password");
ReflectionTestUtils.setField(request, "generation", null);

when(encoder.encode("password")).thenReturn("encodedPassword");
when(memberRepository.existsByEmail("[email protected]")).thenReturn(false);
when(recruitService.getCurrentGeneration()).thenReturn("34기");

memberService.signUp(request);

verify(memberRepository, times(1)).save(argThat(member ->
"34기".equals(member.getGeneration())
));
verify(recruitService, times(1)).getCurrentGeneration();
}


@Test
@DisplayName("회원가입 - 실패")
void signUp_fail() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mock;

@ExtendWith(MockitoExtension.class)
class RecruitServiceTest {
Expand Down Expand Up @@ -102,6 +101,36 @@ void modifyRecruitSchedule_fail() {
assertEquals(ErrorCode.INVALID_TIME_FORMAT, exception.getErrorCode());
}

@Test
@DisplayName("모집 기수 수정")
void modifyGeneration_success() {
// given
Recruit generationRecruit = mock(Recruit.class);
String newGeneration = "35기";
when(recruitRepository.findByKey(ConfigKey.GENERATION)).thenReturn(Optional.of(generationRecruit));

// when
recruitService.modifyGeneration(newGeneration);

// then
verify(generationRecruit, times(1)).updateGeneration(newGeneration);
}

@Test
@DisplayName("기수 조회")
void getCurrentGeneration_success() {
// given
Recruit generationRecruit = mock(Recruit.class);
when(recruitRepository.findByKey(ConfigKey.GENERATION)).thenReturn(Optional.of(generationRecruit));
when(generationRecruit.getValue()).thenReturn("34기");
// when
String currentGeneration = recruitService.getCurrentGeneration();
// then
assertEquals("34기", currentGeneration);
verify(recruitRepository, times(1)).findByKey(ConfigKey.GENERATION);
verify(generationRecruit, times(1)).getValue();
}

@Test
@DisplayName("면접 일정 생성 - 성공")
void createInterviewSlots_success() {
Expand Down Expand Up @@ -196,4 +225,5 @@ void reserveInterviewSlot_fail_alreadyReserved() {
assertEquals(ErrorCode.ALREADY_RESERVED, exception.getErrorCode());
}


}
Loading