generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique name String avatar String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") createdTasks Task[] @relation("TaskCreator") assignedTasks Task[] @relation("TaskAssignee") projectMembers ProjectMember[] requirements Requirement[] watchedTasks TaskWatcher[] @@map("users") } model Product { id String @id @default(cuid()) name String description String @default("") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") projects Project[] requirements Requirement[] versions Version[] @@map("products") } model Project { id String @id @default(cuid()) productId String @map("product_id") name String description String @default("") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") product Product @relation(fields: [productId], references: [id]) sprints Sprint[] tasks Task[] versions Version[] members ProjectMember[] @@map("projects") } model Sprint { id String @id @default(cuid()) projectId String @map("project_id") name String startDate DateTime @map("start_date") endDate DateTime @map("end_date") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") project Project @relation(fields: [projectId], references: [id]) tasks Task[] @@map("sprints") } model Version { id String @id @default(cuid()) productId String @map("product_id") projectId String? @map("project_id") name String description String @default("") status String @default("planned") currentStage String? @map("current_stage") startDate DateTime? @map("start_date") expectedReleaseDate DateTime? @map("expected_release_date") releaseDate DateTime? @map("release_date") members Json @default("[]") progress Json @default("[]") priority Int? links Json @default("{}") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") product Product @relation(fields: [productId], references: [id]) project Project? @relation(fields: [projectId], references: [id]) tasks Task[] @@map("versions") } model Requirement { id String @default(cuid()) productId String @map("product_id") projectId String? @map("project_id") versionId String? @map("version_id") code String title String description String @default("") status String @default("pending_review") priority Int @default(0) type String? sourceType String? @map("source_type") sourceTarget String? @map("source_target") platform String? creatorId String? @map("creator_id") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") product Product @relation(fields: [productId], references: [id]) creator User? @relation(fields: [creatorId], references: [id]) @@id([id, productId]) @@unique([productId, code]) @@map("requirements") } model Task { id String @id @default(cuid()) projectId String @map("project_id") sprintId String? @map("sprint_id") versionId String? @map("version_id") parentId String? @map("parent_id") title String description String @default("") status String @default("todo") priority Int @default(0) assigneeId String? @map("assignee_id") creatorId String @map("creator_id") startDate DateTime? @map("start_date") dueDate DateTime? @map("due_date") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") project Project @relation(fields: [projectId], references: [id]) sprint Sprint? @relation(fields: [sprintId], references: [id]) version Version? @relation(fields: [versionId], references: [id]) parent Task? @relation("TaskChildren", fields: [parentId], references: [id]) children Task[] @relation("TaskChildren") assignee User? @relation("TaskAssignee", fields: [assigneeId], references: [id]) creator User @relation("TaskCreator", fields: [creatorId], references: [id]) watchers TaskWatcher[] comments Comment[] @@map("tasks") } model TaskWatcher { id String @id @default(cuid()) taskId String @map("task_id") userId String @map("user_id") task Task @relation(fields: [taskId], references: [id]) user User @relation(fields: [userId], references: [id]) @@unique([taskId, userId]) @@map("task_watchers") } model Comment { id String @id @default(cuid()) taskId String @map("task_id") authorId String @map("author_id") content String createdAt DateTime @default(now()) @map("created_at") task Task @relation(fields: [taskId], references: [id]) @@map("comments") } model ProjectMember { id String @id @default(cuid()) projectId String @map("project_id") userId String @map("user_id") role String @default("member") project Project @relation(fields: [projectId], references: [id]) user User @relation(fields: [userId], references: [id]) @@unique([projectId, userId]) @@map("project_members") } model TaskCategory { id String @id @default(cuid()) name String code String? group String isSystem Boolean @default(false) @map("is_system") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@unique([group, name]) @@map("task_categories") } model VersionPlan { id String @id @default(cuid()) versionId String @map("version_id") productId String @map("product_id") projectId String? @map("project_id") type String title String status String @default("pending") ownerId String? @map("owner_id") expectedStartAt DateTime? @map("expected_start_at") expectedEndAt DateTime? @map("expected_end_at") actualStartAt DateTime? @map("actual_start_at") completedAt DateTime? @map("completed_at") resultUrl String? @map("result_url") requirementCoverage Json @default("[]") @map("requirement_coverage") logs Json @default("[]") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("version_plans") } model DevTask { id String @default(cuid()) versionId String @map("version_id") productId String @map("product_id") projectId String @map("project_id") requirementId String? @map("requirement_id") requirementProductId String? @map("requirement_product_id") categoryId String? @map("category_id") code String title String description String @default("") status String @default("todo") priority Int @default(0) assigneeId String? @map("assignee_id") creatorId String? @map("creator_id") isBlocked Boolean @default(false) @map("is_blocked") blockReason String? @map("block_reason") expectedStartAt DateTime? @map("expected_start_at") expectedEndAt DateTime? @map("expected_end_at") startDate DateTime? @map("start_date") completedAt DateTime? @map("completed_at") estimateHours Float? @map("estimate_hours") aiEstimateHours Float? @map("ai_estimate_hours") references Json @default("[]") aiDraft Boolean @default(false) @map("ai_draft") aiDraftAt DateTime? @map("ai_draft_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@id([id, versionId]) @@unique([versionId, code]) @@map("dev_tasks") } model TestCase { id String @default(cuid()) versionId String @map("version_id") productId String @map("product_id") projectId String @map("project_id") requirementId String? @map("requirement_id") requirementProductId String? @map("requirement_product_id") categoryId String? @map("category_id") code String title String description String @default("") status String @default("pending") roundNo Int @default(1) @map("round_no") priority Int @default(0) assigneeId String? @map("assignee_id") creatorId String? @map("creator_id") plannedTestAt DateTime? @map("planned_test_at") plannedEndAt DateTime? @map("planned_end_at") startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") estimateHours Float? @map("estimate_hours") aiEstimateHours Float? @map("ai_estimate_hours") references Json @default("[]") aiDraft Boolean @default(false) @map("ai_draft") aiDraftAt DateTime? @map("ai_draft_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@id([id, versionId]) @@unique([versionId, code]) @@map("test_cases") } model Bug { id String @default(cuid()) versionId String @map("version_id") productId String @map("product_id") projectId String @map("project_id") testCaseId String? @map("test_case_id") testCaseVersionId String? @map("test_case_version_id") code String title String description String @default("") status String @default("open") severity String @default("normal") priority Int @default(0) assigneeId String? @map("assignee_id") reporterId String? @map("reporter_id") plannedFixAt DateTime? @map("planned_fix_at") resolvedAt DateTime? @map("resolved_at") closedAt DateTime? @map("closed_at") resolution String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@id([id, versionId]) @@unique([versionId, code]) @@map("bugs") } model WorkActivity { id String @default(cuid()) versionId String? @map("version_id") productId String? @map("product_id") projectId String? @map("project_id") actorId String? @map("actor_id") actorName String @default("") @map("actor_name") sourceType String @map("source_type") sourceId String @map("source_id") sourceVersionId String? @map("source_version_id") action String title String metadata Json @default("{}") occurredAt DateTime @map("occurred_at") createdAt DateTime @default(now()) @map("created_at") @@id([id, createdAt]) @@map("work_activities") } model TaskWorklog { id String @default(cuid()) versionId String? @map("version_id") productId String? @map("product_id") projectId String? @map("project_id") userId String? @map("user_id") sourceType String @map("source_type") sourceId String @map("source_id") sourceVersionId String? @map("source_version_id") workDate DateTime @db.Date @map("work_date") hours Float @default(0) content String @default("") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@id([id, createdAt]) @@map("task_worklogs") } model OvertimeRecord { id String @default(cuid()) productId String? @map("product_id") projectId String? @map("project_id") versionId String? @map("version_id") userId String? @map("user_id") reason String @default("") startAt DateTime @map("start_at") endAt DateTime @map("end_at") hours Float @default(0) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@id([id, createdAt]) @@map("overtime_records") } model XiaobaoRiskSnapshot { id String @default(cuid()) versionId String @map("version_id") snapshotDate DateTime @db.Date @map("snapshot_date") riskLevel String @map("risk_level") riskScore Int @default(0) @map("risk_score") riskSignature String @map("risk_signature") snapshot Json createdAt DateTime @default(now()) @map("created_at") @@id([id, createdAt]) @@map("xiaobao_risk_snapshots") } model XiaobaoRiskInsight { id String @default(cuid()) versionId String @map("version_id") riskSignature String @map("risk_signature") status String @default("generated") insight Json createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@id([id, createdAt]) @@map("xiaobao_risk_insights") } model AiLog { id String @default(cuid()) provider String model String operation String status String promptTokens Int @default(0) @map("prompt_tokens") completionTokens Int @default(0) @map("completion_tokens") durationMs Int @default(0) @map("duration_ms") errorMessage String? @map("error_message") metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @@id([id, createdAt]) @@map("ai_logs") } model XiaobaoRiskSummary { versionId String @id @map("version_id") riskLevel String @map("risk_level") riskScore Int @default(0) @map("risk_score") confidence Int @default(0) forecastReleaseDate DateTime? @map("forecast_release_date") riskSignature String @map("risk_signature") summary Json dirty Boolean @default(false) recomputedAt DateTime? @map("recomputed_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("xiaobao_risk_summaries") } model AppData { key String @id value Json createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("app_data") }