hp-prod-tracker/prisma/schema.prisma
Leivur Djurhuus e5b398d7da feat: Implement automation event bus and rule engine
- Add event bus for dispatching automation events with handlers.
- Create rule engine to evaluate events against defined triggers.
- Introduce chat provider to interface with Claude API and Ollama fallback.
- Define tool schemas for Claude-compatible operations.
- Implement tool executor to map tool calls to service layer functions.
- Develop automation service for CRUD operations on rules and event handling.
2026-03-12 11:20:21 -05:00

497 lines
13 KiB
Text

generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
// ─── Enums ──────────────────────────────────────────────
enum Role {
ADMIN
PRODUCER
ARTIST
}
enum ProjectStatus {
ACTIVE
ON_HOLD
COMPLETED
ARCHIVED
}
enum Priority {
LOW
MEDIUM
HIGH
URGENT
}
enum DeliverableStatus {
NOT_STARTED
IN_PROGRESS
IN_REVIEW
APPROVED
ON_HOLD
}
enum StageStatus {
BLOCKED
NOT_STARTED
IN_PROGRESS
IN_REVIEW
CHANGES_REQUESTED
APPROVED
DELIVERED
SKIPPED
}
enum RevisionStatus {
SUBMITTED
IN_REVIEW
CHANGES_REQUESTED
APPROVED
}
enum NotificationType {
ASSIGNMENT
STATUS_CHANGE
REVISION_SUBMITTED
REVISION_FEEDBACK
COMMENT
DEADLINE_APPROACHING
DEADLINE_OVERDUE
STAGE_UNBLOCKED
}
enum AssignmentRole {
LEAD
SUPPORT
}
enum SkillLevel {
JUNIOR
INTERMEDIATE
SENIOR
LEAD
}
// ─── Organization ───────────────────────────────────────
model Organization {
id String @id @default(cuid())
name String
domain String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
users User[]
projects Project[]
automationRules AutomationRule[]
@@map("organizations")
}
// ─── Auth.js models ─────────────────────────────────────
model User {
id String @id @default(cuid())
name String?
email String @unique
emailVerified DateTime?
image String?
role Role @default(ARTIST)
department String?
maxCapacity Int @default(5)
organizationId String?
organization Organization? @relation(fields: [organizationId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
accounts Account[]
sessions Session[]
assignments StageAssignment[]
comments Comment[]
notifications Notification[]
skills UserSkill[]
searchLogs SearchLog[]
automationRules AutomationRule[] @relation("AutomationCreator")
chatMessages ChatMessage[]
@@map("users")
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@map("accounts")
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}
model VerificationToken {
identifier String
token String
expires DateTime
@@unique([identifier, token])
@@map("verification_tokens")
}
// ─── Pipeline Templates (seed data) ────────────────────
model PipelineStageTemplate {
id String @id @default(cuid())
name String @unique
slug String @unique
order Int @unique
isCriticalGate Boolean @default(false)
isOptional Boolean @default(false)
description String?
estimatedDays Float?
dependsOn PipelineStageDependency[] @relation("DependsOnStage")
dependedBy PipelineStageDependency[] @relation("PrerequisiteStage")
deliverableStages DeliverableStage[]
skillRequirements StageSkillRequirement[]
@@map("pipeline_stage_templates")
}
model PipelineStageDependency {
id String @id @default(cuid())
stageId String
prerequisiteId String
stage PipelineStageTemplate @relation("DependsOnStage", fields: [stageId], references: [id])
prerequisite PipelineStageTemplate @relation("PrerequisiteStage", fields: [prerequisiteId], references: [id])
@@unique([stageId, prerequisiteId])
@@map("pipeline_stage_dependencies")
}
// ─── Project ────────────────────────────────────────────
model Project {
id String @id @default(cuid())
projectCode String @unique
name String
description String?
status ProjectStatus @default(ACTIVE)
priority Priority @default(MEDIUM)
startDate DateTime?
dueDate DateTime?
businessUnit String?
formFactor String?
codeName String?
npiOrRefresh String?
quarter String?
requestor String?
workfrontId String?
omgCode String?
bmtId String?
estimatedCost Float?
actualCost Float?
agency String?
// pgvector embedding for semantic search (raw SQL — Prisma can't query this directly)
embedding Unsupported("vector(768)")?
organizationId String
organization Organization @relation(fields: [organizationId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deliverables Deliverable[]
@@index([organizationId])
@@index([status])
@@map("projects")
}
// ─── Deliverable ────────────────────────────────────────
model Deliverable {
id String @id @default(cuid())
name String
status DeliverableStatus @default(NOT_STARTED)
priority Priority @default(MEDIUM)
dueDate DateTime?
notes String?
cmfSku String?
assetCount Int?
requestedDueDate DateTime?
plannedDeliveryDate DateTime?
actualDeliveryDate DateTime?
wfInputDate DateTime?
// pgvector embedding for semantic search (raw SQL — Prisma can't query this directly)
embedding Unsupported("vector(768)")?
projectId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
stages DeliverableStage[]
@@index([projectId])
@@index([status])
@@map("deliverables")
}
// ─── Deliverable Stage (instance per deliverable) ───────
model DeliverableStage {
id String @id @default(cuid())
status StageStatus @default(BLOCKED)
revisionRound Int @default(0)
startDate DateTime?
completedDate DateTime?
dueDate DateTime?
notes String?
subStatus String?
deliverableId String
deliverable Deliverable @relation(fields: [deliverableId], references: [id], onDelete: Cascade)
templateId String
template PipelineStageTemplate @relation(fields: [templateId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
assignments StageAssignment[]
revisions Revision[]
comments Comment[]
@@unique([deliverableId, templateId])
@@index([deliverableId])
@@index([status])
@@map("deliverable_stages")
}
// ─── Stage Assignment ───────────────────────────────────
model StageAssignment {
id String @id @default(cuid())
role AssignmentRole? @default(LEAD)
deliverableStageId String
deliverableStage DeliverableStage @relation(fields: [deliverableStageId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id])
createdAt DateTime @default(now())
@@unique([deliverableStageId, userId])
@@index([userId])
@@map("stage_assignments")
}
// ─── Revision ───────────────────────────────────────────
model Revision {
id String @id @default(cuid())
roundNumber Int
status RevisionStatus @default(SUBMITTED)
feedbackNotes String?
internalNotes String?
attachments Json?
deliverableStageId String
deliverableStage DeliverableStage @relation(fields: [deliverableStageId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([deliverableStageId])
@@map("revisions")
}
// ─── Comment ────────────────────────────────────────────
model Comment {
id String @id @default(cuid())
content String @db.Text
deliverableStageId String
deliverableStage DeliverableStage @relation(fields: [deliverableStageId], references: [id], onDelete: Cascade)
authorId String
author User @relation(fields: [authorId], references: [id])
parentId String?
parent Comment? @relation("CommentThread", fields: [parentId], references: [id])
replies Comment[] @relation("CommentThread")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([deliverableStageId])
@@index([parentId])
@@map("comments")
}
// ─── Notification ───────────────────────────────────────
model Notification {
id String @id @default(cuid())
type NotificationType
title String
message String
link String?
isRead Boolean @default(false)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@index([userId, isRead])
@@map("notifications")
}
// ─── Skills & Capacity (Phase 6) ────────────────────────
model Skill {
id String @id @default(cuid())
name String @unique
createdAt DateTime @default(now())
users UserSkill[]
stageRequirements StageSkillRequirement[]
@@map("skills")
}
model UserSkill {
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
skillId String
skill Skill @relation(fields: [skillId], references: [id], onDelete: Cascade)
level SkillLevel @default(INTERMEDIATE)
@@id([userId, skillId])
@@map("user_skills")
}
model StageSkillRequirement {
stageTemplateId String
stageTemplate PipelineStageTemplate @relation(fields: [stageTemplateId], references: [id], onDelete: Cascade)
skillId String
skill Skill @relation(fields: [skillId], references: [id], onDelete: Cascade)
importance Int @default(1) // 1=nice-to-have, 2=important, 3=required
@@id([stageTemplateId, skillId])
@@map("stage_skill_requirements")
}
// ─── Automation Engine (Phase 7.1) ──────────────────────
model AutomationRule {
id String @id @default(cuid())
name String
description String?
organizationId String
organization Organization @relation(fields: [organizationId], references: [id])
isEnabled Boolean @default(true)
trigger Json // { event, conditions[] }
actions Json // [{ type, params }]
createdById String
createdBy User @relation("AutomationCreator", fields: [createdById], references: [id])
executions AutomationExecution[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([organizationId])
@@index([isEnabled])
@@map("automation_rules")
}
model AutomationExecution {
id String @id @default(cuid())
ruleId String
rule AutomationRule @relation(fields: [ruleId], references: [id], onDelete: Cascade)
triggeredBy Json // the event payload that triggered execution
result Json // what actions were taken + outcomes
status ExecutionStatus
error String?
executedAt DateTime @default(now())
@@index([ruleId])
@@index([executedAt])
@@map("automation_executions")
}
enum ExecutionStatus {
SUCCESS
PARTIAL_FAILURE
FAILURE
}
// ─── Chat History (CLI Anything) ────────────────────────
model ChatMessage {
id String @id @default(cuid())
sessionId String
role String // "user" | "assistant" | "system"
content String @db.Text
toolCalls Json? // tool calls made by assistant
toolResults Json? // results of tool execution
metadata Json? // context: active project, etc.
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
organizationId String
createdAt DateTime @default(now())
@@index([sessionId])
@@index([userId])
@@map("chat_messages")
}
// ─── Semantic Search (Phase 8.4) ────────────────────────
model SearchLog {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
query String
resultCount Int @default(0)
clickedId String?
createdAt DateTime @default(now())
@@index([userId])
@@map("search_logs")
}