Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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,11 @@ public class SignupRequestDto {
@Schema(description = "비밀번호", example = "password", minLength = 8, maxLength = 128)
private String password;

public Member toEntity(final String password) {
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 = 16, nullable = false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기수 번호는 2자리수인데 속성 길이가 16이나 필요할까요?

private String generation;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import dmu.dasom.api.global.auth.dto.TokenBox;
import dmu.dasom.api.global.auth.jwt.JwtUtil;
import dmu.dasom.api.global.auth.userdetails.UserDetailsImpl;
import dmu.dasom.api.global.generation.service.GenerationService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
Expand All @@ -25,6 +26,7 @@ public class MemberServiceImpl implements MemberService {
private final BCryptPasswordEncoder encoder;
private final MemberRepository memberRepository;
private final JwtUtil jwtUtil;
private final GenerationService generationService;

// 이메일로 사용자 조회
@Override
Expand All @@ -46,8 +48,9 @@ public void signUp(final SignupRequestDto request) {
if (checkByEmail(request.getEmail()))
throw new CustomException(ErrorCode.SIGNUP_FAILED);

// 비밀번호 암호화 후 저장
memberRepository.save(request.toEntity(encoder.encode(request.getPassword())));
String currentGeneration = generationService.getCurrentGeneration();
// 비밀번호 암호화 후 저장 + 기수도 현재 기수로 자동 기입
memberRepository.save(request.toEntity(encoder.encode(request.getPassword()), currentGeneration));
}

// 토큰 갱신
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 @@ -8,6 +8,7 @@
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 dmu.dasom.api.global.generation.service.GenerationService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -24,14 +25,26 @@
public class RecruitServiceImpl implements RecruitService {

private final RecruitRepository recruitRepository;
private final GenerationService generationService;

// 모집 일정 설정 조회
@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 -> {
if(config.getKey() == ConfigKey.GENERATION) { //기수 조회 추가
String currentGeneration = generationService.getCurrentGeneration();
return RecruitConfigResponseDto.builder()
.key(ConfigKey.GENERATION)
.value(currentGeneration)
.build();
} else if(config.getKey() == ConfigKey.INTERVIEW_TIME_START || config.getKey() == ConfigKey.INTERVIEW_TIME_END) {
return config.toTimeResponse();
} else {
return config.toResponse();
}
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if-else 문이 길어질 경우 switch-case 문을 활용해보세요

.toList();
}

// 모집 일정 설정 수정
Expand All @@ -45,9 +58,13 @@ public void modifyRecruitSchedule(final RecruitScheduleModifyRequestDto request)
config.updateTime(time);
return;
}

final LocalDateTime dateTime = parseDateTimeFormat(request.getValue());
config.updateDateTime(dateTime);
else {
final LocalDateTime dateTime = parseDateTimeFormat(request.getValue());
config.updateDateTime(dateTime);
}
final Recruit generationConfig = findByKey(ConfigKey.GENERATION);
String currentGeneration = generationService.getCurrentGeneration();
generationConfig.updateGeneration(currentGeneration);
}

// 모집 기간 여부 확인
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package dmu.dasom.api.global.admin.controller;

import dmu.dasom.api.global.generation.service.GenerationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/admin")
@RequiredArgsConstructor
public class AdminGenerationController {

private final GenerationService generationService;

// 기수 조회
@Operation(summary = "현재 저장된 기수 조회")
@GetMapping("/generation")
public ResponseEntity<String> getCurrentGeneration() {
String currentGeneration = generationService.getCurrentGeneration();
return ResponseEntity.ok(currentGeneration);
}

// 기수 수정
@Operation(summary = "기수 수정")
@PatchMapping("/generation")
public ResponseEntity<Void> updateGeneration(
@RequestParam @Parameter(description = "새로운 기수 (예: '1기')") String generationValue
) {
generationService.saveOrUpdateGeneration(generationValue);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dmu.dasom.api.global.generation.entity;

import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.DynamicUpdate;

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

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 기본키

@Column(nullable = false, unique = true, length = 10)
private String generation; // 기수 (예: "1기", "2기")


public void updateGeneration(String generation) {
this.generation = generation;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dmu.dasom.api.global.generation.repository;

import dmu.dasom.api.global.generation.entity.Generation;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface GenerationRepository extends JpaRepository<Generation, Long> {

// 가장 최근 기수 1개 조회
Optional<Generation> findFirstByOrderByIdDesc();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package dmu.dasom.api.global.generation.service;

import dmu.dasom.api.domain.common.exception.CustomException;
import dmu.dasom.api.domain.common.exception.ErrorCode;
import dmu.dasom.api.global.generation.entity.Generation;
import dmu.dasom.api.global.generation.repository.GenerationRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.regex.Pattern;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GenerationService {

private final GenerationRepository generationRepository;

// 기본값 해당 변수로 관리
private static final String DEFAULT_GENERATION = "34기";

// 정규식: 숫자 + "기" 형식 (예: "1기", "12기")
private static final Pattern GENERATION_PATTERN = Pattern.compile("^[0-9]+기$");

//현재 저장된 기수 조회
public String getCurrentGeneration() {
try {
return generationRepository.findFirstByOrderByIdDesc()
.map(Generation::getGeneration)
.orElseGet(() -> {
log.warn("저장된 기수 없음, 기본값 사용: {}", DEFAULT_GENERATION);
return DEFAULT_GENERATION;
});
} catch (Exception e) {
throw new CustomException(ErrorCode.INTERNAL_SERVER_ERROR);
}
}

//새로운 기수 저장 또는 기존 기수 수정 (유효성 검사 포함)
@Transactional
public void saveOrUpdateGeneration(String generationValue) {
if (!GENERATION_PATTERN.matcher(generationValue).matches()) {
throw new CustomException(ErrorCode.INVALID_GENERATION_FORMAT);
}

try {
Generation generation = generationRepository.findFirstByOrderByIdDesc()
.orElseGet(() -> Generation.builder().build());

generation.updateGeneration(generationValue);
generationRepository.save(generation);

} catch (Exception e) {
throw new CustomException(ErrorCode.WRITE_FAIL);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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.global.generation.service.GenerationService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -28,6 +29,9 @@ class MemberServiceTest {
@Mock
MemberRepository memberRepository;

@Mock
private GenerationService generationService;

@InjectMocks
private MemberServiceImpl memberService;

Expand Down Expand Up @@ -101,12 +105,13 @@ void signUp_success() {
when(request.getPassword()).thenReturn("password");
when(encoder.encode("password")).thenReturn("encodedPassword");
when(memberRepository.existsByEmail("[email protected]")).thenReturn(false);

when(generationService.getCurrentGeneration()).thenReturn("34기");
// when
memberService.signUp(request);

// then
verify(memberRepository, times(1)).save(any());
verify(generationService, times(1)).getCurrentGeneration();
}

@Test
Expand Down
Loading
Loading