const prisma = require("./client") function normalizeIds(ids = []) { return Array.from( new Set( (Array.isArray(ids) ? ids : []) .map((id) => Number(id)) .filter((id) => Number.isInteger(id) && id > 0) ) ) } async function ensureTotalsForDealIds(dealIds = []) { const ids = normalizeIds(dealIds) if (!ids.length) return 0 const existing = await prisma.deal.findMany({ where: { id: { in: ids } }, select: { id: true }, }) const existingIds = new Set(existing.map((d) => d.id)) if (!existingIds.size) return 0 const data = ids.filter((id) => existingIds.has(id)).map((dealId) => ({ dealId })) const result = await prisma.dealAnalyticsTotal.createMany({ data, skipDuplicates: true, }) return result?.count ?? 0 } async function getTotalsByDealIds(dealIds = []) { const ids = normalizeIds(dealIds) if (!ids.length) return [] return prisma.dealAnalyticsTotal.findMany({ where: { dealId: { in: ids } }, select: { dealId: true, impressions: true, views: true, clicks: true, }, }) } function aggregateEventIncrements(events = []) { const byDeal = new Map() for (const event of events) { const dealId = Number(event.dealId) if (!Number.isInteger(dealId) || dealId <= 0) continue const type = String(event.type || "").toUpperCase() const entry = byDeal.get(dealId) || { dealId, impressions: 0, views: 0, clicks: 0 } if (type === "IMPRESSION") entry.impressions += 1 else if (type === "VIEW") entry.views += 1 else if (type === "CLICK") entry.clicks += 1 byDeal.set(dealId, entry) } return Array.from(byDeal.values()) } async function applyDealEventBatch(events = []) { const filtered = (Array.isArray(events) ? events : []).filter( (e) => e && e.dealId && (e.userId || e.ip) ) if (!filtered.length) return { inserted: 0, increments: [] } const data = filtered.map((event) => ({ dealId: Number(event.dealId), type: String(event.type || "IMPRESSION").toUpperCase(), userId: event.userId ? Number(event.userId) : null, ip: event.ip ? String(event.ip) : null, createdAt: event.createdAt ? new Date(event.createdAt) : new Date(), })) const increments = aggregateEventIncrements(data) await prisma.$transaction(async (tx) => { await tx.dealEvent.createMany({ data }) for (const inc of increments) { await tx.dealAnalyticsTotal.upsert({ where: { dealId: inc.dealId }, create: { dealId: inc.dealId, impressions: inc.impressions, views: inc.views, clicks: inc.clicks, }, update: { impressions: { increment: inc.impressions }, views: { increment: inc.views }, clicks: { increment: inc.clicks }, }, }) } }) return { inserted: data.length, increments } } module.exports = { ensureTotalsForDealIds, getTotalsByDealIds, applyDealEventBatch, }