Skip to content

Commit

Permalink
Merge pull request #117 from cussle/weekly/11
Browse files Browse the repository at this point in the history
채팅방 생성 로직 적용
  • Loading branch information
cussle authored Nov 15, 2024
2 parents b7ac434 + 9455e89 commit 7a6a553
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
"/notice",
"/notice/**",
"/qna",
"/qna/**",
"/api/**" // 테스트용 임시
"/qna/**"
).permitAll();
// 그 외의 모든 요청은 인증 필요
auth.anyRequest().authenticated();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@

import com.devcard.devcard.auth.entity.Member;
import com.devcard.devcard.card.entity.Group;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface GroupRepository extends JpaRepository<Group, Long> {

public interface GroupRepository extends JpaRepository<Group, Long>{
List<Group> findByMember(Member member);

Optional<Group> findByIdAndMember(Long id, Member member);

@Query(
"SELECT CASE WHEN COUNT(g) > 0 THEN true ELSE false END " +
"FROM Group g " +
"JOIN g.cards c " +
"WHERE g.member = :member AND c.member.id = :cardOwnerId"
)
boolean existsByMemberAndCards_Id(@Param("member") Member member, @Param("cardOwnerId") Long cardOwnerId);
}
35 changes: 27 additions & 8 deletions src/main/java/com/devcard/devcard/card/service/GroupService.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,36 @@ public List<GroupResponseDto> getGroupsByMember(Member member) {

@Transactional
public void addCardToGroup(Long groupId, Long cardId, Member member) {
// 현재 사용자의 그룹 조회
Group group = groupRepository.findByIdAndMember(groupId, member)
.orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다."));

// 추가하려는 명함(Card) 조회
Card card = cardRepository.findById(cardId)
.orElseThrow(() -> new IllegalArgumentException("해당 ID의 명함이 존재하지 않습니다."));

// 그룹에 이미 해당 카드가 포함되어 있는지 확인
if (group.getCards().contains(card)) {
throw new IllegalArgumentException("이미 해당 그룹에 추가되어 있는 명함입니다.");
}

// 채팅방 생성
logger.debug(
"Chat room participants: Member ID = " + member.getId() + ", Card Owner ID = " + card.getMember().getId());
CreateRoomRequest createRoomRequest = new CreateRoomRequest(Arrays.asList(
member.getId(),
card.getMember().getId()
));
chatRoomService.createChatRoom(createRoomRequest);
// 상대방의 그룹에서 현재 사용자의 Card를 포함하는 그룹이 있는지 확인
boolean isMutuallyAdded = groupRepository.existsByMemberAndCards_Id(card.getMember(), member.getId());

// 양쪽 모두 추가된 경우에만 채팅방 생성
if (isMutuallyAdded) {
logger.debug(
"Chat room participants: Member ID = " + member.getId() + ", Card Owner ID = " + card.getMember().getId());
CreateRoomRequest createRoomRequest = new CreateRoomRequest(Arrays.asList(
member.getId(),
card.getMember().getId()
));
chatRoomService.createChatRoom(createRoomRequest);
} else {
logger.debug("Chat room not created: Mutual addition not satisfied.");
}

// 카드 추가
group.addCard(card);
groupRepository.save(group);
}
Expand Down Expand Up @@ -113,6 +124,14 @@ public void deleteGroup(Long groupId, Member member) {
Group group = groupRepository.findByIdAndMember(groupId, member)
.orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다."));

// 그룹에 포함된 모든 카드의 채팅방 삭제
for (Card card : group.getCards()) {
chatRoomService.deleteChatRoomByParticipants(Arrays.asList(
member.getId(),
card.getMember().getId()
));
}

groupRepository.delete(group); // 그룹 삭제
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.devcard.devcard.chat.repository;

import com.devcard.devcard.chat.model.ChatRoom;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -13,5 +12,19 @@ public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long> {
@Query("SELECT cr FROM ChatRoom cr JOIN cr.participants p WHERE p.id = :userId")
List<ChatRoom> findByParticipantId(@Param("userId") String userId);

Optional<ChatRoom> findByParticipants_IdIn(Collection<Long> participantsId);
@Query(
"SELECT cr FROM ChatRoom cr " +
"WHERE SIZE(cr.participants) = :size " +
"AND cr.id IN (" +
" SELECT cr2.id FROM ChatRoom cr2 " +
" JOIN cr2.participants p " +
" WHERE p.id IN :participantsId " +
" GROUP BY cr2.id " +
" HAVING COUNT(p.id) = :size" +
")"
)
Optional<ChatRoom> findByExactParticipants(
@Param("participantsId") List<Long> participantsId,
@Param("size") int size
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.devcard.devcard.chat.util.Constants.CHAT_ROOM_NOT_FOUND;
import static com.devcard.devcard.chat.util.Constants.CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS;
import static com.devcard.devcard.chat.util.Constants.DUPLICATE_CHAT_ROOM_ERROR;

import com.devcard.devcard.auth.entity.Member;
import com.devcard.devcard.auth.repository.MemberRepository;
Expand Down Expand Up @@ -49,11 +50,22 @@ public ChatRoomService(
* @return 생성된 채팅방 정보
*/
public CreateRoomResponse createChatRoom(CreateRoomRequest createRoomRequest) {
// jpa를 이용해 ChatUser 리스트 가져오기
// 참여자 ID를 기반으로 Member 리스트 가져오기
List<Member> participants = memberRepository.findByIdIn(createRoomRequest.getParticipantsId());
ChatRoom chatRoom = new ChatRoom(participants, LocalDateTime.now()); // chatRoom생성
chatRoomRepository.save(chatRoom); // db에 저장
return makeCreateChatRoomResponse(chatRoom); // Response로 변환
int participantSize = participants.size();

// 동일한 참여자 구성의 채팅방이 있는지 확인
chatRoomRepository.findByExactParticipants(createRoomRequest.getParticipantsId(), participantSize)
.ifPresent(existingRoom -> {
throw new IllegalArgumentException(DUPLICATE_CHAT_ROOM_ERROR);
});

// 새로운 채팅방 생성
ChatRoom chatRoom = new ChatRoom(participants, LocalDateTime.now());
chatRoomRepository.save(chatRoom); // DB에 저장

// Response 변환 및 반환
return makeCreateChatRoomResponse(chatRoom);
}


Expand Down Expand Up @@ -145,8 +157,11 @@ public void deleteChatRoom(String chatId) {
* @param participantsId 채팅방에 참여하는 모든 유저의 ID List
*/
public void deleteChatRoomByParticipants(List<Long> participantsId) {
// 참여자 ID 목록으로 채팅방 조회
ChatRoom chatRoom = chatRoomRepository.findByParticipants_IdIn(participantsId)
// 참여자 수 계산
int size = participantsId.size();

// 정확히 일치하는 채팅방 조회
ChatRoom chatRoom = chatRoomRepository.findByExactParticipants(participantsId, size)
.orElseThrow(() -> new ChatRoomNotFoundException(
CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS + participantsId.toString()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private Long extractParamFromUri(String uri, String paramName) {

/**
* ID를 통해 유저의 프로필을 반환
* @param userId 유저의 ID
* @param userId 유저의 ID
* @return 해당 유저의 name과 이미지 반환
*/
public ChatUserResponse getUserProfileById(String userId) {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/devcard/devcard/chat/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class Constants {
public static final String CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS = "해당 참여자 ID 목록으로 채팅방을 찾을 수 없습니다. 참여자 ID 목록: ";
public static final String USER_NOT_IN_CHAT_ROOM = "사용자가 해당 채팅방의 참여자가 아닙니다.";
public static final String EMPTY_MESSAGE = "메시지가 비어 있습니다.";
public static final String DUPLICATE_CHAT_ROOM_ERROR = "이미 동일한 참여자로 구성된 채팅방이 존재합니다.";

// 멤버 상수
public static final String MEMBER_NOT_FOUND = "멤버를 다음의 id로 찾을 수 없습니다. id: ";
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/static/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ $(document).ready(function () {

if (path === '/home') {
$(".nav-item[data-page='home']").addClass("active"); // MyCard에 active 클래스 추가
} else if (path === '/wallet-list') {
} else if (path === '/wallet-list' || path.startsWith('/groups')) {
$(".nav-item[data-page='wallet']").addClass("active"); // Wallet에 active 클래스 추가
} else if (path === '/chats') {
$(".nav-item[data-page='chats']").addClass("active"); // Chats에 active 클래스 추가
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/templates/wallet-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wallet List</title>

<!-- CSS -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&icon_names=arrow_back_ios,send" />
<link rel="stylesheet" th:href="@{/css/global.css}">
<link rel="stylesheet" th:href="@{/css/card/wallet-list.css}">

Expand All @@ -16,6 +19,7 @@
<div class="container">
<!-- 상단 헤더 -->
<div class="header">
<span class="material-symbols-outlined" id="backButton" onclick="location.href='/wallet-list'">arrow_back_ios</span>
<h2 class="title">Wallet</h2>
</div>

Expand Down

0 comments on commit 7a6a553

Please sign in to comment.