Files
vans-diy-bastelbedarf/d1/schema.sql
T
qciganoandClaude Sonnet 5 af729ba571 Gutscheine "nur einmal pro Person" + Bestell-E-Mail-Benachrichtigung
1) Gutscheincodes können jetzt im Adminbereich auf "nur einmal pro Person einlösbar"
   gestellt werden. Wird serverseitig durchgesetzt (neue Spalte orders.gutschein_code +
   Prüfung in functions/api/orders.js gegen die echte Bestelldatenbank, case-insensitiv
   nach E-Mail-Adresse) — kann also NICHT durch Löschen von localStorage/einen anderen
   Browser umgangen werden, anders als die bisherige rein clientseitige Rabattlogik.
   Stornierte Bestellungen zählen nicht als "schon benutzt". Ausführlich getestet: echter
   Browser-Checkout mit Einmal-Code funktioniert beim ersten Versuch, wird beim zweiten
   Versuch (gleiche E-Mail) korrekt mit klarer Fehlermeldung abgelehnt, mit anderer E-Mail
   weiterhin nutzbar.

2) Bestell-E-Mail-Benachrichtigung an [email protected]: recherchiert und
   vorbereitet (existierte vorher nirgends im Code). Läuft über Resend (kostenlos bis
   3.000 E-Mails/Monat), im Hintergrund per context.waitUntil() nach jeder neuen
   Bestellung — verzögert nie die Antwort an die Kundschaft und kann eine Bestellung
   niemals zum Scheitern bringen, selbst wenn der Versand fehlschlägt (mit ungültigem
   Testschlüssel verifiziert: Bestellung bleibt trotzdem erfolgreich gespeichert). Wird
   automatisch aktiv, sobald ein RESEND_API_KEY als Secret hinterlegt wird.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-03 22:16:38 +02:00

59 lines
2.9 KiB
SQL

-- Van's DIY & Bastelbedarf — echtes Bestellsystem (Phase 2).
--
-- Ersetzt die Beispieldaten in /verwaltung/. Zwei Tabellen: eine Kopf-Tabelle pro Bestellung
-- (orders) + eine Zeilen-Tabelle pro bestelltem Artikel (order_items) — bewusst normalisiert
-- statt alles als ein JSON-Blob zu speichern, damit "meistverkaufte Produkte je Kategorie"
-- eine echte, schnelle SQL-Auswertung ist (GROUP BY) statt jedes Mal alle Bestellungen im
-- Code durchzuparsen.
CREATE TABLE IF NOT EXISTS orders (
-- Interne, garantiert eindeutige numerische ID (SQLite AUTOINCREMENT) — die menschenlesbare
-- Bestellnummer (z.B. "VDB-2026-0201") wird direkt nach dem Einfügen aus dieser ID abgeleitet
-- (siehe functions/api/orders.js), dadurch nie eine Race Condition bei paralleler Bestellung.
id INTEGER PRIMARY KEY AUTOINCREMENT,
bestellnummer TEXT UNIQUE,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
-- bezahlt: Phase-1-Zahlung gilt sofort als erfolgreich (siehe scripts/account.ts-Kommentar zum
-- selben Thema) · bearbeitung/versandVorbereitet/versendet/abgeschlossen: manuelle Pflege durch
-- qciga/VanVan in /verwaltung/ · storniert: für echte Rückabwicklungen/Fehlbestellungen.
status TEXT NOT NULL DEFAULT 'bezahlt'
CHECK (status IN ('bezahlt', 'bearbeitung', 'versandVorbereitet', 'versendet', 'abgeschlossen', 'storniert')),
kunde_name TEXT NOT NULL,
kunde_email TEXT NOT NULL,
land TEXT NOT NULL CHECK (land IN ('de', 'at', 'ch', 'lu')),
strasse TEXT,
plz TEXT,
ort TEXT,
zahlungsart TEXT,
tracking TEXT,
-- Eingelöster Gutscheincode (normalisiert, Großbuchstaben) — NULL, wenn keiner verwendet wurde.
-- Wird gebraucht, um "nur einmal pro Person"-Gutscheine serverseitig durchzusetzen (siehe
-- functions/api/orders.js): vor dem Anlegen einer neuen Bestellung wird geprüft, ob dieselbe
-- E-Mail-Adresse denselben Code schon einmal (in einer nicht-stornierten Bestellung) benutzt hat.
gutschein_code TEXT,
zwischensumme REAL NOT NULL DEFAULT 0,
versandkosten REAL NOT NULL DEFAULT 0,
rabatt_gesamt REAL NOT NULL DEFAULT 0,
summe REAL NOT NULL DEFAULT 0,
treuebonus_verwendet INTEGER NOT NULL DEFAULT 0,
abo_rabatt_verwendet INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS order_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
produkt_slug TEXT NOT NULL,
name TEXT NOT NULL,
kategorie_slug TEXT,
menge INTEGER NOT NULL,
preis REAL NOT NULL,
gratis INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_order_items_order_id ON order_items(order_id);
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
CREATE INDEX IF NOT EXISTS idx_orders_land ON orders(land);
CREATE INDEX IF NOT EXISTS idx_orders_created_at ON orders(created_at);
CREATE INDEX IF NOT EXISTS idx_orders_gutschein_email ON orders(gutschein_code, kunde_email);