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

237 lines
9.5 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ============================================
// 龙虎榜排名表 (聚合根1)
// 存储各周期榜单的实际排名数据
// ============================================
model LeaderboardRanking {
id BigInt @id @default(autoincrement()) @map("ranking_id")
// === 榜单信息 ===
leaderboardType String @map("leaderboard_type") @db.VarChar(30) // DAILY/WEEKLY/MONTHLY
periodKey String @map("period_key") @db.VarChar(20) // 2024-01-15 / 2024-W03 / 2024-01
// === 用户信息 ===
userId BigInt @map("user_id")
isVirtual Boolean @default(false) @map("is_virtual") // 是否虚拟账户
// === 排名信息 ===
rankPosition Int @map("rank_position") // 实际排名
displayPosition Int @map("display_position") // 显示排名(含虚拟)
previousRank Int? @map("previous_rank") // 上次排名
// === 分值信息 ===
totalTeamPlanting Int @default(0) @map("total_team_planting") // 团队总认种
maxDirectTeamPlanting Int @default(0) @map("max_direct_team_planting") // 最大直推团队认种
effectiveScore Int @default(0) @map("effective_score") // 有效分值
// === 用户快照 ===
userSnapshot Json @map("user_snapshot") // { nickname, avatar, accountNo }
// === 时间戳 ===
periodStartAt DateTime @map("period_start_at")
periodEndAt DateTime @map("period_end_at")
calculatedAt DateTime @default(now()) @map("calculated_at")
createdAt DateTime @default(now()) @map("created_at")
@@unique([leaderboardType, periodKey, userId], name: "uk_type_period_user")
@@map("leaderboard_rankings")
@@index([leaderboardType, periodKey, displayPosition], name: "idx_display_rank")
@@index([leaderboardType, periodKey, effectiveScore(sort: Desc)], name: "idx_score")
@@index([userId], name: "idx_ranking_user")
@@index([periodKey], name: "idx_period")
@@index([isVirtual], name: "idx_virtual")
}
// ============================================
// 龙虎榜配置表 (聚合根2)
// 管理榜单开关、虚拟数量、显示设置
// ============================================
model LeaderboardConfig {
id BigInt @id @default(autoincrement()) @map("config_id")
configKey String @unique @map("config_key") @db.VarChar(50) // GLOBAL / DAILY / WEEKLY / MONTHLY
// === 榜单开关 ===
dailyEnabled Boolean @default(true) @map("daily_enabled")
weeklyEnabled Boolean @default(true) @map("weekly_enabled")
monthlyEnabled Boolean @default(true) @map("monthly_enabled")
// === 虚拟排名设置 ===
virtualRankingEnabled Boolean @default(false) @map("virtual_ranking_enabled")
virtualAccountCount Int @default(0) @map("virtual_account_count") // 虚拟账户数量
// === 显示设置 ===
displayLimit Int @default(30) @map("display_limit") // 前端显示数量
// === 刷新设置 ===
refreshIntervalMinutes Int @default(5) @map("refresh_interval_minutes")
// === 时间戳 ===
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("leaderboard_configs")
}
// ============================================
// 虚拟账户表
// 存储系统生成的虚拟排名账户
// ============================================
model VirtualAccount {
id BigInt @id @default(autoincrement()) @map("virtual_account_id")
// === 账户信息 ===
accountType String @map("account_type") @db.VarChar(30) // RANKING_VIRTUAL / SYSTEM_PROVINCE / SYSTEM_CITY / HEADQUARTERS
displayName String @map("display_name") @db.VarChar(100)
avatar String? @map("avatar") @db.VarChar(255)
// === 区域信息(省市公司用)===
provinceCode String? @map("province_code") @db.VarChar(10)
cityCode String? @map("city_code") @db.VarChar(10)
// === 虚拟分值范围(排名虚拟账户用)===
minScore Int? @map("min_score")
maxScore Int? @map("max_score")
currentScore Int @default(0) @map("current_score")
// === 账户余额(省市公司用)===
usdtBalance Decimal @default(0) @map("usdt_balance") @db.Decimal(20, 8)
hashpowerBalance Decimal @default(0) @map("hashpower_balance") @db.Decimal(20, 8)
// === 状态 ===
isActive Boolean @default(true) @map("is_active")
// === 时间戳 ===
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("virtual_accounts")
@@index([accountType], name: "idx_va_type")
@@index([provinceCode], name: "idx_va_province")
@@index([cityCode], name: "idx_va_city")
@@index([isActive], name: "idx_va_active")
}
// ============================================
// 虚拟排名条目表
// 每个周期的虚拟排名数据
// ============================================
model VirtualRankingEntry {
id BigInt @id @default(autoincrement()) @map("entry_id")
// === 关联虚拟账户 ===
virtualAccountId BigInt @map("virtual_account_id")
// === 榜单信息 ===
leaderboardType String @map("leaderboard_type") @db.VarChar(30)
periodKey String @map("period_key") @db.VarChar(20)
// === 排名信息 ===
displayPosition Int @map("display_position") // 占据的显示位置
generatedScore Int @map("generated_score") // 生成的分值
// === 显示信息 ===
displayName String @map("display_name") @db.VarChar(100)
avatar String? @map("avatar") @db.VarChar(255)
// === 时间戳 ===
createdAt DateTime @default(now()) @map("created_at")
@@unique([leaderboardType, periodKey, displayPosition], name: "uk_vr_type_period_pos")
@@map("virtual_ranking_entries")
@@index([virtualAccountId], name: "idx_vr_va")
@@index([leaderboardType, periodKey], name: "idx_vr_type_period")
}
// ============================================
// 榜单历史快照表
// 保存每个周期结束时的完整榜单数据
// ============================================
model LeaderboardSnapshot {
id BigInt @id @default(autoincrement()) @map("snapshot_id")
// === 榜单信息 ===
leaderboardType String @map("leaderboard_type") @db.VarChar(30)
periodKey String @map("period_key") @db.VarChar(20)
// === 快照数据 ===
rankingsData Json @map("rankings_data") // 完整排名数据
// === 统计信息 ===
totalParticipants Int @map("total_participants") // 参与人数
topScore Int @map("top_score") // 最高分
averageScore Int @map("average_score") // 平均分
// === 时间戳 ===
periodStartAt DateTime @map("period_start_at")
periodEndAt DateTime @map("period_end_at")
snapshotAt DateTime @default(now()) @map("snapshot_at")
@@unique([leaderboardType, periodKey], name: "uk_snapshot_type_period")
@@map("leaderboard_snapshots")
@@index([leaderboardType], name: "idx_snapshot_type")
@@index([periodKey], name: "idx_snapshot_period")
}
// ============================================
// 虚拟账户交易记录表
// 记录省市公司账户的资金变动
// ============================================
model VirtualAccountTransaction {
id BigInt @id @default(autoincrement()) @map("transaction_id")
virtualAccountId BigInt @map("virtual_account_id")
// === 交易信息 ===
transactionType String @map("transaction_type") @db.VarChar(30) // INCOME / EXPENSE
amount Decimal @map("amount") @db.Decimal(20, 8)
currency String @map("currency") @db.VarChar(10) // USDT / HASHPOWER
// === 来源信息 ===
sourceType String? @map("source_type") @db.VarChar(50) // PLANTING_REWARD / MANUAL
sourceId String? @map("source_id") @db.VarChar(100)
sourceUserId BigInt? @map("source_user_id")
// === 备注 ===
memo String? @map("memo") @db.VarChar(500)
// === 时间戳 ===
createdAt DateTime @default(now()) @map("created_at")
@@map("virtual_account_transactions")
@@index([virtualAccountId], name: "idx_vat_account")
@@index([transactionType], name: "idx_vat_type")
@@index([createdAt(sort: Desc)], name: "idx_vat_created")
}
// ============================================
// 龙虎榜事件表
// ============================================
model LeaderboardEvent {
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.Timestamp(6)
version Int @default(1) @map("version")
@@map("leaderboard_events")
@@index([aggregateType, aggregateId], name: "idx_lb_event_aggregate")
@@index([eventType], name: "idx_lb_event_type")
@@index([occurredAt], name: "idx_lb_event_occurred")
}