// ============================================================================= // Mining Wallet Service - Prisma Schema // 100% 独立于 1.0 系统,完全隔离的钱包管理服务 // ============================================================================= generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================================================= // 枚举定义 // ============================================================================= // 系统账户类型 enum SystemAccountType { HEADQUARTERS // 总部账户 OPERATION // 运营账户 PROVINCE // 省级公司账户 CITY // 市级公司账户 FEE // 手续费账户 } // 池账户类型 enum PoolAccountType { SHARE_POOL // 积分股池 - 总股池 BLACK_HOLE_POOL // 黑洞积分股池 - 销毁池 CIRCULATION_POOL // 流通积分股池 - 交易流通池 } // 用户钱包账户类型 enum UserWalletType { CONTRIBUTION // 算力账户(hashpower/contribution) TOKEN_STORAGE // 积分股存储账户 GREEN_POINTS // 绿色积分账户 } // 资产类型 enum AssetType { SHARE // 积分股 (RWA Token) USDT // USDT 稳定币 GREEN_POINT // 绿色积分 CONTRIBUTION // 算力值 } // 交易类型 enum TransactionType { // 挖矿相关 MINING_REWARD // 挖矿奖励 MINING_DISTRIBUTE // 挖矿分配 // 划转相关 TRANSFER_IN // 划入 TRANSFER_OUT // 划出 INTERNAL_TRANSFER // 内部划转 // 交易相关 TRADE_BUY // 买入 TRADE_SELL // 卖出 // 提现/充值 WITHDRAW // 提现到链上 DEPOSIT // 从链上充值 // 销毁 BURN // 销毁到黑洞 // 冻结/解冻 FREEZE // 冻结 UNFREEZE // 解冻 // 手续费 FEE_COLLECT // 收取手续费 FEE_DISTRIBUTE // 分发手续费 // 池操作 POOL_INJECT // 注入池 POOL_EXTRACT // 从池提取 // 系统调整 ADJUSTMENT // 系统调整 INITIAL_INJECT // 初始注入 } // 交易对手方类型 enum CounterpartyType { USER // 用户 SYSTEM_ACCOUNT // 系统账户 POOL // 池账户 EXTERNAL // 外部 } // Outbox 状态 enum OutboxStatus { PENDING PUBLISHED FAILED } // ============================================================================= // 区域管理(100% 独立于 1.0) // ============================================================================= // 省份 model Province { id String @id @default(uuid()) code String @unique // 省份代码 e.g. "GD" name String // 省份名称 e.g. "广东省" status String @default("ACTIVE") // ACTIVE, DISABLED createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cities City[] systemAccounts SystemAccount[] @@index([code]) @@map("provinces") } // 城市 model City { id String @id @default(uuid()) provinceId String @map("province_id") code String @unique // 城市代码 e.g. "SZ" name String // 城市名称 e.g. "深圳市" status String @default("ACTIVE") // ACTIVE, DISABLED createdAt DateTime @default(now()) updatedAt DateTime @updatedAt province Province @relation(fields: [provinceId], references: [id]) userMappings UserRegionMapping[] systemAccounts SystemAccount[] @@index([provinceId]) @@index([code]) @@map("cities") } // 用户区域映射(100% 独立于 1.0) model UserRegionMapping { id String @id @default(uuid()) accountSequence String @unique @map("account_sequence") // 用户账户序列号 cityId String @map("city_id") assignedAt DateTime @default(now()) @map("assigned_at") assignedBy String? @map("assigned_by") // 分配人(管理员ID) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt city City @relation(fields: [cityId], references: [id]) @@index([cityId]) @@map("user_region_mappings") } // ============================================================================= // 系统账户(HQ、运营、省/市公司、手续费、热/冷钱包) // ============================================================================= model SystemAccount { id String @id @default(uuid()) accountType SystemAccountType @map("account_type") name String // 账户名称 code String @unique // 账户代码 e.g. "HQ", "OP", "GD-SZ" // 关联区域(省/市级公司账户使用) provinceId String? @map("province_id") cityId String? @map("city_id") // 余额信息 shareBalance Decimal @default(0) @map("share_balance") @db.Decimal(30, 8) usdtBalance Decimal @default(0) @map("usdt_balance") @db.Decimal(30, 8) greenPointBalance Decimal @default(0) @map("green_point_balance") @db.Decimal(30, 8) contributionBalance Decimal @default(0) @map("contribution_balance") @db.Decimal(30, 8) frozenShare Decimal @default(0) @map("frozen_share") @db.Decimal(30, 8) frozenUsdt Decimal @default(0) @map("frozen_usdt") @db.Decimal(30, 8) // 累计统计 totalInflow Decimal @default(0) @map("total_inflow") @db.Decimal(30, 8) totalOutflow Decimal @default(0) @map("total_outflow") @db.Decimal(30, 8) // 链上地址(热/冷钱包使用) blockchainAddress String? @map("blockchain_address") description String? isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") province Province? @relation(fields: [provinceId], references: [id]) city City? @relation(fields: [cityId], references: [id]) transactions SystemAccountTransaction[] @@unique([accountType, provinceId, cityId]) @@index([accountType]) @@index([provinceId]) @@index([cityId]) @@map("system_accounts") } // 系统账户交易明细 model SystemAccountTransaction { id String @id @default(uuid()) systemAccountId String @map("system_account_id") transactionType TransactionType @map("transaction_type") assetType AssetType @map("asset_type") // 金额信息 amount Decimal @db.Decimal(30, 8) balanceBefore Decimal @map("balance_before") @db.Decimal(30, 8) balanceAfter Decimal @map("balance_after") @db.Decimal(30, 8) // 交易对手方信息 counterpartyType CounterpartyType? @map("counterparty_type") counterpartyAccountSeq String? @map("counterparty_account_seq") counterpartyUserId String? @map("counterparty_user_id") counterpartySystemId String? @map("counterparty_system_id") counterpartyPoolType PoolAccountType? @map("counterparty_pool_type") counterpartyAddress String? @map("counterparty_address") // 关联信息 referenceId String? @map("reference_id") referenceType String? @map("reference_type") txHash String? @map("tx_hash") // 详细备注(格式: "手续费收取自用户[U123456], 交易订单ORD20240110001") memo String? @db.Text metadata Json? createdAt DateTime @default(now()) @map("created_at") systemAccount SystemAccount @relation(fields: [systemAccountId], references: [id]) @@index([systemAccountId, createdAt(sort: Desc)]) @@index([transactionType]) @@index([counterpartyAccountSeq]) @@index([counterpartyUserId]) @@index([referenceId]) @@index([createdAt(sort: Desc)]) @@map("system_account_transactions") } // ============================================================================= // 池账户(积分股池、黑洞池、流通池) // ============================================================================= model PoolAccount { id String @id @default(uuid()) poolType PoolAccountType @unique @map("pool_type") name String // 余额信息 balance Decimal @default(0) @db.Decimal(30, 8) totalInflow Decimal @default(0) @map("total_inflow") @db.Decimal(30, 8) totalOutflow Decimal @default(0) @map("total_outflow") @db.Decimal(30, 8) // 黑洞池特有字段 targetBurn Decimal? @map("target_burn") @db.Decimal(30, 8) remainingBurn Decimal? @map("remaining_burn") @db.Decimal(30, 8) isActive Boolean @default(true) @map("is_active") description String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") transactions PoolAccountTransaction[] @@index([poolType]) @@map("pool_accounts") } // 池账户交易明细 model PoolAccountTransaction { id String @id @default(uuid()) poolAccountId String @map("pool_account_id") poolType PoolAccountType @map("pool_type") transactionType TransactionType @map("transaction_type") // 金额信息 amount Decimal @db.Decimal(30, 8) balanceBefore Decimal @map("balance_before") @db.Decimal(30, 8) balanceAfter Decimal @map("balance_after") @db.Decimal(30, 8) // 交易对手方信息(关键:用户ID和账户序列号) counterpartyType CounterpartyType? @map("counterparty_type") counterpartyAccountSeq String? @map("counterparty_account_seq") counterpartyUserId String? @map("counterparty_user_id") counterpartySystemId String? @map("counterparty_system_id") counterpartyPoolType PoolAccountType? @map("counterparty_pool_type") counterpartyAddress String? @map("counterparty_address") // 关联信息 referenceId String? @map("reference_id") referenceType String? @map("reference_type") txHash String? @map("tx_hash") // 详细备注(格式: "挖矿分配给用户[U123456], 算力占比0.5%, 分钟2024-01-10 10:30") memo String? @db.Text metadata Json? createdAt DateTime @default(now()) @map("created_at") poolAccount PoolAccount @relation(fields: [poolAccountId], references: [id]) @@index([poolAccountId, createdAt(sort: Desc)]) @@index([poolType, transactionType]) @@index([counterpartyAccountSeq]) @@index([counterpartyUserId]) @@index([referenceId]) @@index([createdAt(sort: Desc)]) @@map("pool_account_transactions") } // ============================================================================= // 用户钱包账户 // ============================================================================= // 用户钱包(每个用户有多个钱包类型) model UserWallet { id String @id @default(uuid()) accountSequence String @map("account_sequence") walletType UserWalletType @map("wallet_type") // 余额信息 balance Decimal @default(0) @db.Decimal(30, 8) frozenBalance Decimal @default(0) @map("frozen_balance") @db.Decimal(30, 8) // 累计统计 totalInflow Decimal @default(0) @map("total_inflow") @db.Decimal(30, 8) totalOutflow Decimal @default(0) @map("total_outflow") @db.Decimal(30, 8) isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") transactions UserWalletTransaction[] @@unique([accountSequence, walletType]) @@index([accountSequence]) @@index([walletType]) @@map("user_wallets") } // 用户钱包交易明细 model UserWalletTransaction { id String @id @default(uuid()) userWalletId String @map("user_wallet_id") accountSequence String @map("account_sequence") walletType UserWalletType @map("wallet_type") transactionType TransactionType @map("transaction_type") assetType AssetType @map("asset_type") // 金额信息 amount Decimal @db.Decimal(30, 8) balanceBefore Decimal @map("balance_before") @db.Decimal(30, 8) balanceAfter Decimal @map("balance_after") @db.Decimal(30, 8) // 交易对手方信息(关键:用户ID和账户序列号) counterpartyType CounterpartyType? @map("counterparty_type") counterpartyAccountSeq String? @map("counterparty_account_seq") counterpartyUserId String? @map("counterparty_user_id") counterpartySystemId String? @map("counterparty_system_id") counterpartyPoolType PoolAccountType? @map("counterparty_pool_type") counterpartyAddress String? @map("counterparty_address") // 关联信息 referenceId String? @map("reference_id") referenceType String? @map("reference_type") txHash String? @map("tx_hash") // 详细备注(格式: "划转到交易账户, 接收方用户[U789012]") memo String? @db.Text metadata Json? createdAt DateTime @default(now()) @map("created_at") userWallet UserWallet @relation(fields: [userWalletId], references: [id]) @@index([userWalletId, createdAt(sort: Desc)]) @@index([accountSequence, walletType]) @@index([transactionType]) @@index([counterpartyAccountSeq]) @@index([counterpartyUserId]) @@index([referenceId]) @@index([createdAt(sort: Desc)]) @@map("user_wallet_transactions") } // ============================================================================= // 手续费配置 // ============================================================================= model FeeConfig { id String @id @default(uuid()) feeType String @unique @map("fee_type") // WITHDRAW, TRADE, SWAP, TRANSFER // 费率配置 feeRate Decimal @map("fee_rate") @db.Decimal(10, 6) // 费率 e.g. 0.001 = 0.1% minFee Decimal @map("min_fee") @db.Decimal(30, 8) // 最低手续费 maxFee Decimal? @map("max_fee") @db.Decimal(30, 8) // 最高手续费(可选) // 分配比例 headquartersRate Decimal @map("headquarters_rate") @db.Decimal(10, 6) // 总部分成比例 operationRate Decimal @map("operation_rate") @db.Decimal(10, 6) // 运营分成比例 provinceRate Decimal @map("province_rate") @db.Decimal(10, 6) // 省级分成比例 cityRate Decimal @map("city_rate") @db.Decimal(10, 6) // 市级分成比例 isActive Boolean @default(true) @map("is_active") description String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("fee_configs") } // ============================================================================= // Outbox Pattern(事件发布) // ============================================================================= model OutboxEvent { id String @id @default(uuid()) aggregateType String @map("aggregate_type") aggregateId String @map("aggregate_id") eventType String @map("event_type") payload Json topic String @default("mining-wallet.events") key String? status OutboxStatus @default(PENDING) retryCount Int @default(0) @map("retry_count") maxRetries Int @default(10) @map("max_retries") lastError String? @map("last_error") publishedAt DateTime? @map("published_at") nextRetryAt DateTime? @map("next_retry_at") createdAt DateTime @default(now()) @map("created_at") @@index([status]) @@index([nextRetryAt]) @@index([createdAt]) @@map("outbox_events") } // ============================================================================= // 已处理事件(幂等性) // ============================================================================= model ProcessedEvent { id String @id @default(uuid()) eventId String @unique @map("event_id") eventType String @map("event_type") sourceService String @map("source_service") processedAt DateTime @default(now()) @map("processed_at") @@index([sourceService]) @@index([processedAt]) @@map("processed_events") } // ============================================================================= // 审计日志 // ============================================================================= model AuditLog { id String @id @default(uuid()) operatorId String @map("operator_id") operatorType String @map("operator_type") // ADMIN, SYSTEM, USER action String // CREATE, UPDATE, DELETE, TRANSFER, WITHDRAW, etc. resource String // SYSTEM_ACCOUNT, USER_WALLET, POOL, etc. resourceId String? @map("resource_id") oldValue Json? @map("old_value") newValue Json? @map("new_value") ipAddress String? @map("ip_address") userAgent String? @map("user_agent") createdAt DateTime @default(now()) @map("created_at") @@index([operatorId]) @@index([action]) @@index([resource]) @@index([createdAt(sort: Desc)]) @@map("audit_logs") }