INSIGHT-MVP/packages/crm-service/prisma/crm.schema.prisma
Thomas Reitz 56a9ed9647 feat(crm): add Company entity + rename Deals to Vorgaenge
- New Company model with full CRUD under /api/v1/crm/companies
- Contact now has companyId relation + position field
- Deal now has companyId relation
- Company detail includes contacts (top 20) and deals (top 10)
- All endpoints include company in responses
- Swagger tags renamed: Deals -> Vorgaenge (Deals)
- Error messages use "Vorgang" instead of "Deal"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:30:34 +01:00

274 lines
7.9 KiB
Text

// ============================================================
// INSIGHT CRM Service - Prisma Schema
// ============================================================
// Eigenes Schema im PostgreSQL-Schema 'app_crm'
// Eigener Prisma-Client-Output (kein Konflikt mit Core)
// ============================================================
generator client {
provider = "prisma-client-js"
output = "../node_modules/.prisma/crm-client"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DATABASE_URL_DIRECT")
schemas = ["app_crm"]
}
// --------------------------------------------------------
// Company - Unternehmen (uebergeordnete Entity)
// --------------------------------------------------------
model Company {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(200)
industry String? @db.VarChar(100)
// Kontaktdaten
email String? @db.VarChar(255)
phone String? @db.VarChar(50)
website String? @db.VarChar(500)
// Adresse
street String? @db.VarChar(200)
zip String? @db.VarChar(20)
city String? @db.VarChar(100)
state String? @db.VarChar(100)
country String? @default("DE") @db.VarChar(2)
// Zusaetzlich
notes String? @db.Text
tags String[] @default([])
isActive Boolean @default(true) @map("is_active")
// Audit-Trail
createdBy String @map("created_by") @db.Uuid
updatedBy String? @map("updated_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
contacts Contact[]
deals Deal[]
@@index([tenantId])
@@index([tenantId, name])
@@index([tenantId, industry])
@@index([tenantId, isActive])
@@map("companies")
@@schema("app_crm")
}
// --------------------------------------------------------
// Contact - CRM-Kontakte (Personen)
// --------------------------------------------------------
model Contact {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
type ContactType @default(PERSON)
// Person
firstName String? @map("first_name") @db.VarChar(100)
lastName String? @map("last_name") @db.VarChar(100)
// Unternehmenszuordnung
companyId String? @map("company_id") @db.Uuid
companyName String? @map("company_name") @db.VarChar(200)
position String? @db.VarChar(200)
// Kontaktdaten
email String? @db.VarChar(255)
phone String? @db.VarChar(50)
mobile String? @db.VarChar(50)
website String? @db.VarChar(500)
// Adresse
street String? @db.VarChar(200)
zip String? @db.VarChar(20)
city String? @db.VarChar(100)
state String? @db.VarChar(100)
country String? @default("DE") @db.VarChar(2)
// Zusaetzlich
notes String? @db.Text
tags String[] @default([])
isActive Boolean @default(true) @map("is_active")
// Audit-Trail (User-IDs aus platform_core)
createdBy String @map("created_by") @db.Uuid
updatedBy String? @map("updated_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
activities Activity[]
deals Deal[]
@@index([tenantId])
@@index([tenantId, email])
@@index([tenantId, companyId])
@@index([tenantId, companyName])
@@index([tenantId, lastName, firstName])
@@index([tenantId, isActive])
@@map("contacts")
@@schema("app_crm")
}
enum ContactType {
PERSON
ORGANIZATION
@@schema("app_crm")
}
// --------------------------------------------------------
// Activity - CRM-Aktivitaeten (Notizen, Anrufe, E-Mails)
// --------------------------------------------------------
model Activity {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
contactId String @map("contact_id") @db.Uuid
type ActivityType
subject String @db.VarChar(500)
description String? @db.Text
// Terminierung
scheduledAt DateTime? @map("scheduled_at")
completedAt DateTime? @map("completed_at")
// Audit-Trail
createdBy String @map("created_by") @db.Uuid
updatedBy String? @map("updated_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
@@index([tenantId])
@@index([tenantId, contactId])
@@index([tenantId, type])
@@index([tenantId, scheduledAt])
@@map("activities")
@@schema("app_crm")
}
enum ActivityType {
NOTE
CALL
EMAIL
MEETING
TASK
@@schema("app_crm")
}
// --------------------------------------------------------
// Pipeline - Sales-Pipelines (konfigurierbar pro Tenant)
// --------------------------------------------------------
model Pipeline {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(200)
isDefault Boolean @default(false) @map("is_default")
isActive Boolean @default(true) @map("is_active")
// Audit-Trail
createdBy String @map("created_by") @db.Uuid
updatedBy String? @map("updated_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
stages PipelineStage[]
deals Deal[]
@@index([tenantId])
@@index([tenantId, isActive])
@@map("pipelines")
@@schema("app_crm")
}
// --------------------------------------------------------
// PipelineStage - Stufen einer Pipeline (z.B. Lead, Angebot)
// --------------------------------------------------------
model PipelineStage {
id String @id @default(uuid()) @db.Uuid
pipelineId String @map("pipeline_id") @db.Uuid
name String @db.VarChar(200)
sortOrder Int @default(0) @map("sort_order")
color String @default("#6B7280") @db.VarChar(7)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
deals Deal[]
@@index([pipelineId])
@@index([pipelineId, sortOrder])
@@map("pipeline_stages")
@@schema("app_crm")
}
// --------------------------------------------------------
// Deal - Verkaufschancen / Deals
// --------------------------------------------------------
model Deal {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
pipelineId String @map("pipeline_id") @db.Uuid
stageId String @map("stage_id") @db.Uuid
contactId String? @map("contact_id") @db.Uuid
companyId String? @map("company_id") @db.Uuid
title String @db.VarChar(500)
value Decimal? @db.Decimal(15, 2)
currency String @default("EUR") @db.VarChar(3)
status DealStatus @default(OPEN)
expectedCloseDate DateTime? @map("expected_close_date")
closedAt DateTime? @map("closed_at")
notes String? @db.Text
// Audit-Trail
createdBy String @map("created_by") @db.Uuid
updatedBy String? @map("updated_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
stage PipelineStage @relation(fields: [stageId], references: [id])
contact Contact? @relation(fields: [contactId], references: [id], onDelete: SetNull)
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
@@index([tenantId])
@@index([tenantId, pipelineId])
@@index([tenantId, stageId])
@@index([tenantId, contactId])
@@index([tenantId, companyId])
@@index([tenantId, status])
@@map("deals")
@@schema("app_crm")
}
enum DealStatus {
OPEN
WON
LOST
@@schema("app_crm")
}