Skip to content

[feat] 매칭 요청 거절 api V3 마이그레이션#248

Open
hyeeum wants to merge 5 commits intodevfrom
feat/#247-reject-request-v3-migration
Open

[feat] 매칭 요청 거절 api V3 마이그레이션#248
hyeeum wants to merge 5 commits intodevfrom
feat/#247-reject-request-v3-migration

Conversation

@hyeeum
Copy link
Collaborator

@hyeeum hyeeum commented Mar 19, 2026

📌 이슈 번호


closed #247


✅ 어떻게 이슈를 해결했나요?


  • 거절 api 로직은 단순합니다!
  • 요청자: 상태 업데이트(승인 대기 -> 매칭 실패)
  • 생성자 상태 업데이트(새 요청 -> 요청 대기) + 알림 읽음 처리

❤️ To 다진 / To 헤음


  • 매칭 생성 api 가 머지되야 작업이 가능하긴한데, 그냥 공통 함수 복붙해왔십니다.. 대부분 동일..

Summary by CodeRabbit

릴리스 노트

  • New Features
    • 매칭 요청 거절 기능 추가: 그룹 리더가 받은 매칭 요청을 거절할 수 있는 새로운 API 엔드포인트 추가
    • 거절 시 요청자의 상태가 자동으로 업데이트되고 관련 알림이 처리됨

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Warning

Rate limit exceeded

@hyeeum has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 96588901-4880-4177-9903-e2f144e2b50a

📥 Commits

Reviewing files that changed from the base of the PR and between bba7f07 and a24e162.

📒 Files selected for processing (3)
  • src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java
  • src/main/java/at/mateball/domain/groupRequest/GroupRequestService.java
  • src/main/java/at/mateball/domain/groupmember/core/service/GroupMemberV3Service.java

Walkthrough

매칭 요청 거절 기능을 위한 API 엔드포인트를 추가하고, 그룹 리더의 거절 요청을 처리하는 서비스 로직을 구현했습니다. 거절 시 요청자와 리더의 상태를 업데이트하고 알림을 트리거합니다.

Changes

Cohort / File(s) Summary
Controller - Match Rejection Endpoint
src/main/java/at/mateball/domain/group/api/controller/GroupV3Controller.java
PATCH /match-reject/{matchId} 엔드포인트 추가. 인증된 사용자로부터 userId 추출 후 서비스의 rejectRequest() 호출하여 요청 거절 처리.
Service - Rejection Logic & Validation
src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java
공개 메서드 rejectRequest(userId, matchId) 추가로 리더십 검증, 매칭 요청 조회, 양쪽 멤버 상태 업데이트(PENDING_REQUEST, MATCH_FAILED) 및 알림 제거 처리. 헬퍼 메서드 getValidatedGroup(), updateLeaderStatusPending(), updateMemberStatusFailed() 추가.

Sequence Diagram

sequenceDiagram
    actor Client
    participant GroupV3Controller
    participant GroupV3Service
    participant GroupValidator
    participant GroupMemberRepository
    participant AlarmService
    participant Database

    Client->>GroupV3Controller: PATCH /match-reject/{matchId}
    GroupV3Controller->>GroupV3Service: rejectRequest(userId, matchId)
    GroupV3Service->>GroupMemberRepository: getMatchSummary(matchId)
    GroupMemberRepository->>Database: 쿼리 실행
    Database-->>GroupMemberRepository: 매칭 요청 정보
    GroupMemberRepository-->>GroupV3Service: requesterId 반환
    
    GroupV3Service->>GroupValidator: 그룹 리더 검증
    GroupValidator->>Database: 그룹 정보 조회
    Database-->>GroupValidator: 그룹 데이터
    GroupValidator-->>GroupV3Service: 검증 완료
    
    GroupV3Service->>GroupMemberRepository: updateLeaderStatusPending(userId, groupId)
    GroupMemberRepository->>Database: 리더 상태 PENDING_REQUEST로 업데이트
    
    GroupV3Service->>GroupMemberRepository: updateMemberStatusFailed(requesterId, groupId)
    GroupMemberRepository->>Database: 요청자 상태 MATCH_FAILED로 업데이트
    
    GroupV3Service->>AlarmService: readAllAlarms(userId)
    AlarmService->>Database: 알림 처리
    
    GroupV3Service-->>GroupV3Controller: 완료
    GroupV3Controller-->>Client: 200 OK (successWithNoData)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • YangDaJin0104
🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 'V3 마이그레이션' 기능을 명확하게 설명하며, 변경사항과 완전히 일치합니다.
Linked Issues check ✅ Passed PR은 연결된 이슈 #247의 '매칭 요청 거절 API V3 마이그레이션' 목표를 충족하며, 관련 엔드포인트 및 상태 변경 로직을 구현했습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항은 매칭 요청 거절 API V3 마이그레이션 범위 내에 있으며, 불필요한 외부 변경은 없습니다.

✏️ 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/#247-reject-request-v3-migration

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.

Copy link

@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.

🧹 Nitpick comments (4)
src/main/java/at/mateball/exception/code/BusinessErrorCode.java (1)

68-68: 에러 코드가 잘못된 섹션에 위치해 있습니다.

REQUEST_NOT_FOUNDHttpStatus.NOT_FOUND (404)를 사용하지만, 현재 "409 CONFLICT" 주석 섹션 아래에 배치되어 있습니다. 코드 가독성을 위해 "404 NOT FOUND" 섹션(Lines 51-60)으로 이동하세요.

🔧 에러 코드 위치 수정
     // 404 NOT FOUND
     TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, "요청에 해당하는 토큰이 존재하지 않습니다."),
     USER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 사용자입니다."),
     GROUP_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 매칭입니다."),
     REQUESTER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 요청자입니다."),
     GAME_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 경기입니다."),
     MATCH_REQUIREMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "매칭 조건 정보가 존재하지 않습니다."),
     CHATTING_NOT_FOUND(HttpStatus.NOT_FOUND, "오픈채팅이 존재하지 않습니다."),
     ALARM_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 알림입니다."),
     NO_GAME_SCHEDULED(HttpStatus.NOT_FOUND, "선택한 날짜에 경기가 존재하지 않습니다."),
+    REQUEST_NOT_FOUND(HttpStatus.NOT_FOUND, "요청 정보를 찾을 수 없습니다."),

     // 409 CONFLICT
     DUPLICATED_NICKNAME(HttpStatus.CONFLICT, "중복된 닉네임입니다."),
     ...
     DUPLICATED_MATCH_REQUIREMENT(HttpStatus.CONFLICT, "이미 매칭 조건이 존재합니다."),
-    REQUEST_NOT_FOUND(HttpStatus.NOT_FOUND, "요청 정보를 찾을 수 없습니다."),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/at/mateball/exception/code/BusinessErrorCode.java` at line 68,
The enum constant REQUEST_NOT_FOUND in BusinessErrorCode is placed under the 409
CONFLICT section but uses HttpStatus.NOT_FOUND; move the REQUEST_NOT_FOUND entry
into the 404 NOT FOUND section (the block that contains other NOT_FOUND codes)
so it sits with other HttpStatus.NOT_FOUND entries; ensure the enum
comma/semicolon formatting remains correct after relocating the
REQUEST_NOT_FOUND constant.
src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryCustom.java (1)

87-87: updateMemberStatus와 중복되는 메서드입니다.

Line 47에 이미 동일한 시그니처를 가진 updateMemberStatus(Long userId, Long groupId, int status) 메서드가 존재합니다. 새로운 updateStatus 메서드를 추가하는 대신 기존 메서드를 재사용하는 것이 좋습니다.

♻️ 기존 메서드 재사용 제안
-    void updateStatus(Long userId, Long groupId, int status);

서비스에서 groupMemberRepository.updateMemberStatus(...) 를 직접 호출하세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryCustom.java`
at line 87, The new method updateStatus(Long userId, Long groupId, int status)
is a duplicate of the existing updateMemberStatus(Long userId, Long groupId, int
status); remove the redundant updateStatus declaration from
GroupMemberRepositoryCustom and update any callers to use
updateMemberStatus(...) instead so the repository exposes only the single
updateMemberStatus method; verify compile and run tests to ensure no remaining
references to updateStatus.
src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryImpl.java (1)

867-873: 기존 updateMemberStatus 메서드와 중복됩니다.

Lines 424-429의 updateMemberStatus 메서드와 동일한 구현입니다. 중복 코드를 제거하고 기존 메서드를 재사용하세요.

♻️ 중복 메서드 제거 제안
-    `@Override`
-    public void updateStatus(Long userId, Long groupId, int status) {
-        queryFactory.update(groupMember)
-                .set(groupMember.status, status)
-                .where(groupMember.user.id.eq(userId), groupMember.group.id.eq(groupId))
-                .execute();
-    }

인터페이스에서도 updateStatus 선언을 제거하고, 서비스에서 updateMemberStatus를 직접 사용하세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryImpl.java`
around lines 867 - 873, The updateStatus method duplicates existing logic in
updateMemberStatus; remove the redundant updateStatus implementation from
GroupMemberRepositoryImpl and delete its declaration from the repository
interface, then refactor callers to use updateMemberStatus(Long userId, Long
groupId, int status) instead (locate methods by the names updateStatus and
updateMemberStatus to update references).
src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java (1)

330-332: 메서드 호출 불일치 - 중복 메서드 사용 중입니다.

updateLeaderStatusPending (Line 312)은 groupMemberRepository.updateMemberStatus를 호출하고, updateMemberStatusFailedgroupMemberRepository.updateStatus를 호출합니다. 앞서 지적한 대로 updateStatusupdateMemberStatus와 동일한 중복 메서드입니다.

일관성을 위해 모두 updateMemberStatus를 사용하세요.

♻️ 일관된 메서드 사용
 private void updateMemberStatusFailed(Long userId, Long groupId) {
-    groupMemberRepository.updateStatus(userId, groupId, GroupMemberStatus.MATCH_FAILED.getValue());
+    groupMemberRepository.updateMemberStatus(userId, groupId, GroupMemberStatus.MATCH_FAILED.getValue());
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java`
around lines 330 - 332, The method updateMemberStatusFailed currently calls
groupMemberRepository.updateStatus (a duplicate of updateMemberStatus); replace
that call so updateMemberStatusFailed uses
groupMemberRepository.updateMemberStatus(...) instead to match
updateLeaderStatusPending and maintain consistent repository method usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java`:
- Around line 330-332: The method updateMemberStatusFailed currently calls
groupMemberRepository.updateStatus (a duplicate of updateMemberStatus); replace
that call so updateMemberStatusFailed uses
groupMemberRepository.updateMemberStatus(...) instead to match
updateLeaderStatusPending and maintain consistent repository method usage.

In
`@src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryCustom.java`:
- Line 87: The new method updateStatus(Long userId, Long groupId, int status) is
a duplicate of the existing updateMemberStatus(Long userId, Long groupId, int
status); remove the redundant updateStatus declaration from
GroupMemberRepositoryCustom and update any callers to use
updateMemberStatus(...) instead so the repository exposes only the single
updateMemberStatus method; verify compile and run tests to ensure no remaining
references to updateStatus.

In
`@src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryImpl.java`:
- Around line 867-873: The updateStatus method duplicates existing logic in
updateMemberStatus; remove the redundant updateStatus implementation from
GroupMemberRepositoryImpl and delete its declaration from the repository
interface, then refactor callers to use updateMemberStatus(Long userId, Long
groupId, int status) instead (locate methods by the names updateStatus and
updateMemberStatus to update references).

In `@src/main/java/at/mateball/exception/code/BusinessErrorCode.java`:
- Line 68: The enum constant REQUEST_NOT_FOUND in BusinessErrorCode is placed
under the 409 CONFLICT section but uses HttpStatus.NOT_FOUND; move the
REQUEST_NOT_FOUND entry into the 404 NOT FOUND section (the block that contains
other NOT_FOUND codes) so it sits with other HttpStatus.NOT_FOUND entries;
ensure the enum comma/semicolon formatting remains correct after relocating the
REQUEST_NOT_FOUND constant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 904fd88c-ac63-43b5-91e2-e6c55402967e

📥 Commits

Reviewing files that changed from the base of the PR and between 78d5851 and 6c96de1.

📒 Files selected for processing (6)
  • src/main/java/at/mateball/domain/group/api/controller/GroupV3Controller.java
  • src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java
  • src/main/java/at/mateball/domain/groupmember/api/dto/GroupMatchSummaryRes.java
  • src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryCustom.java
  • src/main/java/at/mateball/domain/groupmember/core/repository/querydsl/GroupMemberRepositoryImpl.java
  • src/main/java/at/mateball/exception/code/BusinessErrorCode.java

@hyeeum hyeeum force-pushed the feat/#247-reject-request-v3-migration branch from 57a0c8b to bba7f07 Compare March 22, 2026 18:00
Copy link

@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.

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/at/mateball/domain/group/core/service/GroupV3Service.java (1)

47-55: ⚠️ Potential issue | 🔴 Critical

컴파일 오류: 누락된 필드 선언 및 import

이 코드에는 두 가지 컴파일 오류가 있습니다:

  1. alarmService 필드 누락: Line 370에서 alarmService.readAllAlarms(userId)를 호출하지만, 클래스에 AlarmService 필드가 선언되어 있지 않습니다.

  2. Optional import 누락: Line 364에서 Optional.ofNullable()을 사용하지만, java.util.Optional이 import되어 있지 않습니다.

🐛 필드 및 import 추가 제안
 import java.time.LocalDate;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
     private final GroupRepository groupRepository;
     private final GroupRequestService groupRequestService;
     private final GroupMemberRepository groupMemberRepository;
     private final GroupV3RepositoryCustom groupV3RepositoryCustom;
     private final GroupMatchAggregator groupMatchAggregator;
     private final MatchImageAssembler matchImageAssembler;
     private final MatchingScoreCalculator matchingScoreCalculator;
     private final FileStorage fileStorage;
     private final GroupExecutorV3 groupExecutor;
+    private final AlarmService alarmService;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java`
around lines 47 - 55, Add a missing AlarmService field to GroupV3Service and
import java.util.Optional: declare a final AlarmService alarmService and have it
injected/initialized alongside the other dependencies in the GroupV3Service
constructor so calls like alarmService.readAllAlarms(userId) compile, and add
the import statement for Optional (java.util.Optional) so
Optional.ofNullable(...) resolves.
🧹 Nitpick comments (1)
src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java (1)

341-352: 미사용 반환값: getValidatedGroup

getValidatedGroup 메서드가 Group 객체를 반환하지만, rejectRequest의 호출부(Line 360)에서 반환값을 사용하지 않습니다. 반환값이 필요 없다면 void로 변경하는 것이 명확합니다.

♻️ void 반환 타입으로 변경 제안
-    private Group getValidatedGroup(Long userId, Long groupId) {
+    private void validateGroupLeader(Long userId, Long groupId) {
         Group group = groupRepository.findById(groupId)
                 .orElseThrow(() -> new BusinessException(BusinessErrorCode.GROUP_NOT_FOUND));
 
         GroupValidator.validate(group);
 
         if (!group.getLeader().getId().equals(userId)) {
             throw new BusinessException(BusinessErrorCode.NOT_MATCH_LEADER);
         }
-
-        return group;
     }

호출부도 함께 수정:

-        getValidatedGroup(userId, matchId);
+        validateGroupLeader(userId, matchId);

Also applies to: 360-360

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java`
around lines 341 - 352, The method getValidatedGroup in GroupV3Service returns a
Group but its return value is unused by callers like rejectRequest; change
getValidatedGroup to return void (remove the Group return and return statement)
and keep its validation and leader-check logic, then update its callers (e.g.,
rejectRequest) to call getValidatedGroup(...) without expecting a return value
or assignment; search for any other usages of getValidatedGroup and update their
call sites accordingly, and adjust the method signature and any
references/imports or tests that expect a Group from getValidatedGroup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java`:
- Around line 47-55: Add a missing AlarmService field to GroupV3Service and
import java.util.Optional: declare a final AlarmService alarmService and have it
injected/initialized alongside the other dependencies in the GroupV3Service
constructor so calls like alarmService.readAllAlarms(userId) compile, and add
the import statement for Optional (java.util.Optional) so
Optional.ofNullable(...) resolves.

---

Nitpick comments:
In `@src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java`:
- Around line 341-352: The method getValidatedGroup in GroupV3Service returns a
Group but its return value is unused by callers like rejectRequest; change
getValidatedGroup to return void (remove the Group return and return statement)
and keep its validation and leader-check logic, then update its callers (e.g.,
rejectRequest) to call getValidatedGroup(...) without expecting a return value
or assignment; search for any other usages of getValidatedGroup and update their
call sites accordingly, and adjust the method signature and any
references/imports or tests that expect a Group from getValidatedGroup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a6099de0-a0b7-4a4f-a872-e17e848367c2

📥 Commits

Reviewing files that changed from the base of the PR and between 6c96de1 and bba7f07.

📒 Files selected for processing (2)
  • src/main/java/at/mateball/domain/group/api/controller/GroupV3Controller.java
  • src/main/java/at/mateball/domain/group/core/service/GroupV3Service.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/at/mateball/domain/group/api/controller/GroupV3Controller.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 매칭 요청 거절 api v3 마이그레이션

1 participant