generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" } model GuildConfig { guildId String @id prefix String @default("!") mimicEnabled Boolean @default(false) bigEmojiEnabled Boolean @default(false) locale String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model UserSubscription { userId String @id tier SubscriptionTier @default(FREE) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guilds GuildOwnership[] } model GuildOwnership { guildId String @id ownerId String createdAt DateTime @default(now()) owner UserSubscription @relation(fields: [ownerId], references: [userId], onDelete: Cascade) @@index([ownerId]) } model VoiceGenerator { channelId String @id guildId String categoryId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([guildId]) } model TempVoiceChannel { channelId String @id guildId String ownerId String deleteWhen DeleteCondition @default(EMPTY) createdAt DateTime @default(now()) @@index([guildId]) @@index([ownerId]) } model UserVoiceProfile { userId String guildId String customName String? userLimit Int? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([userId, guildId]) } model UserLocale { userId String @id locale String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } enum SubscriptionTier { FREE STANDARD PRO PREMIUM } enum DeleteCondition { OWNER_LEAVE EMPTY } model AuditChannel { guildId String @id channelId String disabledCategories String[] @default(["BOOT", "SYSTEM"]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model VoiceGuildConfig { guildId String @id defaultNameTemplate String @default("{{username}}'s Room") defaultUserLimit Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model GuildEvent { id String @id @default(uuid()) guildId String title String description String? startsAt DateTime timezone String @default("Asia/Seoul") status EventStatus @default(SCHEDULED) announcementChannelId String? createdByUserId String reminderEnabled Boolean @default(true) reminderOffsets Int[] @default([]) sentReminderOffsets Int[] @default([]) remindedOneHour Boolean @default(false) remindedTenMinutes Boolean @default(false) startedAnnounced Boolean @default(false) announcedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([guildId, startsAt]) @@index([guildId, status]) } enum EventStatus { SCHEDULED CANCELLED COMPLETED } /// 길드별 유료 기능(특성) 플래그. 행이 없거나 해당 컬럼이 false면 미결제로 간주합니다. model GuildPayment { id String @id music Boolean @default(false) minigame Boolean @default(false) broadcast Boolean @default(false) @@map("guild_payment") } model MiniGameConfig { id String @id @default(uuid()) guildId String gameKey String enabled Boolean @default(false) channelId String? updatedAt DateTime @updatedAt @@index([guildId]) @@unique([guildId, gameKey]) } model RefinementProfile { userId String guildId String gold Int @default(1000) weaponLevel Int @default(0) maxWeaponLevel Int @default(0) durability Int @default(10) tryCount Int @default(0) successCount Int @default(0) failCount Int @default(0) destroyCount Int @default(0) battleWin Int @default(0) battleLoss Int @default(0) dailyBattleCount Int @default(0) isDisabled Boolean @default(false) lastCheckIn DateTime? lastBattleReset DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([userId, guildId]) @@index([guildId, weaponLevel(sort: Desc)]) } model AutoRoleConfig { guildId String @id userRoleIds String[] @default([]) botRoleIds String[] @default([]) isEnabled Boolean @default(false) botEnabled Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model RefinementLevelConfig { level Int @id successRate Float destroyRate Float sellMultiplier Float cost Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model RefinementBattleConfig { levelGap Int @id winRate Float createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model RefinementSystemConfig { key String @id value String description String? updatedAt DateTime @updatedAt } // 서버 활동 추이 (시간대별 메시지 수) model ActivityLog { id String @id @default(uuid()) guildId String hour Int dayOfWeek Int count Int @default(0) weekStart DateTime @@unique([guildId, hour, dayOfWeek, weekStart]) @@index([guildId, weekStart]) } // 피버 상태 model FeverState { guildId String @id isActive Boolean @default(false) peakHour Int? bonusRate Float @default(0.1) expiresAt DateTime? updatedAt DateTime @updatedAt } model FishingProfile { userId String guildId String totalCastCount Int @default(0) successCount Int @default(0) failCount Int @default(0) totalGoldEarned Int @default(0) bestCatchReward Int @default(0) commonCatchCount Int @default(0) uncommonCatchCount Int @default(0) rareCatchCount Int @default(0) epicCatchCount Int @default(0) legendaryCatchCount Int @default(0) lastCastAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([userId, guildId]) @@index([guildId, successCount(sort: Desc)]) } model FishingCollectionEntry { userId String guildId String fishId String catchCount Int @default(0) bestRarityId String bestRarityRank Int @default(0) bestSizeCm Float @default(0) lastCaughtAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([userId, guildId, fishId]) @@index([guildId, userId]) }