Neue Funktion jenseits der Lastenheft-Checkliste, explizit im Text als spätere Erweiterung angedacht (§4.4: "ApiCore SOLL später Abstammungsbäume darstellen können"). Königin.motherQueenId ist eine neue optionale Selbstreferenz (additive Migration), zusätzlich zu den bestehenden freien Textfeldern motherLine/fatherLine – letztere bleiben für Fälle, in denen die Mutter nicht selbst in ApiCore erfasst ist. Die Vaterlinie bleibt bewusst Freitext, da eine Königin mit vielen Drohnen aus unterschiedlichen Völkern begattet wird und es keine einzelne "Vater-Königin" gibt, die referenzierbar wäre. Backend: GET /queens/:id/lineage baut die mütterliche Ahnenkette (rekursiv über motherQueenId, Tiefe 8) sowie den Töchterbaum (rekursiv über die neue daughterQueens-Relation) in einer Antwort; create/update lehnen eine nicht existierende oder auf sich selbst zeigende motherQueenId ab. Frontend: neue "Abstammungsbaum"-Karte auf der Königin-Detailseite zeigt die mütterliche Linie als Liste sowie die Töchter als eingerückten Baum, beide mit Links zu den jeweiligen Königinnen. Anlage- und Bearbeiten-Formular bekommen ein "Mutter"-Auswahlfeld (Bearbeiten schließt die Königin selbst aus der Liste aus). Live in Chrome verifiziert: dreistufige Kette (Großmutter → Mutter → Tochter) korrekt in beide Richtungen dargestellt; dabei einen echten Anzeigefehler gefunden und behoben – das Mutter-Auswahlfeld zeigte nach dem Speichern die rohe Datenbank-ID statt des Königin-Codes an (derselbe SelectValue-ohne-children-Fehler wie zuvor bei der Import-Entitätsauswahl).
853 lines
24 KiB
Plaintext
853 lines
24 KiB
Plaintext
// ApiCore MVP-Datenmodell – abgeleitet aus docs/lastenheft.md Abschnitt 13, 4.2-4.22, 26.
|
||
// Prinzip: Historie statt Löschen (siehe ARCHITECTURE.md §4) – fachliche Haupttabellen
|
||
// tragen `status` + `deactivatedAt` statt Hard-Delete. Beziehungen sind relationale FKs,
|
||
// keine Freitextfelder, damit die Rückverfolgbarkeitskette (Abschnitt 16, 29) abfragbar bleibt.
|
||
|
||
generator client {
|
||
provider = "prisma-client-js"
|
||
output = "../generated/prisma"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "postgresql"
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Benutzer / Auth / Audit (Abschnitt 3, 14, 15, 16)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum Role {
|
||
ADMIN
|
||
BEEKEEPER
|
||
STAFF
|
||
READONLY
|
||
API_CLIENT
|
||
}
|
||
|
||
model User {
|
||
id String @id @default(cuid())
|
||
email String @unique
|
||
passwordHash String
|
||
name String
|
||
role Role @default(STAFF)
|
||
isActive Boolean @default(true)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deactivatedAt DateTime?
|
||
|
||
refreshTokens RefreshToken[]
|
||
|
||
inspections Inspection[]
|
||
varroaMeasurements VarroaMeasurement[]
|
||
treatments Treatment[]
|
||
feedings Feeding[]
|
||
harvests Harvest[]
|
||
extractions Extraction[]
|
||
honeyMeasurements HoneyMeasurement[]
|
||
stockMovements StockMovement[]
|
||
assignedTasks Task[] @relation("TaskAssignee")
|
||
createdTasks Task[] @relation("TaskCreator")
|
||
colonyMoves ColonyApiaryHistory[]
|
||
auditLogs AuditLog[]
|
||
bottlingBatches BottlingBatch[]
|
||
notifications Notification[]
|
||
queenEvaluations QueenEvaluation[]
|
||
webhookSubscriptions WebhookSubscription[]
|
||
documents Document[]
|
||
honeyBatchRelocations HoneyBatchRelocation[]
|
||
|
||
@@index([role])
|
||
}
|
||
|
||
model RefreshToken {
|
||
id String @id @default(cuid())
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
tokenHash String @unique
|
||
expiresAt DateTime
|
||
createdAt DateTime @default(now())
|
||
revokedAt DateTime?
|
||
|
||
@@index([userId])
|
||
}
|
||
|
||
enum AuditAction {
|
||
CREATE
|
||
UPDATE
|
||
DEACTIVATE
|
||
DELETE
|
||
}
|
||
|
||
model AuditLog {
|
||
id String @id @default(cuid())
|
||
entityType String
|
||
entityId String
|
||
action AuditAction
|
||
userId String?
|
||
user User? @relation(fields: [userId], references: [id])
|
||
timestamp DateTime @default(now())
|
||
beforeData Json?
|
||
afterData Json?
|
||
|
||
@@index([entityType, entityId])
|
||
@@index([timestamp])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Bienenstände (Abschnitt 4.2)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum ApiaryStatus {
|
||
ACTIVE
|
||
INACTIVE
|
||
}
|
||
|
||
model Apiary {
|
||
id String @id @default(cuid())
|
||
name String
|
||
description String?
|
||
location String?
|
||
latitude Float?
|
||
longitude Float?
|
||
address String?
|
||
status ApiaryStatus @default(ACTIVE)
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deactivatedAt DateTime?
|
||
|
||
colonies Colony[]
|
||
colonyMoves ColonyApiaryHistory[]
|
||
harvests Harvest[]
|
||
|
||
@@index([status])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Völkerverwaltung (Abschnitt 4.3, 4.4)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum ColonyType {
|
||
PRODUCTION_COLONY
|
||
NUCLEUS_COLONY
|
||
YOUNG_COLONY
|
||
CARETAKER_COLONY
|
||
MATING_NUCLEUS
|
||
RESERVE_COLONY
|
||
}
|
||
|
||
enum ColonyStatus {
|
||
ACTIVE
|
||
WEAK
|
||
CONSPICUOUS
|
||
QUEENLESS
|
||
DISSOLVED
|
||
SOLD
|
||
DECEASED
|
||
MERGED
|
||
}
|
||
|
||
model Colony {
|
||
id String @id @default(cuid())
|
||
code String @unique
|
||
apiaryId String
|
||
apiary Apiary @relation(fields: [apiaryId], references: [id])
|
||
hiveType String?
|
||
originText String?
|
||
colonyType ColonyType
|
||
status ColonyStatus @default(ACTIVE)
|
||
strength Int?
|
||
broodStatus String?
|
||
feedStatus String?
|
||
healthStatus String?
|
||
notes String?
|
||
currentQueenId String? @unique
|
||
currentQueen Queen? @relation("ColonyCurrentQueen", fields: [currentQueenId], references: [id])
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deactivatedAt DateTime?
|
||
|
||
apiaryHistory ColonyApiaryHistory[]
|
||
queenHistory QueenColonyHistory[]
|
||
lineageAsSource ColonyLineage[] @relation("LineageFrom")
|
||
lineageAsResult ColonyLineage[] @relation("LineageTo")
|
||
inspections Inspection[]
|
||
varroaMeasurements VarroaMeasurement[]
|
||
treatments Treatment[]
|
||
feedings Feeding[]
|
||
harvests HarvestColony[]
|
||
queenEvaluations QueenEvaluation[]
|
||
|
||
@@index([apiaryId])
|
||
@@index([status])
|
||
}
|
||
|
||
// Verschiebung Volk <-> Bienenstand, historisch nachvollziehbar (Abschnitt 4.2)
|
||
model ColonyApiaryHistory {
|
||
id String @id @default(cuid())
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
apiaryId String
|
||
apiary Apiary @relation(fields: [apiaryId], references: [id])
|
||
movedAt DateTime @default(now())
|
||
movedByUserId String?
|
||
movedByUser User? @relation(fields: [movedByUserId], references: [id])
|
||
notes String?
|
||
|
||
@@index([colonyId])
|
||
@@index([apiaryId])
|
||
}
|
||
|
||
enum LineageType {
|
||
SPLIT
|
||
MERGE
|
||
}
|
||
|
||
// Ableger bilden (SPLIT: from=Muttervolk, to=Ableger) und Völker vereinigen
|
||
// (MERGE: mehrere from-Zeilen auf denselben to=Zielvolk) – Abschnitt 4.4.
|
||
model ColonyLineage {
|
||
id String @id @default(cuid())
|
||
type LineageType
|
||
fromColonyId String
|
||
fromColony Colony @relation("LineageFrom", fields: [fromColonyId], references: [id])
|
||
toColonyId String
|
||
toColony Colony @relation("LineageTo", fields: [toColonyId], references: [id])
|
||
date DateTime
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([fromColonyId])
|
||
@@index([toColonyId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Königinnenverwaltung (Abschnitt 4.5)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum QueenStatus {
|
||
ACTIVE
|
||
RESERVE
|
||
UNMATED
|
||
MATED
|
||
LOST
|
||
REPLACED
|
||
SOLD
|
||
DECEASED
|
||
}
|
||
|
||
model Queen {
|
||
id String @id @default(cuid())
|
||
code String @unique
|
||
hatchYear Int?
|
||
breed String?
|
||
origin String?
|
||
breeder String?
|
||
markingColor String?
|
||
markingNumber String?
|
||
matingType String?
|
||
matingStatus String?
|
||
inseminationData String?
|
||
motherLine String?
|
||
fatherLine String?
|
||
motherQueenId String?
|
||
status QueenStatus @default(ACTIVE)
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
deactivatedAt DateTime?
|
||
|
||
motherQueen Queen? @relation("QueenMotherline", fields: [motherQueenId], references: [id])
|
||
daughterQueens Queen[] @relation("QueenMotherline")
|
||
colony Colony? @relation("ColonyCurrentQueen")
|
||
colonyHistory QueenColonyHistory[]
|
||
evaluations QueenEvaluation[]
|
||
|
||
@@index([status])
|
||
@@index([motherQueenId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Königinnenbewertung (Abschnitt 4.7) – v1.x Modul 31
|
||
// ---------------------------------------------------------------------------
|
||
|
||
model QueenEvaluation {
|
||
id String @id @default(cuid())
|
||
queenId String
|
||
queen Queen @relation(fields: [queenId], references: [id])
|
||
colonyId String?
|
||
colony Colony? @relation(fields: [colonyId], references: [id])
|
||
date DateTime
|
||
colonyStrength Int
|
||
gentleness Int
|
||
combBuild Int
|
||
swarmingTendency Int
|
||
broodPattern Int
|
||
honeyYield Int
|
||
notes String?
|
||
userId String?
|
||
user User? @relation(fields: [userId], references: [id])
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([queenId])
|
||
@@index([colonyId])
|
||
}
|
||
|
||
// Königinnenwechsel historisch nachvollziehbar (Abschnitt 4.5)
|
||
model QueenColonyHistory {
|
||
id String @id @default(cuid())
|
||
queenId String
|
||
queen Queen @relation(fields: [queenId], references: [id])
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
startDate DateTime
|
||
endDate DateTime?
|
||
notes String?
|
||
|
||
@@index([queenId])
|
||
@@index([colonyId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Durchsichten / digitale Stockkarte (Abschnitt 4.6, 4.7)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
model Inspection {
|
||
id String @id @default(cuid())
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
date DateTime
|
||
weather String?
|
||
temperature Float?
|
||
colonyStrength Int?
|
||
broodAmount String?
|
||
broodPattern Int?
|
||
openBroodPresent Boolean?
|
||
cappedBroodPresent Boolean?
|
||
eggsPresent Boolean?
|
||
queenSeen Boolean?
|
||
queenCellsPresent Boolean?
|
||
swarmMood Int?
|
||
gentleness Int?
|
||
combBehavior Int?
|
||
feedStatus String?
|
||
honeySuperStatus String?
|
||
healthIssues String?
|
||
varroaIssues String?
|
||
measures String?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
tasks Task[]
|
||
|
||
@@index([colonyId, date])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Aufgabenmanagement (Abschnitt 4.8)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum TaskPriority {
|
||
LOW
|
||
NORMAL
|
||
HIGH
|
||
URGENT
|
||
}
|
||
|
||
enum TaskStatus {
|
||
OPEN
|
||
IN_PROGRESS
|
||
DONE
|
||
CANCELLED
|
||
}
|
||
|
||
enum TaskRelatedType {
|
||
COLONY
|
||
APIARY
|
||
QUEEN
|
||
HONEY_BATCH
|
||
STORAGE
|
||
GENERAL
|
||
}
|
||
|
||
model Task {
|
||
id String @id @default(cuid())
|
||
title String
|
||
description String?
|
||
priority TaskPriority @default(NORMAL)
|
||
dueDate DateTime?
|
||
status TaskStatus @default(OPEN)
|
||
assignedUserId String?
|
||
assignedUser User? @relation("TaskAssignee", fields: [assignedUserId], references: [id])
|
||
createdByUserId String?
|
||
createdByUser User? @relation("TaskCreator", fields: [createdByUserId], references: [id])
|
||
relatedType TaskRelatedType @default(GENERAL)
|
||
relatedId String?
|
||
sourceInspectionId String?
|
||
sourceInspection Inspection? @relation(fields: [sourceInspectionId], references: [id])
|
||
createdAt DateTime @default(now())
|
||
completedAt DateTime?
|
||
|
||
@@index([status, dueDate])
|
||
@@index([relatedType, relatedId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Varroamanagement (Abschnitt 4.10)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum VarroaMethod {
|
||
NATURAL_MITE_FALL
|
||
POWDERED_SUGAR
|
||
WASHING_METHOD
|
||
DRONE_BROOD_CONTROL
|
||
}
|
||
|
||
model VarroaMeasurement {
|
||
id String @id @default(cuid())
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
date DateTime
|
||
method VarroaMethod
|
||
durationMinutes Int?
|
||
miteCount Int?
|
||
calculatedValue Float?
|
||
assessment String?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([colonyId, date])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Behandlung / Tierarzneimittel (Abschnitt 4.11)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
model Treatment {
|
||
id String @id @default(cuid())
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
date DateTime
|
||
startDate DateTime?
|
||
endDate DateTime?
|
||
product String
|
||
activeIngredient String?
|
||
amount String?
|
||
method String?
|
||
reason String?
|
||
batchNumber String?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([colonyId, date])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Fütterung (Abschnitt 4.12)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum FeedType {
|
||
SUGAR_WATER
|
||
FEED_SYRUP
|
||
FEED_PASTE
|
||
OWN_HONEY
|
||
OTHER
|
||
}
|
||
|
||
model Feeding {
|
||
id String @id @default(cuid())
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
date DateTime
|
||
feedType FeedType
|
||
product String?
|
||
amount Float
|
||
unit String
|
||
batchNumber String?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([colonyId, date])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Ernte / Schleuderung / Honigcharge / Rückverfolgbarkeit (Abschnitt 4.13-4.17)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
model Harvest {
|
||
id String @id @default(cuid())
|
||
apiaryId String
|
||
apiary Apiary @relation(fields: [apiaryId], references: [id])
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
date DateTime
|
||
honeyType String?
|
||
honeySuperCount Int?
|
||
grossWeight Float?
|
||
netWeight Float?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
colonies HarvestColony[]
|
||
extractions ExtractionHarvest[]
|
||
|
||
@@index([apiaryId, date])
|
||
}
|
||
|
||
model HarvestColony {
|
||
id String @id @default(cuid())
|
||
harvestId String
|
||
harvest Harvest @relation(fields: [harvestId], references: [id])
|
||
colonyId String
|
||
colony Colony @relation(fields: [colonyId], references: [id])
|
||
|
||
@@unique([harvestId, colonyId])
|
||
@@index([colonyId])
|
||
}
|
||
|
||
model Extraction {
|
||
id String @id @default(cuid())
|
||
date DateTime
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
amount Float?
|
||
room String?
|
||
waterContent Float?
|
||
temperature Float?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
harvests ExtractionHarvest[]
|
||
honeyBatches HoneyBatch[]
|
||
|
||
@@index([date])
|
||
}
|
||
|
||
model ExtractionHarvest {
|
||
id String @id @default(cuid())
|
||
extractionId String
|
||
extraction Extraction @relation(fields: [extractionId], references: [id])
|
||
harvestId String
|
||
harvest Harvest @relation(fields: [harvestId], references: [id])
|
||
|
||
@@unique([extractionId, harvestId])
|
||
@@index([harvestId])
|
||
}
|
||
|
||
enum HoneyBatchStatus {
|
||
RAW
|
||
EXTRACTED
|
||
CLARIFIED
|
||
CREAMED
|
||
STORED
|
||
BOTTLED
|
||
SOLD
|
||
CONSUMED
|
||
}
|
||
|
||
model HoneyBatch {
|
||
id String @id @default(cuid())
|
||
batchNumber String @unique
|
||
extractionId String
|
||
extraction Extraction @relation(fields: [extractionId], references: [id])
|
||
honeyType String?
|
||
amount Float?
|
||
waterContent Float?
|
||
storageContainerId String?
|
||
storageContainer StorageContainer? @relation(fields: [storageContainerId], references: [id])
|
||
status HoneyBatchStatus @default(RAW)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
measurements HoneyMeasurement[]
|
||
bottlingBatches BottlingBatch[]
|
||
relocations HoneyBatchRelocation[]
|
||
|
||
@@index([status])
|
||
@@index([extractionId])
|
||
}
|
||
|
||
// Honigmessungen (Abschnitt 4.17) – als Teil des HoneyBatch-Moduls im MVP,
|
||
// siehe ARCHITECTURE.md Annahme 1.
|
||
model HoneyMeasurement {
|
||
id String @id @default(cuid())
|
||
honeyBatchId String
|
||
honeyBatch HoneyBatch @relation(fields: [honeyBatchId], references: [id])
|
||
userId String
|
||
user User @relation(fields: [userId], references: [id])
|
||
waterContent Float
|
||
measuredAt DateTime
|
||
device String?
|
||
temperature Float?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([honeyBatchId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Lagerbehälter / grundlegende Lagerverwaltung (Abschnitt 4.18, 4.21)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum StorageContainerStatus {
|
||
EMPTY
|
||
FILLED
|
||
CLEANING
|
||
OUT_OF_SERVICE
|
||
}
|
||
|
||
model StorageContainer {
|
||
id String @id @default(cuid())
|
||
code String @unique
|
||
containerType String?
|
||
capacity Float?
|
||
currentAmount Float?
|
||
location String?
|
||
status StorageContainerStatus @default(EMPTY)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
honeyBatches HoneyBatch[]
|
||
relocationsFrom HoneyBatchRelocation[] @relation("RelocationFrom")
|
||
relocationsTo HoneyBatchRelocation[] @relation("RelocationTo")
|
||
|
||
@@index([status])
|
||
}
|
||
|
||
// Umlagerungshistorie einer Honigcharge zwischen Lagerbehältern (Abschnitt 26, v1.x Modul 32)
|
||
model HoneyBatchRelocation {
|
||
id String @id @default(cuid())
|
||
honeyBatchId String
|
||
honeyBatch HoneyBatch @relation(fields: [honeyBatchId], references: [id])
|
||
fromStorageContainerId String?
|
||
fromStorageContainer StorageContainer? @relation("RelocationFrom", fields: [fromStorageContainerId], references: [id])
|
||
toStorageContainerId String
|
||
toStorageContainer StorageContainer @relation("RelocationTo", fields: [toStorageContainerId], references: [id])
|
||
userId String?
|
||
user User? @relation(fields: [userId], references: [id])
|
||
notes String?
|
||
relocatedAt DateTime @default(now())
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([honeyBatchId, relocatedAt])
|
||
}
|
||
|
||
enum StockCategory {
|
||
HONEY
|
||
CONSUMABLE
|
||
EQUIPMENT_MATERIAL
|
||
}
|
||
|
||
model StockItem {
|
||
id String @id @default(cuid())
|
||
name String
|
||
category StockCategory
|
||
unit String
|
||
quantity Float @default(0)
|
||
minThreshold Float?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
movements StockMovement[]
|
||
|
||
@@index([category])
|
||
}
|
||
|
||
enum StockMovementType {
|
||
IN
|
||
OUT
|
||
TRANSFER
|
||
ADJUSTMENT
|
||
}
|
||
|
||
model StockMovement {
|
||
id String @id @default(cuid())
|
||
stockItemId String
|
||
stockItem StockItem @relation(fields: [stockItemId], references: [id])
|
||
type StockMovementType
|
||
quantity Float
|
||
date DateTime @default(now())
|
||
userId String?
|
||
user User? @relation(fields: [userId], references: [id])
|
||
relatedType String?
|
||
relatedId String?
|
||
notes String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([stockItemId, date])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Abfüllungen und Produkte (Abschnitt 4.19, 4.20) – v1.x Modul 23
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum ProductStatus {
|
||
ACTIVE
|
||
DISCONTINUED
|
||
}
|
||
|
||
model Product {
|
||
id String @id @default(cuid())
|
||
name String
|
||
description String?
|
||
sku String? @unique
|
||
packagingSize Float?
|
||
weight Float?
|
||
salesUnit String?
|
||
status ProductStatus @default(ACTIVE)
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
bottlingBatches BottlingBatch[]
|
||
|
||
@@index([status])
|
||
}
|
||
|
||
model BottlingBatch {
|
||
id String @id @default(cuid())
|
||
honeyBatchId String
|
||
honeyBatch HoneyBatch @relation(fields: [honeyBatchId], references: [id])
|
||
productId String?
|
||
product Product? @relation(fields: [productId], references: [id])
|
||
date DateTime
|
||
jarSize Float
|
||
jarCount Int
|
||
totalAmount Float
|
||
bestBeforeDate DateTime
|
||
lotNumber String @unique
|
||
userId String?
|
||
user User? @relation(fields: [userId], references: [id])
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([honeyBatchId])
|
||
@@index([productId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Inventar (Abschnitt 4.22) – v1.x Modul 24
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum EquipmentCondition {
|
||
NEW
|
||
GOOD
|
||
WORN
|
||
DEFECTIVE
|
||
}
|
||
|
||
model Equipment {
|
||
id String @id @default(cuid())
|
||
inventoryNumber String @unique
|
||
name String
|
||
manufacturer String?
|
||
purchaseDate DateTime?
|
||
condition EquipmentCondition @default(GOOD)
|
||
location String?
|
||
maintenanceDate DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([condition])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Benachrichtigungssystem (Abschnitt 24) – v1.x Modul 26
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum NotificationPriority {
|
||
INFO
|
||
HINWEIS
|
||
WARNUNG
|
||
KRITISCH
|
||
}
|
||
|
||
model Notification {
|
||
id String @id @default(cuid())
|
||
userId String?
|
||
user User? @relation(fields: [userId], references: [id])
|
||
priority NotificationPriority
|
||
message String
|
||
relatedType String?
|
||
relatedId String?
|
||
read Boolean @default(false)
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([userId, read])
|
||
@@index([priority])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Webhooks (Abschnitt 27) – v1.x Modul 28
|
||
// ---------------------------------------------------------------------------
|
||
|
||
model WebhookSubscription {
|
||
id String @id @default(cuid())
|
||
url String
|
||
events String[]
|
||
secret String
|
||
active Boolean @default(true)
|
||
createdByUserId String?
|
||
createdByUser User? @relation(fields: [createdByUserId], references: [id])
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([active])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Dokumente und Bilder (Abschnitt 4.28) – v1.x Modul 29
|
||
// ---------------------------------------------------------------------------
|
||
|
||
enum DocumentEntityType {
|
||
APIARY
|
||
COLONY
|
||
QUEEN
|
||
INSPECTION
|
||
HONEY_BATCH
|
||
}
|
||
|
||
model Document {
|
||
id String @id @default(cuid())
|
||
entityType DocumentEntityType
|
||
entityId String
|
||
fileName String
|
||
mimeType String
|
||
sizeBytes Int
|
||
storagePath String
|
||
uploadedByUserId String?
|
||
uploadedByUser User? @relation(fields: [uploadedByUserId], references: [id])
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([entityType, entityId])
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Automatisierungen (Abschnitt 26) – v1.x Modul 30
|
||
// ---------------------------------------------------------------------------
|
||
|
||
// Fest hinterlegte Trigger (Code, nicht nutzerdefiniert) – die Tabelle erlaubt
|
||
// nur, jeden Trigger zu aktivieren/deaktivieren und seine Schwellenwerte
|
||
// (config) sowie den Aufgabentext (actionTemplate) anzupassen.
|
||
enum AutomationTriggerType {
|
||
QUEENLESS_NO_EGGS
|
||
VARROA_THRESHOLD
|
||
FEED_STATUS_CRITICAL
|
||
}
|
||
|
||
model AutomationRule {
|
||
id String @id @default(cuid())
|
||
triggerType AutomationTriggerType @unique
|
||
active Boolean @default(true)
|
||
config Json?
|
||
actionTemplate String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
}
|