Skip to content

Commit 3492910

Browse files
rlajm1203injae-348westzerorightLeeJaeRyun
authored
release v4.3.0 (#408)
* feat: 배포 자동화 셸 스크립트 작성 * feat: 배포 자동화 셸 스크립트 적용 * feat: 가장 최신 내용의 브랜치로 이동 * feat: nginx proxy 컨테이너 추가 * chore: gitignore에 .pem 추가 * feat: redis config 추가 * refactor: git 디렉터리 에러 해결 * chore: gitignore 에 .key 추가 * refactor: 실행 권한 설정 명령 추가 * rename: 레디스 설정 파일 이름 변경 * refactor: 잘못된 파일 이름 변경 * refactor: 디스코드 발송 에러 해결 * refactor: 디스코드 발송 스크립트 수정 * refactor: 디스코드 발송 스크립트 수정 - env 가 아닌 run 에서 바디 정의 * refactor: discord 알림 발송 워크 플로우 확정 - 디스코드 환경 변수 설정 및 알림 보내기 step 추가 * refactor: discord 알림 발송 워크 플로우 확정 (prod) - 디스코드 환경 변수 설정 및 알림 보내기 step 추가 * refactor: 디스코드 알림 환경 변수 step 제거 * refactor: 디스코드 알림 환경 변수 step 제거 (Prod) * feat: github action 테스트 스크립트 작성 * refactor: 파일 인코딩 변경 * chore: 테스트 스크립트 삭제 * refactor: 필요 없는 주석 삭제 * refactor: 투명 블록 제거 * [chore]: spotless plugin version 6.11.0 -> 6.22.0 변경 * [feat]: 지원 완료 html 템플릿 * [refactor]: html 생성에 템플릿 엔진으로 타임리프 적용 * refactor: 지원서의 합/불 상태 리스트 조회 API에 description 추가 * refactor: PassStateToEnum 은 Response 에 포함되지 않도록 수정 * refactor: ApplicantStateResponse 정의 - Applicant의 state를 전달하는 응답 DTO * fix: backup 디렉터리가 존재하지 않을 경우, 디렉터리를 생성하도록 수정 * refactor: backup 실패 시, printStackTrace 출력하지 않도록 수정 * feat: 사용하지 않는 도커 볼륨 삭제 스크립트 추가 * refactor: 서류 지원 확인 이메일 템플릿 명 변경 * feat: email-first-passed-email 템플릿 추가 * feat: template -> templates * feat: email-first-passed-email -> email-first-passed * chore: api -> infra 모듈로 이동 * style: inline css 적용 * refactor: 멘트 수정 * feat: 최종합격자 이메일 템플릿 추가 * feat: 서류 불합격자 메일 템플릿 추가 * feat: 최종 불합격자 메일 템플릿 추가 * refactor: 최종 합격자 메일 변수 수정 * feat: 합격 상태 별, 이메일 템플릿 추가 * refactor: switch case 문에, break 추가 * feat: DefaultTemplate 클래스 정의 - 기본 이메일 템플릿 * feat: ApplicantEmailService 클래스 작성 - applicant에게 이메일을 전송하는 역할 * refactor: FinalEmailDiscussionEmailScheduler 로직 수정 - 이메일 전송 성공 시 Slack 알림 기능 추가 - ApplicantEmailService 클래스 활용 * refactor: 패키지 이동 및 클래스명 변경 - Recruit-API -> Recruit-Domain - DefaultTemplate -> DefaultEmailTemplate * refactor: EmailTemplateType 수정 - PassSates와 매핑 * refactor: EnumType 이름 변경 * refactor: email 템플릿 infrastructure 모듈에서 domain 모듈로 이전 - 기본 템플릿 * refactor: application.yml 수정 - recruit period 기본값 29기에 맞춰서 수정 - default email template에 필요한 정보 추가 * feat: DefaultEmailProperties 클래스 정의 - DefaultEmail에 들어갈 정보 * feat: DefaultEmailTemplateGenerator 추가 - util로 사용할, 기본 이메일 템플릿 생성 클래스 - 템플릿에 들어갈 내용을, 지원자의 정보에 맞게 생성해준다. * feat: 포트폴리어 파일 경로 추가 * refactor: DefaultEmailGenerator 사용 * comment: 주석 내용 수정 * refactor: switch-case에 걸리지 않을 경우 그대로 리턴 * refactor: DefaultEmailProperties 수정 - LocalDateTime 파싱 로직 추가 * refactor: 시간 정보 text로 변경 - datetime format 사용 * refactor: temporals.format 으로 변경 * feat: Ncp Sms 관련 설정 추가 - sms api url - openfeign에 sms 요청 메소드 추가 * rename: Response -> NcpResponse 클래스 명 변경 * feat: NcpSmsResponse 정의 * feat: NcpSmsResponse 적용 * feat: NcpSmsSender 정의 - NaverCloudPlatform 을 사용한 sms 전송 클래스 * feat: SmsMessageGenerator 정의 * feat: ApplicantSmsService 구현 - 해당 지원자에게 문자 발송 * refactor: EmailSendEvent 수정 - applicantId 필드 추가 * feat: EmailSendEventHandler 정의 - 이메일 발송 완료 이벤트 처리 * feat: sendSms(applicantId) 메소드 추가 * refactor: record @Getter 제거 * feat: NcpClients 클래스 정의 - Ncp 의 여러 클라이언트 관리 * delete: NcpClient 삭제 * refactor: 패키지 명 변경 및, NcpClients 적용 * rename: NcpSmsSender -> NcpSmsHelper * refactor: ncp api url 분리 - base url + uri 로 분리 * refactor: 패키지 이동에 따른 수정 * refactor: 패키지 이동 * refactor: 휴대폰 번호 추출 키 phone -> contacted * refactor: FeignClient 에러 발생 시, Response 값 String 으로 볼 수 있도록 변경 * refactor: charset 변경 * refactor: Message 객체에 Getter 추가 * refactor: NcpSmsClient return type change * refactor: add default constructor * feat: add fromPhoneNumber * feat: 메일 전송 시, 메일 전송 이벤트 발행 * feat: EmailTemplateInvalidStateException 정의 - 해당 State에 맞는 이메일 템플릿이 없을 경우 발생하는 예외 * refactor: 상태에 맞지 않는 템플릿일 경우 던지는 예외 변경 * refactor: retry 횟수 3회로 변경 및 에러 로그 수정 * feat: 최종 합격 공지 대상 필터링 메소드 추가 - FINAL_PASSED , FINAL_FAILED * refactor: 최종 합격자 대상 ot 시간 형식 수정 * feat: 이메일 API 컨트롤러 추가 * style: spotlessApply * fix: Redisson Lock 해제 조건 추가 - 현재 스레드가 락 소유 - 락 상태 on * style: spotlessApply * comment: 주석 추가 * refactor: 메일 발송 성공 시 이벤트 발행 로직 제거 * feat: SecurityConfig에 email 관련 api 추가 * feat: 이벤트 발행 로그 다시 추가 * feat: email api 추가 * feat: sendEmail(year, state) 메소드 추가 * feat: applicantId로 MongoAnswer 찾는 메소드 추가 * feat: applicantId로 지원자 한 명 에게 메일 발송 API 추가 * refactor: 님! 추가 * style: spotlessApply * style: spotlessApply * docs: 포트폴리오 새로운 버전으로 변경 * refactor: 구글폼 링크 추가 * refactor: ot url 설정 추가 * fix: 오타 수정 * fix: orientation url key 수정 * refactor: 불합격자 멘트 수정 * fix: 오타 수정 * refactor: 문자 기본 멘트 변경 * refactor: 띄어쓰기 추가 * [BE-122] 이메일 발송 이벤트 처리를 수정합니다. (#336) * refactor: Transactional 삭제 * refactor: TransactionalEventListener -> EventListener 로 변경 * [feat]: 레디스에 저장할 액세스토큰 엔티티 * [feat]: 화이트리스트 레포지토리 및 레디스 설정 - 해당 레디스 설정을 통해 토큰 삭제 시 Set 모두 삭제됩니다. * [feat]: 매 요청 접속 시 화이트리스트에 액세스 토큰이 있는지 검사 * [feat]: 로그인 시 액세스 토큰을 저장하고 로그아웃 시 삭제 * [refactor]: 기존에 있는 InvalideTokenException을 사용 * [refactor]: 필터에서 레포지토리보다는 포트를 주입받아서 사용 * [feat]: 간소화된 면접 기록 응답 DTO 추가 - SimpleRecordViewResponseDto: 간소화된 면접 기록 DTO - SimpleRecordsViewResponseDto: 페이지 정보 및 간소화된 면접 기록 리스트 반환 DTO * [feat]: 간단한 면접 목록 조회를 위한 executeSimple 메서드 추가 - SimpleRecordsViewResponseDto를 반환하는 executeSimple 메서드 추가 * [feat]: RecordService에 executeSimple 구현 * [feat]: 간소화된 면접 기록 목록 조회 엔드포인트 추가 - 지원자의 면접기록 목록을 페이지 몇 기수별로 조회하는 엔드포인트 추가 - /api/v1/page/{page}/year/{year}/records * [feat]: Record, Applicant, 점수, 페이지 정보를 담는 FilteredRecordsApplicantsDto 추가 * [refactor]: RecordsService의 공통 로직을 private 메서드로 분리 - execute 와 executeSimple 메서드에서 공통되는 부분 private 메서드로 분리 * [feat]: 비밀번호 재설정 기능 구현 * [style]: spotless * [feat]: 이메일로 인증코드 발송 구현 * [feat]: 이메일로 인증코드 발송 구현 * [feat]: 비밀번호 재설정 시 인증 완료 기록 없으면 예외 발생 * [style]: spotless * [chore]: Graphql 의존성 추가 - sprint boot, 확장 스칼라, 테스트 의존성 추가 * [chore]: GraphQL 스키마 초기화 설정 및 로깅 설정 추가 * [feat]: 요청/응답 캐싱 필터에 GraphQL 제외 전략 적용 * [feat]: Method Level 인가 활성화 및 GraphQL 경로 permitAll 설정 - @EnableMethodSecurity 추가로 @PreAuthorize를 통해 Resolver 단에서 인가 적용 - GraphQL 경로는 FilterChain을 통과하되 인증 없이 접근 허용 PreAuthorize를 통해 각 쿼리 별 접근 제한 설정 * [feat]: GraphQL JSON 스칼라 등록 및 Jackson 메시지 컨버터 설정 * [feat]: GraphQL을 통한 필터링된 목록 및 단일 조회 기능 구현 * [feat]: GraphQLExceptionHandler 추가 - RecruitCodeException Handling - 이외의 오류는 Internal Server Error로 처리 * [style]: spotless * [BE-113] 칸반 보드 Columns 조회 시 QueryString으로 year 정보를 받는 V2 API 추가, 지원서 칸반보드 열 생성 V2 API 추가 (#298) * Revert "[BE-113] 칸반 보드 Columns 조회 시 QueryString으로 year 정보를 받는 V2 API 추가, 지원서 …" (#348) This reverts commit 69589ed. * [feat]: 비밀번호 재설정을 위한 이메일 인증 시 존재하지 않는 면접관이면 예외 처리 * [feat]: 회원가입 시 이메일 인증 기능 추가 * [feat]: 시큐리티 경로 추가 * [feat]: 회원가입 시 이메일 인증이 완료되지 않았으면 예외 처리 * [style]: spotless * [refactor]: GraphQL 에외 처리 빌더 메서드를 통한 중복 코드 제거 * [style]: spotless * [refactor]: Graphql 경로 /graphql 에서 /api/graphql로 변경 * [refactor]: Optional 객체에 ifPresentOrElse 적용 * [feat]: 비밀번호 재설정 및 회원가입 완료 시 코드 인증 완료 데이터 삭제 * [refactor]: UserService에 ifPresentOrElse 적용 * [BE-130] 리크루트 모집 on/off 기능 구현 (#352) * feat: application start 엔드포인트 추가 및 usecase 정의 * delete: 클래스 이름 변경에 따른 삭제 * feat: command, dto, states 클래스 정의 * feat: RecruitmentManagementUseCase 구현 및 정의 - 파일 이름 변경 * feat: Recruitment 상태 변경 엔드포인트 추가 * refactor: swagger 설명 수정 * refactor: recruitment 도메인으로 이전 * feat: Recruitment entity, repository, port, adaptor 정의 및 구현 * move: 패키지 이동 * delete: 클래스 삭제 * feat: recruitment 제어에 필요한 클래스 정의 * refactor: RecruitmentDto 및 구조 변경 - year, startAt, endAt 추가 및 state 제거 * refactor: Enum 상태 이름 변경 - NON_START, RECRUITING, END * refactor: Enum 필드 추가 * refactor: 메소드 이름 변경 - SetUp * feat: 이미 예약된 작업이 존재하는지 확인하는 메소드 추가 * feat: RecruitmentEnd, RecruitmentStart 이벤트 정의 * refactor: DomainEvent 상속 * feat: RecruitmentScheduler 정의 - start, end 작업 예약 스케줄러 * feat: findById 메소드 정의 * feat: 생성된 Recruitment 작업 예약 구현 - RecruitmentScheduler 정의 - Recruitment update 메소드 추가 - RecruitmentEventHandler 추가 * feat: Recruitment 도메인 관련 예외 정의 - Exception 클래스 정의 - ErrorCode 정의 * refactor: RecruitmentException 적용 * feat: SchedulingConfig 정의 * refactor: 이벤트 핸들러 로깅 추가 * feat: LatestRecruitmentVo 정의 - 가장 최신 Recruitment을 나타내는 전역 VO * feat: RecruitmentRegister 이벤트, 핸들러 구현 * refactor: RecruitmentRegister 이벤트 적용 * comment: 주석 처리 * rename: 이벤트 이름 재정의 * comment: TODO 코멘트 추가 * delete: 필요 없는 클래스 삭제 * refactor: Event 발행 제거, Task로 직접 처리 * refactor: 필요 없는 메소드 삭제 * feat: findByStates 메소드 추가 * feat: 애플리케이션이 종료되었을 경우, DB에서 수행할 작업을 불러오는 로직 추가 * style: spotlessApply * refactor: findLatestOne 쿼리 수정 * refactor: RecruitmentSetUpDto Validation 추가 * refactor: RecruitmentUseCase setUp 메소드 시그니처 변경 및 command 삭제 * feat: Recruitment 삭제 API 추가 및 구현 * feat: Recruitment 캔슬 로직 추가 * refactor: API 명세 수정 - RecruitmentResponseDto, RecruitmentResponseDto 추가 * refactor: AllArgsConstructor 추가 * refactor: 응답 dto 수정 * feat: quartz 스케줄러 의존성 추가 * feat: getState 메소드 추가 * feat: RecruitmentJob, RecruitmentTrigger 정의 * feat: delete 메소드 추가 및 구현 * feat: QuartzException 정이 - Quartz 내부에서 발생한 예외를 감싸는 예외 * refactor: Spring Scheduler -> Quartz 로 변경 및 모집 삭제 로직 변경 * refactor: RecruitmentSetUpDto 필드 milliSecond 단위로 수정 * refactor: RecruitmentSetUpDto Validation 해제 및 RecruitmentException 추가 * move: 패키지 이동 * refactor: 스프링에서 제공하는 scheduler 사용 * refactor: 상태 변경 메소드 @transactional 추가 * refactor: jobKey 생성 메소드 추가 * refactor: recruitmentJobKey 적용 * refactor: LatestRecruitVo를 사용하도록 변경 * refactor: ApplicantValidator year 필드 삭제 * refactor: Recruitment year 필드 타입 변경 - Long -> Integer * refactor: Recruitment year 필드 타입 변경 - Long -> Integer * refactor: LatestRecruitmentVo 빈 등록 메커니즘 수정 * refactor: Recruitment 생성 검증 로직 수정 * refactor: LatestRecruitmentVo 유효성 검증 로직 수정 * feat: quartz-init.sql 추가 및 quartz 테이블 설정 추가 * refactor: LatestRecruitmentVo 분산락 수정 * refactor: LatestRecruitmentVo validate 수정 * refactor: Recruitment 이벤트 핸들러 로직 수정 - 최신 모집 상태 최신화 로직 추가 * feat: Recruitment 조회 기능 구현 * refactor: swagger 명세 수정 * refactor: swagger 명세 수정 (마크다운 문법 일부 적용) * refactor: 모집 생성 시큐리티 필터체인 적용 및 스웨거 설명 추가 * style: spotlessApply * delete: 필요없는 설정파일 삭제 * refactor: year 환경변수 사용 해제 * refactor: year 환경변수 사용 해제 2 * refactor: year 환경변수 사용 해제 3 * refactor: econovation.recruit.period.start / end 환경변수 삭제 * [BE-133] 등록된 모집이 존재하지 않을경우, 유효성 검증 시 예외가 발생하는 오류 수정 (#353) * fix: 아무런 Recruitment 가 없을 경우, IOBException이 발생하는 에러 수정 * refactor: root log level 수정 * [BE-133] 생성된 모집 조회 페이지네이션 오류를 수정합니다. (#354) * fix: 생성된 모집 조회 페이지네이션 수정 * [BE-113] 칸반 보드 Columns 조회 시 QueryString으로 year 정보를 받는 V2 API 추가, 지원서 칸반보드 열 생성 V2 API 추가 (#357) * [feat]: year에 해당하는 지원서 전체 삭제 컨트롤러 코드 * [style]: 사용하지 않는 클래스 선언 제거 * [feat]: year에 해당하는 전체 지원서 삭제 기능 구현 * [BE-136] 가장 최신 Recruitment 조회 API 추가 및 PageSize 동적 설정 (#360) * style: spotlessApply * refactor: pageSize 동적으로 설정할 수 있도록 수정 * feat: 가장 최근 모집 조회 API 추가 * style: spotlessApply * refactor: swagger 설명 추가 * [BE-137] 모집 정보 조회 필드 추가 (#362) * refactor: year 필드 추가 * style: spotlessApply * [BE-138] Recruitment 등록 시 Columns 을 자동으로 생성합니다. (#364) * refactor: year 환경 변수 제거 * feat: static 생성 함수 추가 * feat: static create 메소드 추가 * feat: ColumnsUtil 정의 - Columns에 관련된 유틸 클래스 * feat: 이벤트 핸들러에, 새로운 모집 등록 시 개발자,디자이너,기획자 컬럼 자동 생성 로직 추가 * test: ColumnsUtil 테스트 코드 작성 * style: spotlessApply * feat: existsColumnsByTitle 메소드 추가 * feat: 이미 컬럼이 존재할 경우 생성하지 않도록 수정 * feat: util 함수 추가 * style: spotlessApply * comment: 주석 추가 * refactor: JPQL 수정 * refactor: Recruitment 등록 시, 컬럼 생성 조건 수정 * style" spotlessApply * refactor: 로그 포맷 수정 * refactor: 비동기 이벤트 핸들러로 수정 * style: spotlessApply * refactor: 시스템 전체 로그 레벨 환경 변수로 변경 (#366) * [BE-139] AsyncConfig 추가 및 비동기 이벤트 핸들 설정 (#367) * refactor: 시스템 전체 로그 레벨 환경 변수로 변경 * refactor: AsyncConfig 추가 및 비동기 이벤트 핸들러 설정 수정 * style: spotlessApply * [BE-139] Quartz 로깅 설정 추가 (#368) * refactor: Quartz 로깅 설정 추가 * [BE-139] RecruitmentRegisteredEventHandler @async 제거 (#369) * refactor: RecruitmentScheduler 예외 로깅 추가 * refactor: Async 사용하지 않도록 수정 * style: spotlessApply * [BE-141] 지원서 접수 시, 기수에 맞지 않는 컬럼에 보드가 생성되는 오류를 수정합니다. (#372) * feat: getColumnByYearAndTitle 메소드 추가 * refactor: 지원서 접수 시, 현재 모집 중인 기수에 맞는 컬럼을 가져오도록 수정 * refactor: param 어노테이션 추가 * style: spotlessApply * [BE-141] Card, Board 생성 시 ColumnsId 를 잘못 가져오는 오류를 수정합니다. (#375) * feat: getColumnByYearAndTitle 메소드 추가 * refactor: 지원서 접수 시, 현재 모집 중인 기수에 맞는 컬럼을 가져오도록 수정 * refactor: param 어노테이션 추가 * style: spotlessApply * fix: columnsId 를 초기화하지 않는 오류 수정 * refactor: getter 메소드 사용 * [docs]: 스웨거 설명 추가 * [docs]: TODO 작성 * [feat]: year에 해당하는 applicantId들을 리스트로 조회 * [feat]: applicantIds에 해당하는 time_table 데이터 삭제 * [refactor]: 변수명 수정 * [feat]: timetable 삭제 로직 리팩토링 및 score 데이터 삭제 * [feat]: score 데이터 삭제 * [feat]: card & board 데이터 삭제 * [style]: spotless * [BE-141] 이메일 인증 로직에서 Optional 리팩토링 및 입력 형식 검증 실패 시 400을 반환 (#377) * [fix]: @Valid 어노테이션 추가 해당 부분을 생략하여 검증 시에 200 상태 코드가 오는 문제가 있었습니다. * [fix]: 잘못 작성된 ExceptionController 삭제 * [feat]: ExceptionHandler를 삭제하고 NullPointerException에 대한 예외 처리를 GlobalExceptionHandler에 추가 * [refactor]: 스웨거에서 codeValid 필드가 노출되는 것을 해결 * [feat]: 컨트롤러에 @Valid 추가 * [refactor]: 잘못 사용한 Optional 코드 되돌림 * [style]: spotless * [feat]: 지원서 ID들을 기반으로 지원서 일괄 삭제 * [feat]: mysql 데이터 삭제 * [feat]: 관리자만 해당 기능을 사용할 수 있도록 설정 * [refactor]: Optional 객체에 대한 get 메서드보다 orElseThrow 사용 * [feat]: 지원서의 name 항목에 대하여 앞뒤 공백 제거 * [feat]: year와 classOf(학번)에 대한 중복 지원 검사를 위해 unique key 설정 * feat: 지원자 검색을 위한 MongoAnswer에 name 필드 추가 * feat: 지원자 이름 자동완성 검색 기능 구현 - prefix → 이름 길이 → 사전순 기준으로 결과 정렬 * feat: 지원자 이름 자동완성 API * feat: 게스트는 해당 요청 불가 * feat: 코멘트 조회 시 TF들은 서로의 코멘트 조회 불가 * feat: 다른 면접관의 댓글은 볼 수 있지만 블러 처리 * refactor: 블러 코멘트 문구 수정 * refactor: 시간 형식을 long에서 LocalDateTime으로 변경 * feat: 코멘트 전체 공개 전환 기능 구현 * refactor: 용어 통일 * feat: 댓글 공개 여부에 따라 블러 처리 * style: spotless * fix: 잘못된 예외 타입 수정 * refactor: 40기까지의 컬럼 데이터 초기화 (#396) * feat: 초기화 sql 추가 * [BE-152] SQL 문법 오류 제거 + 회원가입시 이메일 인증 코드 주석 처리 (#399) * fix: sql 문법 오류 해결 * fix: 회원가입시 이메일 인증 로직 제거 * [feat]: 댓글 전체 공개 상태 조회 * [feat]: 댓글 전체 공개 상태 조회 시큐리티 설정 추가 * [refactor]: 불필요한 코드 제거 해당 DTO는 요청 객체이므로 응답 형식을 지정해주는 코드가 필요하지 않음 * [chore]: @Schema 어노테이션을 사용하기 위한 springdoc 의존성 추가 * [feat]: 스웨거 요청 형식 지정 * [BE-156] 운영 환경에서 Swagger 접속을 막기 (#405) * [CHORE]: 운영 환경에서 swagger 관련 엔드포인트 생성되지 않도록 비활성화 * [FIX]: Swagger 경로를 보안 필터 체인에 포함 & 환경별 Swagger 접근 제어 적용 * [FIX]: Swagger 경로에서 JWT 필터 제외 처리 * [FIX]: FeignClient name 충돌로 인한 Bean 중복 등록 문제 해결 * [BE-157] 권한 변경 API 관리자만 허용 (#407) * [fix]: 권한 변경 API 관리자만 허용 * [style]: spotless * [BE-146] 합/불 상태 변경 가능 여부 계산 로직 추가 (#386) * move: 패키지 이동 * feat: NotOperatedException 정의 * refactor: 상태 변경 로직 수정 - 상태 변경을 할 수 있는지 검증하는 메소드 추가 * refactor: swagger 명세 수정 * refactor: 응답 데이터에 isPassable, isNonPassable 추가 * refactor: 리뷰 반영 * refactor: 리뷰 반영 2 --------- Co-authored-by: injae-348 <ant0593@naver.com> Co-authored-by: JeongInJae <93825184+injae-348@users.noreply.github.com> Co-authored-by: westzeroright <kt8267@naver.com> Co-authored-by: westzeroright <124443419+westzeroright@users.noreply.github.com> Co-authored-by: westzeroright <westzeroright@gmail.com> Co-authored-by: LEE JAERYUN <155902844+LeeJaeRyun@users.noreply.github.com>
1 parent 1a044c8 commit 3492910

File tree

71 files changed

+753
-134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+753
-134
lines changed

server/Recruit-Api/src/main/java/com/econovation/recruit/api/ExceptionController.java

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package com.econovation.recruit.api.applicant.command;
22

33
import java.util.Map;
4-
import lombok.AllArgsConstructor;
54
import lombok.Data;
65
import lombok.Getter;
76
import lombok.NoArgsConstructor;
87
import lombok.ToString;
98
import org.axonframework.modelling.command.TargetAggregateIdentifier;
109

11-
@AllArgsConstructor
1210
@ToString
1311
@Data
1412
@NoArgsConstructor
@@ -17,4 +15,20 @@ public class CreateAnswerCommand {
1715
@TargetAggregateIdentifier private String id;
1816
private Integer year;
1917
private Map<String, Object> qna;
18+
19+
public CreateAnswerCommand(String id, Integer year, Map<String, Object> qna) {
20+
this.id = id;
21+
this.year = year;
22+
setQna(qna);
23+
}
24+
25+
private void setQna(Map<String, Object> qna) {
26+
if (qna != null && qna.containsKey("name")) {
27+
Object value = qna.get("name");
28+
if (value instanceof String str) {
29+
qna.put("name", str.trim());
30+
}
31+
}
32+
this.qna = qna;
33+
}
2034
}

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/ApplicantController.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.econovation.recruit.api.applicant.controller;
22

3+
import static com.econovation.recruitcommon.consts.RecruitStatic.APPLICANTS_BY_YEAR_SUCCESS_DELETE_MESSAGE;
4+
import static com.econovation.recruitcommon.consts.RecruitStatic.APPLICANTS_SUCCESS_DELETE_MESSAGE;
35
import static com.econovation.recruitcommon.consts.RecruitStatic.APPLICANT_SUCCESS_REGISTER_MESSAGE;
46
import static com.econovation.recruitcommon.consts.RecruitStatic.PASS_STATE_KEY;
57

@@ -12,7 +14,6 @@
1214
import com.econovation.recruit.api.applicant.usecase.TimeTableLoadUseCase;
1315
import com.econovation.recruit.api.applicant.usecase.TimeTableRegisterUseCase;
1416
import com.econovation.recruit.api.applicant.validate.ApplicantValidator;
15-
import com.econovation.recruit.api.recruitment.usecase.RecruitmentUseCase;
1617
import com.econovation.recruit.api.recruitment.util.LatestRecruitmentVo;
1718
import com.econovation.recruitcommon.annotation.ApiErrorExceptionsExample;
1819
import com.econovation.recruitcommon.annotation.TimeTrace;
@@ -34,7 +35,15 @@
3435
import org.springdoc.api.annotations.ParameterObject;
3536
import org.springframework.http.HttpStatus;
3637
import org.springframework.http.ResponseEntity;
37-
import org.springframework.web.bind.annotation.*;
38+
import org.springframework.web.bind.annotation.DeleteMapping;
39+
import org.springframework.web.bind.annotation.GetMapping;
40+
import org.springframework.web.bind.annotation.PatchMapping;
41+
import org.springframework.web.bind.annotation.PathVariable;
42+
import org.springframework.web.bind.annotation.PostMapping;
43+
import org.springframework.web.bind.annotation.RequestBody;
44+
import org.springframework.web.bind.annotation.RequestMapping;
45+
import org.springframework.web.bind.annotation.RequestParam;
46+
import org.springframework.web.bind.annotation.RestController;
3847

3948
@RestController
4049
@RequestMapping("/api/v1")
@@ -50,7 +59,6 @@ public class ApplicantController {
5059
private final CommandGateway commandGateway;
5160
private final ApplicantValidator applicantValidator;
5261
private final ApplicantCommandUseCase applicantCommandUseCase;
53-
private final RecruitmentUseCase applicationManagementUseCase;
5462
private final LatestRecruitmentVo latestRecruitInfo;
5563

5664
@Operation(summary = "지원자가 지원서를 작성합니다.", description = "반환 값은 생성된 지원자의 ID입니다.")
@@ -163,10 +171,12 @@ public ResponseEntity<Map<String, String>> updateStatus(
163171
}
164172

165173
@Operation(
166-
summary = "지원서의 합/불 상태를 조회합니다. (합/불 관리자 페이지 전용)",
174+
summary = "지원서의 합/불 상태를 조회합니다.",
167175
description =
168176
"""
169-
응답으로 오는 passState 값의 종류는 non-processed, non-passed, first-passed, final-passed 입니다.
177+
- passState : non-processed | non-passed | first-passed | final-passed
178+
- isPassable : 현재 상태에서 pass 할 수 있는지 여부
179+
- isNonPassable : 현재 상태에서 non-pass 할 수 있는지 여부
170180
""")
171181
@GetMapping("/year/{year}/applicants/pass-state")
172182
public ResponseEntity<List<GetApplicantsStatusResponse>> getApplicantsStatus(
@@ -175,4 +185,26 @@ public ResponseEntity<List<GetApplicantsStatusResponse>> getApplicantsStatus(
175185
applicantQueryUseCase.getApplicantsStatus(year, sortType);
176186
return new ResponseEntity<>(result, HttpStatus.OK);
177187
}
188+
189+
@Operation(summary = "year에 해당하는 모든 지원서를 삭제합니다.")
190+
@DeleteMapping("/applicants/all/{year}")
191+
public ResponseEntity<String> deleteApplicants(@PathVariable("year") Integer year) {
192+
applicantCommandUseCase.deleteByYear(year);
193+
return new ResponseEntity<>(APPLICANTS_BY_YEAR_SUCCESS_DELETE_MESSAGE, HttpStatus.OK);
194+
}
195+
196+
@Operation(summary = "지원서들을 선택해서 일괄 삭제합니다.")
197+
@DeleteMapping("/applicants")
198+
public ResponseEntity<String> deleteApplicant(@RequestBody List<String> applicantIds) {
199+
applicantCommandUseCase.deleteByApplicantIds(applicantIds);
200+
return new ResponseEntity<>(APPLICANTS_SUCCESS_DELETE_MESSAGE, HttpStatus.OK);
201+
}
202+
203+
@Operation(summary = "지원자 검색 시 성함 자동완성")
204+
@GetMapping("/applicants/names/{year}")
205+
public ResponseEntity<List<String>> getApplicantNames(
206+
@PathVariable Integer year, @RequestParam String keyword) {
207+
return new ResponseEntity<>(
208+
applicantQueryUseCase.autocomplete(year, keyword), HttpStatus.OK);
209+
}
178210
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package com.econovation.recruit.api.applicant.dto;
22

3-
public record ApplicantStateResponse(String passState) {
43

5-
public static ApplicantStateResponse of(String passState) {
6-
return new ApplicantStateResponse(passState);
4+
public record ApplicantStateResponse(String passState, boolean isPassable, boolean isNonPassable) {
5+
6+
public static ApplicantStateResponse of(String passState, boolean isPassable, boolean isNonPassable) {
7+
return new ApplicantStateResponse(passState, isPassable, isNonPassable);
78
}
89
}

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/dto/GetApplicantsStatusResponse.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static com.econovation.recruitcommon.consts.RecruitStatic.PASS_STATE_KEY;
44

55
import com.econovation.recruitdomain.domains.applicant.domain.state.ApplicantState;
6+
import com.econovation.recruitdomain.domains.applicant.domain.state.PeriodStates;
67
import com.econovation.recruitdomain.domains.applicant.exception.ApplicantWrongStateException;
78
import java.util.Map;
89
import lombok.AllArgsConstructor;
@@ -21,16 +22,20 @@ public class GetApplicantsStatusResponse {
2122
private Integer year;
2223
private ApplicantStateResponse state;
2324

24-
public static GetApplicantsStatusResponse of(Map<String, Object> result) {
25+
public static GetApplicantsStatusResponse of(Map<String, Object> result, PeriodStates period) {
2526
if (result.get(PASS_STATE_KEY) instanceof ApplicantState applicantState) {
27+
String passState = applicantState.getPassState();
28+
boolean isPassable = applicantState.isPassable(period);
29+
boolean isNonPassable = applicantState.isNonPassable(period);
30+
2631
return GetApplicantsStatusResponse.builder()
2732
.field((String) result.get("field"))
2833
.field1((String) result.get("field1"))
2934
.field2((String) result.get("field2"))
3035
.name((String) result.get("name"))
3136
.id((String) result.get("id"))
3237
.year((Integer) result.get("year"))
33-
.state(ApplicantStateResponse.of(applicantState.getPassState()))
38+
.state(ApplicantStateResponse.of(passState, isPassable, isNonPassable))
3439
.build();
3540
}
3641
throw ApplicantWrongStateException.wrongStatusException;

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerCommandService.java

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,21 @@
44
import com.econovation.recruit.api.applicant.usecase.ApplicantCommandUseCase;
55
import com.econovation.recruit.api.recruitment.util.LatestRecruitmentVo;
66
import com.econovation.recruitdomain.common.aop.domainEvent.Events;
7+
import com.econovation.recruitdomain.domains.applicant.adaptor.AnswerAdaptor;
78
import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer;
89
import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswerAdaptor;
910
import com.econovation.recruitdomain.domains.applicant.domain.state.ApplicantState;
1011
import com.econovation.recruitdomain.domains.applicant.event.domainevent.ApplicantRegisterEvent;
1112
import com.econovation.recruitdomain.domains.applicant.event.domainevent.ApplicantStateModifyEvent;
13+
import com.econovation.recruitdomain.domains.board.adaptor.BoardAdaptor;
14+
import com.econovation.recruitdomain.domains.board.domain.Board;
15+
import com.econovation.recruitdomain.domains.board.exception.BoardNotFoundException;
16+
import com.econovation.recruitdomain.domains.card.adaptor.CardAdaptor;
17+
import com.econovation.recruitdomain.domains.card.domain.Card;
18+
import com.econovation.recruitdomain.domains.label.adaptor.LabelAdaptor;
19+
import com.econovation.recruitdomain.domains.score.adaptor.ScoreAdaptor;
20+
import com.econovation.recruitdomain.domains.timetable.adaptor.TimeTableAdapter;
21+
import java.util.List;
1222
import java.util.Map;
1323
import java.util.UUID;
1424
import lombok.RequiredArgsConstructor;
@@ -18,9 +28,15 @@
1828
@Service
1929
@RequiredArgsConstructor
2030
public class AnswerCommandService implements ApplicantCommandUseCase {
21-
private final MongoAnswerAdaptor answerAdaptor;
31+
private final MongoAnswerAdaptor mongoAnswerAdaptor;
2232
private final ApplicantStateUpdateEventHandler applicantStateUpdateEventHandler;
2333
private final LatestRecruitmentVo latestRecruitInfo;
34+
private final AnswerAdaptor answerAdaptor;
35+
private final TimeTableAdapter timeTableAdapter;
36+
private final ScoreAdaptor scoreAdaptor;
37+
private final LabelAdaptor labelAdaptor;
38+
private final CardAdaptor cardAdaptor;
39+
private final BoardAdaptor boardAdaptor;
2440

2541
@Override
2642
@Transactional
@@ -51,7 +67,7 @@ public UUID execute(Map<String, Object> qna, UUID id) {
5167
.build();
5268
// 학번으로 중복 체크
5369
// validateRegisterApplicant(qna);
54-
answerAdaptor.save(answer);
70+
mongoAnswerAdaptor.save(answer);
5571

5672
String name = qna.get("name").toString();
5773
String hopeField = qna.get("field").toString();
@@ -62,4 +78,48 @@ public UUID execute(Map<String, Object> qna, UUID id) {
6278
Events.raise(applicantRegisterEvent);
6379
return null;
6480
}
81+
82+
@Override
83+
@Transactional
84+
public void deleteByYear(Integer year) {
85+
List<String> applicantIds = answerAdaptor.findApplicantIdsByYear(year);
86+
mongoAnswerAdaptor.delete(year);
87+
88+
timeTableAdapter.deleteAllByApplicantIds(applicantIds);
89+
scoreAdaptor.deleteAllByApplicantIds(applicantIds);
90+
labelAdaptor.deleteAllByApplicantIds(applicantIds);
91+
92+
List<Long> cardIds = cardAdaptor.findAllByApplicantIds(applicantIds);
93+
boardAdaptor.deleteAllByCardIds(cardIds);
94+
cardAdaptor.deleteAllByApplicantIds(applicantIds);
95+
}
96+
97+
@Override
98+
@Transactional
99+
public void deleteByApplicantIds(List<String> applicantIds) {
100+
mongoAnswerAdaptor.deleteByApplicantIds(applicantIds);
101+
102+
timeTableAdapter.deleteAllByApplicantIds(applicantIds);
103+
scoreAdaptor.deleteAllByApplicantIds(applicantIds);
104+
labelAdaptor.deleteAllByApplicantIds(applicantIds);
105+
106+
for (String applicantId : applicantIds) {
107+
deleteBoardByApplicantId(applicantId);
108+
}
109+
110+
cardAdaptor.deleteAllByApplicantIds(applicantIds);
111+
}
112+
113+
private void deleteBoardByApplicantId(String applicantId) {
114+
Card card = cardAdaptor.findByApplicantId(applicantId);
115+
Board deleteBoard = boardAdaptor.getBoardByCardId(card.getId());
116+
117+
Board previousBoard =
118+
boardAdaptor
119+
.getByNextBoardId(deleteBoard.getId())
120+
.orElseThrow(() -> BoardNotFoundException.EXCEPTION);
121+
previousBoard.updateNextBoardID(deleteBoard.getNextBoardId());
122+
123+
boardAdaptor.deleteByCardId(card.getId());
124+
}
65125
}

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/ApplicantService.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
import com.econovation.recruit.api.applicant.dto.AnswersResponseDto;
77
import com.econovation.recruit.api.applicant.dto.GetApplicantsStatusResponse;
88
import com.econovation.recruit.api.applicant.query.AnswerQuery;
9+
import com.econovation.recruit.api.applicant.state.support.PeriodCalculator;
910
import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase;
1011
import com.econovation.recruit.api.recruitment.util.LatestRecruitmentVo;
1112
import com.econovation.recruit.utils.sort.SortHelper;
1213
import com.econovation.recruit.utils.vo.PageInfo;
1314
import com.econovation.recruitdomain.domains.applicant.adaptor.AnswerAdaptor;
1415
import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer;
16+
import com.econovation.recruitdomain.domains.applicant.domain.state.PeriodStates;
1517
import com.econovation.recruitdomain.domains.applicant.exception.ApplicantNotFoundException;
1618
import java.util.Collections;
1719
import java.util.HashMap;
@@ -30,6 +32,7 @@ public class ApplicantService implements ApplicantQueryUseCase {
3032
private final QueryGateway queryGateway;
3133
private final SortHelper<MongoAnswer> sortHelper;
3234
private final LatestRecruitmentVo latestRecruitInfo;
35+
private final PeriodCalculator periodCalculator;
3336

3437
@Transactional(readOnly = true)
3538
public Map<String, Object> execute(String answerId) {
@@ -241,7 +244,12 @@ public List<Map<String, Object>> execute(List<String> fields, Integer page) {
241244
public List<GetApplicantsStatusResponse> getApplicantsStatus(Integer year, String sortType) {
242245
List<MongoAnswer> result = answerAdaptor.findByYear(year);
243246
List<Map<String, Object>> sortedResult = sortAndAddIds(result, sortType);
244-
return sortedResult.stream().map(GetApplicantsStatusResponse::of).toList();
247+
248+
PeriodStates period = periodCalculator.execute();
249+
250+
return sortedResult.stream()
251+
.map(map -> GetApplicantsStatusResponse.of(map, period))
252+
.toList();
245253
}
246254

247255
private List<Map<String, Object>> sortAndAddIds(List<MongoAnswer> result, String sortType) {
@@ -285,4 +293,9 @@ public Map<String, Object> executeFiltered(
285293
qna.put(PASS_STATE_KEY, mongoAnswer.getApplicantStateOrDefault());
286294
return qna;
287295
}
296+
297+
@Transactional(readOnly = true)
298+
public List<String> autocomplete(Integer year, String keyword) {
299+
return answerAdaptor.findApplicantNamesForAutocomplete(year, keyword);
300+
}
288301
}

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.econovation.recruit.api.applicant.usecase;
22

33
import com.econovation.recruitcommon.annotation.UseCase;
4+
import java.util.List;
45
import java.util.Map;
56
import java.util.UUID;
67

@@ -11,4 +12,8 @@ public interface ApplicantCommandUseCase {
1112
String execute(String applicantId, String state);
1213

1314
UUID execute(Map<String, Object> blocks, UUID id);
15+
16+
void deleteByYear(Integer year);
17+
18+
void deleteByApplicantIds(List<String> applicantIds);
1419
}

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantQueryUseCase.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,6 @@ AnswersResponseDto executeFiltered(
5555
List<String> requestedQnaFields);
5656

5757
Map<String, Object> executeFiltered(String applicantId, List<String> requestedQnaFields);
58+
59+
List<String> autocomplete(Integer year, String keyword);
5860
}

server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/validate/ApplicantValidator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.econovation.recruit.api.recruitment.util.LatestRecruitmentVo;
44
import com.econovation.recruitcommon.exception.RecruitCodeException;
55
import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswerAdaptor;
6-
import com.econovation.recruitdomain.domains.applicant.domain.state.RecruitmentStates;
6+
import com.econovation.recruitdomain.domains.recruitment.domain.RecruitmentStates;
77
import com.econovation.recruitdomain.domains.applicant.exception.ApplicantDuplicateSubmitException;
88
import com.econovation.recruitdomain.domains.applicant.exception.ApplicantOutOfDateException;
99
import com.econovation.recruitdomain.domains.applicant.exception.ApplicantWrongPositionException;

0 commit comments

Comments
 (0)