feat: Wabenhain Honig-Shop Anwendung
Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei: Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich (Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung, PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma- Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "OrderStatus" AS ENUM ('NEU', 'BEZAHLT', 'IN_VORBEREITUNG', 'VERSANDBEREIT', 'VERSENDET', 'ABHOLBEREIT', 'ABGEHOLT', 'STORNIERT');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "FulfillmentMethod" AS ENUM ('VERSAND', 'ABHOLUNG');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PaymentStatus" AS ENUM ('PENDING', 'SUCCEEDED', 'FAILED', 'REFUNDED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "BusinessPackage" AS ENUM ('KLASSIK', 'GESCHENK', 'INDIVIDUELL');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "InquiryStatus" AS ENUM ('NEU', 'IN_BEARBEITUNG', 'ABGESCHLOSSEN');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "customers" (
|
||||
"id" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"passwordHash" TEXT NOT NULL,
|
||||
"firstName" TEXT NOT NULL,
|
||||
"lastName" TEXT NOT NULL,
|
||||
"phone" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "customers_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "addresses" (
|
||||
"id" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"label" TEXT NOT NULL DEFAULT 'Zuhause',
|
||||
"firstName" TEXT NOT NULL,
|
||||
"lastName" TEXT NOT NULL,
|
||||
"street" TEXT NOT NULL,
|
||||
"zip" TEXT NOT NULL,
|
||||
"city" TEXT NOT NULL,
|
||||
"country" TEXT NOT NULL DEFAULT 'DE',
|
||||
"isDefault" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "addresses_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "harvests" (
|
||||
"id" TEXT NOT NULL,
|
||||
"year" INTEGER NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"harvestDate" TIMESTAMP(3) NOT NULL,
|
||||
"location" TEXT NOT NULL DEFAULT 'Altenmuenster',
|
||||
"description" TEXT NOT NULL,
|
||||
"images" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "harvests_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "batches" (
|
||||
"id" TEXT NOT NULL,
|
||||
"code" TEXT NOT NULL,
|
||||
"harvestId" TEXT NOT NULL,
|
||||
"fillDate" TIMESTAMP(3) NOT NULL,
|
||||
"bestBeforeDate" TIMESTAMP(3) NOT NULL,
|
||||
"glassCount" INTEGER NOT NULL,
|
||||
"remainingGlasses" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "batches_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "products" (
|
||||
"id" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"harvestId" TEXT NOT NULL,
|
||||
"batchId" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"tasteTags" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
"intensityMild" INTEGER NOT NULL DEFAULT 3,
|
||||
"intensityFloral" INTEGER NOT NULL DEFAULT 3,
|
||||
"intensityKraeftig" INTEGER NOT NULL DEFAULT 3,
|
||||
"consistency" TEXT NOT NULL DEFAULT 'feincremig',
|
||||
"weightGrams" INTEGER NOT NULL,
|
||||
"priceCents" INTEGER NOT NULL,
|
||||
"pricePerKgCents" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'EUR',
|
||||
"images" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "products_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "inventory" (
|
||||
"id" TEXT NOT NULL,
|
||||
"productId" TEXT NOT NULL,
|
||||
"quantity" INTEGER NOT NULL DEFAULT 0,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "inventory_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "orders" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderNumber" TEXT NOT NULL,
|
||||
"customerId" TEXT,
|
||||
"status" "OrderStatus" NOT NULL DEFAULT 'NEU',
|
||||
"fulfillmentMethod" "FulfillmentMethod" NOT NULL DEFAULT 'VERSAND',
|
||||
"email" TEXT NOT NULL,
|
||||
"firstName" TEXT NOT NULL,
|
||||
"lastName" TEXT NOT NULL,
|
||||
"phone" TEXT,
|
||||
"street" TEXT NOT NULL,
|
||||
"zip" TEXT NOT NULL,
|
||||
"city" TEXT NOT NULL,
|
||||
"country" TEXT NOT NULL DEFAULT 'DE',
|
||||
"subtotalCents" INTEGER NOT NULL,
|
||||
"shippingCents" INTEGER NOT NULL DEFAULT 0,
|
||||
"totalCents" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'EUR',
|
||||
"stripeCheckoutSessionId" TEXT,
|
||||
"notes" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "orders_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "order_items" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderId" TEXT NOT NULL,
|
||||
"productId" TEXT NOT NULL,
|
||||
"batchId" TEXT NOT NULL,
|
||||
"productName" TEXT NOT NULL,
|
||||
"unitPriceCents" INTEGER NOT NULL,
|
||||
"quantity" INTEGER NOT NULL,
|
||||
"weightGrams" INTEGER NOT NULL,
|
||||
"totalCents" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "order_items_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "payments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderId" TEXT NOT NULL,
|
||||
"provider" TEXT NOT NULL DEFAULT 'stripe',
|
||||
"stripePaymentIntentId" TEXT,
|
||||
"status" "PaymentStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"amountCents" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'EUR',
|
||||
"paidAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "payments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "shipments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderId" TEXT NOT NULL,
|
||||
"carrier" TEXT,
|
||||
"trackingNumber" TEXT,
|
||||
"shippedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "shipments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "pickups" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderId" TEXT NOT NULL,
|
||||
"location" TEXT NOT NULL DEFAULT 'Altenmuenster',
|
||||
"readyAt" TIMESTAMP(3),
|
||||
"pickedUpAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "pickups_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "invoices" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderId" TEXT NOT NULL,
|
||||
"invoiceNumber" TEXT NOT NULL,
|
||||
"issuedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"totalCents" INTEGER NOT NULL,
|
||||
"pdfUrl" TEXT,
|
||||
|
||||
CONSTRAINT "invoices_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "newsletter_subscribers" (
|
||||
"id" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"customerId" TEXT,
|
||||
"confirmed" BOOLEAN NOT NULL DEFAULT false,
|
||||
"subscribedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"unsubscribedAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "newsletter_subscribers_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "business_inquiries" (
|
||||
"id" TEXT NOT NULL,
|
||||
"companyName" TEXT NOT NULL,
|
||||
"contactPerson" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"phone" TEXT,
|
||||
"desiredQuantity" INTEGER NOT NULL,
|
||||
"desiredDeliveryDate" TIMESTAMP(3),
|
||||
"package" "BusinessPackage" NOT NULL DEFAULT 'KLASSIK',
|
||||
"message" TEXT,
|
||||
"status" "InquiryStatus" NOT NULL DEFAULT 'NEU',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "business_inquiries_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "customers_email_key" ON "customers"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "harvests_slug_key" ON "harvests"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "harvests_year_type_key" ON "harvests"("year", "type");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "batches_code_key" ON "batches"("code");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "products_slug_key" ON "products"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "inventory_productId_key" ON "inventory"("productId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "orders_orderNumber_key" ON "orders"("orderNumber");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "payments_orderId_key" ON "payments"("orderId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "shipments_orderId_key" ON "shipments"("orderId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "pickups_orderId_key" ON "pickups"("orderId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "invoices_orderId_key" ON "invoices"("orderId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "invoices_invoiceNumber_key" ON "invoices"("invoiceNumber");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "newsletter_subscribers_email_key" ON "newsletter_subscribers"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "newsletter_subscribers_customerId_key" ON "newsletter_subscribers"("customerId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "addresses" ADD CONSTRAINT "addresses_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "batches" ADD CONSTRAINT "batches_harvestId_fkey" FOREIGN KEY ("harvestId") REFERENCES "harvests"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "products" ADD CONSTRAINT "products_harvestId_fkey" FOREIGN KEY ("harvestId") REFERENCES "harvests"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "products" ADD CONSTRAINT "products_batchId_fkey" FOREIGN KEY ("batchId") REFERENCES "batches"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "inventory" ADD CONSTRAINT "inventory_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "orders" ADD CONSTRAINT "orders_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "order_items" ADD CONSTRAINT "order_items_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "orders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "order_items" ADD CONSTRAINT "order_items_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "order_items" ADD CONSTRAINT "order_items_batchId_fkey" FOREIGN KEY ("batchId") REFERENCES "batches"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "payments" ADD CONSTRAINT "payments_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "orders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "shipments" ADD CONSTRAINT "shipments_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "orders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "pickups" ADD CONSTRAINT "pickups_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "orders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "invoices" ADD CONSTRAINT "invoices_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "orders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "newsletter_subscribers" ADD CONSTRAINT "newsletter_subscribers_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,10 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProductCategory" AS ENUM ('HONIG', 'KERZEN', 'PROPOLIS');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "order_items" ALTER COLUMN "batchId" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "products" ADD COLUMN "category" "ProductCategory" NOT NULL DEFAULT 'HONIG',
|
||||
ALTER COLUMN "harvestId" DROP NOT NULL,
|
||||
ALTER COLUMN "batchId" DROP NOT NULL;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CustomerRole" AS ENUM ('KUNDE', 'ADMIN');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "customers" ADD COLUMN "role" "CustomerRole" NOT NULL DEFAULT 'KUNDE';
|
||||
@@ -0,0 +1,24 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "newsletter_subscribers" ADD COLUMN "confirmationToken" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "password_reset_tokens" (
|
||||
"id" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"tokenHash" TEXT NOT NULL,
|
||||
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||
"usedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "password_reset_tokens_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "password_reset_tokens_tokenHash_key" ON "password_reset_tokens"("tokenHash");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "newsletter_subscribers_confirmationToken_key" ON "newsletter_subscribers"("confirmationToken");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "customers" ADD COLUMN "failedLoginAttempts" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN "lockedUntil" TIMESTAMP(3),
|
||||
ADD COLUMN "sessionVersion" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN "twoFactorEnabled" BOOLEAN NOT NULL DEFAULT false,
|
||||
ADD COLUMN "twoFactorSecret" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "two_factor_backup_codes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"codeHash" TEXT NOT NULL,
|
||||
"usedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "two_factor_backup_codes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "two_factor_backup_codes_codeHash_key" ON "two_factor_backup_codes"("codeHash");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "two_factor_backup_codes" ADD CONSTRAINT "two_factor_backup_codes_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "customers" ADD COLUMN "blockedAt" TIMESTAMP(3);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "shipping_tiers" (
|
||||
"id" TEXT NOT NULL,
|
||||
"minQuantity" INTEGER NOT NULL,
|
||||
"maxQuantity" INTEGER,
|
||||
"priceCents" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "shipping_tiers_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "DiscountType" AS ENUM ('PERCENT', 'FIXED');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "orders" ADD COLUMN "discountCents" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN "discountCodeId" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "reviews" (
|
||||
"id" TEXT NOT NULL,
|
||||
"productId" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"rating" INTEGER NOT NULL,
|
||||
"comment" TEXT,
|
||||
"isApproved" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "reviews_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "discount_codes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"code" TEXT NOT NULL,
|
||||
"type" "DiscountType" NOT NULL,
|
||||
"value" INTEGER NOT NULL,
|
||||
"minOrderCents" INTEGER NOT NULL DEFAULT 0,
|
||||
"maxUses" INTEGER,
|
||||
"usedCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"validFrom" TIMESTAMP(3),
|
||||
"validUntil" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "discount_codes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "reviews_productId_customerId_key" ON "reviews"("productId", "customerId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "discount_codes_code_key" ON "discount_codes"("code");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "reviews" ADD CONSTRAINT "reviews_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "reviews" ADD CONSTRAINT "reviews_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "orders" ADD CONSTRAINT "orders_discountCodeId_fkey" FOREIGN KEY ("discountCodeId") REFERENCES "discount_codes"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "customers" ADD COLUMN "emailVerifiedAt" TIMESTAMP(3);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "email_verification_tokens" (
|
||||
"id" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"tokenHash" TEXT NOT NULL,
|
||||
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||
"usedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "email_verification_tokens_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "wishlist_items" (
|
||||
"id" TEXT NOT NULL,
|
||||
"customerId" TEXT NOT NULL,
|
||||
"productId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "wishlist_items_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "audit_logs" (
|
||||
"id" TEXT NOT NULL,
|
||||
"adminId" TEXT,
|
||||
"adminEmail" TEXT NOT NULL,
|
||||
"action" TEXT NOT NULL,
|
||||
"entityType" TEXT NOT NULL,
|
||||
"entityId" TEXT,
|
||||
"detail" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "audit_logs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "email_verification_tokens_tokenHash_key" ON "email_verification_tokens"("tokenHash");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "wishlist_items_customerId_productId_key" ON "wishlist_items"("customerId", "productId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "email_verification_tokens" ADD CONSTRAINT "email_verification_tokens_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "wishlist_items" ADD CONSTRAINT "wishlist_items_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "wishlist_items" ADD CONSTRAINT "wishlist_items_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "audit_logs" ADD CONSTRAINT "audit_logs_adminId_fkey" FOREIGN KEY ("adminId") REFERENCES "customers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Bestandskonten, die vor Einfuehrung der E-Mail-Verifizierung registriert
|
||||
-- wurden, gelten rueckwirkend als bestaetigt (createdAt als Zeitstempel) --
|
||||
-- sonst waeren sie ploetzlich vom Checkout ausgesperrt, obwohl sie sich nie
|
||||
-- verifizieren mussten.
|
||||
UPDATE "customers" SET "emailVerifiedAt" = "createdAt" WHERE "emailVerifiedAt" IS NULL;
|
||||
@@ -0,0 +1,17 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "stock_notifications" (
|
||||
"id" TEXT NOT NULL,
|
||||
"productId" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"notifiedAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "stock_notifications_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "stock_notifications_productId_email_key" ON "stock_notifications"("productId", "email");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "stock_notifications" ADD CONSTRAINT "stock_notifications_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "InquiryStatus" ADD VALUE 'ABGELEHNT';
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ReturnStatus" AS ENUM ('ANGEFRAGT', 'ANGENOMMEN', 'ABGELEHNT', 'ERSTATTET');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "return_requests" (
|
||||
"id" TEXT NOT NULL,
|
||||
"orderId" TEXT NOT NULL,
|
||||
"reason" TEXT NOT NULL,
|
||||
"status" "ReturnStatus" NOT NULL DEFAULT 'ANGEFRAGT',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "return_requests_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "return_requests_orderId_key" ON "return_requests"("orderId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "return_requests" ADD CONSTRAINT "return_requests_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "orders"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
Reference in New Issue
Block a user