diff --git a/src/main/java/com/hyunsolution/dangu/participant/controller/ParticipantController.java b/src/main/java/com/hyunsolution/dangu/participant/controller/ParticipantController.java index c0020b0..fb3c15f 100644 --- a/src/main/java/com/hyunsolution/dangu/participant/controller/ParticipantController.java +++ b/src/main/java/com/hyunsolution/dangu/participant/controller/ParticipantController.java @@ -2,16 +2,15 @@ import com.hyunsolution.dangu.common.apiResponse.ApiResponse; import com.hyunsolution.dangu.participant.domain.ParticipantRepository; +import com.hyunsolution.dangu.participant.dto.request.UpdateParticipantMatchRequest; import com.hyunsolution.dangu.participant.dto.response.EnterChatRoomResponse; import com.hyunsolution.dangu.participant.service.ParticipantService; import com.hyunsolution.dangu.user.domain.UserRepository; import com.hyunsolution.dangu.workspace.domain.WorkspaceRepository; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RestController @@ -23,13 +22,19 @@ public class ParticipantController { private final ParticipantService participantService; // 사용자 매칭 버튼 클릭 - @PostMapping("/participant/matching/{roomNumber}") - public ApiResponse matching( + @PostMapping("/participant/matching/{chatRoomId}") + @Operation( + summary = "참가자 매칭 수락/거절", + description = + "참가자 매칭 수락/거절 한다. (isMatch가 true이면 매칭 수락)" + + "workspace의 매칭이 확정된 경우 참여자는 매칭 거절을 할 수 없다.") + public ApiResponse matching( @Parameter(hidden = true) @RequestHeader("Authorization") Long id, - @PathVariable("roomNumber") Long workspaceId) { + @PathVariable("chatRoomId") Long chatRoomId, + @RequestBody UpdateParticipantMatchRequest request) { // 매칭확인버튼 누른 사용자 매칭칼럼 상태 변경 - participantService.changeMatching(id, workspaceId); + participantService.updateMatching(id, chatRoomId, request); return ApiResponse.success(null); } diff --git a/src/main/java/com/hyunsolution/dangu/participant/domain/Participant.java b/src/main/java/com/hyunsolution/dangu/participant/domain/Participant.java index b21e3b5..0db5b58 100644 --- a/src/main/java/com/hyunsolution/dangu/participant/domain/Participant.java +++ b/src/main/java/com/hyunsolution/dangu/participant/domain/Participant.java @@ -42,7 +42,7 @@ private Participant(User user, Workspace workspace, boolean participantMatch) { this.participantMatch = participantMatch; } - public void accept() { - this.participantMatch = true; + public void updateParticipantMatch(boolean isMatch) { + this.participantMatch = isMatch; } } diff --git a/src/main/java/com/hyunsolution/dangu/participant/domain/ParticipantRepository.java b/src/main/java/com/hyunsolution/dangu/participant/domain/ParticipantRepository.java index 3f8256c..24eb28c 100644 --- a/src/main/java/com/hyunsolution/dangu/participant/domain/ParticipantRepository.java +++ b/src/main/java/com/hyunsolution/dangu/participant/domain/ParticipantRepository.java @@ -13,12 +13,14 @@ public interface ParticipantRepository extends JpaRepository List findParticipantIdByWorkspaceId(Long workspaceId); // ID별 매칭버튼 클릭 여부 - Boolean existsByIdAndParticipantMatchTrue(long id); + @Query( + "select count(p) > 0 from Participant p where p.id in :ids and p.participantMatch = true") + Boolean existsByIdAndParticipantMatchTrue(List ids); // 개인 ID 찾기 @Query( value = - "SELECT p from Participant p join p.workspace w where p.user.id =:id and p.workspace.id=:workspaceId") + "SELECT p from Participant p join fetch p.workspace w where p.user.id =:id and p.workspace.id=:workspaceId") Optional findByUserIdAndWorkspaceId( @Param("id") Long id, @Param("workspaceId") Long workspaceId); diff --git a/src/main/java/com/hyunsolution/dangu/participant/dto/request/UpdateParticipantMatchRequest.java b/src/main/java/com/hyunsolution/dangu/participant/dto/request/UpdateParticipantMatchRequest.java new file mode 100644 index 0000000..0617891 --- /dev/null +++ b/src/main/java/com/hyunsolution/dangu/participant/dto/request/UpdateParticipantMatchRequest.java @@ -0,0 +1,3 @@ +package com.hyunsolution.dangu.participant.dto.request; + +public record UpdateParticipantMatchRequest(boolean isMatch) {} diff --git a/src/main/java/com/hyunsolution/dangu/participant/exception/AlreadyMatchedException.java b/src/main/java/com/hyunsolution/dangu/participant/exception/AlreadyMatchedException.java new file mode 100644 index 0000000..ffb344c --- /dev/null +++ b/src/main/java/com/hyunsolution/dangu/participant/exception/AlreadyMatchedException.java @@ -0,0 +1,11 @@ +package com.hyunsolution.dangu.participant.exception; + +import com.hyunsolution.dangu.common.exception.CustomException; + +public class AlreadyMatchedException extends CustomException { + public static final AlreadyMatchedException EXCEPTION = new AlreadyMatchedException(); + + private AlreadyMatchedException() { + super(ParticipantError.ALREADY_MATCHED); + } +} diff --git a/src/main/java/com/hyunsolution/dangu/participant/exception/ParticipantError.java b/src/main/java/com/hyunsolution/dangu/participant/exception/ParticipantError.java index 58605a2..6509480 100644 --- a/src/main/java/com/hyunsolution/dangu/participant/exception/ParticipantError.java +++ b/src/main/java/com/hyunsolution/dangu/participant/exception/ParticipantError.java @@ -9,7 +9,9 @@ @Getter @AllArgsConstructor public enum ParticipantError implements BaseErrorCode { - PARTICIPANT_NOT_FOUND("PARTICIPANT_400_1", HttpStatus.BAD_REQUEST, "해당 채팅방 참여자를 찾을 수 없습니다."); + PARTICIPANT_NOT_FOUND("PARTICIPANT_400_1", HttpStatus.BAD_REQUEST, "해당 채팅방 참여자를 찾을 수 없습니다."), + ALREADY_MATCHED("PARTICIPANT_400_2", HttpStatus.BAD_REQUEST, "이미 매칭된 경우 수락/거절이 불가능합니다."), + ; private final String code; private final HttpStatus httpStatus; diff --git a/src/main/java/com/hyunsolution/dangu/participant/service/ParticipantService.java b/src/main/java/com/hyunsolution/dangu/participant/service/ParticipantService.java index f538d30..0227b2d 100644 --- a/src/main/java/com/hyunsolution/dangu/participant/service/ParticipantService.java +++ b/src/main/java/com/hyunsolution/dangu/participant/service/ParticipantService.java @@ -2,7 +2,9 @@ import com.hyunsolution.dangu.participant.domain.Participant; import com.hyunsolution.dangu.participant.domain.ParticipantRepository; +import com.hyunsolution.dangu.participant.dto.request.UpdateParticipantMatchRequest; import com.hyunsolution.dangu.participant.dto.response.EnterChatRoomResponse; +import com.hyunsolution.dangu.participant.exception.AlreadyMatchedException; import com.hyunsolution.dangu.participant.exception.ParticipantNotFoundException; import com.hyunsolution.dangu.user.domain.User; import com.hyunsolution.dangu.user.domain.UserRepository; @@ -22,33 +24,41 @@ public class ParticipantService { private final WorkspaceRepository workspaceRepository; @Transactional - public void changeMatching(Long id, Long workspaceId) { - // 상태 변경 - Participant participantOptional = + public void updateMatching(Long id, Long chatRoomId, UpdateParticipantMatchRequest request) { + // 1. 참가자 조회 + Participant participant = participantRepository - .findByUserIdAndWorkspaceId(id, workspaceId) + .findByUserIdAndWorkspaceId(id, chatRoomId) .orElseThrow(() -> ParticipantNotFoundException.EXCEPTION); - participantOptional.accept(); + // 2. 이미 매칭된 상태인지 확인 + if (participant.getWorkspace().isMatched()) { + throw AlreadyMatchedException.EXCEPTION; + } + + // 3. 참가자의 매칭 상태 업데이트 + participant.updateParticipantMatch(request.isMatch()); - // participant테이블에서 roomNumber로 들어온 숫자를 통해 누가 있는지 파악 + // 4. 매칭 요청 처리 + if (request.isMatch() && allParticipantsMatched(chatRoomId)) { + finalizeWorkspaceMatching(chatRoomId); + } + } + + // 모든 참가자가 매칭되었는지 확인 + private boolean allParticipantsMatched(Long workspaceId) { List participantIds = participantRepository.findParticipantIdByWorkspaceId(workspaceId); + return participantRepository.existsByIdAndParticipantMatchTrue(participantIds); + } - // 방안에 모든 참가자가 "확정"버튼을 눌렀는지 확인 - for (Long participant : participantIds) { - boolean mathingCheck = - participantRepository.existsByIdAndParticipantMatchTrue(participant); - if (!mathingCheck) { - return; - } - } - // 게임방 테이블 속 매칭 결과를 true로 바꿈 - Workspace workspace1 = + // 워크스페이스의 매칭을 최종 확정 + private void finalizeWorkspaceMatching(Long workspaceId) { + Workspace workspace = workspaceRepository .findById(workspaceId) .orElseThrow(() -> WorkspaceNotFoundException.EXCEPTION); - workspace1.acceptFinal(); + workspace.acceptFinal(); } // 채팅방 입장 메시지 전송 diff --git a/src/main/java/com/hyunsolution/dangu/workspace/domain/WorkspaceRepository.java b/src/main/java/com/hyunsolution/dangu/workspace/domain/WorkspaceRepository.java index bbc1533..0b00786 100644 --- a/src/main/java/com/hyunsolution/dangu/workspace/domain/WorkspaceRepository.java +++ b/src/main/java/com/hyunsolution/dangu/workspace/domain/WorkspaceRepository.java @@ -8,6 +8,6 @@ public interface WorkspaceRepository extends JpaRepository { @EntityGraph(attributePaths = {"participants"}) @Query( - "select w from Workspace w where exists (select 1 from Participant p where p.workspace = w and p.user.id = :userId) and w.chatUpdateAt is not null") + "select w from Workspace w where exists (select 1 from Participant p where p.workspace = w and p.user.id = :userId)") List findByParticipantUserId(Long userId); }