HotTRDealsBackend/db/dealAnalytics.db.js
2026-02-04 06:39:10 +00:00

104 lines
2.9 KiB
JavaScript

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,
}