generator client { provider = "prisma-client-js" } 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 InviteRole { id String @id @default(uuid()) guildId String inviteCode String roleId String createdAt DateTime @default(now()) @@unique([guildId, inviteCode]) } 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 } // ─── Mini Game System ─────────────────────────────────────────────────────── // 서버별 미니게임 활성화 상태 관리 model MiniGameConfig { id String @id @default(uuid()) guildId String gameKey String enabled Boolean @default(false) channelId String? updatedAt DateTime @updatedAt @@unique([guildId, gameKey]) @@index([guildId]) } // 재련 - 유저 상태 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) lastBattleReset DateTime @default(now()) isDisabled Boolean @default(false) lastCheckIn DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([userId, guildId]) @@index([guildId, weaponLevel(sort: Desc)]) } // 재련 - 레벨별 수치 설정 (수치 대조 및 수정용) 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]) }