generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================ // 认种订单表 (状态表) // ============================================ model PlantingOrder { id BigInt @id @default(autoincrement()) @map("order_id") orderNo String @unique @map("order_no") @db.VarChar(50) userId BigInt @map("user_id") // 认种信息 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) provinceCitySelectedAt DateTime? @map("province_city_selected_at") provinceCityConfirmedAt DateTime? @map("province_city_confirmed_at") // 订单状态 status String @default("CREATED") @map("status") @db.VarChar(30) // 底池信息 poolInjectionBatchId BigInt? @map("pool_injection_batch_id") poolInjectionScheduledTime DateTime? @map("pool_injection_scheduled_time") poolInjectionActualTime DateTime? @map("pool_injection_actual_time") poolInjectionTxHash String? @map("pool_injection_tx_hash") @db.VarChar(100) // 挖矿 miningEnabledAt DateTime? @map("mining_enabled_at") // 时间戳 createdAt DateTime @default(now()) @map("created_at") paidAt DateTime? @map("paid_at") fundAllocatedAt DateTime? @map("fund_allocated_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联 fundAllocations FundAllocation[] batch PoolInjectionBatch? @relation(fields: [poolInjectionBatchId], references: [id]) @@index([userId]) @@index([orderNo]) @@index([status]) @@index([poolInjectionBatchId]) @@index([selectedProvince, selectedCity]) @@index([createdAt]) @@index([paidAt]) @@map("planting_orders") } // ============================================ // 资金分配明细表 (行为表, append-only) // ============================================ model FundAllocation { id BigInt @id @default(autoincrement()) @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) // 元数据 metadata Json? @map("metadata") createdAt DateTime @default(now()) @map("created_at") // 关联 order PlantingOrder @relation(fields: [orderId], references: [id]) @@index([orderId]) @@index([targetType, targetAccountId]) @@index([createdAt]) @@map("fund_allocations") } // ============================================ // 用户持仓表 (状态表) // ============================================ model PlantingPosition { id BigInt @id @default(autoincrement()) @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 @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联 distributions PositionDistribution[] @@index([userId]) @@index([totalTreeCount]) @@map("planting_positions") } // ============================================ // 持仓省市分布表 // ============================================ model PositionDistribution { id BigInt @id @default(autoincrement()) @map("distribution_id") userId BigInt @map("user_id") // 省市信息 provinceCode String? @map("province_code") @db.VarChar(10) cityCode String? @map("city_code") @db.VarChar(10) // 数量 treeCount Int @default(0) @map("tree_count") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联 position PlantingPosition @relation(fields: [userId], references: [userId]) @@unique([userId, provinceCode, cityCode]) @@index([userId]) @@index([provinceCode]) @@index([cityCode]) @@map("position_province_city_distribution") } // ============================================ // 底池注入批次表 (状态表) // ============================================ model PoolInjectionBatch { id BigInt @id @default(autoincrement()) @map("batch_id") batchNo String @unique @map("batch_no") @db.VarChar(50) // 批次时间窗口 (5天) startDate DateTime @map("start_date") @db.Date endDate DateTime @map("end_date") @db.Date // 统计信息 orderCount Int @default(0) @map("order_count") totalAmount Decimal @default(0) @map("total_amount") @db.Decimal(20, 8) // 注入状态 status String @default("PENDING") @map("status") @db.VarChar(20) scheduledInjectionTime DateTime? @map("scheduled_injection_time") actualInjectionTime DateTime? @map("actual_injection_time") injectionTxHash String? @map("injection_tx_hash") @db.VarChar(100) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联 orders PlantingOrder[] @@index([batchNo]) @@index([startDate, endDate]) @@index([status]) @@index([scheduledInjectionTime]) @@map("pool_injection_batches") } // ============================================ // 认种事件表 (行为表, append-only) // ============================================ model PlantingEvent { id BigInt @id @default(autoincrement()) @map("event_id") eventType String @map("event_type") @db.VarChar(50) // 聚合根信息 aggregateId String @map("aggregate_id") @db.VarChar(100) aggregateType String @map("aggregate_type") @db.VarChar(50) // 事件数据 eventData Json @map("event_data") // 元数据 userId BigInt? @map("user_id") occurredAt DateTime @default(now()) @map("occurred_at") version Int @default(1) @map("version") @@index([aggregateType, aggregateId]) @@index([eventType]) @@index([userId]) @@index([occurredAt]) @@map("planting_events") }