// ============================================================================= // 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") }