222 lines
9.3 KiB
Plaintext
222 lines
9.3 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// ============================================
|
|
// 奖励流水表 (聚合根1 - 行为表, append-only)
|
|
// 记录每一笔奖励的创建、领取、结算、过期
|
|
// ============================================
|
|
model RewardLedgerEntry {
|
|
id BigInt @id @default(autoincrement()) @map("entry_id")
|
|
userId BigInt @map("user_id") // 接收奖励的用户ID
|
|
accountSequence String @map("account_sequence") @db.VarChar(20) // 账户序列号
|
|
|
|
// === 奖励来源 ===
|
|
sourceOrderNo String @map("source_order_no") @db.VarChar(50) // 来源认种订单号(字符串格式如PLT1765391584505Q0Q6QD)
|
|
sourceUserId BigInt @map("source_user_id") // 触发奖励的用户ID(认种者)
|
|
rightType String @map("right_type") @db.VarChar(50) // 权益类型
|
|
|
|
// === 奖励金额 ===
|
|
usdtAmount Decimal @map("usdt_amount") @db.Decimal(20, 8)
|
|
hashpowerAmount Decimal @default(0) @map("hashpower_amount") @db.Decimal(20, 8)
|
|
|
|
// === 奖励状态 ===
|
|
rewardStatus String @default("PENDING") @map("reward_status") @db.VarChar(20)
|
|
|
|
// === 时间戳 ===
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(6)
|
|
expireAt DateTime? @map("expire_at") // 过期时间(24h后)
|
|
claimedAt DateTime? @map("claimed_at") // 领取时间(用户认种)
|
|
settledAt DateTime? @map("settled_at") // 结算时间
|
|
expiredAt DateTime? @map("expired_at") // 实际过期时间
|
|
|
|
// === 备注 ===
|
|
memo String? @map("memo") @db.VarChar(500)
|
|
|
|
@@map("reward_ledger_entries")
|
|
@@index([userId, rewardStatus], name: "idx_user_status")
|
|
@@index([userId, createdAt(sort: Desc)], name: "idx_user_created")
|
|
@@index([accountSequence, rewardStatus], name: "idx_account_status")
|
|
@@index([accountSequence, createdAt(sort: Desc)], name: "idx_account_created")
|
|
@@index([sourceOrderNo], name: "idx_source_order")
|
|
@@index([sourceUserId], name: "idx_source_user")
|
|
@@index([rightType], name: "idx_right_type")
|
|
@@index([rewardStatus], name: "idx_status")
|
|
@@index([expireAt], name: "idx_expire")
|
|
@@index([createdAt], name: "idx_created")
|
|
}
|
|
|
|
// ============================================
|
|
// 奖励汇总表 (聚合根2 - 状态表)
|
|
// 每个用户的收益汇总,从流水表聚合
|
|
// ============================================
|
|
model RewardSummary {
|
|
id BigInt @id @default(autoincrement()) @map("summary_id")
|
|
userId BigInt @unique @map("user_id")
|
|
accountSequence String @unique @map("account_sequence") @db.VarChar(20) // 账户序列号
|
|
|
|
// === 待领取收益 (24h倒计时) ===
|
|
pendingUsdt Decimal @default(0) @map("pending_usdt") @db.Decimal(20, 8)
|
|
pendingHashpower Decimal @default(0) @map("pending_hashpower") @db.Decimal(20, 8)
|
|
pendingExpireAt DateTime? @map("pending_expire_at") // 最早过期时间
|
|
|
|
// === 可结算收益 ===
|
|
settleableUsdt Decimal @default(0) @map("settleable_usdt") @db.Decimal(20, 8)
|
|
settleableHashpower Decimal @default(0) @map("settleable_hashpower") @db.Decimal(20, 8)
|
|
|
|
// === 已结算收益 (累计) ===
|
|
settledTotalUsdt Decimal @default(0) @map("settled_total_usdt") @db.Decimal(20, 8)
|
|
settledTotalHashpower Decimal @default(0) @map("settled_total_hashpower") @db.Decimal(20, 8)
|
|
|
|
// === 已过期收益 (累计) ===
|
|
expiredTotalUsdt Decimal @default(0) @map("expired_total_usdt") @db.Decimal(20, 8)
|
|
expiredTotalHashpower Decimal @default(0) @map("expired_total_hashpower") @db.Decimal(20, 8)
|
|
|
|
// === 时间戳 ===
|
|
lastUpdateAt DateTime @default(now()) @updatedAt @map("last_update_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
@@map("reward_summaries")
|
|
@@index([userId], name: "idx_summary_user")
|
|
@@index([accountSequence], name: "idx_summary_account")
|
|
@@index([settleableUsdt(sort: Desc)], name: "idx_settleable_desc")
|
|
@@index([pendingExpireAt], name: "idx_pending_expire")
|
|
}
|
|
|
|
// ============================================
|
|
// 权益定义表 (配置表)
|
|
// 定义每种权益的奖励规则
|
|
// ============================================
|
|
model RightDefinition {
|
|
id BigInt @id @default(autoincrement()) @map("definition_id")
|
|
rightType String @unique @map("right_type") @db.VarChar(50)
|
|
|
|
// === 奖励规则 ===
|
|
usdtPerTree Decimal @map("usdt_per_tree") @db.Decimal(20, 8)
|
|
hashpowerPercent Decimal @default(0) @map("hashpower_percent") @db.Decimal(5, 2)
|
|
|
|
// === 分配目标 ===
|
|
payableTo String @map("payable_to") @db.VarChar(50) // USER_ACCOUNT/SYSTEM_ACCOUNT/HEADQUARTERS
|
|
|
|
// === 规则描述 ===
|
|
ruleDescription String? @map("rule_description") @db.Text
|
|
|
|
// === 启用状态 ===
|
|
isEnabled Boolean @default(true) @map("is_enabled")
|
|
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
@@map("right_definitions")
|
|
@@index([rightType], name: "idx_def_right_type")
|
|
@@index([isEnabled], name: "idx_def_enabled")
|
|
}
|
|
|
|
// ============================================
|
|
// 结算记录表 (行为表)
|
|
// 记录每次结算的详情
|
|
// ============================================
|
|
model SettlementRecord {
|
|
id BigInt @id @default(autoincrement()) @map("settlement_id")
|
|
userId BigInt @map("user_id")
|
|
accountSequence String @map("account_sequence") @db.VarChar(20) // 账户序列号
|
|
|
|
// === 结算金额 ===
|
|
usdtAmount Decimal @map("usdt_amount") @db.Decimal(20, 8)
|
|
hashpowerAmount Decimal @map("hashpower_amount") @db.Decimal(20, 8)
|
|
|
|
// === 结算币种 ===
|
|
settleCurrency String @map("settle_currency") @db.VarChar(10) // BNB/OG/USDT/DST
|
|
receivedAmount Decimal @map("received_amount") @db.Decimal(20, 8) // 实际收到的币种数量
|
|
|
|
// === 交易信息 ===
|
|
swapTxHash String? @map("swap_tx_hash") @db.VarChar(100)
|
|
swapRate Decimal? @map("swap_rate") @db.Decimal(20, 8) // SWAP汇率
|
|
|
|
// === 状态 ===
|
|
status String @default("PENDING") @map("status") @db.VarChar(20) // PENDING/SUCCESS/FAILED
|
|
|
|
// === 时间戳 ===
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
completedAt DateTime? @map("completed_at")
|
|
|
|
// === 关联的奖励条目ID列表 ===
|
|
rewardEntryIds BigInt[] @map("reward_entry_ids")
|
|
|
|
@@map("settlement_records")
|
|
@@index([userId], name: "idx_settlement_user")
|
|
@@index([accountSequence], name: "idx_settlement_account")
|
|
@@index([status], name: "idx_settlement_status")
|
|
@@index([createdAt], name: "idx_settlement_created")
|
|
}
|
|
|
|
// ============================================
|
|
// 奖励事件表 (行为表, append-only)
|
|
// 用于事件溯源和审计
|
|
// ============================================
|
|
model RewardEvent {
|
|
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("reward_events")
|
|
@@index([aggregateType, aggregateId], name: "idx_reward_event_aggregate")
|
|
@@index([eventType], name: "idx_reward_event_type")
|
|
@@index([userId], name: "idx_reward_event_user")
|
|
@@index([occurredAt], name: "idx_reward_event_occurred")
|
|
}
|
|
|
|
// ============================================
|
|
// Outbox 事件发件箱表 (Outbox Pattern)
|
|
// 保证事件发布的可靠性:
|
|
// 1. 业务数据和 Outbox 记录在同一个事务中写入
|
|
// 2. 后台任务轮询 Outbox 表并发布到 Kafka
|
|
// 3. 消费方确认后标记为 CONFIRMED
|
|
// ============================================
|
|
model OutboxEvent {
|
|
id BigInt @id @default(autoincrement()) @map("outbox_id")
|
|
|
|
// 事件信息
|
|
eventType String @map("event_type") @db.VarChar(100)
|
|
topic String @map("topic") @db.VarChar(100)
|
|
key String @map("key") @db.VarChar(200)
|
|
payload Json @map("payload")
|
|
|
|
// 聚合根信息 (用于幂等性检查)
|
|
aggregateId String @map("aggregate_id") @db.VarChar(100)
|
|
aggregateType String @map("aggregate_type") @db.VarChar(50)
|
|
|
|
// 发布状态: PENDING -> SENT -> CONFIRMED 或 FAILED
|
|
status String @default("PENDING") @map("status") @db.VarChar(20)
|
|
retryCount Int @default(0) @map("retry_count")
|
|
maxRetries Int @default(5) @map("max_retries")
|
|
lastError String? @map("last_error") @db.Text
|
|
|
|
// 时间戳
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
publishedAt DateTime? @map("published_at")
|
|
nextRetryAt DateTime? @map("next_retry_at")
|
|
|
|
@@map("outbox_events")
|
|
@@index([status, createdAt], name: "idx_outbox_status_created")
|
|
@@index([status, nextRetryAt], name: "idx_outbox_status_retry")
|
|
@@index([aggregateType, aggregateId], name: "idx_outbox_aggregate")
|
|
@@index([topic], name: "idx_outbox_topic")
|
|
}
|