-
Notifications
You must be signed in to change notification settings - Fork 1
[Release] dev → main: 지원자 평가 시스템 + CSV 필터 + 테스트 보강 #177
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
Merged
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
35c52a6
#136 test: recruitment admin CRUD 테스트 추가 (REC-ADMIN-002~009)
seoyeon83 cf06600
#136 test: 검수 피드백 반영 — 누락 경계/분기 케이스 보강
seoyeon83 fd9a0ea
#136 test: 명세서 TC ID 정합 — 신규 케이스 ID 충돌 해소
seoyeon83 ca82026
#170 feat: 지원서 평가 어드민 기능 구현
seoyeon83 a542ae3
#170 fix: 개인 평가 upsert에 flushAutomatically 추가
seoyeon83 166d9e3
#170 test: 지원서 평가 어드민 4계층 테스트 추가
seoyeon83 4fa5b50
#170 feat: 관리자 본인 정보 조회 API 추가
seoyeon83 07998bc
#170 chore: cors 추가
seoyeon83 b1088b6
#170 feat: 지원서 답변 조회 API 추가
seoyeon83 fe6f019
#170 chore: 조회 권한 범위 수정
seoyeon83 21642b8
#170 feat: 개인 평가 면접 질문 추가 및 지원서별 면접 질문 조회 API
seoyeon83 fb0c55d
#170 feat: 차기대표진 신설 — 전 부문 조회/평가는 차기대표진, 최종평가는 현재+차기대표진
seoyeon83 a0affd7
#170 feat: 평가 대시보드에 로그인 본인 개인 평가(decision) 반환
seoyeon83 035ed90
#170 fix: 평가자 풀에 차기대표진 포함 (지원서별 평가/면접질문 조회)
seoyeon83 42edce1
#170 chore: data.sql 평가 시드 데이터 반영 — 차기대표진/final_decision/applicant_eval
seoyeon83 5c21850
Merge pull request #171 from BOAZ-website/feat/#170-applicant-evaluation
seoyeon83 05abfd1
Merge remote-tracking branch 'origin/dev' into test/#136-recruitment-…
seoyeon83 c97e0d3
#136 test: createQuestions DB order_num 중복 케이스 보강 (TC-006b)
seoyeon83 e6cda58
Merge pull request #173 from BOAZ-website/test/#136-recruitment-admin…
seoyeon83 911c540
#172 feat: 지원서 CSV에 최종 평가(final_decision) 컬럼 추가
seoyeon83 4e2da2e
#172 feat: 지원서 CSV 합격/불합격/전체 추출 필터(decision) 추가
seoyeon83 092f1c1
#172 test: 최종 평가 컬럼·decision 필터 테스트 추가/수정
seoyeon83 4acf18a
#172 chore: CSV 추출 필터 테스트용 지원자 시드 추가
seoyeon83 cff81af
Merge pull request #175 from BOAZ-website/feat/#172-csv-decision-filter
seoyeon83 33abfbf
#174 test: Admin 도메인 테스트 코드 추가 (Service/Controller/Repository/Integra…
seoyeon83 cbf2273
Merge pull request #176 from BOAZ-website/test/#174-admin
seoyeon83 fd71c48
#170 docs: 평가 API 권한 설명을 실제 track 접근 규칙(차기대표진 전 부문)에 맞게 정정
seoyeon83 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/main/java/com/boaz/backend/domain/admin/dto/response/AdminMeResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package com.boaz.backend.domain.admin.dto.response; | ||
|
|
||
| import com.boaz.backend.domain.admin.entity.Admin; | ||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| public class AdminMeResponse { | ||
|
|
||
| @Schema(description = "계정 ID", example = "1") | ||
| private Long id; | ||
|
|
||
| @Schema(description = "직책/소속", example = "대표진", | ||
| allowableValues = {"대표진", "디자인팀", "자료연구팀", "운영지원팀", "기획팀", "대외협력팀", "서비스운영팀"}) | ||
| private String teamName; | ||
|
|
||
| @Schema(description = "이름", example = "문혁준") | ||
| private String name; | ||
|
|
||
| public static AdminMeResponse from(Admin admin) { | ||
| return AdminMeResponse.builder() | ||
| .id(admin.getId()) | ||
| .teamName(admin.getTeamName().name()) | ||
| .name(admin.getName()) | ||
| .build(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
...va/com/boaz/backend/domain/recruitment/controller/ApplicantEvaluationAdminController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| package com.boaz.backend.domain.recruitment.controller; | ||
|
|
||
| import com.boaz.backend.domain.recruitment.dto.request.EvaluationSaveRequest; | ||
| import com.boaz.backend.domain.recruitment.dto.request.FinalDecisionUpdateRequest; | ||
| import com.boaz.backend.domain.recruitment.dto.response.*; | ||
| import com.boaz.backend.domain.recruitment.service.RecruitmentService; | ||
| import com.boaz.backend.global.common.ApiResponse; | ||
| import com.boaz.backend.global.security.AdminUserDetails; | ||
|
|
||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import io.swagger.v3.oas.annotations.security.SecurityRequirement; | ||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Tag(name = "[Admin] Applicant Evaluation", description = "Admin 전용 지원서 평가 API") | ||
| @SecurityRequirement(name = "bearerAuth") | ||
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/api/v1/admin/recruitment") | ||
| public class ApplicantEvaluationAdminController { | ||
|
|
||
| private final RecruitmentService recruitmentService; | ||
|
|
||
| @Operation(summary = "전체 지원서 조회 (지원자 대시보드)", | ||
| description = "공고 내 전체 지원서를 반환합니다. DRAFT 포함, 정렬·필터·검색은 프론트에서 처리. 대표진은 전 부문, 그 외는 본인 부문만 조회.") | ||
| @GetMapping("/{recruitmentId}/applicants") | ||
| public ResponseEntity<ApiResponse<List<ApplicantSummaryResponse>>> getApplicants( | ||
| @PathVariable Long recruitmentId, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.getApplicants(recruitmentId, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "전체 지원서 및 평가 조회 (평가 대시보드)", | ||
| description = "공고 내 SUBMITTED 지원서 + 평가 집계(합격/보류/불합 개수·총점) + 최종 평가를 반환합니다. 대표진은 전 부문, 그 외는 본인 부문만 조회.") | ||
| @GetMapping("/{recruitmentId}/applicants/evaluations") | ||
| public ResponseEntity<ApiResponse<List<ApplicantEvaluationResponse>>> getApplicantEvaluations( | ||
| @PathVariable Long recruitmentId, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.getApplicantEvaluations(recruitmentId, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "최종 평가 수정 (대표진 전용)", | ||
| description = "대표진(SUPER & teamName=대표진)만 지원자의 최종 평가(final_decision)를 수정합니다.") | ||
| @PatchMapping("/applicants/{applicantId}/final-decision") | ||
| public ResponseEntity<ApiResponse<FinalDecisionResponse>> updateFinalDecision( | ||
| @PathVariable Long applicantId, | ||
| @RequestBody @Valid FinalDecisionUpdateRequest request, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.updateFinalDecision(applicantId, request, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "지원서별 평가 조회", | ||
| description = "한 지원자에 대한 해당 부문 평가자 전체의 평가를 반환합니다. 미평가 평가자는 null로 포함. 대표진 외에는 본인 부문 지원자만 조회.") | ||
| @GetMapping("/applicants/{applicantId}/evaluations") | ||
| public ResponseEntity<ApiResponse<ApplicantEvaluatorsResponse>> getApplicantEvaluators( | ||
| @PathVariable Long applicantId, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.getApplicantEvaluators(applicantId, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "지원서별 면접 질문 조회", | ||
| description = "한 지원자에 대한 해당 부문 평가자별 면접 질문을 반환합니다. 미작성 평가자는 null로 포함. 대표진 외에는 본인 부문 지원자만 조회.") | ||
| @GetMapping("/applicants/{applicantId}/interview-questions") | ||
| public ResponseEntity<ApiResponse<ApplicantInterviewQuestionsResponse>> getApplicantInterviewQuestions( | ||
| @PathVariable Long applicantId, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.getApplicantInterviewQuestions(applicantId, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "지원서 답변 조회", | ||
| description = "한 지원자가 작성한 문항별 답변을 문항 정보(질문 내용·유형)와 함께 문항 순서대로 반환합니다. (평가 사이드바 지원서 본문) 대표진 외에는 본인 부문 지원자만 조회.") | ||
| @GetMapping("/applicants/{applicantId}/answers") | ||
| public ResponseEntity<ApiResponse<ApplicantAnswersResponse>> getApplicantAnswers( | ||
| @PathVariable Long applicantId, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.getApplicantAnswers(applicantId, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "개인 평가 조회", | ||
| description = "로그인한 평가자 본인이 이 지원자에 매긴 평가를 반환합니다. 미평가 시 data=null.") | ||
| @GetMapping("/applicants/{applicantId}/evaluations/me") | ||
| public ResponseEntity<ApiResponse<MyEvaluationResponse>> getMyEvaluation( | ||
| @PathVariable Long applicantId, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.getMyEvaluation(applicantId, userDetails.getAdmin()))); | ||
| } | ||
|
|
||
| @Operation(summary = "개인 평가 저장 (upsert)", | ||
| description = "로그인한 평가자 본인의 평가를 저장합니다. 본인 부문 지원자만 가능, SUBMITTED만 가능.") | ||
| @PutMapping("/applicants/{applicantId}/evaluations/me") | ||
| public ResponseEntity<ApiResponse<MyEvaluationResponse>> saveMyEvaluation( | ||
| @PathVariable Long applicantId, | ||
| @RequestBody @Valid EvaluationSaveRequest request, | ||
| @AuthenticationPrincipal AdminUserDetails userDetails) { | ||
| return ResponseEntity.ok(ApiResponse.ok( | ||
| recruitmentService.saveMyEvaluation(applicantId, request, userDetails.getAdmin()))); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
src/main/java/com/boaz/backend/domain/recruitment/dto/request/EvaluationSaveRequest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.boaz.backend.domain.recruitment.dto.request; | ||
|
|
||
| import com.boaz.backend.domain.recruitment.entity.EvaluationDecision; | ||
| import jakarta.validation.constraints.Max; | ||
| import jakarta.validation.constraints.Min; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| public class EvaluationSaveRequest { | ||
|
|
||
| @NotNull | ||
| private EvaluationDecision decision; | ||
|
|
||
| // 1~10 또는 null (미점수). null이면 검증 통과 | ||
| @Min(1) | ||
| @Max(10) | ||
| private Integer score; | ||
|
|
||
| private String memo; | ||
|
|
||
| // 면접 질문 (null 허용) | ||
| private String interviewQuestion; | ||
| } |
14 changes: 14 additions & 0 deletions
14
...main/java/com/boaz/backend/domain/recruitment/dto/request/FinalDecisionUpdateRequest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.boaz.backend.domain.recruitment.dto.request; | ||
|
|
||
| import com.boaz.backend.domain.recruitment.entity.EvaluationDecision; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Getter | ||
| @NoArgsConstructor | ||
| public class FinalDecisionUpdateRequest { | ||
|
|
||
| @NotNull | ||
| private EvaluationDecision finalDecision; | ||
|
seoyeon83 marked this conversation as resolved.
|
||
| } | ||
44 changes: 44 additions & 0 deletions
44
src/main/java/com/boaz/backend/domain/recruitment/dto/response/ApplicantAnswersResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package com.boaz.backend.domain.recruitment.dto.response; | ||
|
|
||
| import com.boaz.backend.domain.recruitment.entity.ApplicationQuestion; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| public class ApplicantAnswersResponse { | ||
|
|
||
| private final Long applicantId; | ||
|
|
||
| private final List<AnswerDetailResponse> answers; | ||
|
|
||
| public static ApplicantAnswersResponse of(Long applicantId, List<AnswerDetailResponse> answers) { | ||
| return ApplicantAnswersResponse.builder() | ||
| .applicantId(applicantId) | ||
| .answers(answers) | ||
| .build(); | ||
| } | ||
|
|
||
| @Getter | ||
| @Builder | ||
| public static class AnswerDetailResponse { | ||
|
|
||
| private final Long questionId; | ||
|
|
||
| private final String label; | ||
|
|
||
| private final ApplicationQuestion.Category category; | ||
|
|
||
| private final ApplicationQuestion.Type type; | ||
|
|
||
| private final String content; | ||
|
|
||
| private final Integer orderNum; | ||
|
|
||
| // TEXT → 문자열, TABLE → 객체 (사용자용 AnswerItemResponse와 동일 규약) | ||
| private final JsonNode answer; | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.