Skip to content

feat/KD-74: 논문 및 자격증 제출의 개별적 승인 및 반려 API 구현#333

Merged
JangYeongHu merged 4 commits intodevelopfrom
feat/KD-74
Mar 29, 2026
Merged

feat/KD-74: 논문 및 자격증 제출의 개별적 승인 및 반려 API 구현#333
JangYeongHu merged 4 commits intodevelopfrom
feat/KD-74

Conversation

@JangYeongHu
Copy link
Copy Markdown
Contributor

Summary

논문 및 자격증 제출의 개별적 승인 및 반려 API를 구현하였습니다.

Tasks

  • 논문 및 자격증 제출의 개별적 승인 및 반려 API
  • 해당 API에 대한 테스트 코드 작성
  • 일괄적 반려 API에 대한 테스트 코드 수정

@JangYeongHu JangYeongHu self-assigned this Mar 27, 2026
@JangYeongHu JangYeongHu added the ✨feature create new feature label Mar 27, 2026
@JangYeongHu JangYeongHu linked an issue Mar 27, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fae69df9-df6c-44ce-bc5e-9864733bfe61

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

요약

졸업 사용자 관리 모듈에 단일 제출물 승인/반려 기능을 추가합니다. approveSubmissiondisapproveSubmission 메서드를 파사드 및 컨트롤러 계층에 도입하여 인증서 및 논문 제출물 유형 모두를 지원합니다.

변경 사항

코호트 / 파일 요약
파사드 계층
aics-admin/src/main/java/kgu/developers/admin/graduationUser/application/GraduationUserAdminFacade.java
두 개의 새로운 메서드 approveSubmission()disapproveSubmission() 추가. 졸업 유형(CERTIFICATE/THESIS)에 따라 해당 커맨드 서비스로 위임하고 graduationUserId를 반환합니다.
컨트롤러 계층
aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminController.java, aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminControllerImpl.java
단일 제출물 관리를 위한 두 개의 REST 엔드포인트 추가. PATCH /approve/{graduationUserId}/{submissionId}PATCH /disapprove/{graduationUserId}/{submissionId} 경로를 통해 파사드 메서드를 호출하고 GraduationUserPersistResponse로 응답합니다.
테스트
aics-admin/src/testFixtures/java/graduationUser/application/GraduationUserAdminFacadeTest.java
새로운 단위 테스트 4개 추가: 인증서/논문 유형의 승인/반려 동작 검증. 기존 테스트 로직도 배치 승인 호출을 통해 리팩토링됩니다.

예상 코드 리뷰 난이도

🎯 3 (보통) | ⏱️ ~20분

관련 가능 PR

제안 리뷰어

  • LeeHanEum
  • dkdltm221
  • 2heunxun
  • hoTan35
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경 사항의 핵심 내용인 개별적 승인 및 반려 API 구현을 명확하게 설명하고 있으며, 구체적이고 의미 있는 정보를 전달합니다.
Description check ✅ Passed PR 설명이 개별 승인/반려 API 구현, 테스트 코드 작성, 기존 테스트 수정 등 변경 사항과 관련된 내용을 포함하고 있습니다.

✏️ 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/KD-74

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.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 27, 2026

Test Coverage Report

Overall Project 80.05% -0.35% 🍏
Files changed 87.1% 🍏

Module Coverage
aics-admin 90.7% -1.36% 🍏
Files
Module File Coverage
aics-admin GraduationUserAdminFacade.java 86.54% -2.31% 🍏

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 27, 2026

Codecov Report

❌ Patch coverage is 70.00000% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ionUser/application/GraduationUserAdminFacade.java 70.00% 1 Missing and 5 partials ⚠️

Impacted file tree graph

@@              Coverage Diff              @@
##             develop     #333      +/-   ##
=============================================
- Coverage      86.97%   85.38%   -1.60%     
- Complexity        67       79      +12     
=============================================
  Files             24       24              
  Lines            261      301      +40     
  Branches          15       30      +15     
=============================================
+ Hits             227      257      +30     
- Misses            21       22       +1     
- Partials          13       22       +9     
Files with missing lines Coverage Δ Complexity Δ
...ionUser/application/GraduationUserAdminFacade.java 76.52% <70.00%> (-0.82%) 28.00 <7.00> (+12.00) ⬇️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d2a862b...9379572. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminControllerImpl.java (2)

155-156: 변수명 camelCase 불일치

동일하게 disapprovedGraduationuserIddisapprovedGraduationUserId로 수정이 필요합니다.

✏️ 네이밍 수정 제안
-        Long disapprovedGraduationuserId = graduationUserAdminFacade.disapproveSubmission(graduationUserId,submissionId);
-        return ResponseEntity.ok(GraduationUserPersistResponse.of(disapprovedGraduationuserId));
+        Long disapprovedGraduationUserId = graduationUserAdminFacade.disapproveSubmission(graduationUserId, submissionId);
+        return ResponseEntity.ok(GraduationUserPersistResponse.of(disapprovedGraduationUserId));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminControllerImpl.java`
around lines 155 - 156, Rename the local variable disapprovedGraduationuserId to
disapprovedGraduationUserId to fix the camelCase inconsistency; update the
declaration and any subsequent usages (the assignment from
graduationUserAdminFacade.disapproveSubmission(graduationUserId, submissionId)
and the ResponseEntity return that calls GraduationUserPersistResponse.of(...))
so they reference disapprovedGraduationUserId.

145-146: 변수명 camelCase 불일치

approvedGraduationuserId에서 u가 소문자입니다. camelCase 컨벤션에 따라 approvedGraduationUserId로 수정하는 것이 좋습니다.

✏️ 네이밍 수정 제안
-        Long approvedGraduationuserId = graduationUserAdminFacade.approveSubmission(graduationUserId,submissionId);
-        return ResponseEntity.ok(GraduationUserPersistResponse.of(approvedGraduationuserId));
+        Long approvedGraduationUserId = graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId);
+        return ResponseEntity.ok(GraduationUserPersistResponse.of(approvedGraduationUserId));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminControllerImpl.java`
around lines 145 - 146, The local variable name approvedGraduationuserId in
GraduationUserAdminControllerImpl violates camelCase; rename it to
approvedGraduationUserId and update any subsequent uses (e.g., the call to
GraduationUserPersistResponse.of and any other references) so the variable
matches camelCase; keep the call to
graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId)
intact and only change the variable name.
aics-admin/src/testFixtures/java/graduationUser/application/GraduationUserAdminFacadeTest.java (1)

376-438: 소유권 검증 실패 케이스에 대한 테스트 추가 필요

happy path 테스트는 잘 작성되었으나, facade에서 플래그된 보안 이슈와 관련하여 다음 케이스에 대한 테스트 추가를 권장합니다:

  1. submissionId가 해당 graduationUser에 속하지 않는 경우
  2. graduationType이 null인 사용자에 대한 승인 시도

소유권 검증 로직이 추가된 후 해당 테스트도 함께 추가해 주세요.

🧪 추가 테스트 케이스 제안
`@Test`
`@DisplayName`("approveSubmission은 다른 사용자의 제출물을 승인하려 할 때 예외를 던진다.")
public void approveSubmission_InvalidSubmissionId_ThrowsException() {
    // given
    Long graduationUserId = 1L; // CERTIFICATE type user
    Long invalidSubmissionId = 999L; // 존재하지 않거나 다른 사용자의 제출물

    // when & then
    assertThrows(IllegalArgumentException.class, () -> 
        graduationUserAdminFacade.approveSubmission(graduationUserId, invalidSubmissionId)
    );
}

`@Test`
`@DisplayName`("approveSubmission은 graduationType이 null인 사용자에 대해 예외를 던진다.")
public void approveSubmission_NullGraduationType_ThrowsException() {
    // given
    Long graduationUserId = 3L; // graduationType이 null인 사용자
    Long submissionId = 1L;

    // when & then
    assertThrows(IllegalStateException.class, () -> 
        graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId)
    );
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@aics-admin/src/testFixtures/java/graduationUser/application/GraduationUserAdminFacadeTest.java`
around lines 376 - 438, Tests only cover happy paths; add negative tests that
assert ownership and null-type checks for the facade methods. In the test class
GraduationUserAdminFacadeTest add tests for approveSubmission (and similarly
disapproveSubmission if desired) that call
graduationUserAdminFacade.approveSubmission with a submissionId that does not
belong to the given graduationUserId and assert the appropriate exception (e.g.,
IllegalArgumentException), and another test where the GraduationUser has
graduationType == null and calling approveSubmission throws the expected
exception (e.g., IllegalStateException); ensure these tests exercise the same
fake repositories (fakeCertificateRepository / fakeThesisRepository) and IDs
used elsewhere so they trigger the new ownership and null-type validation paths
in approveSubmission/disapproveSubmission.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@aics-admin/src/main/java/kgu/developers/admin/graduationUser/application/GraduationUserAdminFacade.java`:
- Around line 228-246: approveSubmission and disapproveSubmission call
CertificateCommandService/ThesisCommandService with a submissionId without
verifying the submission belongs to the GraduationUser, allowing unauthorized
approval/disapproval; before invoking
certificateCommandService.approve/disapprove or
thesisCommandService.approve/disapprove in GraduationUserAdminFacade, load the
target submission (e.g., via a CertificateQueryService.getById or
ThesisQueryService.getById or a submission lookup method), verify its
owner/graduationUserId equals the fetched GraduationUser.id, and if not throw an
appropriate access/validation exception; alternatively, change the command
methods to accept and verify the graduationUserId internally (update
CertificateCommandService.approve/disapprove and
ThesisCommandService.approve/disapprove to perform ownership checks) and ensure
both approveSubmission and disapproveSubmission perform or rely on that
ownership validation before returning graduationUserId.
- Around line 230-234: The current logic in GraduationUserAdminFacade (where
graduationUser.getGraduationType() is inspected to call
certificateCommandService.approve(submissionId) or
thesisCommandService.approve(submissionId)) ignores the case when graduationType
is null; add an explicit null check on graduationUser.getGraduationType() before
the existing if/else and throw a clear runtime exception (e.g.,
IllegalStateException or a domain-specific exception) that includes the
graduationUser id and submissionId, so callers get a failing response instead of
silent success.

---

Nitpick comments:
In
`@aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminControllerImpl.java`:
- Around line 155-156: Rename the local variable disapprovedGraduationuserId to
disapprovedGraduationUserId to fix the camelCase inconsistency; update the
declaration and any subsequent usages (the assignment from
graduationUserAdminFacade.disapproveSubmission(graduationUserId, submissionId)
and the ResponseEntity return that calls GraduationUserPersistResponse.of(...))
so they reference disapprovedGraduationUserId.
- Around line 145-146: The local variable name approvedGraduationuserId in
GraduationUserAdminControllerImpl violates camelCase; rename it to
approvedGraduationUserId and update any subsequent uses (e.g., the call to
GraduationUserPersistResponse.of and any other references) so the variable
matches camelCase; keep the call to
graduationUserAdminFacade.approveSubmission(graduationUserId, submissionId)
intact and only change the variable name.

In
`@aics-admin/src/testFixtures/java/graduationUser/application/GraduationUserAdminFacadeTest.java`:
- Around line 376-438: Tests only cover happy paths; add negative tests that
assert ownership and null-type checks for the facade methods. In the test class
GraduationUserAdminFacadeTest add tests for approveSubmission (and similarly
disapproveSubmission if desired) that call
graduationUserAdminFacade.approveSubmission with a submissionId that does not
belong to the given graduationUserId and assert the appropriate exception (e.g.,
IllegalArgumentException), and another test where the GraduationUser has
graduationType == null and calling approveSubmission throws the expected
exception (e.g., IllegalStateException); ensure these tests exercise the same
fake repositories (fakeCertificateRepository / fakeThesisRepository) and IDs
used elsewhere so they trigger the new ownership and null-type validation paths
in approveSubmission/disapproveSubmission.
🪄 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: 7cb48ebf-9687-4484-a02a-b9ff9d492cf6

📥 Commits

Reviewing files that changed from the base of the PR and between d2a862b and 8e1b4fc.

📒 Files selected for processing (4)
  • aics-admin/src/main/java/kgu/developers/admin/graduationUser/application/GraduationUserAdminFacade.java
  • aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminController.java
  • aics-admin/src/main/java/kgu/developers/admin/graduationUser/presentation/GraduationUserAdminControllerImpl.java
  • aics-admin/src/testFixtures/java/graduationUser/application/GraduationUserAdminFacadeTest.java

Copy link
Copy Markdown
Contributor

@2heunxun 2heunxun left a comment

Choose a reason for hiding this comment

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

LGTM 수고하셨습니다~

Copy link
Copy Markdown
Contributor

@dkdltm221 dkdltm221 left a comment

Choose a reason for hiding this comment

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

LGTM!고생하셨습니다.

@hoTan35
Copy link
Copy Markdown
Contributor

hoTan35 commented Mar 28, 2026

LGTM! 수고 많으셨습니다!

@JangYeongHu JangYeongHu merged commit 3231219 into develop Mar 29, 2026
5 checks passed
@JangYeongHu JangYeongHu deleted the feat/KD-74 branch March 29, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨feature create new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

논문 및 자격증 제출의 개별적 승인 및 반려 API

4 participants