Neu: Partner-/Influencer-Rabattcodes (Warenkorb, Checkout, Admin)
Neben dem allgemeinen Gutscheincode gibt es jetzt einen zweiten, unabhängigen "Partner-Rabattcode"-Slot — für Codes, die VanVan gezielt mit einzelnen Streamer:innen/Content-Creator:innen aushandelt. Kund:innen lösen ihn genauso ein wie einen Gutschein (eigene, optisch identische Box direkt unter dem Gutschein im Warenkorb bzw. im Checkout), beide Codes können unabhängig voneinander gleichzeitig aktiv sein und ihre Rabatte werden addiert (auf die Zwischensumme gedeckelt, damit der Preis nie unter 0 € fällt). Admin (Sveltia CMS): neuer Bereich "🤝 Partner-Rabattcodes", getrennt von den allgemeinen Gutscheinen geführt. Pro Code lässt sich hinterlegen, zu welcher Partnerin/welchem Partner er gehört (nur für VanVans eigene Übersicht, wird Kund:innen nirgends gezeigt), Prozent- ODER Betrags- Rabatt, optionales Ablaufdatum, ein "Aktiv"-Schalter zum Pausieren ohne Löschen, sowie ein freies Notizfeld für die vereinbarten Konditionen (z.B. Provision) — echtes automatisches Auswerten, wer wie oft welchen Code einlöst, bräuchte ein eigenes Backend (Phase 2) und ist bewusst nicht Teil dieser rein statischen Umsetzung. Nebenbei einen bestehenden Bug behoben: die define:vars-Variablenliste im Checkout-Skript war bei EN/CH/FR unvollständig (discountLabel, couponInvalid, Klarna-/Bank-Texte fehlten) — dadurch wären dort Teile der Checkout-Seitenleiste als "undefined" gerendert worden. Jetzt an die vollständige Liste der DE-Version angeglichen. Neu erstellte Dateien lokal mit Test-Codes durchgespielt (Gutschein + Partnercode gleichzeitig eingelöst, Rabatte korrekt addiert, Admin- Formular mit allen Feldern geprüft) und wieder auf leere Listen zurückgesetzt vor dem Commit. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
45f64b95ee
commit
6fc64e0972
@@ -0,0 +1,56 @@
|
||||
// Partner-/Influencer-Rabattcodes — eigene Codes, die VanVan z.B. mit Streamer:innen oder
|
||||
// Content-Creator:innen aushandelt: Kund:innen bekommen damit Rabatt beim Einkauf, während VanVan
|
||||
// im Adminbereich für jeden Code hinterlegt, zu welcher Partnerin/welchem Partner er gehört (für
|
||||
// die eigene Übersicht, z.B. welche vereinbarte Provision dahintersteckt).
|
||||
//
|
||||
// Fachlich fast identisch zu einem normalen Gutschein (Rabatt auf den Warenwert), aber bewusst als
|
||||
// eigene, separate Liste geführt — allgemeine Rabattaktionen (Gutscheine) und individuell mit
|
||||
// einzelnen Partner:innen ausgehandelte Codes sollen im Admin nicht durcheinandergeraten.
|
||||
//
|
||||
// WICHTIG (Grenze von Phase 1 — reine statische Seite ohne eigenes Backend): Diese Codes können
|
||||
// einen Rabatt gewähren, aber es gibt (noch) keine automatische Zähl-/Provisions-Auswertung, WER
|
||||
// wie oft welchen Code eingelöst hat — das bräuchte einen echten Server (Phase 2, siehe
|
||||
// Tech-Stack-Entscheidung im Projekt-Vault). Bis dahin: das `notiz`-Feld im Admin dient VanVan als
|
||||
// Gedächtnisstütze für die vereinbarten Konditionen.
|
||||
|
||||
// @ts-ignore -- JSON-Import, zur Build-Zeit von Astro/Vite aufgelöst
|
||||
import partnercodesRaw from "../content/partnercodes.json";
|
||||
|
||||
export interface Partnercode {
|
||||
code: string;
|
||||
/** Name der Partnerin/des Partners (Streamer:in, Creator:in, ...) — nur für VanVans eigene
|
||||
* Übersicht im Admin, wird Kund:innen nirgends angezeigt. */
|
||||
partner: string;
|
||||
prozent?: number;
|
||||
betrag?: number;
|
||||
bis?: string; // ISO-Datum, optional
|
||||
/** Auf false setzen, um einen Code zu pausieren, ohne ihn (und die Partner-Historie) zu löschen. */
|
||||
aktiv?: boolean;
|
||||
}
|
||||
|
||||
const partnercodes = (partnercodesRaw as { codes: Partnercode[] }).codes ?? [];
|
||||
|
||||
function istGueltig(bis?: string): boolean {
|
||||
if (!bis) return true;
|
||||
return new Date() <= new Date(`${bis}T23:59:59`);
|
||||
}
|
||||
|
||||
/** Sucht einen Partnercode anhand des eingegebenen Codes (Groß-/Kleinschreibung egal). Pausierte
|
||||
* (aktiv: false) oder abgelaufene Codes gelten als nicht gefunden. */
|
||||
export function findePartnercode(code: string): Partnercode | undefined {
|
||||
const normalisiert = code.trim().toUpperCase();
|
||||
return partnercodes.find(
|
||||
(c) => c.code.toUpperCase() === normalisiert && c.aktiv !== false && istGueltig(c.bis)
|
||||
);
|
||||
}
|
||||
|
||||
/** Berechnet den Rabatt-Betrag in Euro für einen gegebenen Warenwert. */
|
||||
export function partnercodeRabatt(code: Partnercode, warenwert: number): number {
|
||||
if (typeof code.prozent === "number" && code.prozent > 0) {
|
||||
return Math.min(warenwert, warenwert * (code.prozent / 100));
|
||||
}
|
||||
if (typeof code.betrag === "number" && code.betrag > 0) {
|
||||
return Math.min(warenwert, code.betrag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user