Skip to content

feat: 지원 대학 관련 CRUD 추가#779

Merged
whqtker merged 10 commits into
developfrom
feat/778-univ-apply-info-crud
Jun 20, 2026
Merged

feat: 지원 대학 관련 CRUD 추가#779
whqtker merged 10 commits into
developfrom
feat/778-univ-apply-info-crud

Conversation

@whqtker

@whqtker whqtker commented Jun 20, 2026

Copy link
Copy Markdown
Member

관련 이슈

작업 내용

  • CUD: 어드민 전용
  • R: 전체 접근 허용 / 기존 대학 검색 확장(termId, homeUniversityId 추가)

특이 사항

리뷰 요구사항 (선택)

  • 삭제 시 이를 참조하는 데이터(좋아요, 지원서(soft delete 포함))가 있는 경우 삭제되지 않도록 일단 구현했습니다. 추후 이 경우 어떻게 처리할지 논의가 필요해보입니다.

@whqtker whqtker self-assigned this Jun 20, 2026
@whqtker whqtker added the 기능 label Jun 20, 2026
@whqtker whqtker requested a review from Gyuhyeok99 as a code owner June 20, 2026 11:02
@whqtker whqtker added the 진행 중 자유롭게 merge 가능 label Jun 20, 2026
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@whqtker, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 25 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ada65034-e973-4441-aff2-b0019b3b0b27

📥 Commits

Reviewing files that changed from the base of the PR and between 707cce4 and 9963bf6.

📒 Files selected for processing (4)
  • src/main/java/com/example/solidconnection/admin/university/controller/AdminUnivApplyInfoController.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminUnivApplyInfoResponse.java
  • src/main/java/com/example/solidconnection/admin/university/service/AdminUnivApplyInfoService.java
  • src/test/java/com/example/solidconnection/admin/university/service/AdminUnivApplyInfoServiceTest.java

Walkthrough

이번 PR에서는 크게 두 가지 중요한 변경이 이루어졌습니다.

1️⃣ 관리자 UnivApplyInfo CRUD 기능 추가

  • 요청/응답 DTO(AdminUnivApplyInfoCreateRequest·AdminUnivApplyInfoUpdateRequest·AdminUnivApplyInfoLanguageRequirementRequest·AdminUnivApplyInfoResponse) 신규 추가
  • UnivApplyInfo 도메인에 update(), clearLanguageRequirements() 메서드 추가로 부분 갱신 및 언어 요건 초기화 지원
  • 참조 무결성 검증을 위해 LikedUnivApplyInfoRepository.existsByUnivApplyInfoId(), ApplicationRepository.existsByChoicesUnivApplyInfoId() 메서드 추가
  • AdminUnivApplyInfoService에 생성·수정·삭제 로직 구현 및 UNIV_APPLY_INFO_HAS_REFERENCES 에러코드 추가
  • AdminUnivApplyInfoController 엔드포인트 재배치(POST /import 분리, 기본 POST·PATCH/{id}·DELETE/{id} 추가)
  • 광범위한 테스트 케이스(유효 생성/수정/삭제, 참조 검증, 예외 처리) 추가

2️⃣ UnivApplyInfo 텍스트 검색 필터 확장

  • findAllByText 리포지토리 메서드에 homeUniversityId 파라미터 추가 및 QueryDSL where 조건 확장
  • homeUniversityIdEq 헬퍼 메서드 도입으로 선택적 필터링 지원
  • searchUnivApplyInfoByText를 3-인자(text, homeUniversityId, termId)로 확장, resolveTerm 헬퍼로 학기 결정 로직 분리
  • 캐시 키를 {0} 단일에서 {0}:{1}:{2} 복합 형태로 변경
  • 컨트롤러 /search/text 엔드포인트 파라미터 확장 및 관련 테스트 전면 갱신
  • homeUniversityId·termId 필터 검증 테스트 블록 추가

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • wibaek
  • lsy1307
  • Hexeong
  • JAEHEE25
  • sukangpunch
  • Gyuhyeok99
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 요약하고 있습니다. 지원 대학 관련 CRUD 기능 추가라는 핵심 내용이 간결하게 표현되었습니다.
Description check ✅ Passed PR 설명이 필수 섹션(관련 이슈, 작업 내용)을 포함하고 있으며, 관리자 전용 CUD와 전체 접근 허용 R에 대해 명확히 기술했고, 삭제 참조 검증에 대한 논의 필요사항도 제시했습니다.
Linked Issues check ✅ Passed 코드 변경사항이 연결된 이슈 #778의 모든 핵심 요구사항을 충족합니다: 관리자 전용 CUD 엔드포인트 구현, 전체 사용자 접근 허용 R 기능, termId/homeUniversityId 필터 추가 등.
Out of Scope Changes check ✅ Passed 모든 변경사항이 지원 대학 CRUD 기능 구현이라는 명확한 범위 내에 있습니다. 핵심 기능 이외의 불필요한 변경은 발견되지 않았습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/778-univ-apply-info-crud

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d1b6fb9a35

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
src/test/java/com/example/solidconnection/university/service/UnivApplyInfoQueryServiceTest.java (1)

226-239: ⚡ Quick win

1) homeUniversityId 필터 테스트에 대조 데이터가 없어 회귀를 놓칠 수 있습니다.

  • Line 226-239 테스트는 현재 데이터 1건만 생성해서, 필터가 실제로 적용되지 않아도 통과할 수 있습니다.
  • 다른 homeUniversityId 데이터를 함께 넣고 배제되는지까지 검증하면 회귀 탐지력이 올라갑니다.
보강 예시
             void homeUniversityId를_지정하면_해당_국내대학의_지원_정보만_반환한다() {
                 // given
                 UnivApplyInfo 괌대학_지원_정보 = univApplyInfoFixture.괌대학_A_지원_정보(term.getId());
+                UnivApplyInfo 메이지대학_지원_정보 = univApplyInfoFixture.메이지대학_지원_정보(term.getId());
                 Long homeUniversityId = 괌대학_지원_정보.getHomeUniversity().getId();
+                assertThat(메이지대학_지원_정보.getHomeUniversity().getId()).isNotEqualTo(homeUniversityId);

                 // when
                 UnivApplyInfoPreviewResponses response =
                         univApplyInfoQueryService.searchUnivApplyInfoByText(null, homeUniversityId, null);

                 // then
                 assertThat(response.univApplyInfoPreviews())
                         .hasSize(1)
-                        .allMatch(r -> r.id() == 괌대학_지원_정보.getId());
+                        .extracting(UnivApplyInfoPreviewResponse::id)
+                        .containsExactly(괌대학_지원_정보.getId());
             }
🤖 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/example/solidconnection/university/service/UnivApplyInfoQueryServiceTest.java`
around lines 226 - 239, The test method
homeUniversityId를_지정하면_해당_국내대학의_지원_정보만_반환한다() only creates a single
UnivApplyInfo record with one homeUniversityId, which means the filter could be
broken and the test would still pass since there's nothing to exclude. Add a
second UnivApplyInfo fixture with a different homeUniversityId using
univApplyInfoFixture, then verify that when searchUnivApplyInfoByText() is
called with the first homeUniversityId, only the first record is returned and
the second record with the different homeUniversityId is correctly filtered out.
Update the assertion to verify the response size and that the excluded record is
not present in the results.
src/test/java/com/example/solidconnection/admin/university/service/AdminUnivApplyInfoServiceTest.java (1)

545-565: ⚡ Quick win

1) 부분 수정 계약을 고정하는 회귀 테스트를 추가해 주세요.

Line 545-565는 언어요건 교체 성공만 검증하고, nullable 필드 전달 시 기존 값 보존/삭제의 기대 동작을 잠그지 못합니다. languageRequirements = null(미전달)과 languageRequirements = [](명시적 비움)을 분리해 검증하는 케이스를 추가하면 데이터 소거 회귀를 빠르게 잡을 수 있습니다.

🤖 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/example/solidconnection/admin/university/service/AdminUnivApplyInfoServiceTest.java`
around lines 545 - 565, The current test in the 수정_시_언어_요건이_기존_것과_교체된다 method
only validates successful replacement of language requirements but does not lock
down the expected behavior for partial updates with null or empty fields. Add
two separate regression test cases to the AdminUnivApplyInfoServiceTest class:
one that passes languageRequirements as null (to verify existing language
requirements are preserved when the field is not provided), and another that
passes languageRequirements as an empty list (to verify existing language
requirements are explicitly cleared/deleted). This will establish a clear
contract for the updateUnivApplyInfo method's behavior when handling nullable
collection fields during partial updates.
🤖 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/example/solidconnection/admin/university/dto/AdminUnivApplyInfoCreateRequest.java`:
- Line 21: The `languageRequirements` field in `AdminUnivApplyInfoCreateRequest`
class currently uses `@Valid` on the List, but this does not prevent null
elements within the list (e.g., `[null]` will pass validation), causing
NullPointerException later when the service accesses properties like
`languageTestType()`. Add element-level validation constraints to the
`languageRequirements` field to ensure null elements are rejected at the request
validation stage. Apply the same validation pattern to the corresponding update
DTO class to maintain consistency and prevent similar NPE issues.

In
`@src/main/java/com/example/solidconnection/admin/university/dto/AdminUnivApplyInfoUpdateRequest.java`:
- Around line 9-17: The DTO in AdminUnivApplyInfoUpdateRequest contains nullable
fields (studentCapacity, semesterAvailableForDispatch, semesterRequirement,
detailsForLanguage, gpaRequirement, gpaRequirementCriteria,
detailsForAccommodation, extraInfo, languageRequirements) that are being
directly applied to the entity in the PUT update flow, which creates a data loss
risk when clients omit fields. You need to clarify the update contract: if this
should be a complete replacement, add `@NotNull` validation annotations to
required fields to enforce full updates; if this should be a partial/patch
update, modify the update service logic to implement null-aware merging that
preserves existing entity values when the DTO fields are null instead of
overwriting them.

In
`@src/main/java/com/example/solidconnection/university/domain/UnivApplyInfo.java`:
- Around line 107-109: The clearLanguageRequirements() method is currently being
called unconditionally in the update flow, which causes existing language
requirements to be deleted even when the field is not provided in the request.
To fix this, locate where clearLanguageRequirements() is being invoked and wrap
the call with a null check to ensure it only executes when languageRequirements
are explicitly provided in the request. This way, missing fields in the request
will not trigger deletion of existing data, while explicitly provided (even if
empty) languageRequirements will be properly cleared and recreated.
- Around line 87-105: The update method in UnivApplyInfo directly assigns all
parameters without null checks, which causes existing values to be overwritten
with null when fields are omitted from the update request. To maintain a partial
update contract, add null checks before each assignment in the update method
(lines 97-104). For each field including studentCapacity,
semesterAvailableForDispatch, semesterRequirement, detailsForLanguage,
gpaRequirement, gpaRequirementCriteria, detailsForAccommodation, and extraInfo,
only assign the new value if the parameter is not null, preserving the existing
value when null is passed.

In
`@src/main/java/com/example/solidconnection/university/service/UnivApplyInfoQueryService.java`:
- Around line 46-50: The cache key in the `@ThunderingHerdCaching` annotation for
the searchUnivApplyInfoByText method only includes {0} (text parameter), which
causes different requests with different homeUniversityId and termId values to
reuse the same cached result. Update the cache key to include all parameters
that affect the search results: {0} for text, {1} for homeUniversityId, and {2}
for termId. This ensures that requests with different filter combinations
generate distinct cache entries and do not return mixed or incorrect results.

---

Nitpick comments:
In
`@src/test/java/com/example/solidconnection/admin/university/service/AdminUnivApplyInfoServiceTest.java`:
- Around line 545-565: The current test in the 수정_시_언어_요건이_기존_것과_교체된다 method
only validates successful replacement of language requirements but does not lock
down the expected behavior for partial updates with null or empty fields. Add
two separate regression test cases to the AdminUnivApplyInfoServiceTest class:
one that passes languageRequirements as null (to verify existing language
requirements are preserved when the field is not provided), and another that
passes languageRequirements as an empty list (to verify existing language
requirements are explicitly cleared/deleted). This will establish a clear
contract for the updateUnivApplyInfo method's behavior when handling nullable
collection fields during partial updates.

In
`@src/test/java/com/example/solidconnection/university/service/UnivApplyInfoQueryServiceTest.java`:
- Around line 226-239: The test method
homeUniversityId를_지정하면_해당_국내대학의_지원_정보만_반환한다() only creates a single
UnivApplyInfo record with one homeUniversityId, which means the filter could be
broken and the test would still pass since there's nothing to exclude. Add a
second UnivApplyInfo fixture with a different homeUniversityId using
univApplyInfoFixture, then verify that when searchUnivApplyInfoByText() is
called with the first homeUniversityId, only the first record is returned and
the second record with the different homeUniversityId is correctly filtered out.
Update the assertion to verify the response size and that the excluded record is
not present in the results.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 44a49eb7-c0fe-4798-a96d-2bbcb5716ea5

📥 Commits

Reviewing files that changed from the base of the PR and between 4622ace and d1b6fb9.

📒 Files selected for processing (16)
  • src/main/java/com/example/solidconnection/admin/university/controller/AdminUnivApplyInfoController.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminUnivApplyInfoCreateRequest.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminUnivApplyInfoLanguageRequirementRequest.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminUnivApplyInfoResponse.java
  • src/main/java/com/example/solidconnection/admin/university/dto/AdminUnivApplyInfoUpdateRequest.java
  • src/main/java/com/example/solidconnection/admin/university/service/AdminUnivApplyInfoService.java
  • src/main/java/com/example/solidconnection/application/repository/ApplicationRepository.java
  • src/main/java/com/example/solidconnection/common/exception/ErrorCode.java
  • src/main/java/com/example/solidconnection/university/controller/UnivApplyInfoController.java
  • src/main/java/com/example/solidconnection/university/domain/UnivApplyInfo.java
  • src/main/java/com/example/solidconnection/university/repository/LikedUnivApplyInfoRepository.java
  • src/main/java/com/example/solidconnection/university/repository/custom/UnivApplyInfoFilterRepository.java
  • src/main/java/com/example/solidconnection/university/repository/custom/UnivApplyInfoFilterRepositoryImpl.java
  • src/main/java/com/example/solidconnection/university/service/UnivApplyInfoQueryService.java
  • src/test/java/com/example/solidconnection/admin/university/service/AdminUnivApplyInfoServiceTest.java
  • src/test/java/com/example/solidconnection/university/service/UnivApplyInfoQueryServiceTest.java

@whqtker whqtker force-pushed the feat/778-univ-apply-info-crud branch from 707cce4 to 9963bf6 Compare June 20, 2026 12:59
@whqtker whqtker merged commit d808166 into develop Jun 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

기능 진행 중 자유롭게 merge 가능

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 특정 국내 대학, 특정 학기에 지원 가능한 대학 CRUD 구현

1 participant