/* ===================================================================== GET /api/bestseller — liefert die Slugs der 6 echten meistverkauften Produkte, automatisch aus den echten Bestelldaten berechnet (04.08.2026, auf ausdrücklichen Wunsch: "die Seite soll von alleine wissen, welche Sachen am meisten verkauft werden"). BEWUSST öffentlich (kein Zugangscode-Sonderfall in functions/_middleware.js nötig): Diese Route verhält sich genau wie /api/orders (Bestellung anlegen) — während der Vorschau-Phase greift die normale Zugangsschranke wie bei jeder anderen /api/*-Route auch (nur qciga/VanVan kommen ran), sobald der Shop später per SITE_PUBLIC=true live geht, wird sie automatisch mit-öffentlich, ohne dass hier etwas geändert werden muss. Liefert NUR eine Liste von Produkt-Slugs zurück — keinerlei Bestell-/Kundendaten (Namen, E-Mails, Adressen, Beträge), die bleiben ausschließlich in /api/verwaltung/* (fest hinter der doppelten Schranke). Zählweise (bewusst dieselbe Grundlage wie die "Bestseller je Kategorie"-Auswertung in /verwaltung/, siehe src/pages/verwaltung/index.astro): - Storniert und noch nicht bezahlte (zahlungOffen) Bestellungen zählen NICHT mit — sonst würden Fehlbestellungen/nie bezahlte Überweisungen die Rangliste verfälschen. - Kostenlose Positionen (gratis=1, z.B. der Teddy aus dem Abo) zählen NICHT mit — das war kein echtes Kaufinteresse, sondern eine Prämie, würde sonst die Rangliste verzerren. - Bei Gleichstand entscheidet der Produkt-Slug alphabetisch (rein für ein stabiles, immer gleiches Ergebnis bei jedem Aufruf, keine fachliche Bedeutung). */ import { json } from "../_shared/http.js"; export async function onRequestGet(context) { const { env } = context; // Kein DB-Binding (z.B. sehr früher lokaler Dev-Stand ohne D1) oder noch gar keine Bestellungen // -> einfach eine leere Liste, kein Fehler. Das Bestseller-Kästchen im Shop-Filter zeigt dann // schlicht "keine Produkte gefunden", genau wie bei jeder anderen Filterkombination ohne Treffer. if (!env.DB) { return json(200, { ok: true, slugs: [] }); } try { const { results } = await env.DB.prepare( `SELECT oi.produkt_slug AS slug, SUM(oi.menge) AS verkauft FROM order_items oi JOIN orders o ON o.id = oi.order_id WHERE o.status NOT IN ('storniert', 'zahlungOffen') AND oi.gratis = 0 GROUP BY oi.produkt_slug ORDER BY verkauft DESC, slug ASC LIMIT 6` ).all(); return json(200, { ok: true, slugs: results.map((r) => r.slug) }); } catch { // Lieber still eine leere Liste als einen Fehler an den Shop-Filter durchreichen — eine // kaputte Bestseller-Berechnung soll nie den ganzen Filterbereich lahmlegen. return json(200, { ok: true, slugs: [] }); } }