Files
recipe-app/backend/prisma/schema.prisma
T
Nils-Johan Gynther 21dc06829a feat(meal-plan): add servings field to MealPlanEntry and update related functionality
feat(products): implement bulk update for product categories

feat(recipes): add servings input to WriteRecipePage and update MealPlanClient for servings management

refactor(types): enhance Product and Category types with additional properties
2026-04-17 22:50:41 +02:00

219 lines
6.3 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
username String @unique
email String @unique
firstName String?
lastName String?
passwordHash String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userProducts UserProduct[]
ownedRecipes Recipe[] @relation("RecipeOwner")
sharedRecipes RecipeShare[]
ownedProducts Product[]
}
model Product {
id Int @id @default(autoincrement())
name String
normalizedName String @unique
category String?
subcategory String?
brand String?
canonicalName String?
isActive Boolean @default(true)
deletedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
inventoryItems InventoryItem[]
recipeIngredients RecipeIngredient[]
pantryItems PantryItem[]
receiptAliases ReceiptAlias[]
tags ProductTag[]
nutrition Nutrition?
ownerId Int?
owner User? @relation(fields: [ownerId], references: [id], onDelete: SetNull)
userProducts UserProduct[]
categoryId Int?
categoryRef Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
}
model Category {
id Int @id @default(autoincrement())
name String
parentId Int?
parent Category? @relation("CategoryTree", fields: [parentId], references: [id], onDelete: SetNull)
children Category[] @relation("CategoryTree")
products Product[]
@@unique([name, parentId])
@@index([parentId])
}
model UserProduct {
id Int @id @default(autoincrement())
userId Int
productId Int
note String? @db.Text
preferredBrand String?
preferredStore String?
isPrivate Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@unique([userId, productId])
@@index([userId])
@@index([productId])
}
model InventoryItem {
id Int @id @default(autoincrement())
productId Int
quantity Decimal @db.Decimal(10, 2)
unit String
brand String?
receiptName String?
location String?
priority Int?
purchaseDate DateTime?
opened Boolean?
shelfNote String?
suitableFor String?
isOnSale Boolean?
priceLevel Int?
bestBeforeDate DateTime?
proteinType String?
isLeftover Boolean?
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
consumptions InventoryConsumption[]
@@index([productId])
}
model InventoryConsumption {
id Int @id @default(autoincrement())
inventoryItem InventoryItem @relation(fields: [inventoryItemId], references: [id])
inventoryItemId Int
amountUsed Decimal @db.Decimal(10, 2)
comment String?
createdAt DateTime @default(now())
}
model Recipe {
id Int @id @default(autoincrement())
name String
description String? @db.Text
instructions String? @db.Text
imageUrl String?
servings Int?
isPublic Boolean @default(false)
ownerId Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
owner User? @relation("RecipeOwner", fields: [ownerId], references: [id], onDelete: SetNull)
ingredients RecipeIngredient[]
mealPlanEntries MealPlanEntry[]
shares RecipeShare[]
}
model RecipeShare {
recipeId Int
userId Int
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([recipeId, userId])
@@index([userId])
}
model RecipeIngredient {
id Int @id @default(autoincrement())
recipe Recipe @relation(fields: [recipeId], references: [id])
recipeId Int
product Product @relation(fields: [productId], references: [id])
productId Int
quantity Decimal @db.Decimal(10, 2)
unit String
note String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model PantryItem {
id Int @id @default(autoincrement())
productId Int @unique
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ReceiptAlias {
id Int @id @default(autoincrement())
receiptName String @unique // normaliserat kvittonamn (lowercase, trim)
productId Int
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
}
model MealPlanEntry {
id Int @id @default(autoincrement())
date DateTime @db.Date
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
recipeId Int
servings Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([date])
@@index([date])
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
products ProductTag[]
}
model ProductTag {
productId Int
tagId Int
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
@@id([productId, tagId])
@@index([tagId])
}
model Nutrition {
id Int @id @default(autoincrement())
productId Int @unique
calories Float?
protein Float?
fat Float?
carbohydrates Float?
salt Float?
sugar Float?
fiber Float?
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
}