Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: merge into main #187

Merged
merged 37 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8991643
[feat] 지원 서류 삭제 기능 (#177)
hyunihs Jul 25, 2024
c1e559b
Merge branch 'dev' of https://github.com/CEOS-Developers/CEOS-BE into…
yoonsseo Jul 27, 2024
4330d02
[feat] 지원서 목록 보기 API required false인 parameter들에 대해 default value 설정
letskuku Jul 28, 2024
7dd214c
[test] 지원서 목록 보기 API required false인 parameter들에 대한 테스트 코드 작성
letskuku Jul 28, 2024
5a2e5f3
[feat] 지원서 목록 보기 API enum 타입인 parameter들에 대해 allowable values 설정
letskuku Jul 28, 2024
622648f
[test] 지원서 목록 보기 API enum 타입인 parameter들에 대해 테스트 코드 작성
letskuku Jul 28, 2024
dc84a12
[fix] 지원서 엑셀 파일 생성 시각 API 테스트 status code 수정
letskuku Jul 28, 2024
5844f73
[revert] 코드 수정 내역 되돌림
letskuku Jul 28, 2024
764a207
[feat] 지원서 목록 보기 API required false인 parameter들에 대해 default value 설정
letskuku Jul 28, 2024
2437c97
[test] 지원서 목록 보기 API required false인 parameter들에 대한 테스트 코드 작성
letskuku Jul 28, 2024
8523853
[feat] 지원서 목록 보기 API enum 타입인 parameter들에 대해 allowable values 설정
letskuku Jul 28, 2024
7edb14c
[test] 지원서 목록 보기 API enum 타입인 parameter들에 대해 테스트 코드 작성
letskuku Jul 28, 2024
c6cf483
[fix] 지원서 엑셀 파일 생성 시각 API 테스트 status code 수정
letskuku Jul 28, 2024
1dd991c
[revert] 코드 수정 내역 되돌림
letskuku Jul 28, 2024
530b39b
[feat] 지원서 목록 보기 API required false인 parameter들에 대해 default value 설정
letskuku Jul 28, 2024
9380e57
[test] 지원서 목록 보기 API required false인 parameter들에 대한 테스트 코드 작성
letskuku Jul 28, 2024
a1b085f
[feat] 지원서 목록 보기 API enum 타입인 parameter들에 대해 allowable values 설정
letskuku Jul 28, 2024
41234fe
[test] 지원서 목록 보기 API enum 타입인 parameter들에 대해 테스트 코드 작성
letskuku Jul 28, 2024
c468d53
[fix] 지원서 엑셀 파일 생성 시각 API 테스트 status code 수정
letskuku Jul 28, 2024
d27e35a
Merge branch 'dev' of https://github.com/CEOS-Developers/CEOS-BE into…
yoonsseo Jul 30, 2024
54d2bd1
[feat] 면접 참여 여부 확인용 DTO 생성 #180
yoonsseo Jul 31, 2024
53ae428
[feat] 최종 활동 여부 확인용 DTO 생성 #180
yoonsseo Jul 31, 2024
b844d51
[feat] 불가능 사유 unableReason 필드 및 해당 필드 업데이트 로직 추가 #180
yoonsseo Jul 31, 2024
34e28d4
[feat] 최종 활동 여부 확인용 DTO 생성 #180
yoonsseo Jul 31, 2024
ea24716
[feat] 면접 참여 가능 여부 확인과 활동 가능 여부 확인 Service 로직 작성 #180
yoonsseo Jul 31, 2024
17cc9f3
[feat] 활동 가능 여부 확인 시 최종 합격 여부 검증하는 validator 작성 #180
yoonsseo Jul 31, 2024
48243b0
Merge branch 'feat/getApplications' of https://github.com/CEOS-Develo…
yoonsseo Aug 2, 2024
85d4517
feat: 면접 참여 및 활동 가능 여부 확인용 Controller 작성
yoonsseo Aug 2, 2024
a0a8487
feat: 면접 참여 및 활동 가능 여부 확인용 Controller 작성 #180
yoonsseo Aug 2, 2024
ee6c50b
Merge branch 'feat/availability' of https://github.com/CEOS-Developer…
yoonsseo Aug 2, 2024
907b10f
Merge pull request #179 from CEOS-Developers/feat/getApplications
letskuku Aug 4, 2024
d32f568
Merge pull request #181 from CEOS-Developers/feat/availability
yoonsseo Aug 8, 2024
07a84e4
[refact] 회고록 목록 보기 response dto 필드 수정
letskuku Aug 12, 2024
ff28871
[refact] 회고록 상세 보기/수정 response dto 필드 수정
letskuku Aug 12, 2024
b01f13c
Merge pull request #184 from CEOS-Developers/refact/retrospect
letskuku Aug 13, 2024
758d399
Merge branch 'main' into dev
hyunihs Aug 13, 2024
cb9a203
[refact] 리프레시 토큰 발급 로직 수정 (#186)
suhhyun524 Aug 14, 2024
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
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @hyunihs @suhhyun524 @mushroom1324 @haen-su @mirageoasis
* @hyunihs @mushroom1324 @letskuku @yoonsseo @itsme-shawn @YoungGyo-00
13 changes: 9 additions & 4 deletions src/main/java/ceos/backend/domain/admin/AdminController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ceos.backend.global.config.user.AdminDetails;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -21,6 +22,8 @@
public class AdminController {

private final AdminService adminService;
private static final String MOBILE = "mobile";
private static final String WEB = "web";

@Operation(summary = "닉네임 확인")
@PostMapping("/username")
Expand All @@ -38,9 +41,10 @@ public void signUp(@RequestBody @Valid SignUpRequest signUpRequest) {

@Operation(summary = "로그인")
@PostMapping("/signin")
public TokenResponse signIn(@RequestBody @Valid SignInRequest signInRequest) {
public TokenResponse signIn(HttpServletRequest request, @RequestBody @Valid SignInRequest signInRequest) {
log.info("로그인");
return adminService.signIn(signInRequest);
String device = request.getHeader("User-Agent").contains("mobile") ? MOBILE : WEB;
return adminService.signIn(device, signInRequest);
}

@Operation(summary = "아이디 찾기")
Expand Down Expand Up @@ -68,9 +72,10 @@ public void resetPwd(

@Operation(summary = "로그아웃")
@PostMapping("/logout")
public void logout(@AuthenticationPrincipal AdminDetails adminUser) {
public void logout(HttpServletRequest request, @AuthenticationPrincipal AdminDetails adminUser) {
log.info("로그아웃");
adminService.logout(adminUser);
String device = request.getHeader("User-Agent").contains("mobile") ? MOBILE : WEB;
adminService.logout(device, adminUser);
}

@Operation(summary = "토큰 재발급")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,18 @@ public void signUp(SignUpRequest signUpRequest) {
}

@Transactional
public TokenResponse signIn(SignInRequest signInRequest) {
public TokenResponse signIn(String device, SignInRequest signInRequest) {

final Admin admin = adminHelper.findForSignIn(signInRequest);
final Authentication authentication = adminHelper.adminAuthorizationInput(admin);

adminHelper.checkRole(admin);

String redisKey = admin.getId().toString() + ":" + device;

// 토큰 발급
final String accessToken = tokenProvider.createAccessToken(admin.getId(), authentication);
final String refreshToken = tokenProvider.createRefreshToken(admin.getId(), authentication);
final String refreshToken = tokenProvider.createRefreshToken(admin.getId(), authentication, redisKey);

return adminMapper.toTokenResponse(accessToken, refreshToken);
}
Expand Down Expand Up @@ -97,11 +99,13 @@ public void resetPwd(ResetPwdRequest resetPwdRequest, AdminDetails adminUser) {
}

@Transactional
public void logout(AdminDetails adminUser) {
public void logout(String device, AdminDetails adminUser) {
final Admin admin = adminUser.getAdmin();

String redisKey = admin.getId().toString() + ":" + device;

// 레디스 삭제
tokenProvider.deleteRefreshToken(admin.getId());
tokenProvider.deleteRefreshToken(redisKey);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

package ceos.backend.domain.application;


Expand All @@ -7,16 +8,13 @@
import ceos.backend.domain.application.dto.request.UpdateAttendanceRequest;
import ceos.backend.domain.application.dto.request.UpdateInterviewTime;
import ceos.backend.domain.application.dto.request.UpdatePassStatus;
import ceos.backend.domain.application.dto.response.GetApplication;
import ceos.backend.domain.application.dto.response.GetApplicationQuestion;
import ceos.backend.domain.application.dto.response.GetApplications;
import ceos.backend.domain.application.dto.response.GetCreationTime;
import ceos.backend.domain.application.dto.response.GetInterviewTime;
import ceos.backend.domain.application.dto.response.GetResultResponse;
import ceos.backend.domain.application.dto.response.*;
import ceos.backend.domain.application.service.ApplicationExcelService;
import ceos.backend.domain.application.service.ApplicationService;
import ceos.backend.global.common.entity.Part;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.nio.file.Path;
Expand All @@ -26,15 +24,7 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
Expand All @@ -48,10 +38,13 @@ public class ApplicationController {
@Operation(summary = "지원자 목록 보기")
@GetMapping
public GetApplications getApplications(
@RequestParam(value = "part", required = false) Part part,
@RequestParam(value = "docPass", required = false) Pass docPass,
@RequestParam(value = "finalPass", required = false) Pass finalPass,
@RequestParam(value = "applicantName", required = false) String applicantName,
@Parameter(schema = @Schema(allowableValues = {"PRODUCT", "DESIGN", "FRONTEND", "BACKEND"}))
@RequestParam(value = "part", required = false, defaultValue = "") Part part,
@Parameter(schema = @Schema(allowableValues = {"PASS", "FAIL"}))
@RequestParam(value = "docPass", required = false, defaultValue = "") Pass docPass,
@Parameter(schema = @Schema(allowableValues = {"PASS", "FAIL"}))
@RequestParam(value = "finalPass", required = false, defaultValue = "") Pass finalPass,
@RequestParam(value = "applicantName", required = false, defaultValue = "") String applicantName,
@RequestParam("pageNum") int pageNum,
@RequestParam("limit") int limit) {
log.info("지원자 목록 보기");
Expand Down Expand Up @@ -150,6 +143,13 @@ public void updateDocumentPassStatus(
applicationService.updateDocumentPassStatus(applicationId, updatePassStatus);
}

@Operation(summary = "면접 참여 가능 여부 확인", description = "resultDateDoc ~ resultDateFinal 전날")
@GetMapping(value = "/{applicationId}/interview/availability")
public GetInterviewAvailability getInterviewAvailability(@PathVariable("applicationId") Long applicationId) {
log.info("면접 참여 가능 여부 확인");
return applicationService.getInterviewAvailability(applicationId);
}

@Operation(summary = "최종 합격 여부 변경", description = "resultDateDoc ~ ResultDateFinal 전날")
@PatchMapping(value = "/{applicationId}/final")
public void updateFinalPassStatus(
Expand All @@ -159,6 +159,13 @@ public void updateFinalPassStatus(
applicationService.updateFinalPassStatus(applicationId, updatePassStatus);
}

@Operation(summary = "활동 가능 여부 확인", description = "resultDateDoc ~ resultDateFinal 전날")
@GetMapping(value = "/{applicationId}/final/availability")
public GetFinalAvailability getFinalPass(@PathVariable("applicationId") Long applicationId) {
log.info("활동 가능 여부 확인");
return applicationService.getFinalAvailability(applicationId);
}

@Operation(summary = "지원서 엑셀 파일 생성")
@GetMapping(value = "/file/create")
public GetCreationTime createApplicationExcel() {
Expand Down Expand Up @@ -191,4 +198,11 @@ public GetCreationTime getApplicationExcelCreationTime() {
log.info("지원서 엑셀 파일 생성 시각 확인");
return applicationExcelService.getApplicationExcelCreationTime();
}

@Operation(summary = "지원서 전체 삭제")
@DeleteMapping(value = "/delete")
public void deleteAllApplications() {
log.info("지원서 전체 삭제");
applicationService.deleteAllApplications();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -36,17 +38,20 @@ public class Application extends BaseEntity {
@ColumnDefault("false")
private boolean interviewCheck;

@Size(max = 100)
private String unableReason;

@NotNull
@Enumerated(EnumType.STRING)
private Pass documentPass;

@NotNull
@ColumnDefault("false")
private boolean finalCheck;
private boolean finalCheck; // 활동 가능 여부

@NotNull
@Enumerated(EnumType.STRING)
private Pass finalPass;
private Pass finalPass; // 최종 합격 결과

@OneToMany(mappedBy = "application", cascade = CascadeType.ALL)
private List<ApplicationAnswer> applicationAnswers = new ArrayList<>();
Expand Down Expand Up @@ -85,6 +90,8 @@ public void updateInterviewCheck(boolean check) {
this.interviewCheck = check;
}

public void updateUnableReason(String reason) { this.unableReason = reason; }

public void updateFinalCheck(boolean check) {
this.finalCheck = check;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class ApplicationAnswer extends BaseEntity {
private Long id;

// Question : Answer = 1:1 (단방향)
@OneToOne(cascade = CascadeType.ALL)
@OneToOne
@JoinColumn(name = "application_question_id")
private ApplicationQuestion applicationQuestion;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ceos.backend.domain.application.dto.response;

import ceos.backend.domain.application.domain.Application;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class GetFinalAvailability {
private boolean finalAvailability; // 활동 가능 여부
private String reason; // 활동 불가능 사유

@Builder
public GetFinalAvailability(boolean finalCheck, String reason) {
this.finalAvailability = finalCheck;
this.reason = reason;
}

public static GetFinalAvailability of(Application application) {
return GetFinalAvailability.builder()
.finalAvailability(application.isFinalCheck())
.reason(application.getUnableReason())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ceos.backend.domain.application.dto.response;

import ceos.backend.domain.application.domain.Application;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class GetInterviewAvailability {
private boolean interviewAvailability; // 참여 가능 여부
private String reason; // 참여 불가능 사유

@Builder
public GetInterviewAvailability(boolean interviewCheck, String reason) {
this.interviewAvailability = interviewCheck;
this.reason = reason;
}

public static GetInterviewAvailability of(Application application) {
return GetInterviewAvailability.builder()
.interviewAvailability(application.isInterviewCheck())
.reason(application.getUnableReason())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum ApplicationErrorCode implements BaseErrorCode {
SAME_PASS_STATUS(BAD_REQUEST, "APPLICATION_400_7", "같은 상태로 변경할 수 없습니다."),
NOT_SET_INTERVIEW_TIME(BAD_REQUEST, "APPLICATION_400_8", "면접 시간이 정해지지 않았습니다."),
APPLICATION_STILL_EXIST(BAD_REQUEST, "APPLICATION_400_9", "기존 지원자 데이터가 남아있습니다."),
NOT_DELETABLE_DURING_RECRUITMENT(BAD_REQUEST, "APPLICATION_400_10", "최종 발표 전 지원자를 삭제할 수 없습니다."),

APPLICANT_NOT_FOUND(BAD_REQUEST, "APPLICATION_404_3", "존재하지 않는 지원자입니다."),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ceos.backend.domain.application.exception.exceptions;

import ceos.backend.domain.application.exception.ApplicationErrorCode;
import ceos.backend.global.error.BaseErrorException;

public class NotDeletableDuringRecruitment extends BaseErrorException {
public static final NotDeletableDuringRecruitment EXCEPTION = new NotDeletableDuringRecruitment();

private NotDeletableDuringRecruitment() {
super(ApplicationErrorCode.NOT_DELETABLE_DURING_RECRUITMENT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
import ceos.backend.domain.application.dto.request.UpdateAttendanceRequest;
import ceos.backend.domain.application.dto.request.UpdateInterviewTime;
import ceos.backend.domain.application.dto.request.UpdatePassStatus;
import ceos.backend.domain.application.dto.response.GetApplication;
import ceos.backend.domain.application.dto.response.GetApplicationQuestion;
import ceos.backend.domain.application.dto.response.GetApplications;
import ceos.backend.domain.application.dto.response.GetInterviewTime;
import ceos.backend.domain.application.dto.response.GetResultResponse;
import ceos.backend.domain.application.dto.response.*;
import ceos.backend.domain.application.exception.exceptions.NotDeletableDuringRecruitment;
import ceos.backend.domain.application.helper.ApplicationHelper;
import ceos.backend.domain.application.mapper.ApplicationMapper;
import ceos.backend.domain.application.repository.ApplicationAnswerRepository;
Expand All @@ -35,6 +32,8 @@
import ceos.backend.global.common.entity.Part;
import ceos.backend.global.util.InterviewDateTimeConvertor;
import ceos.backend.global.util.ParsedDurationConvertor;

import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -165,6 +164,7 @@ public void updateInterviewAttendance(
application.updateInterviewCheck(true);
applicationRepository.save(application);
} else {
application.updateUnableReason(request.getReason());
applicationHelper.sendSlackUnableReasonMessage(application, request, false);
}
}
Expand Down Expand Up @@ -193,6 +193,7 @@ public void updateParticipationAvailability(
application.updateFinalCheck(true);
applicationRepository.save(application);
} else {
application.updateUnableReason(request.getReason());
applicationHelper.sendSlackUnableReasonMessage(application, request, true);
}
}
Expand Down Expand Up @@ -246,6 +247,16 @@ public void updateInterviewTime(Long applicationId, UpdateInterviewTime updateIn
application.updateInterviewTime(duration);
}

@Transactional(readOnly = true)
public GetInterviewAvailability getInterviewAvailability(Long applicationId) {
applicationValidator.validateExistingApplicant(applicationId); // 유저 검증
final Application application = applicationHelper.getApplicationById(applicationId);
applicationValidator.validateDocumentPassStatus(application); // 서류 통과 검증

return GetInterviewAvailability.of(application);
}


@Transactional
public void updateDocumentPassStatus(Long applicationId, UpdatePassStatus updatePassStatus) {
recruitmentValidator.validateBetweenStartDateDocAndResultDateDoc(); // 기간 검증
Expand All @@ -264,4 +275,26 @@ public void updateFinalPassStatus(Long applicationId, UpdatePassStatus updatePas

application.updateFinalPass(updatePassStatus.getPass());
}

@Transactional(readOnly = true)
public GetFinalAvailability getFinalAvailability(Long applicationId) {
applicationValidator.validateExistingApplicant(applicationId); // 유저 검증
final Application application = applicationHelper.getApplicationById(applicationId);
applicationValidator.validateFinalPassStatus(application); // 최종 합격 검증

return GetFinalAvailability.of(application);
}


@Transactional
public void deleteAllApplications() {
Recruitment recruitment = recruitmentHelper.takeRecruitment();
// 현재 시간이 resultDateFinal 이전이면 삭제 불가
if(LocalDateTime.now().isBefore(recruitment.getResultDateFinal())) {
throw NotDeletableDuringRecruitment.EXCEPTION;
}
// application, applicationAnswer, applicationInterview 삭제 (cascade)
applicationRepository.deleteAll();
}

}
Loading
Loading