generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================ // 钱包账户表 (状态表) // ============================================ model WalletAccount { id BigInt @id @default(autoincrement()) @map("wallet_id") accountSequence String @unique @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 (全局唯一业务ID) userId BigInt @unique @map("user_id") // 保留兼容 // USDT 余额 usdtAvailable Decimal @default(0) @map("usdt_available") @db.Decimal(20, 8) usdtFrozen Decimal @default(0) @map("usdt_frozen") @db.Decimal(20, 8) // DST 余额 dstAvailable Decimal @default(0) @map("dst_available") @db.Decimal(20, 8) dstFrozen Decimal @default(0) @map("dst_frozen") @db.Decimal(20, 8) // BNB 余额 bnbAvailable Decimal @default(0) @map("bnb_available") @db.Decimal(20, 8) bnbFrozen Decimal @default(0) @map("bnb_frozen") @db.Decimal(20, 8) // OG 余额 ogAvailable Decimal @default(0) @map("og_available") @db.Decimal(20, 8) ogFrozen Decimal @default(0) @map("og_frozen") @db.Decimal(20, 8) // RWAD 余额 rwadAvailable Decimal @default(0) @map("rwad_available") @db.Decimal(20, 8) rwadFrozen Decimal @default(0) @map("rwad_frozen") @db.Decimal(20, 8) // 算力 hashpower Decimal @default(0) @map("hashpower") @db.Decimal(20, 8) // 待领取收益 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) // 状态 status String @default("ACTIVE") @map("status") @db.VarChar(20) // 是否已认种过(认种后分享权益直接进入可结算) hasPlanted Boolean @default(false) @map("has_planted") // 乐观锁版本号 version Int @default(0) @map("version") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("wallet_accounts") @@index([userId]) @@index([usdtAvailable(sort: Desc)]) @@index([hashpower(sort: Desc)]) @@index([status]) } // ============================================ // 账本流水表 (行为表, append-only) // ============================================ model LedgerEntry { id BigInt @id @default(autoincrement()) @map("entry_id") accountSequence String @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 userId BigInt @map("user_id") // 保留兼容 // 流水类型 entryType String @map("entry_type") @db.VarChar(50) // 金额变动 (正数入账, 负数支出) amount Decimal @map("amount") @db.Decimal(20, 8) assetType String @map("asset_type") @db.VarChar(20) // 余额快照 (操作后余额) balanceAfter Decimal? @map("balance_after") @db.Decimal(20, 8) // 关联引用 refOrderId String? @map("ref_order_id") @db.VarChar(100) refTxHash String? @map("ref_tx_hash") @db.VarChar(100) // 备注 memo String? @map("memo") @db.VarChar(500) // 扩展数据 payloadJson Json? @map("payload_json") createdAt DateTime @default(now()) @map("created_at") @@map("wallet_ledger_entries") @@index([accountSequence, createdAt(sort: Desc)]) @@index([userId, createdAt(sort: Desc)]) @@index([entryType]) @@index([assetType]) @@index([refOrderId]) @@index([refTxHash]) @@index([createdAt]) } // ============================================ // 充值订单表 // ============================================ model DepositOrder { id BigInt @id @default(autoincrement()) @map("order_id") accountSequence String @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 userId BigInt @map("user_id") // 保留兼容 // 充值信息 chainType String @map("chain_type") @db.VarChar(20) amount Decimal @map("amount") @db.Decimal(20, 8) txHash String @unique @map("tx_hash") @db.VarChar(100) // 状态 status String @default("PENDING") @map("status") @db.VarChar(20) confirmedAt DateTime? @map("confirmed_at") createdAt DateTime @default(now()) @map("created_at") @@map("deposit_orders") @@index([accountSequence]) @@index([userId]) @@index([txHash]) @@index([status]) @@index([chainType]) } // ============================================ // 结算订单表 // ============================================ model SettlementOrder { id BigInt @id @default(autoincrement()) @map("order_id") userId BigInt @map("user_id") // 结算信息 usdtAmount Decimal @map("usdt_amount") @db.Decimal(20, 8) settleCurrency String @map("settle_currency") @db.VarChar(10) // SWAP 信息 swapTxHash String? @map("swap_tx_hash") @db.VarChar(100) receivedAmount Decimal? @map("received_amount") @db.Decimal(20, 8) // 状态 status String @default("PENDING") @map("status") @db.VarChar(20) settledAt DateTime? @map("settled_at") createdAt DateTime @default(now()) @map("created_at") @@map("settlement_orders") @@index([userId]) @@index([status]) @@index([settleCurrency]) @@index([createdAt]) } // ============================================ // 提现订单表 // ============================================ model WithdrawalOrder { id BigInt @id @default(autoincrement()) @map("order_id") orderNo String @unique @map("order_no") @db.VarChar(50) accountSequence String @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 userId BigInt @map("user_id") // 提现信息 amount Decimal @map("amount") @db.Decimal(20, 8) // 提现金额 fee Decimal @map("fee") @db.Decimal(20, 8) // 手续费 chainType String @map("chain_type") @db.VarChar(20) // 目标链 (BSC/KAVA) toAddress String @map("to_address") @db.VarChar(100) // 提现目标地址 // 交易信息 txHash String? @map("tx_hash") @db.VarChar(100) // 链上交易哈希 // 内部转账标识 isInternalTransfer Boolean @default(false) @map("is_internal_transfer") // 是否为内部转账(ID转ID) toAccountSequence String? @map("to_account_sequence") @db.VarChar(20) // 接收方ID(内部转账时有值) toUserId BigInt? @map("to_user_id") // 接收方用户ID(内部转账时有值) // 状态 status String @default("PENDING") @map("status") @db.VarChar(20) errorMessage String? @map("error_message") @db.VarChar(500) // 时间戳 frozenAt DateTime? @map("frozen_at") broadcastedAt DateTime? @map("broadcasted_at") confirmedAt DateTime? @map("confirmed_at") createdAt DateTime @default(now()) @map("created_at") @@map("withdrawal_orders") @@index([accountSequence]) @@index([userId]) @@index([status]) @@index([chainType]) @@index([txHash]) @@index([createdAt]) } // ============================================ // 待领取奖励表 (逐笔记录) // 每笔待领取奖励独立跟踪过期时间 // ============================================ model PendingReward { id BigInt @id @default(autoincrement()) @map("pending_reward_id") accountSequence String @map("account_sequence") @db.VarChar(20) // 跨服务关联标识 userId BigInt @map("user_id") // 保留兼容 // 奖励金额 usdtAmount Decimal @map("usdt_amount") @db.Decimal(20, 8) hashpowerAmount Decimal @map("hashpower_amount") @db.Decimal(20, 8) // 来源信息 sourceOrderId String @map("source_order_id") @db.VarChar(100) // 触发奖励的认种订单 allocationType String @map("allocation_type") @db.VarChar(50) // 分配类型 (SHARE_RIGHT, TEAM_RIGHT 等) // 过期时间 expireAt DateTime @map("expire_at") // 状态: PENDING(待领取) / SETTLED(已结算) / EXPIRED(已过期) status String @default("PENDING") @map("status") @db.VarChar(20) // 结算/过期时间 settledAt DateTime? @map("settled_at") expiredAt DateTime? @map("expired_at") createdAt DateTime @default(now()) @map("created_at") @@map("pending_rewards") @@index([accountSequence, status]) @@index([userId, status]) @@index([status, expireAt]) // 用于定时任务查询过期奖励 @@index([sourceOrderId]) @@index([createdAt]) } // ============================================ // 法币提现订单表 // 用于法币提现 (银行卡/支付宝/微信) // 与 WithdrawalOrder (区块链划转) 分开管理 // ============================================ model FiatWithdrawalOrder { id BigInt @id @default(autoincrement()) @map("order_id") orderNo String @unique @map("order_no") @db.VarChar(50) accountSequence String @map("account_sequence") @db.VarChar(20) userId BigInt @map("user_id") // 提现金额信息 amount Decimal @map("amount") @db.Decimal(20, 8) // 提现金额 (绿积分, 1:1 人民币) fee Decimal @map("fee") @db.Decimal(20, 8) // 手续费 // 收款方式: BANK_CARD / ALIPAY / WECHAT paymentMethod String @map("payment_method") @db.VarChar(20) // 银行卡信息 bankName String? @map("bank_name") @db.VarChar(100) bankCardNo String? @map("bank_card_no") @db.VarChar(50) cardHolderName String? @map("card_holder_name") @db.VarChar(100) // 支付宝信息 alipayAccount String? @map("alipay_account") @db.VarChar(100) alipayRealName String? @map("alipay_real_name") @db.VarChar(100) // 微信信息 wechatAccount String? @map("wechat_account") @db.VarChar(100) wechatRealName String? @map("wechat_real_name") @db.VarChar(100) // 状态: PENDING -> FROZEN -> REVIEWING -> APPROVED -> PAYING -> COMPLETED // 或 REJECTED / FAILED / CANCELLED status String @default("PENDING") @map("status") @db.VarChar(20) errorMessage String? @map("error_message") @db.VarChar(500) // 审核信息 reviewedBy String? @map("reviewed_by") @db.VarChar(100) reviewedAt DateTime? @map("reviewed_at") reviewRemark String? @map("review_remark") @db.VarChar(500) // 打款信息 paidBy String? @map("paid_by") @db.VarChar(100) paidAt DateTime? @map("paid_at") paymentProof String? @map("payment_proof") @db.VarChar(500) paymentRemark String? @map("payment_remark") @db.VarChar(500) // 详细备注 (操作记录) detailMemo String? @map("detail_memo") @db.Text // 时间戳 frozenAt DateTime? @map("frozen_at") completedAt DateTime? @map("completed_at") createdAt DateTime @default(now()) @map("created_at") @@map("fiat_withdrawal_orders") @@index([accountSequence]) @@index([userId]) @@index([status]) @@index([paymentMethod]) @@index([reviewedBy]) @@index([createdAt]) } // ============================================ // 提取手续费配置表 // ============================================ model WithdrawalFeeConfig { id BigInt @id @default(autoincrement()) @map("config_id") // 费率类型: FIXED(固定金额) / PERCENTAGE(百分比) feeType String @map("fee_type") @db.VarChar(20) // 费率值: 固定金额时为具体数值,百分比时为小数 (如 0.001 = 0.1%) feeValue Decimal @map("fee_value") @db.Decimal(20, 8) // 最小手续费 (百分比模式下生效) minFee Decimal @default(0) @map("min_fee") @db.Decimal(20, 8) // 最大手续费 (百分比模式下生效,0表示不限制) maxFee Decimal @default(0) @map("max_fee") @db.Decimal(20, 8) // 是否启用 isActive Boolean @default(true) @map("is_active") // 备注 memo String? @map("memo") @db.VarChar(200) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("withdrawal_fee_configs") @@index([isActive]) } // ============================================ // 已处理事件表 (幂等性检查) // 用于确保 Kafka 事件不会被重复处理 // ============================================ model ProcessedEvent { id BigInt @id @default(autoincrement()) @map("processed_id") // 事件标识 (聚合根ID + 事件类型) eventId String @map("event_id") @db.VarChar(200) eventType String @map("event_type") @db.VarChar(100) // 来源服务 sourceService String @map("source_service") @db.VarChar(50) // 处理时间 processedAt DateTime @default(now()) @map("processed_at") @@unique([eventId, eventType]) @@map("processed_events") @@index([eventId]) @@index([eventType]) @@index([processedAt]) }