feat: Custom fields — JSONB with schema per entity (PRD §5.5)

Models: CustomFieldDef (schema definitions) + CustomFieldValue (entity values)
- Per entity type: company, person, deal, project, invoice, ticket, contract
- Field types: string, number, boolean, date, select, multiselect
- Options for select/multiselect stored as JSON
- Unique constraint: (entityType, key) for definitions, (entityType, entityId, fieldDefId) for values

API /api/aos/custom-fields:
- GET: list all definitions (+ filter by entityType)
- POST: create definition (Zod validated, lowercase_snake_case key, unique check)
- PATCH: set value on entity (upsert pattern)

Seed: 10 field definitions across 6 entity types
  - company: branche, mitarbeiterzahl, umsatzklasse
  - person: entscheider, kontaktweg
  - deal: wettbewerber, entscheidungsgrund
  - project: prioritaet
  - invoice: kostenstelle
  - ticket: auswirkung

Verified: 10 defs, 3 company fields, duplicate→409, invalid key→400
This commit is contained in:
Z User committed 2026-10-27 22:19:25 +00:00
1 parent d5dc2a1832
commit 81acd9df7a
5 files changed
+199

No files matched your search

+33
View File
@@ -753,3 +753,36 @@ model Jahresarchiv {
createdBy String
notes String?
}
// ---------------------------------------------------------------------------
// Custom Fields (PRD §5.5: "Custom fields: JSONB with a schema table per entity")
// ---------------------------------------------------------------------------
model CustomFieldDef {
id String @id @default(cuid())
entityType String // company|person|deal|project|invoice|ticket|contract
key String // field key, e.g. "branche", "lead_source_detail"
label String // display label, e.g. "Branche"
type String // string|number|boolean|date|select|multiselect
options String? // JSON array for select/multiselect
required Boolean @default(false)
sortOrder Int @default(0)
values CustomFieldValue[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([entityType, key])
}
model CustomFieldValue {
id String @id @default(cuid())
fieldDefId String
fieldDef CustomFieldDef @relation(fields: [fieldDefId], references: [id])
entityType String // denormalized for fast lookup
entityId String // the entity's ID
value String? // JSON-encoded value (string, number, bool, array)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([entityType, entityId, fieldDefId])
}