Auf ausdrücklichen Wunsch, mit Fokus auf rechtliche Absicherung: - Klarna komplett entfernt (hätte eigene Händlerprüfung + Bonitätsprüfungs- Pflichten nach der neuen EU-Verbraucherkreditrichtlinie vorausgesetzt). - Eigene Kreditkarten-Eingabemaske komplett entfernt (wäre PCI-DSS-pflichtig gewesen — für einen kleinen Shop praktisch nicht stemmbar). Kartenzahlung bleibt möglich: PayPals eigener, PCI-zertifizierter Gast-Checkout bietet Kredit-/Debitkarte an, ohne dass Kartendaten je unsere Seite berühren. - PayPal ist jetzt ECHT server-seitig verifiziert statt dem Browser blind zu vertrauen: eigener Cloudflare-Function-Flow (functions/_shared/paypal.js + functions/api/paypal/) legt die PayPal-Bestellung server-seitig an, zieht die Zahlung nach Bestätigung server-seitig ein und prüft den eingezogenen Betrag gegen die Bestellsumme — die Bestellung wird ausschließlich bei bestätigter, betragsgleicher Zahlung angelegt. /api/orders lehnt direkte PayPal-Bestellungen jetzt ausdrücklich ab (verhindert vorgetäuschte "bezahlte" Bestellungen ohne echte Zahlung). - Neuer, ehrlicherer Bestellstatus "zahlungOffen": Überweisungs-Bestellungen starten jetzt so (Geld noch nicht da) statt fälschlich sofort "bezahlt" zu heißen — Schutz vor Warenversand, bevor das Geld wirklich angekommen ist. Eigene Kachel/Filter/Badge-Farbe in der Verwaltung, Umsatz-/Auswertungs- Zahlen zählen "zahlungOffen" bewusst nicht mit. - Rechtstexte (AGB, Datenschutzerklärung, FAQ, Versand & Zahlung) auf allen 4 Sprachen aktualisiert: nur noch PayPal + Überweisung erwähnt, inkl. DSGVO- Hinweis zur internationalen Datenübertragung an PayPal (Data Privacy Framework-Zertifizierung). - D1-Migration 0003: neue Spalte paypal_order_id (Zahlungsbeleg) + erweiterter Status-Wertebereich, auf Live-Datenbank angewendet, bestehende Daten intakt. Mit echten Testbestellungen lokal verifiziert: Überweisung legt korrekt "zahlungOffen" an, direkter PayPal-Bypass-Versuch an /api/orders wird abgelehnt, PayPal-Route meldet sauber "noch nicht eingerichtet" ohne Zugangsdaten. Checkout-UI zeigt nur noch 2 Zahlungsarten, Bestellknopf ist bei PayPal ausgeblendet (Zahlung läuft exklusiv über den echten PayPal-Button). Für den echten Zahlungseingang fehlt noch VanVans eigenes PayPal-Business- Konto (Client-ID + Secret) — Details in der Vault-Dokumentation. Co-Authored-By: Claude Sonnet 5 <[email protected]>
67 lines
3.5 KiB
SQL
67 lines
3.5 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,
|
|
-- zahlungOffen: Bestellung eingegangen, Zahlung (Überweisung/Vorkasse) steht noch aus — Ware
|
|
-- darf NICHT verschickt werden, bis qciga/VanVan den Geldeingang sieht und manuell auf
|
|
-- "bezahlt" stellt (Schutz vor Warenverlust bei nie eingegangener Zahlung) · bezahlt: Zahlung
|
|
-- bestätigt — bei PayPal ausschließlich, nachdem functions/api/paypal/capture-order.js die
|
|
-- Zahlung server-seitig bei PayPal verifiziert hat (nie durch bloßes Absenden des Formulars) ·
|
|
-- bearbeitung/versandVorbereitet/versendet/abgeschlossen: manuelle Pflege durch qciga/VanVan in
|
|
-- /verwaltung/ · storniert: für echte Rückabwicklungen/Fehlbestellungen.
|
|
status TEXT NOT NULL DEFAULT 'zahlungOffen'
|
|
CHECK (status IN ('zahlungOffen', '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,
|
|
-- Echte PayPal-Bestell-ID (aus der server-seitig verifizierten Zahlung, siehe
|
|
-- functions/api/paypal/capture-order.js) — NULL bei allen anderen Zahlungsarten. Dient als
|
|
-- Nachweis/Beleg, falls es je Rückfragen zu einer bestimmten PayPal-Zahlung gibt.
|
|
paypal_order_id 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);
|