generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum Platform { VK TELEGRAM YOUTUBE } enum GiveawayStatus { DRAFT FETCHING READY SNAPSHOT_LOCKED DRAWN PUBLISHED CANCELLED } enum ParticipantSource { LIKES COMMENTS REPOSTS COMBINED } model Giveaway { id String @id @default(cuid()) platform Platform @default(VK) sourceUrl String platformOwnerId String platformPostId String title String description String? postImageUrl String? postLikesCount Int @default(0) postCommentsCount Int @default(0) postRepostsCount Int @default(0) status GiveawayStatus @default(DRAFT) filterRules Json // FilterRules object winnersCount Int @default(1) reserveWinnersCount Int @default(0) seed String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt drawnAt DateTime? participants Participant[] snapshots ParticipantSnapshot[] drawResult DrawResult? auditRecord AuditRecord? @@index([platform, platformOwnerId, platformPostId]) } model Participant { id String @id @default(cuid()) giveawayId String giveaway Giveaway @relation(fields: [giveawayId], references: [id], onDelete: Cascade) platformUserId String firstName String lastName String username String? avatarUrl String? source ParticipantSource @default(LIKES) liked Boolean @default(false) commented Boolean @default(false) commentsCount Int @default(0) reposted Boolean @default(false) subscribed Boolean @default(false) eligible Boolean @default(true) exclusionReason String? createdAt DateTime @default(now()) @@unique([giveawayId, platformUserId]) @@index([giveawayId, eligible]) } model ParticipantSnapshot { id String @id @default(cuid()) giveawayId String giveaway Giveaway @relation(fields: [giveawayId], references: [id], onDelete: Cascade) version Int @default(1) createdAt DateTime @default(now()) eligibleParticipants Json // Canonical JSON array of FilteredParticipant filterRulesSnapshot Json // Canonical JSON snapshot of FilterRules participantCount Int participantsSnapshotHash String conditionsHash String drawResult DrawResult? auditRecord AuditRecord? @@unique([giveawayId, version]) @@index([giveawayId]) } model DrawResult { id String @id @default(cuid()) drawId String // Original domain drawId (e.g. draw_8f9102ab...) giveawayId String @unique giveaway Giveaway @relation(fields: [giveawayId], references: [id], onDelete: Cascade) snapshotId String @unique snapshot ParticipantSnapshot @relation(fields: [snapshotId], references: [id], onDelete: Restrict) winners Json // Array of Winner entities reserveWinners Json // Array of Winner entities winnerIds Json // string[] reserveWinnerIds Json // string[] totalEligibleCount Int totalLoadedCount Int seedUsed String algorithmVersion String @default("HMAC_SHA256_FY_V1") deterministicProofHash String auditEventHash String drawnAt DateTime @default(now()) } model AuditRecord { id String @id @default(cuid()) giveawayId String @unique giveaway Giveaway @relation(fields: [giveawayId], references: [id], onDelete: Cascade) snapshotId String @unique snapshot ParticipantSnapshot @relation(fields: [snapshotId], references: [id], onDelete: Restrict) algorithmVersion String @default("HMAC_SHA256_FY_V1") seed String participantsSnapshotHash String conditionsHash String deterministicProofHash String auditEventHash String winnerIds Json // string[] reserveWinnerIds Json // string[] eligibleCount Int drawId String drawnAt DateTime @default(now()) verifiedAt DateTime @default(now()) }