feat: [alt-248] 사용자 목록 응답에 프로필 이미지 필드 추가#90
Conversation
- getWorkspaceWorkerListWithCursor: 매니저 근무자 목록 - getUserWorkspaceWorkerListWithCursor: 유저 근무자 목록 - getExchangeableWorkerListWithCursor: 대타 대상 근무자 선택 목록 - getUserWorkspaceManagerListWithCursor: 유저 매니저 목록 - getManagerWorkspaceManagerListWithCursor: 매니저 매니저 목록 File 엔티티를 USER_PROFILE + ATTACHED 조건으로 left join하고 file.fileUrl을 projection하여 각 워커/매니저의 프로필 이미지 URL 포함
- getReceivedRequestListWithCursor: 요청자, 수락자 - getSentRequestDetail: 요청자, 수락자, 각 대상자 - getManagerRequestListWithCursor: 요청자, 수락자 각 인물별 QFile 별칭(requesterFile/acceptedFile/targetFile)으로 USER_PROFILE + ATTACHED 조건 left join하여 프로필 이미지 URL 포함
- WorkerInfo.of(): Long workerId, String workerName, String profileImageUrl - ManagerWorkerInfo.of(): 동일 확장 - ReceivedSubstituteRequestResponseDto.of(): requester/acceptedWorker profileImageUrl 전달 - SubstituteRequestDetailResponseDto.of(): requester/acceptedWorker/targets profileImageUrl 전달 - ManagerSubstituteRequestResponseDto.of(): requester/acceptedWorker profileImageUrl 전달 - SubstituteRequestTargetResponseDto.of(): target profileImageUrl 전달 readonly 응답의 프로필 URL을 inbound DTO의 nested WorkerInfo로 매핑
|
Warning Review limit reached
More reviews will be available in 7 minutes and 46 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 Walkthrough워크스루이 PR은 근무자 및 사용자 응답 데이터 전반에 프로필 이미지 URL 정보를 추가하는 기능 변경입니다. WorkerInfo 계약을 확장하고, 모든 관련 DTO와 쿼리를 업데이트하여 프로필 이미지 URL을 일관되게 제공합니다. 변경사항프로필 이미지 URL 기능 추가
🎯 3 (Moderate) | ⏱️ ~20 분 제안 레이블
제안 리뷰어
🚥 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 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: 3
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/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java (1)
524-536:⚠️ Potential issue | 🟠 MajorleftJoin으로 인해 중복 row(커서/응답 왜곡) 가능—사용자당 ATTACHED 1건 보장 필요
WorkspaceQueryRepositoryImpl.getUserWorkspaceManagerListWithCursor에서qFile을leftJoin하고(USER_PROFILE+ATTACHED),groupBy/distinct없이fetch()합니다. 따라서 한 사용자에게ATTACHEDUSER_PROFILE파일이 2건 이상 존재하면 동일 매니저가 여러 row로 반환될 수 있습니다(페이지/커서 결과가 깨지거나fileUrl의미가 흔들림).
File엔티티에는id만unique=true로 보이고,(targetType, targetId, status=ATTACHED)같은 복합 유니크 제약(또는 단일 ATTACHED 강제) 근거가 없습니다.다음 중 하나로 “사용자당 ATTACHED 1건”을 강제해 주세요.
- DB 레벨 유니크 제약/인덱스로
(target_type, target_id, status=ATTACHED)단일화를 보장- 또는 조회 시 사용자/매니저 기준으로
ATTACHED파일을 1건만 고정해서 조인(서브쿼리/exists 등)- 또는 첨부 로직에서 기존
ATTACHED전체를 정리하고 최종적으로 1건만 유지🤖 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/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java` around lines 524 - 536, The leftJoin of qFile in WorkspaceQueryRepositoryImpl.getUserWorkspaceManagerListWithCursor can return duplicate rows when a user has multiple ATTACHED USER_PROFILE files; fix by limiting the join to at most one ATTACHED file per user: replace the direct leftJoin(qFile) with a join to a subquery that selects a single ATTACHED file per targetId (e.g., the latest by id or createdAt) and join on that subquery (matching targetType=FileTargetType.USER_PROFILE, status=FileStatus.ATTACHED, and targetId=qUser.id.stringValue()), or alternatively enforce uniqueness at DB level by adding a unique index on (target_type, target_id, status) for ATTACHED files; ensure the change is applied within getUserWorkspaceManagerListWithCursor and keeps the existing where(cursorConditions(...)), orderBy(qUser.name.asc(), qManagerUser.id.asc()), limit(pageRequest.pageSize()) and uses pageRequest.cursor() semantics.
🤖 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/dreamteam/alter/adapter/outbound/workspace/persistence/SubstituteRequestQueryRepositoryImpl.java`:
- Around line 200-211: Extract the repeated leftJoin block that joins a profile
image file (the pattern using requesterFile/acceptedFile,
FileTargetType.USER_PROFILE, .targetId.eq(<user>.id.stringValue()), and
FileStatus.ATTACHED) into a private helper inside
SubstituteRequestQueryRepositoryImpl (e.g., addProfileImageLeftJoin or
joinProfileImageForUser). Replace each repeated block (where
requesterFile/acceptedFile are joined against requesterUser/acceptedUser via
acceptedWorker, substituteRequest, etc.) with calls to that helper, passing the
file alias (requesterFile, acceptedFile), the user alias/expression
(requesterUser, acceptedUser or acceptedWorker.user), and the target type/status
constants (FileTargetType.USER_PROFILE, FileStatus.ATTACHED) so the join logic
(targetType, targetId, status) is centralized and reused.
- Around line 200-211: The left joins on requesterFile and acceptedFile using
(FileTargetType.USER_PROFILE, targetId, FileStatus.ATTACHED) can produce
duplicate rows if multiple ATTACHED user-profile files exist; update
SubstituteRequestQueryRepositoryImpl to ensure only one file per user is joined
(either by enforcing uniqueness in the DB/domain or by changing the join to a
subquery that picks a single file per target, e.g., select the latest/first
attached profile file) — modify the leftJoin calls for requesterFile and
acceptedFile (the .leftJoin(requesterFile).on(...) and
.leftJoin(acceptedFile).on(...)) to join against a subselect that filters and
limits to one row per targetId (or add an explicit dedup predicate such as
comparing to a max(id) or createdAt) so the request/accepted user rows are not
duplicated.
In
`@src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java`:
- Around line 196-201: 반복되는 프로필 이미지 leftJoin 패턴(qFile.leftJoin 조건:
qFile.targetType.eq(FileTargetType.USER_PROFILE),
qFile.targetId.eq(qUser.id.stringValue()),
qFile.status.eq(FileStatus.ATTACHED))을 헬퍼 메서드로 추출해 재사용하세요; 예를 들어
WorkspaceQueryRepositoryImpl과 SubstitueRequestQueryRepositoryImpl에서 사용 중인 qFile,
qUser를 파라미터로 받아 JPAQuery에 동일한 leftJoin 조건을 적용하는 메서드(예: applyProfileImageLeftJoin
또는 joinUserProfileImage)를 추가하고 기존 쿼리들(문제 지적된 위치들과 동일한 패턴이 사용된 303-308, 418-423,
524-529, 586-591 등)을 해당 헬퍼 호출로 대체해 중복을 제거하세요.
---
Outside diff comments:
In
`@src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java`:
- Around line 524-536: The leftJoin of qFile in
WorkspaceQueryRepositoryImpl.getUserWorkspaceManagerListWithCursor can return
duplicate rows when a user has multiple ATTACHED USER_PROFILE files; fix by
limiting the join to at most one ATTACHED file per user: replace the direct
leftJoin(qFile) with a join to a subquery that selects a single ATTACHED file
per targetId (e.g., the latest by id or createdAt) and join on that subquery
(matching targetType=FileTargetType.USER_PROFILE, status=FileStatus.ATTACHED,
and targetId=qUser.id.stringValue()), or alternatively enforce uniqueness at DB
level by adding a unique index on (target_type, target_id, status) for ATTACHED
files; ensure the change is applied within getUserWorkspaceManagerListWithCursor
and keeps the existing where(cursorConditions(...)), orderBy(qUser.name.asc(),
qManagerUser.id.asc()), limit(pageRequest.pageSize()) and uses
pageRequest.cursor() semantics.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2a7d2ca2-1d0c-4e83-aad6-ff21f3d6bea0
📒 Files selected for processing (16)
src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/ReceivedSubstituteRequestResponseDto.javasrc/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/SubstituteRequestDetailResponseDto.javasrc/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/SubstituteRequestTargetResponseDto.javasrc/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/WorkerInfo.javasrc/main/java/com/dreamteam/alter/adapter/inbound/general/user/dto/UserWorkspaceWorkerResponseDto.javasrc/main/java/com/dreamteam/alter/adapter/inbound/manager/schedule/dto/ManagerSubstituteRequestResponseDto.javasrc/main/java/com/dreamteam/alter/adapter/inbound/manager/schedule/dto/ManagerWorkerInfo.javasrc/main/java/com/dreamteam/alter/adapter/inbound/manager/workspace/dto/WorkspaceWorkerResponseDto.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/SubstituteRequestQueryRepositoryImpl.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/ManagerSubstituteRequestListResponse.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/ReceivedSubstituteRequestListResponse.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/SentSubstituteRequestDetailResponse.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/SubstituteRequestTargetInfo.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/UserWorkspaceWorkerResponse.javasrc/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/WorkspaceWorkerResponse.java
변경사항
사용자 기본 프로필 도입
Summary by CodeRabbit