[WTH-220] 동아리 이미지도 File을 타도록 수정#40
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthrough클럽 생성·수정 DTO의 이미지 필드가 문자열 storageKey에서 Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ManageClubUseCase
participant ClubRepository
participant FileRepository
participant FileEntity
rect rgba(100,150,200,0.5)
Note over Client,ManageClubUseCase: 클럽 생성(이미지 포함)
Client->>ManageClubUseCase: createClub(request with profileImage, backgroundImage)
ManageClubUseCase->>ClubRepository: save(club)
ManageClubUseCase->>FileRepository: save(File from profileImage) / save(File from backgroundImage)
FileRepository-->>FileEntity: create UPLOADED files
FileRepository-->>ManageClubUseCase: saved File entities
ManageClubUseCase-->>Client: return created club
end
rect rgba(150,100,200,0.5)
Note over Client,ManageClubUseCase: 프로필 이미지 교체
Client->>ManageClubUseCase: updateClub(request with new profileImage)
ManageClubUseCase->>FileRepository: findAllByOwnerTypeAndOwnerIdAndStatus(CLUB_PROFILE, clubId, UPLOADED)
FileRepository-->>ManageClubUseCase: existing uploaded files
ManageClubUseCase->>FileEntity: markDeleted() on existing files
ManageClubUseCase->>FileRepository: save(new File from profileImage)
FileRepository-->>ManageClubUseCase: saved new File
ManageClubUseCase->>ClubRepository: save(club with new storageKey)
ManageClubUseCase-->>Client: return updated club
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.kt`:
- Around line 168-174: The storageKey string in ManageClubUseCaseTest within the
FileSaveRequest constructor exceeds the 120-char line limit; extract that long
string into a local val (e.g., val storageKey =
"CLUB_PROFILE/2026-03/550e8400-e29b-41d4-a716-446655440000_profile.png") above
the FileSaveRequest call and then pass storageKey = storageKey, or alternatively
break the string across concatenated literals so the storageKey assignment line
stays under 120 chars; update the FileSaveRequest usage accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ad2f93b6-2506-4434-bfba-9d2769b21356
📒 Files selected for processing (6)
src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubCreateRequest.ktsrc/main/kotlin/com/weeth/domain/club/application/dto/request/ClubUpdateRequest.ktsrc/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCase.ktsrc/main/kotlin/com/weeth/domain/club/domain/entity/Club.ktsrc/main/kotlin/com/weeth/domain/file/domain/enums/FileOwnerType.ktsrc/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.kt
💤 Files with no reviewable changes (1)
- src/main/kotlin/com/weeth/domain/club/domain/entity/Club.kt
src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/main/kotlin/com/weeth/domain/user/domain/repository/UserRepository.kt (1)
30-30:⚠️ Potential issue | 🔴 Critical
existsByStudentId메서드 제거 필요해당 메서드는 codebase 어디에서도 사용되지 않습니다. school-scoped 버전인
existsBySchoolAndStudentIdAndIdIsNot가 존재하므로, 이 메서드를 제거해 주세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/kotlin/com/weeth/domain/user/domain/repository/UserRepository.kt` at line 30, Remove the unused repository method declaration existsByStudentId from the UserRepository interface; rely on the existing school-scoped method existsBySchoolAndStudentIdAndIdIsNot instead, so delete the line "fun existsByStudentId(studentId: String): Boolean" from UserRepository (no other changes needed unless compilation flags complain about unused imports).src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt (1)
25-35:⚠️ Potential issue | 🟡 Minor불필요한 임포트 제거
Line 5에서
AutoPenaltyDeleteNotAllowedException을 임포트하고 있으나 코드에서 사용되지 않습니다. 제거하세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt` around lines 25 - 35, Remove the unused import AutoPenaltyDeleteNotAllowedException from DeletePenaltyUseCase.kt; locate the class/file containing the delete logic in DeletePenaltyUseCase (the block using penaltyRepository.findByIdWithLock, clubMemberRepository.findByIdWithLock, lockedMember.decrementPenaltyCount, and penaltyRepository.delete) and delete the unused import, then run an auto-import/organize-imports pass so no other unused imports remain.
🧹 Nitpick comments (2)
src/main/kotlin/com/weeth/domain/club/presentation/ClubAdminController.kt (1)
108-118:acceptMemberdeprecated 표시 확인
deprecated = true로 표시되었습니다. 해당 엔드포인트의 대체 API가 있다면@Deprecated어노테이션의replaceWith속성이나 API 문서에 대안을 명시하는 것이 사용자 경험에 도움이 됩니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/kotlin/com/weeth/domain/club/presentation/ClubAdminController.kt` around lines 108 - 118, The `@Operation` on acceptMember is marked deprecated but no replacement is documented; update the controller by adding a Kotlin `@Deprecated` annotation to the acceptMember function and set the message and replaceWith parameters to point to the replacement API (or indicate no replacement), e.g. `@Deprecated`(message = "...", replaceWith = ReplaceWith("replacementFunctionName(...)")), and also update the Operation summary or KDoc to mention the alternative endpoint; ensure you reference acceptMember and the `@Operation` declaration when making the change.src/test/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCaseTest.kt (1)
124-133:restore()실패 케이스 테스트 누락현재 테스트는 추방된 멤버를 복구하는 성공 케이스만 검증합니다.
ClubMember.restore()메서드는 멤버가BANNED상태가 아닐 경우 예외를 발생시키므로, 해당 실패 케이스에 대한 테스트 추가를 권장합니다.🧪 추가 테스트 케이스 제안
it("추방되지 않은 멤버는 복구할 수 없다") { val activeMember = ClubMemberTestFixture.createActiveMember(club = club) every { clubPermissionPolicy.requireAdmin(1L, 10L) } returns adminMember every { clubMemberPolicy.getMemberInClub(1L, 20L) } returns activeMember shouldThrow<IllegalStateException> { useCase.restore(1L, 10L, 20L) } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCaseTest.kt` around lines 124 - 133, Add a failing-case unit test to AdminClubMemberUseCaseTest that verifies useCase.restore(...) throws when the target member is not BANNED: create an active member via ClubMemberTestFixture.createActiveMember(club = club), mock clubPermissionPolicy.requireAdmin(1L, 10L) to return adminMember and clubMemberPolicy.getMemberInClub(1L, 20L) to return the active member, then assert that calling useCase.restore(1L, 10L, 20L) results in shouldThrow<IllegalStateException>; this exercises ClubMember.restore()'s precondition and complements the existing success test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCase.kt`:
- Around line 68-78: The restore() path currently lets ClubMember.restore()
throw IllegalStateException via kotlin.check(), which bypasses the BaseException
domain framework; either change ClubMember.restore() to validate state and throw
a domain BaseException subtype (e.g., MemberNotBannedException) instead of using
check(), or add explicit validation in AdminClubMemberUseCase.restore() after
clubMemberPolicy.getMemberInClub(...) and before calling member.restore() and
throw the appropriate domain exception; update references in tests/handlers to
expect the new domain exception so the global exception handler can map it to
the correct error code (see methods: AdminClubMemberUseCase.restore,
clubMemberPolicy.getMemberInClub, ClubMember.restore).
In
`@src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt`:
- Around line 36-39: 현재 SavePenaltyUseCase.kt의 클럽 멤버 패널티 카운트
로직(clubMemberRepository.findByIdWithLock(...) 및
lockedMember.incrementPenaltyCount())은 신규 변경만 반영하므로, 배포 전에 기존 데이터의
club_member.penalty_count를 penalty 테이블 집계값으로 재계산하는 마이그레이션 또는 일회성 배치 작업을 추가하세요;
구체적으로 penalty 테이블에서 member_id별 COUNT를 집계해 club_member.penalty_count를 업데이트하는
스크립트(또는 트랜잭션/락을 사용한 배치 메서드)를 만들고, idempotent하게 설계해 배포 전 실행하거나 배포 직후 즉시 실행되도록 하며
삭제 로직(패널티 삭제 시 감소하는 코드)과 일관되도록 검증 케이스를 추가하세요.
In
`@src/main/kotlin/com/weeth/domain/user/application/usecase/command/UpdateUserProfileUseCase.kt`:
- Around line 37-39: Current behavior enforces school+studentId uniqueness only
in UpdateUserProfileUseCase via existsBySchoolAndStudentIdAndIdIsNot(...) while
SocialLoginUseCase performs no studentId uniqueness check; make them consistent
by adding the same uniqueness validation to SocialLoginUseCase (use or add a
repository method like existsBySchoolAndStudentId(...) to check before creating)
or, if the intended rule is different, remove/adjust the update check in
UpdateUserProfileUseCase to match the creation path—update both use cases to use
the same repository method and throw the same domain exception (e.g.,
StudentIdExistsException) for consistency.
---
Outside diff comments:
In
`@src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.kt`:
- Around line 25-35: Remove the unused import
AutoPenaltyDeleteNotAllowedException from DeletePenaltyUseCase.kt; locate the
class/file containing the delete logic in DeletePenaltyUseCase (the block using
penaltyRepository.findByIdWithLock, clubMemberRepository.findByIdWithLock,
lockedMember.decrementPenaltyCount, and penaltyRepository.delete) and delete the
unused import, then run an auto-import/organize-imports pass so no other unused
imports remain.
In `@src/main/kotlin/com/weeth/domain/user/domain/repository/UserRepository.kt`:
- Line 30: Remove the unused repository method declaration existsByStudentId
from the UserRepository interface; rely on the existing school-scoped method
existsBySchoolAndStudentIdAndIdIsNot instead, so delete the line "fun
existsByStudentId(studentId: String): Boolean" from UserRepository (no other
changes needed unless compilation flags complain about unused imports).
---
Nitpick comments:
In `@src/main/kotlin/com/weeth/domain/club/presentation/ClubAdminController.kt`:
- Around line 108-118: The `@Operation` on acceptMember is marked deprecated but
no replacement is documented; update the controller by adding a Kotlin
`@Deprecated` annotation to the acceptMember function and set the message and
replaceWith parameters to point to the replacement API (or indicate no
replacement), e.g. `@Deprecated`(message = "...", replaceWith =
ReplaceWith("replacementFunctionName(...)")), and also update the Operation
summary or KDoc to mention the alternative endpoint; ensure you reference
acceptMember and the `@Operation` declaration when making the change.
In
`@src/test/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCaseTest.kt`:
- Around line 124-133: Add a failing-case unit test to
AdminClubMemberUseCaseTest that verifies useCase.restore(...) throws when the
target member is not BANNED: create an active member via
ClubMemberTestFixture.createActiveMember(club = club), mock
clubPermissionPolicy.requireAdmin(1L, 10L) to return adminMember and
clubMemberPolicy.getMemberInClub(1L, 20L) to return the active member, then
assert that calling useCase.restore(1L, 10L, 20L) results in
shouldThrow<IllegalStateException>; this exercises ClubMember.restore()'s
precondition and complements the existing success test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 67dabc03-3788-4586-b775-d162a7210856
📒 Files selected for processing (25)
src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubMemberRoleUpdateRequest.ktsrc/main/kotlin/com/weeth/domain/club/application/exception/ClubErrorCode.ktsrc/main/kotlin/com/weeth/domain/club/application/exception/SelfBanNotAllowedException.ktsrc/main/kotlin/com/weeth/domain/club/application/exception/SelfRoleChangeNotAllowedException.ktsrc/main/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCase.ktsrc/main/kotlin/com/weeth/domain/club/domain/entity/ClubMember.ktsrc/main/kotlin/com/weeth/domain/club/presentation/ClubAdminController.ktsrc/main/kotlin/com/weeth/domain/club/presentation/ClubController.ktsrc/main/kotlin/com/weeth/domain/club/presentation/ClubResponseCode.ktsrc/main/kotlin/com/weeth/domain/file/application/dto/request/FileSaveRequest.ktsrc/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.ktsrc/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.ktsrc/main/kotlin/com/weeth/domain/penalty/application/mapper/PenaltyMapper.ktsrc/main/kotlin/com/weeth/domain/penalty/application/usecase/command/DeletePenaltyUseCase.ktsrc/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.ktsrc/main/kotlin/com/weeth/domain/penalty/domain/entity/Penalty.ktsrc/main/kotlin/com/weeth/domain/penalty/domain/enums/PenaltyType.ktsrc/main/kotlin/com/weeth/domain/schedule/application/usecase/query/GetScheduleQueryService.ktsrc/main/kotlin/com/weeth/domain/university/presentation/UniversityController.ktsrc/main/kotlin/com/weeth/domain/user/application/usecase/command/UpdateUserProfileUseCase.ktsrc/main/kotlin/com/weeth/domain/user/domain/repository/UserRepository.ktsrc/main/kotlin/com/weeth/domain/user/presentation/UserController.ktsrc/test/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCaseTest.ktsrc/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.ktsrc/test/kotlin/com/weeth/domain/club/fixture/ClubMemberTestFixture.kt
💤 Files with no reviewable changes (4)
- src/main/kotlin/com/weeth/domain/penalty/domain/enums/PenaltyType.kt
- src/main/kotlin/com/weeth/domain/penalty/application/dto/response/PenaltyDetailResponse.kt
- src/main/kotlin/com/weeth/domain/penalty/application/dto/request/SavePenaltyRequest.kt
- src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubMemberRoleUpdateRequest.kt
✅ Files skipped from review due to trivial changes (4)
- src/main/kotlin/com/weeth/domain/university/presentation/UniversityController.kt
- src/main/kotlin/com/weeth/domain/club/presentation/ClubResponseCode.kt
- src/main/kotlin/com/weeth/domain/file/application/dto/request/FileSaveRequest.kt
- src/main/kotlin/com/weeth/domain/schedule/application/usecase/query/GetScheduleQueryService.kt
src/main/kotlin/com/weeth/domain/club/application/usecase/command/AdminClubMemberUseCase.kt
Show resolved
Hide resolved
src/main/kotlin/com/weeth/domain/penalty/application/usecase/command/SavePenaltyUseCase.kt
Show resolved
Hide resolved
src/main/kotlin/com/weeth/domain/user/application/usecase/command/UpdateUserProfileUseCase.kt
Show resolved
Hide resolved
# Conflicts: # src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCase.kt # src/main/kotlin/com/weeth/domain/club/presentation/ClubResponseCode.kt # src/main/kotlin/com/weeth/domain/user/presentation/UserController.kt # src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.kt
📌 Summary
동아리 프사, 배경사진도 File 도메인을 타도록 수정했습니당.
📝 Changes
What
Why
CDN 도입시 원활하게 연동시키기 위함
How
File에 저장한 후 그 key를 저장하도록 수정
📸 Screenshots / Logs
💡 Reviewer 참고사항
동아리 API 테스트 후 수정 사항 본 PR에 같이 올리겠습니당!
✅ Checklist
Summary by CodeRabbit
New Features
버그 수정 / 동작 개선
호환성 변경