feat: implement per-user soft delete for conversations with automatic restoration on new messages

This commit is contained in:
pradeepkumar
2026-04-10 16:48:12 +05:30
parent d80f75a39e
commit 78133497b3
2 changed files with 39 additions and 7 deletions

View File

@@ -507,6 +507,10 @@ model Conversation {
userClearedAt DateTime?
agentClearedAt DateTime?
// Soft delete (per-user) — conversation hidden for that user until a new message arrives
userDeletedAt DateTime?
agentDeletedAt DateTime?
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

View File

@@ -140,6 +140,21 @@ export class MessagesService {
},
include: conversationInclude,
});
} else {
// Clear soft-delete flag for the caller so the conversation reappears
const needsClear = callerRole === UserRole.AGENT
? conversation.agentDeletedAt !== null
: conversation.userDeletedAt !== null;
if (needsClear) {
conversation = await this.prisma.conversation.update({
where: { id: conversation.id },
data: callerRole === UserRole.AGENT
? { agentDeletedAt: null }
: { userDeletedAt: null },
include: conversationInclude,
});
}
}
// Transform to include otherParty based on caller role
@@ -275,6 +290,9 @@ export class MessagesService {
...(isUser
? { agentUnreadCount: { increment: 1 } }
: { userUnreadCount: { increment: 1 } }),
// Clear soft-delete flags so conversation reappears for both parties
userDeletedAt: null,
agentDeletedAt: null,
},
});
@@ -315,7 +333,10 @@ export class MessagesService {
}
conversations = await this.prisma.conversation.findMany({
where: { agentProfileId: agentProfile.id },
where: {
agentProfileId: agentProfile.id,
agentDeletedAt: null, // Exclude soft-deleted conversations
},
include: {
user: {
select: {
@@ -362,7 +383,10 @@ export class MessagesService {
} else {
// Regular user
conversations = await this.prisma.conversation.findMany({
where: { userId },
where: {
userId,
userDeletedAt: null, // Exclude soft-deleted conversations
},
include: {
agentProfile: {
select: {
@@ -781,13 +805,17 @@ export class MessagesService {
throw new ForbiddenException('You are not part of this conversation');
}
// Delete all messages first, then the conversation
await this.prisma.message.deleteMany({
where: { conversationId },
});
// Soft delete: mark conversation as deleted for this user only
// The other party still sees the conversation and all messages.
// If a new message arrives later, the deletedAt flag is cleared so
// the conversation reappears for the user who deleted it.
const now = new Date();
await this.prisma.conversation.delete({
await this.prisma.conversation.update({
where: { id: conversationId },
data: isUser
? { userDeletedAt: now, userClearedAt: now, userUnreadCount: 0 }
: { agentDeletedAt: now, agentClearedAt: now, agentUnreadCount: 0 },
});
return null;