From 68781589d8be8c404f055dc71704f0a1c92d70b2 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Wed, 19 Aug 2026 07:27:27 +0200 Subject: [PATCH] SQL and Seed into App --- .../migration.sql | 22 ++ prisma/seed-demo.ts | 212 ++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 prisma/migrations/20260819040000_fix_images_tastetags_json_type/migration.sql create mode 100644 prisma/seed-demo.ts diff --git a/prisma/migrations/20260819040000_fix_images_tastetags_json_type/migration.sql b/prisma/migrations/20260819040000_fix_images_tastetags_json_type/migration.sql new file mode 100644 index 0000000..c6e2da7 --- /dev/null +++ b/prisma/migrations/20260819040000_fix_images_tastetags_json_type/migration.sql @@ -0,0 +1,22 @@ +-- Schema/Migrations-Drift beheben: "images"/"tasteTags" wurden in +-- schema.prisma von String[] auf Json umgestellt (MySQL kennt keine nativen +-- Skalar-Arrays), die urspruengliche Init-Migration hat die Spalten aber nie +-- entsprechend geaendert — sie blieben TEXT[]. "prisma migrate deploy" +-- validiert nicht gegen das Schema, daher blieb das unbemerkt bis zum ersten +-- echten Seed-Lauf ("malformed array literal" beim Insert eines JSON-Werts +-- in eine TEXT[]-Spalte). to_jsonb() wandelt bestehende TEXT[]-Werte 1:1 in +-- ein JSON-Array um. +ALTER TABLE "harvests" + ALTER COLUMN "images" DROP DEFAULT, + ALTER COLUMN "images" TYPE JSONB USING to_jsonb("images"), + ALTER COLUMN "images" SET DEFAULT '[]'::jsonb; + +ALTER TABLE "products" + ALTER COLUMN "tasteTags" DROP DEFAULT, + ALTER COLUMN "tasteTags" TYPE JSONB USING to_jsonb("tasteTags"), + ALTER COLUMN "tasteTags" SET DEFAULT '[]'::jsonb; + +ALTER TABLE "products" + ALTER COLUMN "images" DROP DEFAULT, + ALTER COLUMN "images" TYPE JSONB USING to_jsonb("images"), + ALTER COLUMN "images" SET DEFAULT '[]'::jsonb; diff --git a/prisma/seed-demo.ts b/prisma/seed-demo.ts new file mode 100644 index 0000000..9478743 --- /dev/null +++ b/prisma/seed-demo.ts @@ -0,0 +1,212 @@ +// Wird direkt per "tsx" aufgerufen (nicht ueber "prisma db seed"), daher +// laedt hier — anders als bei prisma.config.ts/seed.ts — niemand sonst die +// .env-Datei fuer die lokale Entwicklung. +import "dotenv/config"; +import { PrismaClient } from "../src/generated/prisma/client"; +import { PrismaClient as MySqlPrismaClient } from "../src/generated/prisma-mysql/client"; +import { createDbAdapter } from "../src/lib/db-adapter"; + +// Beispieldaten (Ernten, Chargen, Produkte, Lagerbestand, Versandstaffeln) +// fuer lokales Testen/Screenshots. BEWUSST GETRENNT von prisma/seed.ts (das +// automatisch bei jedem Container-Start laeuft, siehe Dockerfile-CMD in der +// runner-Stage) — ein produktiv gebautes Image soll nie automatisch +// Fake-Produkte in einer echten Datenbank anlegen. Manuell ausfuehren: +// "pnpm db:seed:demo". + +const adapter = createDbAdapter(); +const prisma: PrismaClient = + (process.env.DATABASE_PROVIDER ?? "postgresql").trim() === "mysql" + ? (new MySqlPrismaClient({ adapter }) as unknown as PrismaClient) + : new PrismaClient({ adapter }); + +async function main() { + // Ueberspringt alles, sobald bereits Produkte existieren — legt echte, + // im Adminbereich spaeter geaenderte/geloeschte Produkte nie erneut an. + const productCount = await prisma.product.count(); + if (productCount > 0) { + console.log("Produkte bereits vorhanden, ueberspringe Demo-Daten-Seed."); + return; + } + + const fruehtracht = await prisma.harvest.upsert({ + where: { slug: "fruehtracht-2026" }, + update: {}, + create: { + year: 2026, + type: "Frühtracht", + slug: "fruehtracht-2026", + harvestDate: new Date("2026-05-10"), + location: "Altenmünster", + description: + "Die erste Ernte des Jahres entsteht aus dem Nektar von Obstblüte, Raps und Löwenzahn rund um Altenmünster. Mild, floral und feincremig — der Auftakt jeder Wabenhain-Saison.", + images: [], + }, + }); + + const sommertracht = await prisma.harvest.upsert({ + where: { slug: "sommertracht-2026" }, + update: {}, + create: { + year: 2026, + type: "Sommertracht", + slug: "sommertracht-2026", + harvestDate: new Date("2026-07-18"), + location: "Altenmünster", + description: + "Im Hochsommer sammeln unsere Völker Nektar von Linde, Wiesenblumen und Wald. Das Ergebnis ist kräftiger, aromatischer und charaktervoller als die Frühtracht.", + images: [], + }, + }); + + const fhBatch = await prisma.batch.upsert({ + where: { code: "FH-26-01" }, + update: {}, + create: { + code: "FH-26-01", + harvestId: fruehtracht.id, + fillDate: new Date("2026-06-02"), + bestBeforeDate: new Date("2028-06-02"), + glassCount: 200, + remainingGlasses: 167, + }, + }); + + const stBatch = await prisma.batch.upsert({ + where: { code: "ST-26-01" }, + update: {}, + create: { + code: "ST-26-01", + harvestId: sommertracht.id, + fillDate: new Date("2026-08-05"), + bestBeforeDate: new Date("2028-08-05"), + glassCount: 150, + remainingGlasses: 150, + }, + }); + + const fhProduct = await prisma.product.upsert({ + where: { slug: "fruehtracht-2026" }, + update: { tasteTags: ["mild", "floral", "feincremig"] }, + create: { + slug: "fruehtracht-2026", + name: "Frühtracht 2026", + harvestId: fruehtracht.id, + batchId: fhBatch.id, + description: + "Mild, floral und feincremig. Unsere erste Ernte des Jahres aus dem Raum Altenmünster.", + tasteTags: ["mild", "floral", "feincremig"], + intensityMild: 4, + intensityFloral: 4, + intensityKraeftig: 2, + consistency: "feincremig", + weightGrams: 500, + priceCents: 990, + pricePerKgCents: 1980, + images: [], + isActive: true, + }, + }); + + const stProduct = await prisma.product.upsert({ + where: { slug: "sommertracht-2026" }, + update: { tasteTags: ["kräftig", "aromatisch", "charaktervoll"] }, + create: { + slug: "sommertracht-2026", + name: "Sommertracht 2026", + harvestId: sommertracht.id, + batchId: stBatch.id, + description: "Kräftiger, aromatischer und charaktervoller Sommerhonig aus Altenmünster.", + tasteTags: ["kräftig", "aromatisch", "charaktervoll"], + intensityMild: 2, + intensityFloral: 2, + intensityKraeftig: 5, + consistency: "cremig", + weightGrams: 500, + priceCents: 1090, + pricePerKgCents: 2180, + images: [], + isActive: true, + }, + }); + + const candleProduct = await prisma.product.upsert({ + where: { slug: "bienenwachskerze-rund" }, + update: { tasteTags: ["handgegossen", "reines Bienenwachs", "rußarm"] }, + create: { + slug: "bienenwachskerze-rund", + name: "Bienenwachskerze, rund", + category: "KERZEN", + description: + "Handgegossen aus reinem Bienenwachs unserer eigenen Völker. Brennt gleichmäßig, rußarm und verströmt einen dezenten Honigduft.", + tasteTags: ["handgegossen", "reines Bienenwachs", "rußarm"], + consistency: "fest", + weightGrams: 150, + priceCents: 1290, + pricePerKgCents: 8600, + images: [], + isActive: true, + }, + }); + + const propolisProduct = await prisma.product.upsert({ + where: { slug: "propolis-tinktur" }, + update: { tasteTags: ["schonend verarbeitet", "ohne Zusätze"] }, + create: { + slug: "propolis-tinktur", + name: "Propolis-Tinktur", + category: "PROPOLIS", + description: + "Schonend angesetzte Propolis-Tinktur aus dem Harz unserer Bienenstöcke rund um Altenmünster. Ohne synthetische Zusätze.", + tasteTags: ["schonend verarbeitet", "ohne Zusätze"], + consistency: "flüssig", + weightGrams: 30, + priceCents: 1490, + pricePerKgCents: 49666, + images: [], + isActive: true, + }, + }); + + await prisma.inventory.upsert({ + where: { productId: fhProduct.id }, + update: { quantity: 167 }, + create: { productId: fhProduct.id, quantity: 167 }, + }); + + await prisma.inventory.upsert({ + where: { productId: stProduct.id }, + update: { quantity: 150 }, + create: { productId: stProduct.id, quantity: 150 }, + }); + + await prisma.inventory.upsert({ + where: { productId: candleProduct.id }, + update: { quantity: 60 }, + create: { productId: candleProduct.id, quantity: 60 }, + }); + + await prisma.inventory.upsert({ + where: { productId: propolisProduct.id }, + update: { quantity: 40 }, + create: { productId: propolisProduct.id, quantity: 40 }, + }); + + await prisma.shippingTier.createMany({ + data: [ + { minQuantity: 0, maxQuantity: 3, priceCents: 700 }, + { minQuantity: 4, maxQuantity: 9, priceCents: 850 }, + { minQuantity: 10, maxQuantity: 19, priceCents: 1100 }, + ], + }); + console.log("Versandstaffeln angelegt: 0-3=7,00€, 4-9=8,50€, 10-19=11,00€."); + console.log("Demo-Seed abgeschlossen: 2 Ernten, 2 Chargen, 4 Produkte (Honig, Kerzen, Propolis)."); +} + +main() + .catch((error: unknown) => { + console.error(error); + process.exitCode = 1; + }) + .finally(async () => { + await prisma.$disconnect(); + });