1153 lines
40 KiB
Plaintext
1153 lines
40 KiB
Plaintext
// =============================================================================
|
||
// Admin Service - Prisma Schema
|
||
// =============================================================================
|
||
|
||
generator client {
|
||
provider = "prisma-client-js"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
// =============================================================================
|
||
// App Version Management
|
||
// =============================================================================
|
||
|
||
model AppVersion {
|
||
id String @id @default(uuid())
|
||
platform Platform
|
||
versionCode Int // Android: versionCode, iOS: CFBundleVersion
|
||
versionName String // 用户可见版本号,如 "1.2.3"
|
||
buildNumber String // 构建号
|
||
downloadUrl String // APK/IPA 下载地址
|
||
fileSize BigInt // 文件大小(字节)
|
||
fileSha256 String // 文件 SHA-256 校验和
|
||
minOsVersion String? // 最低操作系统版本要求
|
||
changelog String // 更新日志
|
||
isForceUpdate Boolean @default(false) // 是否强制更新
|
||
isEnabled Boolean @default(true) // 是否启用
|
||
releaseDate DateTime? // 发布日期
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
createdBy String // 创建人ID
|
||
updatedBy String? // 更新人ID
|
||
|
||
@@index([platform, isEnabled])
|
||
@@index([platform, versionCode])
|
||
@@map("app_versions")
|
||
}
|
||
|
||
enum Platform {
|
||
ANDROID
|
||
IOS
|
||
}
|
||
|
||
// =============================================================================
|
||
// Notification System (通知系统)
|
||
// =============================================================================
|
||
|
||
/// 系统通知 - 管理员发布的公告/通知
|
||
model Notification {
|
||
id String @id @default(uuid())
|
||
title String // 通知标题
|
||
content String // 通知内容
|
||
type NotificationType // 通知类型
|
||
priority NotificationPriority @default(NORMAL) // 优先级
|
||
targetType TargetType @default(ALL) // 目标用户类型
|
||
targetLogic TargetLogic @default(ANY) @map("target_logic") // 多标签匹配逻辑
|
||
imageUrl String? // 可选的图片URL
|
||
linkUrl String? // 可选的跳转链接
|
||
isEnabled Boolean @default(true) // 是否启用
|
||
publishedAt DateTime? // 发布时间(null表示草稿)
|
||
expiresAt DateTime? // 过期时间(null表示永不过期)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
createdBy String // 创建人ID
|
||
|
||
// 关联
|
||
readRecords NotificationRead[]
|
||
targetTags NotificationTagTarget[] // BY_TAG 时使用
|
||
targetUsers NotificationUserTarget[] // SPECIFIC 时使用
|
||
|
||
@@index([isEnabled, publishedAt])
|
||
@@index([type])
|
||
@@index([targetType])
|
||
@@map("notifications")
|
||
}
|
||
|
||
/// 用户已读记录
|
||
model NotificationRead {
|
||
id String @id @default(uuid())
|
||
notificationId String
|
||
userSerialNum String // 用户序列号
|
||
readAt DateTime @default(now())
|
||
|
||
notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([notificationId, userSerialNum])
|
||
@@index([userSerialNum])
|
||
@@map("notification_reads")
|
||
}
|
||
|
||
/// 通知类型
|
||
enum NotificationType {
|
||
SYSTEM // 系统通知
|
||
ACTIVITY // 活动通知
|
||
REWARD // 收益通知
|
||
UPGRADE // 升级通知
|
||
ANNOUNCEMENT // 公告
|
||
}
|
||
|
||
/// 通知优先级
|
||
enum NotificationPriority {
|
||
LOW
|
||
NORMAL
|
||
HIGH
|
||
URGENT
|
||
}
|
||
|
||
/// 目标用户类型
|
||
enum TargetType {
|
||
ALL // 所有用户
|
||
BY_TAG // 按标签匹配
|
||
SPECIFIC // 指定用户列表
|
||
}
|
||
|
||
/// 多标签匹配逻辑
|
||
enum TargetLogic {
|
||
ANY // 匹配任一标签
|
||
ALL // 匹配所有标签
|
||
}
|
||
|
||
/// 通知-标签关联
|
||
model NotificationTagTarget {
|
||
id String @id @default(uuid())
|
||
notificationId String @map("notification_id")
|
||
tagId String @map("tag_id")
|
||
|
||
notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)
|
||
tag UserTag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([notificationId, tagId])
|
||
@@index([tagId])
|
||
@@map("notification_tag_targets")
|
||
}
|
||
|
||
/// 通知-用户关联 (指定用户)
|
||
model NotificationUserTarget {
|
||
id String @id @default(uuid())
|
||
notificationId String @map("notification_id")
|
||
accountSequence String @map("account_sequence") @db.VarChar(12)
|
||
|
||
notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([notificationId, accountSequence])
|
||
@@index([accountSequence])
|
||
@@map("notification_user_targets")
|
||
}
|
||
|
||
// =============================================================================
|
||
// User Profile System (用户画像系统) - 面向通知 + 广告
|
||
// =============================================================================
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 标签分类 (Tag Category) - 标签的分组管理
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 标签分类
|
||
model TagCategory {
|
||
id String @id @default(uuid())
|
||
code String @unique @db.VarChar(50) // "lifecycle", "value", "behavior"
|
||
name String @db.VarChar(100) // "生命周期", "价值分层", "行为特征"
|
||
description String? @db.Text
|
||
sortOrder Int @default(0) @map("sort_order")
|
||
isEnabled Boolean @default(true) @map("is_enabled")
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
tags UserTag[]
|
||
|
||
@@index([code])
|
||
@@index([isEnabled])
|
||
@@map("tag_categories")
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 用户标签 (User Tag) - 增强版
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 标签类型
|
||
enum TagType {
|
||
MANUAL // 手动打标 (管理员操作)
|
||
AUTO // 自动打标 (规则驱动)
|
||
COMPUTED // 计算型 (实时计算,不存储关联)
|
||
SYSTEM // 系统内置 (不可删除)
|
||
}
|
||
|
||
/// 标签值类型
|
||
enum TagValueType {
|
||
BOOLEAN // 布尔型: 有/无
|
||
ENUM // 枚举型: 高/中/低
|
||
NUMBER // 数值型: 0-100分
|
||
STRING // 字符串型
|
||
}
|
||
|
||
/// 用户标签定义
|
||
model UserTag {
|
||
id String @id @default(uuid())
|
||
categoryId String? @map("category_id")
|
||
code String @unique @db.VarChar(50) // "vip", "new_user", "whale"
|
||
name String @db.VarChar(100) // "VIP用户", "新用户", "大客户"
|
||
description String? @db.Text
|
||
color String? @db.VarChar(20) // "#FF5722"
|
||
|
||
type TagType @default(MANUAL) // 标签类型
|
||
valueType TagValueType @default(BOOLEAN) @map("value_type") // 标签值类型
|
||
|
||
// 枚举型标签的可选值
|
||
// 例如: ["高", "中", "低"] 或 ["活跃", "沉默", "流失"]
|
||
enumValues Json? @map("enum_values")
|
||
|
||
// 关联的自动规则 (type=AUTO 时使用)
|
||
ruleId String? @unique @map("rule_id")
|
||
rule UserClassificationRule? @relation(fields: [ruleId], references: [id], onDelete: SetNull)
|
||
|
||
// 广告相关
|
||
isAdvertisable Boolean @default(true) @map("is_advertisable") // 是否可用于广告定向
|
||
estimatedUsers Int? @map("estimated_users") // 预估覆盖用户数
|
||
|
||
isEnabled Boolean @default(true) @map("is_enabled")
|
||
sortOrder Int @default(0) @map("sort_order")
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
// 关联
|
||
category TagCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||
assignments UserTagAssignment[]
|
||
notifications NotificationTagTarget[]
|
||
|
||
@@index([categoryId])
|
||
@@index([code])
|
||
@@index([type])
|
||
@@index([isEnabled])
|
||
@@index([isAdvertisable])
|
||
@@map("user_tags")
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 用户-标签关联 - 支持标签值
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 用户-标签关联
|
||
model UserTagAssignment {
|
||
id String @id @default(uuid())
|
||
accountSequence String @map("account_sequence") @db.VarChar(12)
|
||
tagId String @map("tag_id")
|
||
|
||
// 标签值 (根据 valueType)
|
||
// BOOLEAN: null (存在即为true)
|
||
// ENUM: "高" / "中" / "低"
|
||
// NUMBER: "85" (字符串存储)
|
||
// STRING: 任意字符串
|
||
value String? @db.VarChar(100)
|
||
|
||
assignedAt DateTime @default(now()) @map("assigned_at")
|
||
assignedBy String? @map("assigned_by") // null=系统自动, 否则为管理员ID
|
||
expiresAt DateTime? @map("expires_at") // 可选过期时间
|
||
source String? @db.VarChar(50) // 来源: "rule:xxx", "import", "manual", "kafka"
|
||
|
||
tag UserTag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([accountSequence, tagId])
|
||
@@index([accountSequence])
|
||
@@index([tagId])
|
||
@@index([value])
|
||
@@index([expiresAt])
|
||
@@map("user_tag_assignments")
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 用户分类规则 (Classification Rule)
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 用户分类规则
|
||
model UserClassificationRule {
|
||
id String @id @default(uuid())
|
||
name String @db.VarChar(100) // "30天内新用户"
|
||
description String? @db.Text
|
||
|
||
// 规则条件 (JSON)
|
||
// 示例:
|
||
// {
|
||
// "type": "AND",
|
||
// "rules": [
|
||
// { "field": "registeredAt", "operator": "within_days", "value": 30 },
|
||
// { "field": "kycStatus", "operator": "eq", "value": "VERIFIED" }
|
||
// ]
|
||
// }
|
||
conditions Json
|
||
|
||
isEnabled Boolean @default(true) @map("is_enabled")
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
// 关联的自动标签
|
||
tag UserTag?
|
||
|
||
@@map("user_classification_rules")
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 用户特征 (User Features) - 数值型指标
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 用户特征 - 计算后的用户画像指标
|
||
model UserFeature {
|
||
id String @id @default(uuid())
|
||
accountSequence String @unique @map("account_sequence") @db.VarChar(12)
|
||
|
||
// RFM 模型
|
||
rfmRecency Int? @map("rfm_recency") // 最近一次活跃距今天数
|
||
rfmFrequency Int? @map("rfm_frequency") // 过去30天活跃天数
|
||
rfmMonetary Decimal? @map("rfm_monetary") @db.Decimal(18, 2) // 累计消费金额
|
||
rfmScore Int? @map("rfm_score") // RFM综合分 (0-100)
|
||
|
||
// 活跃度
|
||
activeLevel String? @map("active_level") @db.VarChar(20) // "高活跃", "中活跃", "低活跃", "沉默"
|
||
lastActiveAt DateTime? @map("last_active_at")
|
||
|
||
// 价值分层
|
||
valueLevel String? @map("value_level") @db.VarChar(20) // "高价值", "中价值", "低价值", "潜力"
|
||
lifetimeValue Decimal? @map("lifetime_value") @db.Decimal(18, 2) // 用户生命周期价值 LTV
|
||
|
||
// 生命周期
|
||
lifecycleStage String? @map("lifecycle_stage") @db.VarChar(20) // "新用户", "成长期", "成熟期", "衰退期", "流失"
|
||
|
||
// 自定义特征 (JSON扩展)
|
||
customFeatures Json? @map("custom_features")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
@@index([rfmScore])
|
||
@@index([activeLevel])
|
||
@@index([valueLevel])
|
||
@@index([lifecycleStage])
|
||
@@map("user_features")
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 人群包 (Audience Segment) - 复杂定向
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 人群包用途
|
||
enum SegmentUsageType {
|
||
GENERAL // 通用
|
||
NOTIFICATION // 通知定向
|
||
ADVERTISING // 广告定向
|
||
ANALYTICS // 数据分析
|
||
}
|
||
|
||
/// 人群包 - 多条件组合的用户群
|
||
model AudienceSegment {
|
||
id String @id @default(uuid())
|
||
name String @db.VarChar(100) // "高价值活跃用户"
|
||
description String? @db.Text
|
||
|
||
// 定向条件 (JSON)
|
||
// {
|
||
// "type": "AND",
|
||
// "conditions": [
|
||
// { "type": "tag", "tagCode": "vip", "operator": "eq", "value": true },
|
||
// { "type": "feature", "field": "rfmScore", "operator": "gte", "value": 80 },
|
||
// { "type": "profile", "field": "province", "operator": "in", "value": ["广东", "浙江"] }
|
||
// ]
|
||
// }
|
||
conditions Json
|
||
|
||
// 预估数据
|
||
estimatedUsers Int? @map("estimated_users")
|
||
lastCalculated DateTime? @map("last_calculated")
|
||
|
||
// 用途
|
||
usageType SegmentUsageType @default(GENERAL) @map("usage_type")
|
||
|
||
isEnabled Boolean @default(true) @map("is_enabled")
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
createdBy String @map("created_by")
|
||
|
||
@@index([usageType])
|
||
@@index([isEnabled])
|
||
@@map("audience_segments")
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// 标签变更日志 (审计追踪)
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/// 标签变更操作
|
||
enum TagAction {
|
||
ASSIGN // 打标签
|
||
UPDATE // 更新标签值
|
||
REMOVE // 移除标签
|
||
EXPIRE // 过期移除
|
||
}
|
||
|
||
/// 标签变更日志
|
||
model UserTagLog {
|
||
id String @id @default(uuid())
|
||
accountSequence String @map("account_sequence") @db.VarChar(12)
|
||
tagCode String @map("tag_code") @db.VarChar(50)
|
||
|
||
action TagAction
|
||
oldValue String? @map("old_value") @db.VarChar(100)
|
||
newValue String? @map("new_value") @db.VarChar(100)
|
||
|
||
reason String? @db.VarChar(200) // "规则触发", "管理员操作", "导入", "过期清理"
|
||
operatorId String? @map("operator_id")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
|
||
@@index([accountSequence, createdAt])
|
||
@@index([tagCode])
|
||
@@index([action])
|
||
@@index([createdAt])
|
||
@@map("user_tag_logs")
|
||
}
|
||
|
||
// =============================================================================
|
||
// User Query View (用户查询视图 - 通过 Kafka 事件同步)
|
||
// =============================================================================
|
||
|
||
/// 用户查询视图 - 本地物化视图,通过消费 Kafka 事件同步维护
|
||
/// 用于 admin-web 用户管理页面的查询,避免跨服务 HTTP 调用
|
||
model UserQueryView {
|
||
userId BigInt @id @map("user_id")
|
||
accountSequence String @unique @map("account_sequence") @db.VarChar(12)
|
||
|
||
// 基本信息 (来自 identity-service 事件)
|
||
nickname String? @db.VarChar(100)
|
||
avatarUrl String? @map("avatar_url") @db.Text
|
||
phoneNumberMasked String? @map("phone_number_masked") @db.VarChar(20) // 脱敏: 138****8888
|
||
|
||
// 推荐关系
|
||
inviterSequence String? @map("inviter_sequence") @db.VarChar(12)
|
||
|
||
// KYC 状态
|
||
kycStatus String @default("NOT_VERIFIED") @map("kyc_status") @db.VarChar(20)
|
||
|
||
// 认种统计 (来自 planting-service 事件)
|
||
personalAdoptionCount Int @default(0) @map("personal_adoption_count")
|
||
teamAddressCount Int @default(0) @map("team_address_count")
|
||
teamAdoptionCount Int @default(0) @map("team_adoption_count")
|
||
|
||
// 授权统计 (来自 authorization-service 事件)
|
||
provinceAdoptionCount Int @default(0) @map("province_adoption_count")
|
||
cityAdoptionCount Int @default(0) @map("city_adoption_count")
|
||
|
||
// 排名
|
||
leaderboardRank Int? @map("leaderboard_rank")
|
||
|
||
// 状态
|
||
status String @default("ACTIVE") @db.VarChar(20)
|
||
isOnline Boolean @default(false) @map("is_online")
|
||
|
||
// 时间戳
|
||
registeredAt DateTime @map("registered_at")
|
||
lastActiveAt DateTime? @map("last_active_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence])
|
||
@@index([nickname])
|
||
@@index([status])
|
||
@@index([registeredAt])
|
||
@@index([personalAdoptionCount])
|
||
@@index([inviterSequence])
|
||
@@map("user_query_view")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Referral Query View (推荐关系查询视图 - 通过 CDC 同步)
|
||
// =============================================================================
|
||
|
||
/// 推荐关系查询视图 - 通过 Debezium CDC 从 referral-service 同步
|
||
/// 用于 admin-web 查看用户推荐关系,避免跨服务调用
|
||
model ReferralQueryView {
|
||
id BigInt @id @map("relationship_id")
|
||
userId BigInt @unique @map("user_id")
|
||
accountSequence String @unique @map("account_sequence") @db.VarChar(12)
|
||
|
||
// 推荐人信息
|
||
referrerId BigInt? @map("referrer_id")
|
||
rootUserId BigInt? @map("root_user_id")
|
||
|
||
// 推荐码
|
||
myReferralCode String @unique @map("my_referral_code") @db.VarChar(20)
|
||
usedReferralCode String? @map("used_referral_code") @db.VarChar(20)
|
||
|
||
// 推荐链信息
|
||
ancestorPath BigInt[] @map("ancestor_path")
|
||
depth Int @default(0) @map("depth")
|
||
|
||
// 直推统计
|
||
directReferralCount Int @default(0) @map("direct_referral_count")
|
||
activeDirectCount Int @default(0) @map("active_direct_count")
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([referrerId])
|
||
@@index([accountSequence])
|
||
@@index([myReferralCode])
|
||
@@index([usedReferralCode])
|
||
@@index([rootUserId])
|
||
@@index([depth])
|
||
@@map("referral_query_view")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Wallet Query Views (钱包查询视图 - 通过 CDC 同步)
|
||
// =============================================================================
|
||
|
||
/// 钱包账户查询视图 - 通过 Debezium CDC 从 wallet-service 同步
|
||
model WalletAccountQueryView {
|
||
id BigInt @id @map("wallet_id")
|
||
accountSequence String @unique @map("account_sequence") @db.VarChar(20)
|
||
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)
|
||
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")
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence])
|
||
@@index([usdtAvailable(sort: Desc)])
|
||
@@index([hashpower(sort: Desc)])
|
||
@@index([status])
|
||
@@map("wallet_account_query_view")
|
||
}
|
||
|
||
/// 提现订单查询视图 - 通过 Debezium CDC 从 wallet-service 同步
|
||
model WithdrawalOrderQueryView {
|
||
id BigInt @id @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)
|
||
toAddress String @map("to_address") @db.VarChar(100)
|
||
|
||
// 交易信息
|
||
txHash String? @map("tx_hash") @db.VarChar(100)
|
||
|
||
// 内部转账标识
|
||
isInternalTransfer Boolean @default(false) @map("is_internal_transfer")
|
||
toAccountSequence String? @map("to_account_sequence") @db.VarChar(20)
|
||
toUserId BigInt? @map("to_user_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 @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence])
|
||
@@index([userId])
|
||
@@index([status])
|
||
@@index([chainType])
|
||
@@index([txHash])
|
||
@@index([createdAt])
|
||
@@map("withdrawal_order_query_view")
|
||
}
|
||
|
||
/// 法币提现订单查询视图 - 通过 Debezium CDC 从 wallet-service 同步
|
||
model FiatWithdrawalOrderQueryView {
|
||
id BigInt @id @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)
|
||
|
||
// 收款方式
|
||
paymentMethod String @map("payment_method") @db.VarChar(20)
|
||
|
||
// 银行卡信息 (脱敏)
|
||
bankName String? @map("bank_name") @db.VarChar(100)
|
||
bankCardNoMasked String? @map("bank_card_no_masked") @db.VarChar(50)
|
||
cardHolderName String? @map("card_holder_name") @db.VarChar(100)
|
||
|
||
// 支付宝/微信 (脱敏)
|
||
alipayAccountMasked String? @map("alipay_account_masked") @db.VarChar(100)
|
||
wechatAccountMasked String? @map("wechat_account_masked") @db.VarChar(100)
|
||
|
||
// 状态
|
||
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")
|
||
|
||
// 时间戳
|
||
frozenAt DateTime? @map("frozen_at")
|
||
completedAt DateTime? @map("completed_at")
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence])
|
||
@@index([userId])
|
||
@@index([status])
|
||
@@index([paymentMethod])
|
||
@@index([reviewedBy])
|
||
@@index([createdAt])
|
||
@@map("fiat_withdrawal_order_query_view")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Planting Query Views (认种查询视图 - 通过 CDC 同步)
|
||
// =============================================================================
|
||
|
||
/// 认种订单查询视图 - 通过 Debezium CDC 从 planting-service 同步
|
||
model PlantingOrderQueryView {
|
||
id BigInt @id @map("order_id")
|
||
orderNo String @unique @map("order_no") @db.VarChar(50)
|
||
userId BigInt @map("user_id")
|
||
accountSequence String @map("account_sequence") @db.VarChar(20)
|
||
|
||
// 认种信息
|
||
treeCount Int @map("tree_count")
|
||
totalAmount Decimal @map("total_amount") @db.Decimal(20, 8)
|
||
|
||
// 省市选择
|
||
selectedProvince String? @map("selected_province") @db.VarChar(10)
|
||
selectedCity String? @map("selected_city") @db.VarChar(10)
|
||
|
||
// 订单状态
|
||
status String @default("CREATED") @map("status") @db.VarChar(30)
|
||
|
||
// 底池信息
|
||
poolInjectionBatchId BigInt? @map("pool_injection_batch_id")
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
paidAt DateTime? @map("paid_at")
|
||
fundAllocatedAt DateTime? @map("fund_allocated_at")
|
||
miningEnabledAt DateTime? @map("mining_enabled_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([userId])
|
||
@@index([accountSequence])
|
||
@@index([status])
|
||
@@index([selectedProvince, selectedCity])
|
||
@@index([createdAt])
|
||
@@index([paidAt])
|
||
@@map("planting_order_query_view")
|
||
}
|
||
|
||
/// 用户持仓查询视图 - 通过 Debezium CDC 从 planting-service 同步
|
||
model PlantingPositionQueryView {
|
||
id BigInt @id @map("position_id")
|
||
userId BigInt @unique @map("user_id")
|
||
|
||
// 持仓统计
|
||
totalTreeCount Int @default(0) @map("total_tree_count")
|
||
effectiveTreeCount Int @default(0) @map("effective_tree_count")
|
||
pendingTreeCount Int @default(0) @map("pending_tree_count")
|
||
|
||
// 挖矿状态
|
||
firstMiningStartAt DateTime? @map("first_mining_start_at")
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([totalTreeCount])
|
||
@@map("planting_position_query_view")
|
||
}
|
||
|
||
/// 合同签署任务查询视图 - 通过 Debezium CDC 从 planting-service 同步
|
||
model ContractSigningTaskQueryView {
|
||
id BigInt @id @map("task_id")
|
||
|
||
// 关联信息
|
||
orderNo String @unique @map("order_no") @db.VarChar(50)
|
||
contractNo String @unique @map("contract_no") @db.VarChar(30)
|
||
userId BigInt @map("user_id")
|
||
accountSequence String @map("account_sequence") @db.VarChar(20)
|
||
|
||
// 合同信息
|
||
contractVersion String @map("contract_version") @db.VarChar(20)
|
||
|
||
// 订单信息快照
|
||
treeCount Int @map("tree_count")
|
||
totalAmount Decimal @map("total_amount") @db.Decimal(20, 8)
|
||
provinceCode String @map("province_code") @db.VarChar(10)
|
||
provinceName String @map("province_name") @db.VarChar(50)
|
||
cityCode String @map("city_code") @db.VarChar(10)
|
||
cityName String @map("city_name") @db.VarChar(50)
|
||
|
||
// 签署状态
|
||
status String @default("PENDING") @map("status") @db.VarChar(30)
|
||
expiresAt DateTime @map("expires_at")
|
||
|
||
// 签署时间戳
|
||
signedAt DateTime? @map("signed_at")
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([userId])
|
||
@@index([status])
|
||
@@index([expiresAt])
|
||
@@map("contract_signing_task_query_view")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Authorization Query Views (授权查询视图 - 通过 CDC 同步)
|
||
// =============================================================================
|
||
|
||
/// 授权角色查询视图 - 通过 Debezium CDC 从 authorization-service 同步
|
||
model AuthorizationRoleQueryView {
|
||
id String @id
|
||
userId String @map("user_id")
|
||
accountSequence String @map("account_sequence")
|
||
roleType String @map("role_type") @db.VarChar(30)
|
||
regionCode String @map("region_code")
|
||
regionName String @map("region_name")
|
||
status String @default("PENDING") @db.VarChar(20)
|
||
displayTitle String @map("display_title")
|
||
|
||
// 授权信息
|
||
authorizedAt DateTime? @map("authorized_at")
|
||
authorizedBy String? @map("authorized_by")
|
||
revokedAt DateTime? @map("revoked_at")
|
||
revokedBy String? @map("revoked_by")
|
||
|
||
// 软删除
|
||
deletedAt DateTime? @map("deleted_at")
|
||
|
||
// 考核配置
|
||
initialTargetTreeCount Int @map("initial_target_tree_count")
|
||
monthlyTargetType String @map("monthly_target_type") @db.VarChar(20)
|
||
|
||
// 权益状态
|
||
benefitActive Boolean @default(false) @map("benefit_active")
|
||
benefitActivatedAt DateTime? @map("benefit_activated_at")
|
||
|
||
// 月度考核追踪
|
||
lastAssessmentMonth String? @map("last_assessment_month")
|
||
monthlyTreesAdded Int @default(0) @map("monthly_trees_added")
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence])
|
||
@@index([userId])
|
||
@@index([roleType, regionCode])
|
||
@@index([status])
|
||
@@index([deletedAt])
|
||
@@map("authorization_role_query_view")
|
||
}
|
||
|
||
/// 月度考核查询视图 - 通过 Debezium CDC 从 authorization-service 同步
|
||
model MonthlyAssessmentQueryView {
|
||
id String @id
|
||
authorizationId String @map("authorization_id")
|
||
userId String @map("user_id")
|
||
accountSequence String @map("account_sequence")
|
||
roleType String @map("role_type") @db.VarChar(30)
|
||
regionCode String @map("region_code")
|
||
|
||
// 考核月份
|
||
assessmentMonth String @map("assessment_month")
|
||
monthIndex Int @map("month_index")
|
||
|
||
// 考核目标
|
||
monthlyTarget Int @map("monthly_target")
|
||
cumulativeTarget Int @map("cumulative_target")
|
||
|
||
// 完成情况
|
||
monthlyCompleted Int @default(0) @map("monthly_completed")
|
||
cumulativeCompleted Int @default(0) @map("cumulative_completed")
|
||
completedAt DateTime? @map("completed_at")
|
||
|
||
// 考核结果
|
||
result String @default("NOT_ASSESSED") @db.VarChar(20)
|
||
|
||
// 排名
|
||
rankingInRegion Int? @map("ranking_in_region")
|
||
isFirstPlace Boolean @default(false) @map("is_first_place")
|
||
|
||
// 豁免
|
||
isBypassed Boolean @default(false) @map("is_bypassed")
|
||
|
||
// 时间戳
|
||
assessedAt DateTime? @map("assessed_at")
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence, assessmentMonth])
|
||
@@index([userId, assessmentMonth])
|
||
@@index([roleType, regionCode, assessmentMonth])
|
||
@@index([assessmentMonth, result])
|
||
@@map("monthly_assessment_query_view")
|
||
}
|
||
|
||
/// 权益考核记录查询视图 - 通过 Debezium CDC 从 authorization-service 同步
|
||
/// 独立于火柴人排名(MonthlyAssessment),专门记录权益有效性考核历史
|
||
model BenefitAssessmentQueryView {
|
||
id String @id
|
||
authorizationId String @map("authorization_id")
|
||
userId String @map("user_id")
|
||
accountSequence String @map("account_sequence")
|
||
roleType String @map("role_type") @db.VarChar(30)
|
||
regionCode String @map("region_code")
|
||
regionName String @map("region_name")
|
||
|
||
// 考核月份
|
||
assessmentMonth String @map("assessment_month")
|
||
monthIndex Int @map("month_index")
|
||
|
||
// 考核目标
|
||
monthlyTarget Int @map("monthly_target")
|
||
cumulativeTarget Int @map("cumulative_target")
|
||
|
||
// 完成情况
|
||
treesCompleted Int @map("trees_completed")
|
||
treesRequired Int @map("trees_required")
|
||
|
||
// 权益状态变化
|
||
benefitActionTaken String @map("benefit_action_taken") @db.VarChar(20)
|
||
previousBenefitStatus Boolean @map("previous_benefit_status")
|
||
newBenefitStatus Boolean @map("new_benefit_status")
|
||
newValidUntil DateTime? @map("new_valid_until")
|
||
|
||
// 考核结果
|
||
result String @default("NOT_ASSESSED") @db.VarChar(20)
|
||
|
||
// 备注
|
||
remarks String? @map("remarks") @db.VarChar(500)
|
||
|
||
// 时间戳
|
||
assessedAt DateTime @map("assessed_at")
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@unique([authorizationId, assessmentMonth])
|
||
@@index([accountSequence, assessmentMonth])
|
||
@@index([userId, assessmentMonth])
|
||
@@index([roleType, regionCode, assessmentMonth])
|
||
@@index([assessmentMonth, result])
|
||
@@map("benefit_assessment_query_view")
|
||
}
|
||
|
||
/// 系统账户查询视图 - 通过 Debezium CDC 从 authorization-service 同步
|
||
model SystemAccountQueryView {
|
||
id BigInt @id @map("account_id")
|
||
accountType String @map("account_type") @db.VarChar(30)
|
||
|
||
// 区域信息
|
||
regionCode String? @map("region_code") @db.VarChar(10)
|
||
regionName String? @map("region_name") @db.VarChar(50)
|
||
|
||
// 钱包地址
|
||
walletAddress String? @map("wallet_address") @db.VarChar(42)
|
||
|
||
// 余额
|
||
usdtBalance Decimal @default(0) @map("usdt_balance") @db.Decimal(20, 8)
|
||
hashpower Decimal @default(0) @map("hashpower") @db.Decimal(20, 8)
|
||
|
||
// 累计统计
|
||
totalReceived Decimal @default(0) @map("total_received") @db.Decimal(20, 8)
|
||
totalTransferred Decimal @default(0) @map("total_transferred") @db.Decimal(20, 8)
|
||
|
||
// 状态
|
||
status String @default("ACTIVE") @map("status") @db.VarChar(20)
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountType])
|
||
@@index([walletAddress])
|
||
@@map("system_account_query_view")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Ledger Views (分类账视图 - 通过 CDC 同步)
|
||
// =============================================================================
|
||
|
||
/// 钱包流水分类账 - 通过 Debezium CDC 从 wallet-service 同步
|
||
/// 记录所有用户钱包的资金变动(充值/提现/收益/扣款等)
|
||
model WalletLedgerEntryView {
|
||
id BigInt @id @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.Text
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountSequence, createdAt(sort: Desc)])
|
||
@@index([userId, createdAt(sort: Desc)])
|
||
@@index([entryType])
|
||
@@index([assetType])
|
||
@@index([refOrderId])
|
||
@@index([refTxHash])
|
||
@@index([createdAt])
|
||
@@map("wallet_ledger_entry_view")
|
||
}
|
||
|
||
/// 认种资金分配分类账 - 通过 Debezium CDC 从 planting-service 同步
|
||
/// 记录每笔认种订单的资金分配明细
|
||
model FundAllocationView {
|
||
id BigInt @id @map("allocation_id")
|
||
orderId BigInt @map("order_id")
|
||
|
||
// 分配信息
|
||
targetType String @map("target_type") @db.VarChar(50)
|
||
amount Decimal @map("amount") @db.Decimal(20, 8)
|
||
targetAccountId String? @map("target_account_id") @db.VarChar(100)
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([orderId])
|
||
@@index([targetType, targetAccountId])
|
||
@@index([createdAt])
|
||
@@map("fund_allocation_view")
|
||
}
|
||
|
||
/// 系统账户流水分类账 - 通过 Debezium CDC 从 authorization-service 同步
|
||
/// 记录系统账户(成本账户、运营账户、区域账户)的资金变动
|
||
model SystemAccountLedgerView {
|
||
id BigInt @id @map("ledger_id")
|
||
accountId BigInt @map("account_id")
|
||
|
||
// 流水类型
|
||
entryType String @map("entry_type") @db.VarChar(30)
|
||
|
||
// 金额
|
||
amount Decimal @map("amount") @db.Decimal(20, 8)
|
||
balanceAfter Decimal @map("balance_after") @db.Decimal(20, 8)
|
||
|
||
// 关联信息
|
||
sourceOrderId BigInt? @map("source_order_id")
|
||
sourceRewardId BigInt? @map("source_reward_id")
|
||
txHash String? @map("tx_hash") @db.VarChar(66)
|
||
|
||
memo String? @map("memo") @db.VarChar(500)
|
||
|
||
// 时间戳
|
||
createdAt DateTime @map("created_at")
|
||
syncedAt DateTime @default(now()) @map("synced_at")
|
||
|
||
@@index([accountId, createdAt(sort: Desc)])
|
||
@@index([sourceOrderId])
|
||
@@index([txHash])
|
||
@@index([createdAt])
|
||
@@map("system_account_ledger_view")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Kafka Event Tracking (事件消费追踪)
|
||
// =============================================================================
|
||
|
||
/// 事件消费位置追踪 - 用于幂等性和断点续传
|
||
model EventConsumerOffset {
|
||
id BigInt @id @default(autoincrement())
|
||
consumerGroup String @map("consumer_group") @db.VarChar(100)
|
||
topic String @db.VarChar(100)
|
||
partition Int
|
||
offset BigInt
|
||
updatedAt DateTime @default(now()) @map("updated_at")
|
||
|
||
@@unique([consumerGroup, topic, partition])
|
||
@@map("event_consumer_offsets")
|
||
}
|
||
|
||
/// 已处理事件记录 - 用于幂等性检查
|
||
model ProcessedEvent {
|
||
id BigInt @id @default(autoincrement())
|
||
eventId String @unique @map("event_id") @db.VarChar(100)
|
||
eventType String @map("event_type") @db.VarChar(50)
|
||
processedAt DateTime @default(now()) @map("processed_at")
|
||
|
||
@@index([eventType])
|
||
@@index([processedAt])
|
||
@@map("processed_events")
|
||
}
|
||
|
||
// =============================================================================
|
||
// System Config (系统配置)
|
||
// =============================================================================
|
||
|
||
/// 系统配置 - 键值对存储,用于存储各种系统设置
|
||
model SystemConfig {
|
||
id String @id @default(uuid())
|
||
key String @unique @db.VarChar(100) // 配置键
|
||
value String @db.Text // 配置值 (JSON 格式)
|
||
description String? @db.VarChar(255) // 配置描述
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
updatedBy String? @map("updated_by") // 更新人ID
|
||
|
||
@@index([key])
|
||
@@map("system_configs")
|
||
}
|
||
|
||
// =============================================================================
|
||
// System Maintenance (系统维护公告)
|
||
// =============================================================================
|
||
|
||
/// 系统维护公告 - 用于系统升级/维护期间阻断用户操作
|
||
model SystemMaintenance {
|
||
id String @id @default(uuid())
|
||
title String @db.VarChar(100) // 标题:如"系统升级中"
|
||
message String @db.Text // 说明:如"预计10:00恢复,请稍候"
|
||
startTime DateTime @map("start_time") // 维护开始时间
|
||
endTime DateTime @map("end_time") // 维护结束时间
|
||
isActive Boolean @default(false) @map("is_active") // 是否激活
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
createdBy String @map("created_by") // 创建人ID
|
||
updatedBy String? @map("updated_by") // 更新人ID
|
||
|
||
@@index([isActive])
|
||
@@index([startTime, endTime])
|
||
@@map("system_maintenances")
|
||
}
|
||
|
||
// =============================================================================
|
||
// Co-Managed Wallet System (共管钱包系统)
|
||
// =============================================================================
|
||
|
||
/// 共管钱包会话状态
|
||
enum WalletSessionStatus {
|
||
WAITING // 等待参与方加入
|
||
READY // 所有参与方已就绪
|
||
PROCESSING // 密钥生成中
|
||
COMPLETED // 创建完成
|
||
FAILED // 创建失败
|
||
CANCELLED // 已取消
|
||
}
|
||
|
||
/// 共管钱包会话 - 钱包创建过程的会话记录
|
||
model CoManagedWalletSession {
|
||
id String @id @default(uuid())
|
||
walletName String @map("wallet_name") @db.VarChar(100) // 钱包名称
|
||
thresholdT Int @map("threshold_t") // 签名阈值 T
|
||
thresholdN Int @map("threshold_n") // 参与方总数 N
|
||
inviteCode String @unique @map("invite_code") @db.VarChar(20) // 邀请码
|
||
status WalletSessionStatus @default(WAITING) // 会话状态
|
||
participants String @db.Text // 参与方列表 (JSON)
|
||
currentRound Int @default(0) @map("current_round") // 当前密钥生成轮次
|
||
totalRounds Int @default(3) @map("total_rounds") // 总轮次
|
||
publicKey String? @map("public_key") @db.VarChar(200) // 生成的公钥
|
||
error String? @db.Text // 错误信息
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
createdBy String @map("created_by") @db.VarChar(100) // 创建者
|
||
|
||
@@index([inviteCode])
|
||
@@index([status])
|
||
@@index([createdBy])
|
||
@@index([createdAt])
|
||
@@map("co_managed_wallet_sessions")
|
||
}
|
||
|
||
/// 共管钱包 - 创建成功后的钱包记录
|
||
model CoManagedWallet {
|
||
id String @id @default(uuid())
|
||
sessionId String @unique @map("session_id") // 关联的会话 ID
|
||
name String @db.VarChar(100) // 钱包名称
|
||
publicKey String @map("public_key") @db.VarChar(200) // 钱包公钥
|
||
thresholdT Int @map("threshold_t") // 签名阈值 T
|
||
thresholdN Int @map("threshold_n") // 参与方总数 N
|
||
participants String @db.Text // 参与方列表 (JSON)
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
createdBy String @map("created_by") @db.VarChar(100) // 创建者
|
||
|
||
@@index([sessionId])
|
||
@@index([publicKey])
|
||
@@index([createdBy])
|
||
@@index([createdAt])
|
||
@@map("co_managed_wallets")
|
||
}
|