INSIGHT-MVP/packages/crm-service/prisma/crm.schema.prisma
Thomas Reitz 6bfce4af97 feat(crm): Vorgangsart (DealType) konfigurierbares Dropdown + Pipeline-Leerstate
- crm-service: Neues DealType-Model (deal_types Tabelle) mit name, color, sortOrder
  und Relation zu Deal.dealTypeId; Migration 20260313_deal_type
- crm-service: Vollstaendiger CRUD REST-Endpoint /crm/deal-types (TenantGuard)
- crm-service: CreateDealDto um optionales dealTypeId erweitert
- frontend: DealType Interface, API (dealTypesApi), Hooks (useDealTypes/...)
- frontend: CrmSettingsPage > Weitere Einstellungen > DealTypesConfig mit Farbpicker
- frontend: DealFormModal: Vorgangsart-Dropdown + Hinweis bei leerer Pipeline-Liste

Deployment: prisma migrate deploy && prisma generate im crm-service ausfuehren.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 16:15:02 +01:00

868 lines
28 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"]
}
// --------------------------------------------------------
// Industry - Branche (admin-konfigurierbar pro Tenant)
// --------------------------------------------------------
model Industry {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(100)
color String @default("#6B7280") @db.VarChar(7)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
companies Company[]
@@unique([tenantId, name])
@@index([tenantId])
@@map("industries")
@@schema("app_crm")
}
// --------------------------------------------------------
// AccountType - Kontotyp (admin-konfigurierbar pro Tenant)
// --------------------------------------------------------
model AccountType {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(100)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
companies Company[]
@@unique([tenantId, name])
@@index([tenantId])
@@map("account_types")
@@schema("app_crm")
}
// --------------------------------------------------------
// RelationshipType - Beziehungstyp (admin-konfigurierbar)
// --------------------------------------------------------
model RelationshipType {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(100)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
relationships CompanyRelationship[]
@@unique([tenantId, name])
@@index([tenantId])
@@map("relationship_types")
@@schema("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)
// Admin-konfigurierbare Felder
industryId String? @map("industry_id") @db.Uuid
accountTypeId String? @map("account_type_id") @db.Uuid
ownerId String? @map("owner_id") @db.Uuid
ownerName String? @map("owner_name") @db.VarChar(200)
// Phase 1: Registerdaten
vatId String? @map("vat_id") @db.VarChar(50)
taxId String? @map("tax_id") @db.VarChar(50)
tradeRegisterNumber String? @map("trade_register_number") @db.VarChar(100)
registerCourt String? @map("register_court") @db.VarChar(200)
companySize CompanySize? @map("company_size")
// Kontaktdaten (Legacy-Einzelfelder, deprecated — siehe emails[]/phones[])
email String? @db.VarChar(255)
phone String? @db.VarChar(50)
website String? @db.VarChar(500)
// Adresse (Hauptsitz)
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)
// Adresse (Lieferung)
deliveryStreet String? @map("delivery_street") @db.VarChar(200)
deliveryZip String? @map("delivery_zip") @db.VarChar(20)
deliveryCity String? @map("delivery_city") @db.VarChar(100)
deliveryCountry String? @map("delivery_country") @db.VarChar(2)
// Zusaetzlich
notes String? @db.Text
tags String[] @default([])
// Status (Phase 1: EntityStatus Enum ersetzt isActive)
status EntityStatus @default(ACTIVE)
isActive Boolean @default(true) @map("is_active") // DEPRECATED: Synchron gehalten
// Datenanreicherung
dataEnrichedAt DateTime? @map("data_enriched_at")
dataEnrichedSource String? @map("data_enriched_source") @db.VarChar(200)
// Lexware Office Integration
lexwareContactId String? @map("lexware_contact_id") @db.VarChar(36)
lexwareContactVersion Int? @map("lexware_contact_version")
lexwareSyncedAt DateTime? @map("lexware_synced_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
industryRef Industry? @relation(fields: [industryId], references: [id], onDelete: SetNull)
accountType AccountType? @relation(fields: [accountTypeId], references: [id], onDelete: SetNull)
contacts Contact[]
deals Deal[]
activities Activity[]
lexwareVouchers LexwareVoucher[]
relationships CompanyRelationship[] @relation("companyRelationships")
relatedRelationships CompanyRelationship[] @relation("relatedCompanyRelationships")
contracts Contract[]
emails ContactEmail[]
phones ContactPhone[]
owners CompanyOwner[]
@@unique([tenantId, lexwareContactId])
@@index([tenantId])
@@index([tenantId, name])
@@index([tenantId, industry])
@@index([tenantId, industryId])
@@index([tenantId, accountTypeId])
@@index([tenantId, isActive])
@@index([tenantId, status])
@@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 (Legacy-Einzelfelder, deprecated — siehe emails[]/phones[])
email String? @db.VarChar(255)
phone String? @db.VarChar(50)
mobile String? @db.VarChar(50)
website String? @db.VarChar(500)
// Phase 1: Neue Felder
linkedinUrl String? @map("linkedin_url") @db.VarChar(500)
birthday DateTime?
source ContactSource?
department String? @db.VarChar(200)
// 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([])
// Status (Phase 1: EntityStatus Enum ersetzt isActive)
status EntityStatus @default(ACTIVE)
isActive Boolean @default(true) @map("is_active") // DEPRECATED: Synchron gehalten
// Lexware Office Integration
lexwareContactId String? @map("lexware_contact_id") @db.VarChar(36)
lexwareContactVersion Int? @map("lexware_contact_version")
lexwareSyncedAt DateTime? @map("lexware_synced_at")
// 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[]
lexwareVouchers LexwareVoucher[]
emails ContactEmail[]
phones ContactPhone[]
owners ContactOwner[]
@@unique([tenantId, lexwareContactId])
@@index([tenantId])
@@index([tenantId, email])
@@index([tenantId, companyId])
@@index([tenantId, companyName])
@@index([tenantId, lastName, firstName])
@@index([tenantId, isActive])
@@index([tenantId, status])
@@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
companyId String? @map("company_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)
company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade)
@@index([tenantId])
@@index([tenantId, contactId])
@@index([tenantId, companyId])
@@index([tenantId, type])
@@index([tenantId, scheduledAt])
@@map("activities")
@@schema("app_crm")
}
enum ActivityType {
NOTE
CALL
EMAIL
MEETING
TASK
FOLLOWUP
@@schema("app_crm")
}
// --------------------------------------------------------
// Phase 1 Enums — Kontakt-Herkunft, Status, Owner, etc.
// --------------------------------------------------------
enum ContactSource {
TRADE_FAIR
REFERRAL
WEBSITE
COLD_CALL
IMPORT
BUSINESS_CARD
OTHER
@@schema("app_crm")
}
enum EntityStatus {
ACTIVE
INACTIVE
BLOCKED
@@schema("app_crm")
}
enum CompanySize {
SIZE_1_10
SIZE_11_50
SIZE_51_200
SIZE_201_500
SIZE_500_PLUS
@@schema("app_crm")
}
enum OwnerRole {
OWNER
MEMBER
WATCHER
@@schema("app_crm")
}
enum LostReason {
PRICE
TIMING
COMPETITOR
NO_NEED
OTHER
@@schema("app_crm")
}
enum EmailType {
WORK
PERSONAL
OTHER
@@schema("app_crm")
}
enum PhoneType {
OFFICE
MOBILE
FAX
@@schema("app_crm")
}
// --------------------------------------------------------
// CompanyRelationship - Beziehungen zwischen Unternehmen (N:M)
// --------------------------------------------------------
model CompanyRelationship {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
companyId String @map("company_id") @db.Uuid
relatedCompanyId String @map("related_company_id") @db.Uuid
relationshipTypeId String @map("relationship_type_id") @db.Uuid
notes String? @db.Text
createdBy String @map("created_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
// Relationen
company Company @relation("companyRelationships", fields: [companyId], references: [id], onDelete: Cascade)
relatedCompany Company @relation("relatedCompanyRelationships", fields: [relatedCompanyId], references: [id], onDelete: Cascade)
relationshipType RelationshipType @relation(fields: [relationshipTypeId], references: [id], onDelete: Restrict)
@@unique([companyId, relatedCompanyId, relationshipTypeId])
@@index([tenantId])
@@index([tenantId, companyId])
@@index([tenantId, relatedCompanyId])
@@map("company_relationships")
@@schema("app_crm")
}
// --------------------------------------------------------
// Contract - Vertraege (Platzhalter fuer zukuenftiges Modul)
// --------------------------------------------------------
model Contract {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
companyId String @map("company_id") @db.Uuid
title String @db.VarChar(255)
status ContractStatus @default(DRAFT)
startDate DateTime? @map("start_date")
endDate DateTime? @map("end_date")
value Decimal? @db.Decimal(15, 2)
currency String @default("EUR") @db.VarChar(3)
notes String? @db.Text
createdBy String @map("created_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: Cascade)
files ContractFile[]
@@index([tenantId, companyId])
@@map("contracts")
@@schema("app_crm")
}
model ContractFile {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
contractId String @map("contract_id") @db.Uuid
originalName String @map("original_name") @db.VarChar(500)
storagePath String @map("storage_path") @db.VarChar(1000)
mimeType String @map("mime_type") @db.VarChar(200)
size Int
uploadedBy String @map("uploaded_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
@@index([contractId])
@@map("contract_files")
@@schema("app_crm")
}
enum ContractStatus {
DRAFT
ACTIVE
EXPIRED
CANCELLED
@@schema("app_crm")
}
// --------------------------------------------------------
// DealType - Vorgangsart (admin-konfigurierbar pro Tenant)
// --------------------------------------------------------
model DealType {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(100)
color String @default("#6B7280") @db.VarChar(7)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deals Deal[]
@@unique([tenantId, name])
@@index([tenantId])
@@map("deal_types")
@@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)
probability Decimal @default(0) @map("probability") @db.Decimal(3, 2)
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
// Vorgangsart
dealTypeId String? @map("deal_type_id") @db.Uuid
// Phase 1: Lost-Reason
lostReason LostReason? @map("lost_reason")
lostReasonText String? @map("lost_reason_text") @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)
dealType DealType? @relation(fields: [dealTypeId], references: [id], onDelete: SetNull)
dealVouchers DealVoucher[]
owners DealOwner[]
@@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")
}
// --------------------------------------------------------
// Lexware Office Integration - Voucher Types
// --------------------------------------------------------
enum VoucherType {
QUOTATION
ORDER_CONFIRMATION
INVOICE
CREDIT_NOTE
@@schema("app_crm")
}
// --------------------------------------------------------
// LexwareVoucher - Gecachte Belege aus Lexware Office
// --------------------------------------------------------
model LexwareVoucher {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
lexwareVoucherId String @map("lexware_voucher_id") @db.VarChar(36)
voucherType VoucherType @map("voucher_type")
voucherNumber String? @map("voucher_number") @db.VarChar(100)
voucherDate DateTime? @map("voucher_date")
voucherStatus String? @map("voucher_status") @db.VarChar(50)
totalGrossAmount Decimal? @map("total_gross_amount") @db.Decimal(15, 2)
totalNetAmount Decimal? @map("total_net_amount") @db.Decimal(15, 2)
totalTaxAmount Decimal? @map("total_tax_amount") @db.Decimal(15, 2)
currency String @default("EUR") @db.VarChar(3)
title String? @db.VarChar(500)
lineItemsCount Int? @map("line_items_count")
lineItemsJson String? @map("line_items_json") @db.Text
// Verknuepfung zu Lexware-Kontakt und CRM-Entitaeten
lexwareContactId String @map("lexware_contact_id") @db.VarChar(36)
companyId String? @map("company_id") @db.Uuid
contactId String? @map("contact_id") @db.Uuid
lexwareDeepLink String? @map("lexware_deep_link") @db.VarChar(500)
fetchedAt DateTime @default(now()) @map("fetched_at")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relationen
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
contact Contact? @relation(fields: [contactId], references: [id], onDelete: SetNull)
deals DealVoucher[]
@@unique([tenantId, lexwareVoucherId])
@@index([tenantId])
@@index([tenantId, companyId])
@@index([tenantId, contactId])
@@index([tenantId, lexwareContactId])
@@index([tenantId, voucherType])
@@map("lexware_vouchers")
@@schema("app_crm")
}
// --------------------------------------------------------
// DealVoucher - Verknuepfung Deal <-> Lexware-Beleg (m:n)
// --------------------------------------------------------
model DealVoucher {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
dealId String @map("deal_id") @db.Uuid
voucherId String @map("voucher_id") @db.Uuid
linkedBy String @map("linked_by") @db.Uuid
linkedAt DateTime @default(now()) @map("linked_at")
// Relationen
deal Deal @relation(fields: [dealId], references: [id], onDelete: Cascade)
voucher LexwareVoucher @relation(fields: [voucherId], references: [id], onDelete: Cascade)
@@unique([dealId, voucherId])
@@index([tenantId])
@@index([tenantId, dealId])
@@index([tenantId, voucherId])
@@map("deal_vouchers")
@@schema("app_crm")
}
// --------------------------------------------------------
// ContactEmail - Multi-Value E-Mail-Adressen (Phase 1)
// --------------------------------------------------------
model ContactEmail {
id String @id @default(uuid()) @db.Uuid
contactId String? @map("contact_id") @db.Uuid
companyId String? @map("company_id") @db.Uuid
email String @db.VarChar(255)
type EmailType @default(WORK)
isPrimary Boolean @default(false) @map("is_primary")
createdAt DateTime @default(now()) @map("created_at")
contact Contact? @relation(fields: [contactId], references: [id], onDelete: Cascade)
company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade)
@@index([contactId])
@@index([companyId])
@@map("contact_emails")
@@schema("app_crm")
}
// --------------------------------------------------------
// ContactPhone - Multi-Value Telefonnummern (Phase 1)
// --------------------------------------------------------
model ContactPhone {
id String @id @default(uuid()) @db.Uuid
contactId String? @map("contact_id") @db.Uuid
companyId String? @map("company_id") @db.Uuid
phone String @db.VarChar(50)
type PhoneType @default(OFFICE)
isPrimary Boolean @default(false) @map("is_primary")
createdAt DateTime @default(now()) @map("created_at")
contact Contact? @relation(fields: [contactId], references: [id], onDelete: Cascade)
company Company? @relation(fields: [companyId], references: [id], onDelete: Cascade)
@@index([contactId])
@@index([companyId])
@@map("contact_phones")
@@schema("app_crm")
}
// --------------------------------------------------------
// ContactOwner - Zustaendige pro Kontakt (m:n, Phase 1)
// --------------------------------------------------------
model ContactOwner {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
contactId String @map("contact_id") @db.Uuid
userId String @map("user_id") @db.Uuid
role OwnerRole @default(OWNER)
createdAt DateTime @default(now()) @map("created_at")
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
@@unique([contactId, userId])
@@index([tenantId])
@@index([tenantId, contactId])
@@map("contact_owners")
@@schema("app_crm")
}
// --------------------------------------------------------
// CompanyOwner - Zustaendige pro Unternehmen (m:n, Phase 1)
// --------------------------------------------------------
model CompanyOwner {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
companyId String @map("company_id") @db.Uuid
userId String @map("user_id") @db.Uuid
role OwnerRole @default(OWNER)
createdAt DateTime @default(now()) @map("created_at")
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
@@unique([companyId, userId])
@@index([tenantId])
@@index([tenantId, companyId])
@@map("company_owners")
@@schema("app_crm")
}
// --------------------------------------------------------
// DealOwner - Zustaendige pro Deal (m:n, Phase 1)
// --------------------------------------------------------
model DealOwner {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
dealId String @map("deal_id") @db.Uuid
userId String @map("user_id") @db.Uuid
role OwnerRole @default(OWNER)
createdAt DateTime @default(now()) @map("created_at")
deal Deal @relation(fields: [dealId], references: [id], onDelete: Cascade)
@@unique([dealId, userId])
@@index([tenantId])
@@index([tenantId, dealId])
@@map("deal_owners")
@@schema("app_crm")
}
// --------------------------------------------------------
// Phase 2.1 Enums — Custom Fields
// --------------------------------------------------------
enum CustomFieldEntityType {
PERSON
COMPANY
DEAL
@@schema("app_crm")
}
enum CustomFieldType {
TEXT
TEXTAREA
NUMBER
DATE
DROPDOWN
MULTI_SELECT
CHECKBOX
URL
@@schema("app_crm")
}
// --------------------------------------------------------
// CustomFieldDef - Benutzerdefinierte Feld-Definitionen (Phase 2.1)
// --------------------------------------------------------
model CustomFieldDef {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
entityType CustomFieldEntityType @map("entity_type")
name String @db.VarChar(200)
label String @db.VarChar(200)
fieldType CustomFieldType @map("field_type")
options Json? @db.JsonB
isRequired Boolean @default(false) @map("is_required")
position Int @default(0)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
values CustomFieldValue[]
@@unique([tenantId, entityType, name])
@@index([tenantId])
@@index([tenantId, entityType])
@@map("crm_custom_field_defs")
@@schema("app_crm")
}
// --------------------------------------------------------
// CustomFieldValue - Benutzerdefinierte Feld-Werte (Phase 2.1)
// --------------------------------------------------------
model CustomFieldValue {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
fieldDefId String @map("field_def_id") @db.Uuid
entityId String @map("entity_id") @db.Uuid
valueText String? @map("value_text") @db.Text
valueNumber Decimal? @map("value_number") @db.Decimal(15, 4)
valueDate DateTime? @map("value_date")
valueBoolean Boolean? @map("value_boolean")
valueJson Json? @map("value_json") @db.JsonB
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
fieldDef CustomFieldDef @relation(fields: [fieldDefId], references: [id], onDelete: Cascade)
@@unique([fieldDefId, entityId])
@@index([tenantId])
@@index([tenantId, entityId])
@@index([fieldDefId])
@@map("crm_custom_field_values")
@@schema("app_crm")
}
// --------------------------------------------------------
// TradeEvent - Messe-/Event-Timer (admin-konfigurierbar)
// --------------------------------------------------------
model TradeEvent {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String @db.VarChar(200)
description String? @db.Text
startDate DateTime @map("start_date")
endDate DateTime @map("end_date")
location String? @db.VarChar(300)
boothInfo String? @map("booth_info") @db.VarChar(200)
websiteUrl String? @map("website_url") @db.VarChar(500)
isActive Boolean @default(true) @map("is_active")
sortOrder Int @default(0) @map("sort_order")
// 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")
@@unique([tenantId, name])
@@index([tenantId])
@@index([tenantId, isActive])
@@index([tenantId, startDate])
@@map("trade_events")
@@schema("app_crm")
}