Files
coop/backend/prisma/schema.prisma
T
hobokenchicken e8d9b1fd42 feat: add CoopCredits Solana media rewards ecosystem
Add complete  token system with Plex/Tautulli/Overseer integration:
- Anchor program for SPL token mint/burn/transfer
- Express backend with OAuth, webhooks, Solana integration
- Next.js frontend with dashboard, admin panel, wallet management
- Docker deployment for 172.20.1.0/24 infrastructure
- Production configs with SSL, Nginx, health monitoring

Tautulli webhooks auto-mint  on watch events.
Overseer integration burns  for content requests.
2026-04-14 11:09:50 -04:00

190 lines
5.0 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
plexId String @unique @map("plex_id")
plexUsername String @map("plex_username")
email String?
isAdmin Boolean @default(false) @map("is_admin")
isActive Boolean @default(true) @map("is_active")
// Solana wallet
walletAddress String? @unique @map("wallet_address")
encryptedPrivateKey String? @map("encrypted_private_key")
// Stats
totalEarned Int @default(0) @map("total_earned")
totalSpent Int @default(0) @map("total_spent")
watchTimeMinutes Int @default(0) @map("watch_time_minutes")
// Relations
transactions Transaction[]
watchEvents WatchEvent[]
contentRequests ContentRequest[]
sessions Session[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([plexId])
@@index([walletAddress])
@@map("users")
}
model Transaction {
id String @id @default(uuid())
userId String @map("user_id")
user User @relation(fields: [userId], references: [id])
type TransactionType
amount Int
// For earned transactions
watchEventId String? @map("watch_event_id")
watchEvent WatchEvent? @relation(fields: [watchEventId], references: [id])
// For spent transactions
requestId String? @map("request_id")
request ContentRequest? @relation(fields: [requestId], references: [id])
// Solana transaction reference
solanaSignature String? @map("solana_signature")
// Metadata
description String?
contentTitle String? @map("content_title")
createdAt DateTime @default(now()) @map("created_at")
@@index([userId])
@@index([type])
@@index([createdAt])
@@map("transactions")
}
model WatchEvent {
id String @id @default(uuid())
userId String @map("user_id")
user User @relation(fields: [userId], references: [id])
// Tautulli data
sessionId String @map("session_id")
ratingKey String @map("rating_key")
contentType String @map("content_type") // movie, episode
title String
grandparentTitle String? @map("grandparent_title") // Show name for episodes
// Watch stats
duration Int // seconds watched
percentComplete Int @map("percent_complete")
// Credits earned
creditsEarned Int @map("credits_earned")
isProcessed Boolean @default(false) @map("is_processed")
// Relations
transactions Transaction[]
watchedAt DateTime @map("watched_at")
createdAt DateTime @default(now()) @map("created_at")
@@unique([sessionId])
@@index([userId])
@@index([watchedAt])
@@map("watch_events")
}
model ContentRequest {
id String @id @default(uuid())
userId String @map("user_id")
user User @relation(fields: [userId], references: [id])
// Overseer data
overseerRequestId Int @map("overseer_request_id")
// Content info
mediaType String @map("media_type") // movie, tv
tmdbId Int @map("tmdb_id")
title String
// Cost
creditsCost Int @map("credits_cost")
// Status
status RequestStatus @default(PENDING)
// Relations
transaction Transaction?
requestedAt DateTime @map("requested_at")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([userId])
@@index([status])
@@map("content_requests")
}
model Session {
id String @id @default(uuid())
userId String @map("user_id")
user User @relation(fields: [userId], references: [id])
token String @unique
expiresAt DateTime @map("expires_at")
createdAt DateTime @default(now()) @map("created_at")
@@index([userId])
@@index([token])
@@map("sessions")
}
model SystemSettings {
id String @id @default(cuid())
// Minting settings
creditsPerMinute Int @default(10) @map("credits_per_minute")
minWatchPercent Int @default(80) @map("min_watch_percent")
minWatchMinutes Int @default(5) @map("min_watch_minutes")
// Spending settings
movieRequestCost Int @default(100) @map("movie_request_cost")
tvRequestCost Int @default(200) @map("tv_request_cost")
tvPerSeasonCost Int @default(50) @map("tv_per_season_cost")
// Multipliers
newReleaseMultiplier Decimal @default(1.5) @map("new_release_multiplier") @db.Decimal(3, 2)
bonusMultiplierActive Boolean @default(false) @map("bonus_multiplier_active")
bonusMultiplier Decimal @default(2.0) @map("bonus_multiplier") @db.Decimal(3, 2)
// System state
mintingPaused Boolean @default(false) @map("minting_paused")
updatedAt DateTime @updatedAt @map("updated_at")
updatedBy String? @map("updated_by")
@@map("system_settings")
}
enum TransactionType {
EARN
SPEND
BONUS
ADJUSTMENT
}
enum RequestStatus {
PENDING
APPROVED
DECLINED
COMPLETED
}