chore: snapshot comment authors before user deletion

This commit is contained in:
Esdras Renan 2025-10-19 14:30:59 -03:00
parent 846e575637
commit 63d6a65334
6 changed files with 319 additions and 5976 deletions

View file

@ -642,6 +642,79 @@ export const importPrismaSnapshot = mutation({
},
})
export const backfillTicketCommentAuthorSnapshots = mutation({
args: {
limit: v.optional(v.number()),
dryRun: v.optional(v.boolean()),
},
handler: async (ctx, { limit, dryRun }) => {
const effectiveDryRun = Boolean(dryRun)
const maxUpdates = limit && limit > 0 ? limit : null
const comments = await ctx.db.query("ticketComments").collect()
let updated = 0
let skippedExisting = 0
let missingAuthors = 0
for (const comment of comments) {
if (comment.authorSnapshot) {
skippedExisting += 1
continue
}
if (maxUpdates !== null && updated >= maxUpdates) {
break
}
const author = await ctx.db.get(comment.authorId)
let name: string | null = author?.name ?? null
const email: string | null = author?.email ?? null
let avatarUrl: string | null = author?.avatarUrl ?? null
const teams: string[] | undefined = (author?.teams ?? undefined) as string[] | undefined
if (!author) {
missingAuthors += 1
const events = await ctx.db
.query("ticketEvents")
.withIndex("by_ticket", (q) => q.eq("ticketId", comment.ticketId))
.collect()
const matchingEvent = events.find(
(event) => event.type === "COMMENT_ADDED" && event.createdAt === comment.createdAt,
)
if (matchingEvent && matchingEvent.payload && typeof matchingEvent.payload === "object") {
const payload = matchingEvent.payload as { authorName?: string; authorAvatar?: string }
if (typeof payload.authorName === "string" && payload.authorName.trim().length > 0) {
name = payload.authorName.trim()
}
if (typeof payload.authorAvatar === "string" && payload.authorAvatar.trim().length > 0) {
avatarUrl = payload.authorAvatar
}
}
}
const snapshot = pruneUndefined({
name: name && name.trim().length > 0 ? name : "Usuário removido",
email: email ?? undefined,
avatarUrl: avatarUrl ?? undefined,
teams: teams && teams.length > 0 ? teams : undefined,
})
if (!effectiveDryRun) {
await ctx.db.patch(comment._id, { authorSnapshot: snapshot })
}
updated += 1
}
return {
dryRun: effectiveDryRun,
totalComments: comments.length,
updated,
skippedExisting,
missingAuthors,
limit: maxUpdates,
}
},
})
export const syncMachineCompanyReferences = mutation({
args: {
tenantId: v.optional(v.string()),