// 删除测试用户 + 其所有 vote / fanSupport / signIn 数据, // 并把 artist.voteCount 回滚到投票前的值。 // // 用法: node scripts/cleanup-test-user.mjs import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient({ log: ["error"] }); const phone = process.argv[2]; if (!phone) { console.error("用法: node scripts/cleanup-test-user.mjs "); process.exit(2); } const user = await prisma.user.findUnique({ where: { phone }, select: { id: true, nickname: true }, }); if (!user) { console.log(`[skip] 没有找到 phone=${phone} 的用户,无需 cleanup`); await prisma.$disconnect(); process.exit(0); } console.log(`[cleanup] 用户 id=${user.id} (${user.nickname}) phone=${phone}`); // 1. 把该用户的投票回滚到 artist.voteCount const votes = await prisma.vote.findMany({ where: { userId: user.id }, select: { artistId: true, count: true }, }); console.log(` 待回滚 ${votes.length} 条投票`); await prisma.$transaction(async (tx) => { // 1. 减回 artist.voteCount for (const v of votes) { await tx.artist.update({ where: { id: v.artistId }, data: { voteCount: { decrement: v.count } }, }); } // 2. 删除 Vote / FanSupport / SignIn(都有 onDelete: Cascade,删 user 就够,但显式更清晰) // 3. 删除 user 本身 —— cascade 会清掉关联表 await tx.user.delete({ where: { id: user.id } }); }); console.log("[cleanup] 完成"); await prisma.$disconnect();