-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChatParticipant.java
More file actions
149 lines (131 loc) · 3.98 KB
/
ChatParticipant.java
File metadata and controls
149 lines (131 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package app.dearobjet.backend.domain.chat.entity;
import app.dearobjet.backend.domain.user.entity.User;
import app.dearobjet.backend.global.common.entity.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
/**
* 채팅방 참여자 엔티티
*/
@Entity
@Table(name = "chat_participants",
uniqueConstraints = {
@UniqueConstraint(
name = "uk_room_user",
columnNames = {"chat_room_id", "user_id"}
)
},
indexes = {
@Index(name = "idx_user_room", columnList = "user_id, chat_room_id")
}
)
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class ChatParticipant extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 참여 중인 사용자
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
/**
* 참여 중인 채팅방
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "chat_room_id", nullable = false)
private ChatRoom chatRoom;
/**
* 읽지 않은 메시지 수
*/
@Column(name = "unread_count", nullable = false)
private Integer unreadCount;
/**
* 채팅방 참여 시점
*/
@Column(name = "joined_at", nullable = false)
private LocalDateTime joinedAt;
/**
* 마지막으로 메시지를 읽은 시점
*
* 읽음 표시 구현 방식:
* 1. 사용자가 채팅방 진입 시 현재 시간으로 업데이트
* 2. 메시지의 createdAt과 비교하여 읽음 여부 판단
* 3. message.createdAt <= participant.lastReadAt → 읽음
*/
@Column(name = "last_read_at")
private LocalDateTime lastReadAt;
// ====================================================================
// 비즈니스 메서드
// ====================================================================
/**
* 읽지 않은 메시지 수 증가
* 새 메시지가 도착했을 때 호출
*/
public void incrementUnreadCount() {
if (this.unreadCount == null) {
this.unreadCount = 0;
}
this.unreadCount++;
}
/**
* 메시지 읽음 처리
* 채팅방 진입 시 호출
*/
public void markAsRead() {
this.lastReadAt = LocalDateTime.now();
this.unreadCount = 0;
}
/**
* 읽지 않은 메시지 수 업데이트
* 배치 작업 등에서 사용
*
* @param count 새로운 읽지 않은 메시지 수
*/
public void updateUnreadCount(int count) {
this.unreadCount = Math.max(0, count); // 음수 방지
}
/**
* 특정 시점 이후의 메시지를 읽음 처리
*
* @param readUntil 읽음 처리할 시점
*/
public void markAsReadUntil(LocalDateTime readUntil) {
this.lastReadAt = readUntil;
}
// ====================================================================
// JPA Lifecycle Callbacks
// ====================================================================
/**
* 엔티티 저장 전 호출
* joinedAt 자동 설정
*/
@PrePersist
protected void onCreate() {
if (joinedAt == null) {
joinedAt = LocalDateTime.now();
}
if (unreadCount == null) {
unreadCount = 0;
}
}
// ====================================================================
// 편의 메서드
// ====================================================================
/**
* 특정 메시지를 읽었는지 확인
*
* @param messageCreatedAt 메시지 생성 시간
* @return true - 읽음, false - 안 읽음
*/
public boolean hasRead(LocalDateTime messageCreatedAt) {
if (lastReadAt == null) {
return false;
}
return !messageCreatedAt.isAfter(lastReadAt);
}
}