[Feat] 직접 추가 문항 후보 API 구현#72
Conversation
- 직접 추가 문항 후보 생성 API 추가 - 문항 후보 응답에 custom 필드 추가 - 직접 추가 문항을 선택 확정 전까지 후보로만 관리 - 후보 목록 조회 시 기본 문항과 직접 추가 문항 함께 반환 - 직접 추가 문항 후보 저장 및 조회 테스트 추가
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds support for user-created custom question candidates: new JPA entity and repository, DTO and response changes, service logic to merge/default-validate/upsert custom candidates, a POST controller endpoint, and tests covering creation, duplicate handling, and response flags. ChangesCustom Question Candidates Feature
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/test/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionServiceTest.java (1)
114-137: ⚡ Quick winAdd regression tests for duplicate-content edge paths.
Please add tests for (1) rejecting content equal to a default candidate and (2) duplicate custom content requests returning the same candidate instead of failing. Those are key behavior contracts for this feature.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionServiceTest.java` around lines 114 - 137, Add two tests in QuestionServiceTest that cover the requested regressions: (1) a test that calls questionService.addCustomQuestionCandidate(...) with content identical to an existing default candidate and asserts the request is rejected (e.g., throws or returns a validation error) and that no new candidate is created in questionRepository.findAllByMockApplyId(...); (2) a test that calls questionService.addCustomQuestionCandidate(...) twice with the same custom content and asserts the second call returns the same QuestionCandidateResponse (same questionId and properties) and does not create a duplicate in questionRepository.findAllByMockApplyId(...); use the existing helpers saveUser, saveMockApply and questionService.getQuestionCandidates(...) to verify candidate lists.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/main/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionService.java`:
- Around line 93-99: The current pattern using
customQuestionCandidateRepository.findByMockApplyIdAndContent(...).orElseGet(()
-> customQuestionCandidateRepository.save(CustomQuestionCandidate.create(...)))
is race-prone and can throw a unique-constraint error under concurrent requests;
fix by performing a safe upsert or by catching the persistence exception on save
(e.g., DataIntegrityViolationException/ConstraintViolationException) inside the
method that creates CustomQuestionCandidate, then re-query with
customQuestionCandidateRepository.findByMockApplyIdAndContent(...) to return the
existing record; alternatively use a DB-native upsert if supported by the
repository/ORM, ensuring the method that calls
CustomQuestionCandidate.create(...) and
customQuestionCandidateRepository.save(...) is idempotent and returns the
existing entity on conflict.
---
Nitpick comments:
In
`@src/test/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionServiceTest.java`:
- Around line 114-137: Add two tests in QuestionServiceTest that cover the
requested regressions: (1) a test that calls
questionService.addCustomQuestionCandidate(...) with content identical to an
existing default candidate and asserts the request is rejected (e.g., throws or
returns a validation error) and that no new candidate is created in
questionRepository.findAllByMockApplyId(...); (2) a test that calls
questionService.addCustomQuestionCandidate(...) twice with the same custom
content and asserts the second call returns the same QuestionCandidateResponse
(same questionId and properties) and does not create a duplicate in
questionRepository.findAllByMockApplyId(...); use the existing helpers saveUser,
saveMockApply and questionService.getQuestionCandidates(...) to verify candidate
lists.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 40b5c47c-6cfb-4a16-8641-e30a4dac7544
📒 Files selected for processing (7)
src/main/java/com/jobdri/jobdri_api/domain/analysis/controller/QuestionController.javasrc/main/java/com/jobdri/jobdri_api/domain/analysis/dto/request/QuestionCandidateCreateRequest.javasrc/main/java/com/jobdri/jobdri_api/domain/analysis/dto/response/QuestionCandidateResponse.javasrc/main/java/com/jobdri/jobdri_api/domain/analysis/entity/CustomQuestionCandidate.javasrc/main/java/com/jobdri/jobdri_api/domain/analysis/repository/CustomQuestionCandidateRepository.javasrc/main/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionService.javasrc/test/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionServiceTest.java
- 직접 추가 문항 후보 저장 시 unique 충돌 재조회 처리 - 동시 중복 요청에서도 기존 후보를 반환하도록 보완 - 기본 문항과 동일한 직접 추가 후보 등록 차단 테스트 추가 - 중복 custom 문항 후보 요청 idempotency 테스트 추가
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionService.java (1)
96-101:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
selected응답값이 기존 선택 상태와 불일치할 수 있습니다.중복 요청으로 기존 후보를 반환하는 경우에도
selected를false로 고정해서 반환하고 있어, 이미 선택된 문항이면GET /candidates결과와 응답이 달라집니다. 선택 여부를 실제 저장 상태 기준으로 계산해 반환해 주세요.💡 Suggested patch
public QuestionCandidateResponse addCustomQuestionCandidate( User user, Long mockApplyId, QuestionCandidateCreateRequest request ) { MockApply mockApply = getOwnedMockApply(user, mockApplyId); String content = request.content().trim(); validateCustomCandidate(content); CustomQuestionCandidate candidate = findOrCreateCustomCandidate(mockApply, content, request.charLimit()); + boolean selected = questionRepository.findAllByMockApplyId(mockApply.getId()).stream() + .anyMatch(question -> question.getContent().equals(candidate.getContent())); return new QuestionCandidateResponse( candidate.getId(), candidate.getContent(), candidate.getLimit(), - false, + selected, true ); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionService.java` around lines 96 - 101, The response always hardcodes the selected flag to false when building a QuestionCandidateResponse in QuestionService, which can mismatch persisted state on duplicate requests; change the constructor call to compute selected from the actual stored state (e.g., use candidate.isSelected() or query the repository/aggregate that represents selection) and pass that boolean into new QuestionCandidateResponse(candidate.getId(), candidate.getContent(), candidate.getLimit(), /*selected=*/ computedSelected, true) so the returned selected reflects the true saved selection state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@src/main/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionService.java`:
- Around line 96-101: The response always hardcodes the selected flag to false
when building a QuestionCandidateResponse in QuestionService, which can mismatch
persisted state on duplicate requests; change the constructor call to compute
selected from the actual stored state (e.g., use candidate.isSelected() or query
the repository/aggregate that represents selection) and pass that boolean into
new QuestionCandidateResponse(candidate.getId(), candidate.getContent(),
candidate.getLimit(), /*selected=*/ computedSelected, true) so the returned
selected reflects the true saved selection state.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f1b0e93a-70b5-4266-897e-4cd5268ab0f2
📒 Files selected for processing (2)
src/main/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionService.javasrc/test/java/com/jobdri/jobdri_api/domain/analysis/service/QuestionServiceTest.java
✨ 어떤 이유로 PR를 하셨나요?
📋 세부 내용 - 왜 해당 PR이 필요한지 작업 내용을 자세하게 설명해주세요
📸 작업 화면 스크린샷
🚨 관련 이슈 번호 [#39 ]
Summary by CodeRabbit
New Features
Bug Fixes
Tests