mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-25 01:36:39 +02:00
- 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>
274 lines
7.9 KiB
Text
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")
|
|
}
|