Skip to content

Commit 37dbf0b

Browse files
authored
Merge pull request #87 from DorumDorum/fix/#86/그룹-채팅-멤버-퇴장추방-시-미읽음-카운트-집계-오류
[FIX] 그룹 채팅 퇴장/강퇴 unread 집계 보정 및 테스트 안정화
2 parents 3287ce8 + 86869e7 commit 37dbf0b

File tree

17 files changed

+311
-18
lines changed

17 files changed

+311
-18
lines changed

.github/workflows/cicd.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ jobs:
3333
- name: Setup Gradle cache
3434
uses: gradle/actions/setup-gradle@v4
3535

36+
- name: Ensure Docker is available (Testcontainers)
37+
run: |
38+
echo ">>> [CI] Checking Docker daemon..."
39+
docker info
40+
3641
- name: Run tests
3742
run: |
3843
echo ">>> [CI] Running tests..."

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,7 @@ pinpoint-agent/tools/
5252
.claude
5353

5454
### env ###
55-
.env
55+
.env
56+
57+
# macOS artefacts
58+
.DS_Store

src/main/java/com/project/dorumdorum/domain/chat/application/dto/response/ChatMessageResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ public record ChatMessageResponse(
99
String senderNickname,
1010
String content,
1111
String messageType,
12-
LocalDateTime sentAt
12+
LocalDateTime sentAt,
13+
int unreadCount
1314
) {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.project.dorumdorum.domain.chat.application.dto.response;
2+
3+
import java.time.LocalDateTime;
4+
5+
public record ChatReadReceiptResponse(
6+
String chatRoomNo,
7+
String readerUserNo,
8+
LocalDateTime readAt
9+
) {}

src/main/java/com/project/dorumdorum/domain/chat/application/event/RoommateKickedEventListener.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.project.dorumdorum.domain.chat.application.dto.response.ChatMessageResponse;
44
import com.project.dorumdorum.domain.chat.domain.entity.ChatMessage;
55
import com.project.dorumdorum.domain.chat.domain.entity.ChatRoom;
6+
import com.project.dorumdorum.domain.chat.domain.entity.ChatRoomMember;
67
import com.project.dorumdorum.domain.chat.domain.entity.MessageType;
78
import com.project.dorumdorum.domain.chat.domain.service.ChatMessageService;
89
import com.project.dorumdorum.domain.chat.domain.service.ChatRoomMemberService;
@@ -17,6 +18,8 @@
1718
import org.springframework.transaction.event.TransactionPhase;
1819
import org.springframework.transaction.event.TransactionalEventListener;
1920

21+
import java.time.LocalDateTime;
22+
2023
@Slf4j
2124
@Component
2225
@RequiredArgsConstructor
@@ -40,17 +43,20 @@ public class RoommateKickedEventListener {
4043
public void handle(RoommateKickedEvent event) {
4144
chatRoomService.findByRoomNo(event.roomNo()).ifPresent(chatRoom -> {
4245
if (chatRoomMemberService.isMember(chatRoom, event.kickedUserNo())) {
43-
chatRoomMemberService.leave(
44-
chatRoomMemberService.findByChatRoomAndUserNo(chatRoom, event.kickedUserNo())
45-
);
46+
ChatRoomMember member = chatRoomMemberService.findByChatRoomAndUserNo(chatRoom, event.kickedUserNo());
47+
LocalDateTime fromTime = member.getLastReadAt() != null
48+
? member.getLastReadAt()
49+
: member.getJoinedAt();
50+
chatMessageService.decreaseUnreadCount(chatRoom.getChatRoomNo(), fromTime, event.kickedUserNo());
51+
chatRoomMemberService.leave(member);
4652
User kicked = userService.findById(event.kickedUserNo());
4753
String displayName = (kicked.getNickname() != null && !kicked.getNickname().isBlank())
4854
? kicked.getNickname() : kicked.getName();
4955
String content = displayName + "가 퇴장했습니다.";
5056
ChatMessage message = chatMessageService.save(chatRoom, "SYSTEM", content, MessageType.SYSTEM, 0);
5157
ChatMessageResponse response = new ChatMessageResponse(
5258
message.getMessageNo(), chatRoom.getChatRoomNo(),
53-
"SYSTEM", null, content, MessageType.SYSTEM.name(), message.getCreatedAt());
59+
"SYSTEM", null, content, MessageType.SYSTEM.name(), message.getCreatedAt(), message.getUnreadCount());
5460
broadcastSafely(chatRoom, response);
5561
}
5662
});

src/main/java/com/project/dorumdorum/domain/chat/application/usecase/JoinChatRoomUseCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public void handle(RoommateAcceptedEvent event) {
6868
ChatMessage message = chatMessageService.save(chatRoom, "SYSTEM", content, MessageType.SYSTEM, 0);
6969
ChatMessageResponse response = new ChatMessageResponse(
7070
message.getMessageNo(), chatRoom.getChatRoomNo(),
71-
"SYSTEM", null, content, MessageType.SYSTEM.name(), message.getCreatedAt());
71+
"SYSTEM", null, content, MessageType.SYSTEM.name(), message.getCreatedAt(), message.getUnreadCount());
7272
broadcastSafely(chatRoom, response);
7373
}
7474
}

src/main/java/com/project/dorumdorum/domain/chat/application/usecase/LeaveChatRoomUseCase.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.springframework.stereotype.Service;
2121
import org.springframework.transaction.annotation.Transactional;
2222

23+
import java.time.LocalDateTime;
24+
2325
import static com.project.dorumdorum.global.exception.code.status.ChatErrorStatus.HOST_CANNOT_LEAVE;
2426

2527
@Service
@@ -61,6 +63,13 @@ private void leaveGroupChatRoom(ChatRoom chatRoom, ChatRoomMember member, String
6163
throw new RestApiException(HOST_CANNOT_LEAVE);
6264
}
6365

66+
if (memberCount > 1) {
67+
LocalDateTime fromTime = member.getLastReadAt() != null
68+
? member.getLastReadAt()
69+
: member.getJoinedAt();
70+
chatMessageService.decreaseUnreadCount(chatRoom.getChatRoomNo(), fromTime, userNo);
71+
}
72+
6473
chatRoomMemberService.leave(member);
6574
roommateService.leaveRoom(userNo, chatRoom.getRoomNo());
6675
room.minusCurrentMate();
@@ -79,6 +88,13 @@ private void leaveDirectChatRoom(ChatRoom chatRoom, ChatRoomMember member, Strin
7988
throw new RestApiException(HOST_CANNOT_LEAVE);
8089
}
8190

91+
if (memberCount > 1) {
92+
LocalDateTime fromTime = member.getLastReadAt() != null
93+
? member.getLastReadAt()
94+
: member.getJoinedAt();
95+
chatMessageService.decreaseUnreadCount(chatRoom.getChatRoomNo(), fromTime, userNo);
96+
}
97+
8298
chatRoomMemberService.leave(member);
8399

84100
if (memberCount == 1) {
@@ -99,7 +115,7 @@ private void sendLeaveSystemMessage(ChatRoom chatRoom, String userNo) {
99115
ChatMessage message = chatMessageService.save(chatRoom, "SYSTEM", content, MessageType.SYSTEM, 0);
100116
ChatMessageResponse response = new ChatMessageResponse(
101117
message.getMessageNo(), chatRoomNo,
102-
"SYSTEM", null, content, MessageType.SYSTEM.name(), message.getCreatedAt());
118+
"SYSTEM", null, content, MessageType.SYSTEM.name(), message.getCreatedAt(), message.getUnreadCount());
103119
messagingTemplate.convertAndSend("/topic/chat-room/" + chatRoomNo, response);
104120
}
105121
}

src/main/java/com/project/dorumdorum/domain/chat/application/usecase/MarkChatRoomReadUseCase.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.project.dorumdorum.domain.chat.application.usecase;
22

3+
import com.project.dorumdorum.domain.chat.application.dto.response.ChatReadReceiptResponse;
34
import com.project.dorumdorum.domain.chat.domain.entity.ChatRoomMember;
45
import com.project.dorumdorum.domain.chat.domain.service.ChatMessageService;
56
import com.project.dorumdorum.domain.chat.domain.service.ChatRoomMemberService;
67
import lombok.RequiredArgsConstructor;
78
import org.springframework.stereotype.Service;
9+
import org.springframework.messaging.simp.SimpMessagingTemplate;
810
import org.springframework.transaction.annotation.Transactional;
911

1012
import java.time.LocalDateTime;
@@ -15,6 +17,7 @@ public class MarkChatRoomReadUseCase {
1517

1618
private final ChatRoomMemberService chatRoomMemberService;
1719
private final ChatMessageService chatMessageService;
20+
private final SimpMessagingTemplate messagingTemplate;
1821

1922
/**
2023
* 채팅방 읽음 처리
@@ -31,6 +34,12 @@ public void execute(String chatRoomNo, String userNo) {
3134
: member.getJoinedAt();
3235

3336
chatMessageService.decreaseUnreadCount(chatRoomNo, fromTime, userNo);
34-
chatRoomMemberService.updateLastReadAt(member, LocalDateTime.now());
37+
LocalDateTime readAt = LocalDateTime.now();
38+
chatRoomMemberService.updateLastReadAt(member, readAt);
39+
40+
messagingTemplate.convertAndSend(
41+
"/topic/chat-room/" + chatRoomNo + "/read",
42+
new ChatReadReceiptResponse(chatRoomNo, userNo, readAt)
43+
);
3544
}
3645
}

src/main/java/com/project/dorumdorum/domain/chat/application/usecase/SendGroupChatMessageUseCase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public void send(String chatRoomNo, String senderNo, String content) {
7171
senderNickname,
7272
content,
7373
MessageType.TEXT.name(),
74-
message.getCreatedAt()
74+
message.getCreatedAt(),
75+
message.getUnreadCount()
7576
);
7677
messagingTemplate.convertAndSend("/topic/chat-room/" + chatRoomNo, response);
7778

src/main/java/com/project/dorumdorum/domain/roommate/domain/service/RoommateService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public void leaveRoom(String userNo, String roomNo) {
6767
Roommate roommate = roommateRepository.findByUserNoAndRoomNo(userNo, roomNo)
6868
.orElseThrow(() -> new RestApiException(_NOT_FOUND));
6969
roommateRepository.delete(roommate);
70+
roommateRepository.flush();
7071
}
7172

7273
public List<MyRoommateResponse> findMyRoommates(String userNo) {

0 commit comments

Comments
 (0)