-
Notifications
You must be signed in to change notification settings - Fork 3
[Release] BE v1.0.5 배포 #626
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
Changes from all commits
23ff2e3
a4eea63
c4f8aa4
a95ecf6
c7a79d7
4e73fd0
596a0e4
b2de6c7
f04def2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package moadong.club.payload.request; | ||
|
|
||
| import jakarta.validation.constraints.NotNull; | ||
| import jakarta.validation.constraints.Size; | ||
| import moadong.club.enums.ApplicationStatus; | ||
|
|
||
| public record ClubApplicantEditRequest( | ||
| @NotNull | ||
| @Size(max = 500) | ||
| String memo, | ||
|
|
||
| @NotNull | ||
| ApplicationStatus status | ||
| ) { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,12 @@ | ||
| package moadong.club.service; | ||
|
|
||
| import jakarta.transaction.Transactional; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import moadong.club.entity.*; | ||
| import moadong.club.enums.ClubApplicationQuestionType; | ||
| import moadong.club.payload.dto.ClubApplicantsResult; | ||
| import moadong.club.payload.request.ClubApplicantEditRequest; | ||
| import moadong.club.payload.request.ClubApplicationCreateRequest; | ||
| import moadong.club.payload.request.ClubApplicationEditRequest; | ||
| import moadong.club.payload.request.ClubApplyRequest; | ||
|
|
@@ -123,6 +125,38 @@ public ClubApplyInfoResponse getClubApplyInfo(String clubId, CustomUserDetails u | |
| .build(); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void editApplicantDetail(String clubId, String appId, ClubApplicantEditRequest request, 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); | ||
| } | ||
|
|
||
| ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId) | ||
| .orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND)); | ||
|
|
||
| application.updateDetail(request.memo(), request.status()); | ||
|
|
||
| clubApplicationRepository.save(application); | ||
| } | ||
|
|
||
| @Transactional | ||
| public void deleteApplicant(String clubId, String appId, 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); | ||
| } | ||
|
|
||
| ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId) | ||
| .orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND)); | ||
|
|
||
| clubApplicationRepository.delete(application); | ||
| } | ||
|
Comment on lines
+145
to
+158
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain지원자 삭제: 연관 엔티티 삭제 보장, 감사 로깅, 중복 로직 추출 제안
중복 제거용 최소 변경 diff: - Club club = clubRepository.findById(clubId)
- .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));
-
- if (!user.getId().equals(club.getUserId())) {
- throw new RestApiException(ErrorCode.USER_UNAUTHORIZED);
- }
+ Club club = getAuthorizedClubOrThrow(clubId, user);
- ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId)
- .orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND));
+ ClubApplication application = getApplicantOrThrow(appId, clubId);연관 삭제 설정 점검 스크립트: 🏁 Script executed: #!/bin/bash
set -euo pipefail
# answers 매핑에 orphanRemoval / cascade 설정 확인
fd -t f 'ClubApplication.java' | xargs -I {} rg -n --context 5 'answers|@OneToMany|@ElementCollection|cascade|orphanRemoval' {}Length of output: 509 중복 로직 추출 및 연관 엔티티 삭제 설정 적용 제안 ClubApplication 삭제 시 답변( • ClubApplication.answers 필드에 JPA 매핑 추가
예시 최소 변경 diff: --- a/backend/src/main/java/moadong/club/entity/ClubApplication.java
+++ b/backend/src/main/java/moadong/club/entity/ClubApplication.java
@@
- @Builder.Default
- private List<ClubQuestionAnswer> answers = new ArrayList<>();
+ @OneToMany(
+ mappedBy = "application",
+ cascade = CascadeType.ALL,
+ orphanRemoval = true
+ )
+ @Builder.Default
+ private List<ClubQuestionAnswer> answers = new ArrayList<>();--- a/backend/src/main/java/moadong/club/service/ClubApplyService.java
+++ b/backend/src/main/java/moadong/club/service/ClubApplyService.java
@@ public void deleteApplicant(String clubId, String appId, 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);
- }
+ Club club = getAuthorizedClubOrThrow(clubId, user);
@@
- ClubApplication application = clubApplicationRepository.findByIdAndQuestionId(appId, clubId)
- .orElseThrow(() -> new RestApiException(ErrorCode.APPLICANT_NOT_FOUND));
+ ClubApplication application = getApplicantOrThrow(appId, clubId);
🤖 Prompt for AI Agents |
||
|
|
||
| private void validateAnswers(List<ClubApplyRequest.Answer> answers, ClubQuestion clubQuestion) { | ||
| // 미리 질문과 응답 id 만들어두기 | ||
| Map<Long, ClubApplicationQuestion> questionMap = clubQuestion.getQuestions().stream() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,7 +39,8 @@ public enum ErrorCode { | |
| QUESTION_NOT_FOUND(HttpStatus.NOT_FOUND, "800-4", "존재하지 않은 질문입니다."), | ||
| REQUIRED_QUESTION_MISSING(HttpStatus.BAD_REQUEST, "800-5", "필수 응답 질문이 누락되었습니다."), | ||
|
|
||
| AES_CIPHER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "900-1", "암호화 중 오류가 발생했습니다.") | ||
| AES_CIPHER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "900-1", "암호화 중 오류가 발생했습니다."), | ||
| APPLICANT_NOT_FOUND(HttpStatus.NOT_FOUND, "900-2", "지원서가 존재하지 않습니다."), | ||
| ; | ||
|
Comment on lines
+42
to
44
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오류 코드 중복 정의
🤖 Prompt for AI Agents |
||
|
|
||
| private final HttpStatus httpStatus; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
지원자 수정: 상태 전이 검증·동시성 보호(@Version)·중복 로직 추출 제안
ClubApplication엔티티에@Version(낙관적 락)을 도입하는 것을 권장합니다.deleteApplicant와 반복됩니다. 헬퍼 메서드로 추출하면 가독성과 재사용성이 좋아집니다.save유지/제거는 팀 컨벤션에 맞추세요.중복 제거용 최소 변경 diff:
헬퍼 메서드(파일 내 적절한 위치에 추가):
상태/동시성 관련 확인 스크립트:
🏁 Script executed:
Length of output: 2625
지원자 수정 작업에 아래 사항 보강 필요
ClubApplicantEditRequest의memo(@NotNull, @SiZe(max=500))와status(@NotNull)에 Bean Validation이 적용되어 있습니다.ClubApplication.updateDetail(...)내부에 SCREENING → SCREENING_PASSED 등 도메인 전이 유효성을 체크하는 로직이 없어 서비스 레이어에서 불법 전이를 차단해야 합니다.ClubApplication엔티티에@Version필드가 없어 다중 관리자 동시 수정 시 데이터 손실 위험이 있습니다.editApplicantDetail과deleteApplicant에서 클럽 조회·권한 검증, 지원서 조회 로직이 반복됩니다. 헬퍼 메서드로 분리해 가독성과 재사용성을 높이세요.MongoRepository는 변경 감지를 통해 저장하지만, 명시적
save(...)호출 여부를 팀 컨벤션에 맞춰 통일하세요.필요한 최소 변경 예시:
헬퍼 메서드 예시 (클래스 내 적절한 위치에 추가):
낙관적 락 적용을 위해
ClubApplication엔티티에 다음 필드를 추가하세요:🤖 Prompt for AI Agents