feat: implement per-user soft delete for conversations with automatic restoration on new messages
This commit is contained in:
@@ -507,6 +507,10 @@ model Conversation {
|
|||||||
userClearedAt DateTime?
|
userClearedAt DateTime?
|
||||||
agentClearedAt DateTime?
|
agentClearedAt DateTime?
|
||||||
|
|
||||||
|
// Soft delete (per-user) — conversation hidden for that user until a new message arrives
|
||||||
|
userDeletedAt DateTime?
|
||||||
|
agentDeletedAt DateTime?
|
||||||
|
|
||||||
// Timestamps
|
// Timestamps
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|||||||
@@ -140,6 +140,21 @@ export class MessagesService {
|
|||||||
},
|
},
|
||||||
include: conversationInclude,
|
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
|
// Transform to include otherParty based on caller role
|
||||||
@@ -275,6 +290,9 @@ export class MessagesService {
|
|||||||
...(isUser
|
...(isUser
|
||||||
? { agentUnreadCount: { increment: 1 } }
|
? { agentUnreadCount: { increment: 1 } }
|
||||||
: { userUnreadCount: { 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({
|
conversations = await this.prisma.conversation.findMany({
|
||||||
where: { agentProfileId: agentProfile.id },
|
where: {
|
||||||
|
agentProfileId: agentProfile.id,
|
||||||
|
agentDeletedAt: null, // Exclude soft-deleted conversations
|
||||||
|
},
|
||||||
include: {
|
include: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
@@ -362,7 +383,10 @@ export class MessagesService {
|
|||||||
} else {
|
} else {
|
||||||
// Regular user
|
// Regular user
|
||||||
conversations = await this.prisma.conversation.findMany({
|
conversations = await this.prisma.conversation.findMany({
|
||||||
where: { userId },
|
where: {
|
||||||
|
userId,
|
||||||
|
userDeletedAt: null, // Exclude soft-deleted conversations
|
||||||
|
},
|
||||||
include: {
|
include: {
|
||||||
agentProfile: {
|
agentProfile: {
|
||||||
select: {
|
select: {
|
||||||
@@ -781,13 +805,17 @@ export class MessagesService {
|
|||||||
throw new ForbiddenException('You are not part of this conversation');
|
throw new ForbiddenException('You are not part of this conversation');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all messages first, then the conversation
|
// Soft delete: mark conversation as deleted for this user only
|
||||||
await this.prisma.message.deleteMany({
|
// The other party still sees the conversation and all messages.
|
||||||
where: { conversationId },
|
// 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 },
|
where: { id: conversationId },
|
||||||
|
data: isUser
|
||||||
|
? { userDeletedAt: now, userClearedAt: now, userUnreadCount: 0 }
|
||||||
|
: { agentDeletedAt: now, agentClearedAt: now, agentUnreadCount: 0 },
|
||||||
});
|
});
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user