const prisma = require("./client") const { Prisma } = require("@prisma/client") async function findLike(commentId, userId, db) { const p = db || prisma return p.commentLike.findUnique({ where: { commentId_userId: { commentId, userId } }, }) } async function findLikesByUserAndCommentIds(userId, commentIds, db) { const p = db || prisma return p.commentLike.findMany({ where: { userId, commentId: { in: commentIds } }, select: { commentId: true }, }) } async function setCommentLike({ commentId, userId, like }) { return prisma.$transaction(async (tx) => { const comment = await tx.comment.findUnique({ where: { id: commentId }, select: { id: true, likeCount: true }, }) if (!comment) throw new Error("Yorum bulunamadı.") const existing = await findLike(commentId, userId, tx) if (like) { if (existing) { return { liked: true, delta: 0, likeCount: comment.likeCount } } await tx.commentLike.create({ data: { commentId, userId }, }) const updated = await tx.comment.update({ where: { id: commentId }, data: { likeCount: { increment: 1 } }, select: { likeCount: true }, }) return { liked: true, delta: 1, likeCount: updated.likeCount } } if (!existing) { return { liked: false, delta: 0, likeCount: comment.likeCount } } await tx.commentLike.delete({ where: { commentId_userId: { commentId, userId } }, }) const updated = await tx.comment.update({ where: { id: commentId }, data: { likeCount: { decrement: 1 } }, select: { likeCount: true }, }) return { liked: false, delta: -1, likeCount: updated.likeCount } }) } async function applyCommentLikeBatch(items = []) { if (!items.length) return { inserted: 0, deleted: 0 } const likes = items.filter((i) => i.like) const unlikes = items.filter((i) => !i.like) return prisma.$transaction(async (tx) => { let inserted = 0 let deleted = 0 if (likes.length) { const values = Prisma.join( likes.map((i) => Prisma.sql`(${i.commentId}, ${i.userId})`) ) const insertSql = Prisma.sql` WITH input("commentId","userId") AS (VALUES ${values}), ins AS ( INSERT INTO "CommentLike" ("commentId","userId") SELECT "commentId","userId" FROM input ON CONFLICT ("commentId","userId") DO NOTHING RETURNING "commentId" ), agg AS ( SELECT "commentId", COUNT(*)::int AS cnt FROM ins GROUP BY "commentId" ) UPDATE "Comment" c SET "likeCount" = c."likeCount" + agg.cnt FROM agg WHERE c.id = agg."commentId" RETURNING agg.cnt ` const rows = await tx.$queryRaw(insertSql) if (Array.isArray(rows)) { inserted = rows.reduce((sum, row) => sum + Number(row.cnt || 0), 0) } } if (unlikes.length) { const values = Prisma.join( unlikes.map((i) => Prisma.sql`(${i.commentId}, ${i.userId})`) ) const deleteSql = Prisma.sql` WITH input("commentId","userId") AS (VALUES ${values}), del AS ( DELETE FROM "CommentLike" cl WHERE (cl."commentId", cl."userId") IN (SELECT "commentId","userId" FROM input) RETURNING "commentId" ), agg AS ( SELECT "commentId", COUNT(*)::int AS cnt FROM del GROUP BY "commentId" ) UPDATE "Comment" c SET "likeCount" = c."likeCount" - agg.cnt FROM agg WHERE c.id = agg."commentId" RETURNING agg.cnt ` const rows = await tx.$queryRaw(deleteSql) if (Array.isArray(rows)) { deleted = rows.reduce((sum, row) => sum + Number(row.cnt || 0), 0) } } return { inserted, deleted } }) } module.exports = { findLikesByUserAndCommentIds, setCommentLike, applyCommentLikeBatch, }