generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model UserAccount { userId BigInt @id @default(autoincrement()) @map("user_id") accountSequence BigInt @unique @map("account_sequence") phoneNumber String? @unique @map("phone_number") @db.VarChar(20) nickname String @db.VarChar(100) avatarUrl String? @map("avatar_url") @db.VarChar(500) inviterSequence BigInt? @map("inviter_sequence") referralCode String @unique @map("referral_code") @db.VarChar(10) provinceCode String @map("province_code") @db.VarChar(10) cityCode String @map("city_code") @db.VarChar(10) address String? @db.VarChar(500) kycStatus String @default("NOT_VERIFIED") @map("kyc_status") @db.VarChar(20) realName String? @map("real_name") @db.VarChar(100) idCardNumber String? @map("id_card_number") @db.VarChar(20) idCardFrontUrl String? @map("id_card_front_url") @db.VarChar(500) idCardBackUrl String? @map("id_card_back_url") @db.VarChar(500) kycVerifiedAt DateTime? @map("kyc_verified_at") status String @default("ACTIVE") @db.VarChar(20) registeredAt DateTime @default(now()) @map("registered_at") lastLoginAt DateTime? @map("last_login_at") updatedAt DateTime @updatedAt @map("updated_at") devices UserDevice[] walletAddresses WalletAddress[] @@index([phoneNumber], name: "idx_phone") @@index([accountSequence], name: "idx_sequence") @@index([referralCode], name: "idx_referral_code") @@index([inviterSequence], name: "idx_inviter") @@index([provinceCode, cityCode], name: "idx_province_city") @@index([kycStatus], name: "idx_kyc_status") @@index([status], name: "idx_status") @@map("user_accounts") } model UserDevice { id BigInt @id @default(autoincrement()) userId BigInt @map("user_id") deviceId String @map("device_id") @db.VarChar(100) deviceName String? @map("device_name") @db.VarChar(100) addedAt DateTime @default(now()) @map("added_at") lastActiveAt DateTime @default(now()) @map("last_active_at") user UserAccount @relation(fields: [userId], references: [userId], onDelete: Cascade) @@unique([userId, deviceId], name: "uk_user_device") @@index([deviceId], name: "idx_device") @@index([userId], name: "idx_user") @@index([lastActiveAt], name: "idx_last_active") @@map("user_devices") } model WalletAddress { addressId BigInt @id @default(autoincrement()) @map("address_id") userId BigInt @map("user_id") chainType String @map("chain_type") @db.VarChar(20) address String @db.VarChar(100) encryptedMnemonic String? @map("encrypted_mnemonic") @db.Text status String @default("ACTIVE") @db.VarChar(20) boundAt DateTime @default(now()) @map("bound_at") user UserAccount @relation(fields: [userId], references: [userId], onDelete: Cascade) @@unique([userId, chainType], name: "uk_user_chain") @@unique([chainType, address], name: "uk_chain_address") @@index([userId], name: "idx_wallet_user") @@index([address], name: "idx_address") @@map("wallet_addresses") } model AccountSequenceGenerator { id Int @id @default(1) currentSequence BigInt @default(0) @map("current_sequence") updatedAt DateTime @updatedAt @map("updated_at") @@map("account_sequence_generator") } model UserEvent { eventId BigInt @id @default(autoincrement()) @map("event_id") eventType String @map("event_type") @db.VarChar(50) aggregateId String @map("aggregate_id") @db.VarChar(100) aggregateType String @map("aggregate_type") @db.VarChar(50) eventData Json @map("event_data") userId BigInt? @map("user_id") occurredAt DateTime @default(now()) @map("occurred_at") @db.Timestamp(6) version Int @default(1) @@index([aggregateType, aggregateId], name: "idx_aggregate") @@index([eventType], name: "idx_event_type") @@index([userId], name: "idx_event_user") @@index([occurredAt], name: "idx_occurred") @@map("user_events") } model DeviceToken { id BigInt @id @default(autoincrement()) userId BigInt @map("user_id") deviceId String @map("device_id") @db.VarChar(100) refreshTokenHash String @unique @map("refresh_token_hash") @db.VarChar(64) expiresAt DateTime @map("expires_at") createdAt DateTime @default(now()) @map("created_at") revokedAt DateTime? @map("revoked_at") @@index([userId, deviceId], name: "idx_user_device_token") @@index([expiresAt], name: "idx_expires") @@map("device_tokens") } model DeadLetterEvent { id BigInt @id @default(autoincrement()) topic String @db.VarChar(100) eventId String @map("event_id") @db.VarChar(100) eventType String @map("event_type") @db.VarChar(50) aggregateId String @map("aggregate_id") @db.VarChar(100) aggregateType String @map("aggregate_type") @db.VarChar(50) payload Json? errorMessage String @map("error_message") @db.Text errorStack String? @map("error_stack") @db.Text retryCount Int @default(0) @map("retry_count") createdAt DateTime @default(now()) @map("created_at") processedAt DateTime? @map("processed_at") @@index([topic], name: "idx_topic") @@index([eventType], name: "idx_dead_letter_event_type") @@index([createdAt], name: "idx_dead_letter_created") @@index([processedAt], name: "idx_processed") @@map("dead_letter_events") } model SmsCode { id BigInt @id @default(autoincrement()) phoneNumber String @map("phone_number") @db.VarChar(20) code String @db.VarChar(10) purpose String @db.VarChar(50) expiresAt DateTime @map("expires_at") createdAt DateTime @default(now()) @map("created_at") usedAt DateTime? @map("used_at") @@index([phoneNumber, purpose], name: "idx_phone_purpose") @@index([expiresAt], name: "idx_sms_expires") @@map("sms_codes") }