rwadurian/backend/services/identity-service/prisma/schema.prisma

177 lines
5.7 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// 用户账户表
model UserAccount {
id 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)
// KYC信息
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[]
events UserEvent[]
@@index([phoneNumber])
@@index([accountSequence])
@@index([referralCode])
@@index([inviterSequence])
@@index([provinceCode, cityCode])
@@index([kycStatus])
@@index([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: [id], onDelete: Cascade)
@@unique([userId, deviceId])
@@index([deviceId])
@@index([userId])
@@index([lastActiveAt])
@@map("user_devices")
}
// 区块链钱包地址表
model WalletAddress {
id 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: [id], onDelete: Cascade)
@@unique([userId, chainType])
@@unique([chainType, address])
@@index([userId])
@@index([address])
@@map("wallet_addresses")
}
// 设备Token表
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])
@@index([expiresAt])
@@map("device_tokens")
}
// 用户事件表
model UserEvent {
id 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.Timestamptz(6)
version Int @default(1)
user UserAccount? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([aggregateType, aggregateId])
@@index([eventType])
@@index([userId])
@@index([occurredAt])
@@map("user_events")
}
// 短信验证码表
model SmsCode {
id BigInt @id @default(autoincrement())
phoneNumber String @map("phone_number") @db.VarChar(20)
code String @db.VarChar(6)
type String @db.VarChar(20) // REGISTER, LOGIN, BIND, RECOVER
expiresAt DateTime @map("expires_at")
usedAt DateTime? @map("used_at")
createdAt DateTime @default(now()) @map("created_at")
@@index([phoneNumber, type])
@@index([expiresAt])
@@map("sms_codes")
}
// 死信队列表
model DeadLetterEvent {
id BigInt @id @default(autoincrement())
topic String @db.VarChar(100)
eventId String @map("event_id") @db.VarChar(50)
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])
@@index([eventType])
@@index([createdAt])
@@index([processedAt])
@@map("dead_letter_events")
}