[feature] 동아리 지원자의 목록을 확인할 수 있다#532
Conversation
- questionId, status, answers
- `/apply/info` 엔드포인트 추가 - 사용자별 클럽 지원 정보 반환 로직 구현
- 클럽 지원 정보 응답용 DTO 생성 - total, reviewRequired, scheduledInterview, accepted 필드 추가 - 지원자 목록을 포함하는 applicants 필드 추가
- 사용자별 클럽 지원 정보 반환 메서드 추가 - 제출된 상태별 지원서 통계 계산 로직 구현
|
""" Walkthrough동아리 지원자의 목록 및 상태별 통계 정보를 반환하는 새로운 GET API( Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as ClubApplyController
participant Service as ClubApplyService
participant Repository as ClubApplicationRepository
Client->>Controller: GET /api/club/{clubId}/apply/info (Bearer Token)
Controller->>Service: getClubApplyInfo(clubId, user)
Service->>Repository: findAllByClubId(clubId)
Repository-->>Service: List<ClubApplication>
Service->>Service: 지원자 필터링/집계 및 DTO 매핑
Service-->>Controller: ClubApplyInfoResponse
Controller-->>Client: ResponseEntity<ClubApplyInfoResponse>
Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 없음) Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Test Results75 tests 75 ✅ 2s ⏱️ Results for commit 144b341. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
backend/src/main/java/moadong/club/service/ClubApplyService.java (2)
84-91: 인증 로직 중복 제거 권장기존
getClubQuestion메서드와 동일한 인증 로직이 중복되어 있습니다. 공통 메서드로 추출하여 코드 중복을 제거하는 것을 권장합니다.다음과 같이 공통 메서드를 추출할 수 있습니다:
+private void validateClubOwnership(String clubId, CustomUserDetails user) { + Club club = clubRepository.findById(clubId) + .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND)); + + if (!user.getId().equals(club.getUserId())) { + throw new RestApiException(ErrorCode.USER_UNAUTHORIZED); + } +}그리고 메서드 시작 부분을 다음과 같이 변경:
public ClubApplyInfoResponse getClubApplyInfo(String clubId, CustomUserDetails user) { - Club club = clubRepository.findById(clubId) - .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND)); - - if (!user.getId().equals(club.getUserId())) { - throw new RestApiException(ErrorCode.USER_UNAUTHORIZED); - } + validateClubOwnership(clubId, user);
106-121: 성능 최적화 및 상태 그룹핑 로직 개선동일한 컬렉션에 대해 여러 번의 스트림 연산을 수행하고 있으며, 상태 그룹핑 로직이 하드코딩되어 있습니다. 단일 스트림으로 최적화하고 상태 그룹핑 로직을 별도 메서드로 추출하는 것을 권장합니다.
다음과 같이 개선할 수 있습니다:
+private boolean isReviewRequired(ApplicationStatus status) { + return status == ApplicationStatus.SUBMITTED || status == ApplicationStatus.SCREENING; +} + +private boolean isScheduledInterview(ApplicationStatus status) { + return status == ApplicationStatus.SCREENING_PASSED || + status == ApplicationStatus.INTERVIEW_SCHEDULED || + status == ApplicationStatus.INTERVIEW_IN_PROGRESS; +} + +private boolean isAccepted(ApplicationStatus status) { + return status == ApplicationStatus.INTERVIEW_PASSED || + status == ApplicationStatus.OFFERED || + status == ApplicationStatus.ACCEPTED; +}그리고 카운팅 로직을 다음과 같이 개선:
+int reviewRequired = 0; +int scheduledInterview = 0; +int accepted = 0; + +for (ClubApplication app : submittedApplications) { + ApplicationStatus status = app.getStatus(); + if (isReviewRequired(status)) reviewRequired++; + else if (isScheduledInterview(status)) scheduledInterview++; + else if (isAccepted(status)) accepted++; +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
backend/src/main/java/moadong/club/controller/ClubApplyController.java(3 hunks)backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java(1 hunks)backend/src/main/java/moadong/club/payload/response/ClubApplyInfoResponse.java(1 hunks)backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java(1 hunks)backend/src/main/java/moadong/club/service/ClubApplyService.java(2 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: seongwon030
PR: Moadong/moadong#195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Learnt from: Zepelown
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/entity/ClubApplicationQuestion.java:32-33
Timestamp: 2025-05-15T12:03:57.356Z
Learning: 엔티티 클래스는 요청/응답 객체(DTO)에 의존해서는 안 됩니다. 계층 간 의존성 문제를 방지하기 위해 엔티티와 DTO는 분리되어야 합니다. 예를 들어, `ClubApplicationQuestion` 엔티티가 `ClubApplicationRequest.Options`와 같은 요청 객체를 직접 참조하는 대신, 엔티티 패키지 내에 `QuestionOptions`와 같은 별도의 클래스를 정의하고 사용해야 합니다. 이렇게 하면 요청 객체 변경이 데이터베이스 스키마나 엔티티 계층에 영향을 미치지 않습니다.
backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java (2)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: Zepelown
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/entity/ClubApplicationQuestion.java:32-33
Timestamp: 2025-05-15T12:03:57.356Z
Learning: 엔티티 클래스는 요청/응답 객체(DTO)에 의존해서는 안 됩니다. 계층 간 의존성 문제를 방지하기 위해 엔티티와 DTO는 분리되어야 합니다. 예를 들어, `ClubApplicationQuestion` 엔티티가 `ClubApplicationRequest.Options`와 같은 요청 객체를 직접 참조하는 대신, 엔티티 패키지 내에 `QuestionOptions`와 같은 별도의 클래스를 정의하고 사용해야 합니다. 이렇게 하면 요청 객체 변경이 데이터베이스 스키마나 엔티티 계층에 영향을 미치지 않습니다.
backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java (2)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: Zepelown
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/entity/ClubApplicationQuestion.java:32-33
Timestamp: 2025-05-15T12:03:57.356Z
Learning: 엔티티 클래스는 요청/응답 객체(DTO)에 의존해서는 안 됩니다. 계층 간 의존성 문제를 방지하기 위해 엔티티와 DTO는 분리되어야 합니다. 예를 들어, `ClubApplicationQuestion` 엔티티가 `ClubApplicationRequest.Options`와 같은 요청 객체를 직접 참조하는 대신, 엔티티 패키지 내에 `QuestionOptions`와 같은 별도의 클래스를 정의하고 사용해야 합니다. 이렇게 하면 요청 객체 변경이 데이터베이스 스키마나 엔티티 계층에 영향을 미치지 않습니다.
backend/src/main/java/moadong/club/payload/response/ClubApplyInfoResponse.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/club/controller/ClubApplyController.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/club/service/ClubApplyService.java (2)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
Learnt from: Zepelown
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/entity/ClubApplicationQuestion.java:32-33
Timestamp: 2025-05-15T12:03:57.356Z
Learning: 엔티티 클래스는 요청/응답 객체(DTO)에 의존해서는 안 됩니다. 계층 간 의존성 문제를 방지하기 위해 엔티티와 DTO는 분리되어야 합니다. 예를 들어, `ClubApplicationQuestion` 엔티티가 `ClubApplicationRequest.Options`와 같은 요청 객체를 직접 참조하는 대신, 엔티티 패키지 내에 `QuestionOptions`와 같은 별도의 클래스를 정의하고 사용해야 합니다. 이렇게 하면 요청 객체 변경이 데이터베이스 스키마나 엔티티 계층에 영향을 미치지 않습니다.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (3)
backend/src/main/java/moadong/club/repository/ClubApplicationRepository.java (1)
9-10: 레포지토리 메서드 추가 승인Spring Data JPA 네이밍 규칙을 따른 명확한 메서드 구현입니다. 메서드명과 반환 타입이 적절합니다.
backend/src/main/java/moadong/club/payload/dto/ClubApplicantsResult.java (1)
9-15: DTO 레코드 구현 승인불변성을 제공하는 레코드 구조와 @builder 어노테이션을 활용한 깔끔한 DTO 구현입니다. 필드 타입과 네이밍이 적절합니다.
backend/src/main/java/moadong/club/payload/response/ClubApplyInfoResponse.java (1)
8-16: 응답 레코드 구현 승인통계 정보와 상세 지원자 정보를 포함한 명확한 응답 구조입니다. 필드명이 비즈니스 로직과 일치하며 타입 선택이 적절합니다.
backend/src/main/java/moadong/club/service/ClubApplyService.java
Outdated
Show resolved
Hide resolved
backend/src/main/java/moadong/club/service/ClubApplyService.java
Outdated
Show resolved
Hide resolved
- questionId로 조회하면서 DRAFT 상태 문서는 제외하도록 변경
- repository 레벨에서 `status != 'DRAFT'` 쿼리로 대체
backend/src/main/java/moadong/club/service/ClubApplyService.java
Outdated
Show resolved
Hide resolved
- stream().filter().count() 반복을 제거하고 for + switch로 상태별 카운트 수행
#️⃣연관된 이슈
📝작업 내용
동아리 지원자 현황을 보기 위한 get api를 제작했습니다.
ClubAppySevice ce61013
null또는DRAFT일 때 서류에 카운트되지 않습니다.reviewRequired-> 제출완료+서류심사중scheduledInterview-> 서류통과+면접일정확정+면접진행중accepted-> 면접통과+최종합격제안+제안수락ApplicationStatus.java
중점적으로 리뷰받고 싶은 부분(선택)
status에 따른 카운트 방식 확인 부탁드립니다
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
Summary by CodeRabbit