sofia-cloud / prisma /schema.prisma
Gmagl
fix: correcciones cr铆ticas y refactorizaci贸n de componentes
3eebcd0
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ============================================
// MODELOS BASE
// ============================================
model User {
id String @id @default(cuid())
email String? @unique
name String?
externalId String? // ID externo (Telegram chatId, etc.)
source String? // "telegram", "web", "onlyfans", etc.
tier String @default("free") // free, basic, premium, pro
stripeCustomerId String?
totalSpent Float @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
chatSessions ChatSession[]
assetDeliveries AssetDelivery[]
influencerSubscriptions InfluencerSubscription[]
@@unique([externalId, source])
}
model Project {
id String @id @default(cuid())
name String
description String?
style String @default("default")
status String @default("active")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
repos Repo[]
analyses Analysis[]
contents Content[]
}
model Repo {
id String @id @default(cuid())
url String
name String
status String @default("cloned")
projectId String?
project Project? @relation(fields: [projectId], references: [id])
analyses Analysis[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Analysis {
id String @id @default(cuid())
type String
result String
summary String?
repoId String?
repo Repo? @relation(fields: [repoId], references: [id])
projectId String?
project Project? @relation(fields: [projectId], references: [id])
createdAt DateTime @default(now())
}
model AgentTask {
id String @id @default(cuid())
type String
status String @default("pending")
input String
output String?
createdAt DateTime @default(now())
completedAt DateTime?
}
// ============================================
// MODELOS DE INFLUENCER (CHARACTER)
// ============================================
model Character {
id String @id @default(cuid())
name String
slug String @unique
displayName String?
shortBio String?
description String?
referenceImage String? // Imagen can贸nica para consistencia facial
bodyReference String? // Referencia corporal
traits String? // JSON con rasgos de personalidad
orientation String? // Orientaci贸n/estilo (mujer, hombre gay, etc.)
styleDescription String? // Descripci贸n visual para generaci贸n de im谩genes
systemPrompt String? // Prompt base para el chat
telegramBotToken String? // Token del bot de Telegram espec铆fico
// Storytelling
backstory String? // Historia de fondo
personality String? // Personalidad detallada
interests String? // JSON array de intereses
catchphrases String? // JSON array de frases t铆picas
// Configuraci贸n de chat por tier
chatFreeLimit Int @default(10) // Mensajes gratis por d铆a
chatBasicTone String? // Tono para tier basic
chatPremiumTone String? // Tono para tier premium (铆ntimo)
chatProTone String? // Tono para tier pro (novia IA)
isActive Boolean @default(true)
contents Content[]
pets Pet[]
chatSessions ChatSession[]
assetDeliveries AssetDelivery[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE CHAT / NOVIA IA
// ============================================
model ChatSession {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id])
characterId String
character Character @relation(fields: [characterId], references: [id])
channel String @default("telegram") // telegram, web, etc.
heatScore Int @default(0) // 0-100, sube con interacci贸n
msgCountToday Int @default(0)
lastMessageAt DateTime?
isActive Boolean @default(true)
messages ChatMessage[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([userId, characterId, channel])
}
model ChatMessage {
id String @id @default(cuid())
sessionId String
session ChatSession @relation(fields: [sessionId], references: [id])
role String // "user", "assistant", "system"
content String
metadata String? // JSON (ej: si se envi贸 un asset)
createdAt DateTime @default(now())
}
// ============================================
// MODELOS DE CONTENIDO MULTIMEDIA
// ============================================
model Content {
id String @id @default(cuid())
type String // "image", "video", "audio", "text", "reel", "story", "carousel"
title String
description String?
prompt String
optimizedPrompt String?
filePath String?
thumbnail String?
platform String @default("general")
status String @default("pending")
nsfwLevel Int @default(0) // 0=SFW, 1=suggestive, 2=NSFW, 3=explicit
metadata String?
projectId String?
project Project? @relation(fields: [projectId], references: [id])
characterId String?
character Character? @relation(fields: [characterId], references: [id])
petId String?
pet Pet? @relation(fields: [petId], references: [id])
censorFlags CensorFlag[]
posts Post[]
assetDeliveries AssetDelivery[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// Tracking de qu茅 assets se han enviado a qu茅 usuario
model AssetDelivery {
id String @id @default(cuid())
contentId String
content Content @relation(fields: [contentId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
characterId String
character Character @relation(fields: [characterId], references: [id])
channel String @default("telegram")
deliveredAt DateTime @default(now())
@@unique([contentId, userId]) // No repetir el mismo asset al mismo usuario
}
// ============================================
// MODELOS DE CENSURA
// ============================================
model CensorRule {
id String @id @default(cuid())
platform String
category String
rule String
severity String @default("medium")
autoAction String @default("warn")
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model CensorFlag {
id String @id @default(cuid())
contentId String
content Content @relation(fields: [contentId], references: [id])
category String
reason String
severity String
action String
createdAt DateTime @default(now())
}
// ============================================
// MODELOS DE MONETIZACI脫N
// ============================================
model MonetizationPlatform {
id String @id @default(cuid())
name String // OnlyFans, Patreon, Fansly, etc.
type String // "subscription", "tips", "ppv", "mixed"
url String?
apiKey String?
accountId String?
accountName String?
legalTerms String? // JSON con t茅rminos legales
contentRules String? // JSON con reglas de contenido
feePercentage Float?
payoutSchedule String?
isActive Boolean @default(true)
isVerified Boolean @default(false)
metadata String?
posts Post[]
earnings Earning[]
subscribers Subscriber[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Subscriber {
id String @id @default(cuid())
platformId String
platform MonetizationPlatform @relation(fields: [platformId], references: [id])
externalId String?
username String?
tier String?
status String @default("active")
joinedAt DateTime?
expiresAt DateTime?
totalSpent Float @default(0)
metadata String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Earning {
id String @id @default(cuid())
platformId String
platform MonetizationPlatform @relation(fields: [platformId], references: [id])
subscriptionId String?
subscription InfluencerSubscription? @relation(fields: [subscriptionId], references: [id])
type String // "subscription", "post", "tip", "ppv"
amount Float
currency String @default("USD")
postId String?
subscriberId String?
status String @default("pending") // pending, completed, failed
paymentMethod String? // "card", "bank_transfer", "paypal"
stripePaymentIntentId String? // Para rastrear en Stripe
isRecurring Boolean @default(false)
description String?
processedAt DateTime?
metadata String?
createdAt DateTime @default(now())
}
// ============================================
// MODELOS DE PUBLICACI脫N
// ============================================
model Post {
id String @id @default(cuid())
title String?
caption String?
hashtags String?
type String
status String @default("draft")
contentId String?
content Content? @relation(fields: [contentId], references: [id])
platformId String?
platform MonetizationPlatform? @relation(fields: [platformId], references: [id])
scheduledAt DateTime?
publishedAt DateTime?
externalPostId String?
postUrl String?
engagementStats String?
storyId String?
story Story? @relation(fields: [storyId], references: [id])
metadata String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE STORYTELLING
// ============================================
model Story {
id String @id @default(cuid())
title String
description String?
genre String?
targetAudience String?
tone String?
structure String?
characterIds String?
totalEpisodes Int @default(1)
currentEpisode Int @default(1)
status String @default("draft")
monetizationStrategy String?
posts Post[]
episodes StoryEpisode[]
analytics StoryAnalytics?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model StoryEpisode {
id String @id @default(cuid())
storyId String
story Story @relation(fields: [storyId], references: [id])
episodeNum Int
title String
synopsis String?
content String
hook String?
cliffhanger String?
status String @default("draft")
scheduledAt DateTime?
publishedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model StoryAnalytics {
id String @id @default(cuid())
storyId String @unique
story Story @relation(fields: [storyId], references: [id])
totalViews Int @default(0)
totalEngagement Float @default(0)
avgWatchTime Float?
completionRate Float?
revenue Float @default(0)
subscriberGain Int @default(0)
bestPerformingEpisode Int?
metadata String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE AUTOMATIZACI脫N
// ============================================
model Automation {
id String @id @default(cuid())
name String
description String?
type String
trigger String
triggerConfig String?
actions String
isActive Boolean @default(true)
lastRunAt DateTime?
nextRunAt DateTime?
runCount Int @default(0)
metadata String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model AutomationLog {
id String @id @default(cuid())
automationId String?
status String
input String?
output String?
error String?
duration Int?
createdAt DateTime @default(now())
}
// ============================================
// MODELOS DE TENDENCIAS
// ============================================
model Trend {
id String @id @default(cuid())
platform String
type String
name String
description String?
volume Int?
growth Float?
startDate DateTime?
endDate DateTime?
relatedTags String?
contentIdeas String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE PLANTILLAS
// ============================================
model PromptTemplate {
id String @id @default(cuid())
name String
category String
template String
variables String
platform String @default("general")
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ContentTemplate {
id String @id @default(cuid())
name String
type String
platform String
structure String
hooks String?
ctas String?
hashtags String?
bestTimes String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE MASCOTAS/COMPA脩EROS
// ============================================
model Pet {
id String @id @default(cuid())
name String
type String
breed String?
description String?
referenceImage String?
traits String?
personality String?
color String?
accessories String?
characterId String?
character Character? @relation(fields: [characterId], references: [id], onDelete: Cascade)
contents Content[]
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE INFLUENCERS IA DE REFERENCIA
// ============================================
model AIInfluencer {
id String @id @default(cuid())
name String
handle String?
platform String
followers Int?
engagement Float?
niche String?
style String?
contentTypes String?
postingSchedule String?
visualStyle String?
monetizationType String?
signatureElements String?
petCompanion Boolean @default(false)
petType String?
analysis String?
lessons String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
influencerSubscriptions InfluencerSubscription[]
}
// Suscripciones por influencer: cada cliente se suscribe por separado a cada influencer
model InfluencerSubscription {
id String @id @default(cuid())
influencerId String
influencer AIInfluencer @relation(fields: [influencerId], references: [id])
userId String?
user User? @relation(fields: [userId], references: [id])
tier String // tier contratado para esta suscripci贸n (basic, premium, etc.)
status String @default("active") // active, paused, expired, cancelled
joinedAt DateTime @default(now())
expiresAt DateTime?
nextRenewalDate DateTime? // Pr贸xima fecha de renovaci贸n autom谩tica
autoRenew Boolean @default(true) // Renovaci贸n autom谩tica activada
price Float?
currency String @default("USD")
// Integraci贸n con Stripe
stripeSubscriptionId String? // ID de suscripci贸n en Stripe
stripeCustomerId String? // ID de cliente en Stripe
paymentMethodId String? // ID del m茅todo de pago en Stripe
metadata String?
earnings Earning[] // Relaci贸n con pagos registrados
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============================================
// MODELOS DE ESTRATEGIAS VIRALES
// ============================================
model ViralStrategy {
id String @id @default(cuid())
name String
description String?
platform String
contentType String
hook String?
structure String?
elements String?
estimatedReach Int?
difficulty String @default("medium")
timeframe String?
examples String?
tags String?
successRate Float?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}