Docker Image bauen und veroeffentlichen / lint (push) Canceled after 0s
Docker Image bauen und veroeffentlichen / typecheck (push) Canceled after 0s
Docker Image bauen und veroeffentlichen / test (push) Canceled after 0s
Docker Image bauen und veroeffentlichen / build-and-push (push) Canceled after 0s
Abo-Stufen 1 bis 24 je bezahltem Monat, danach VIP. SEPA fuer Abos mit Neukunden-Frist, Verzug und Sperre nach Rueckbuchung. Stripe-Einrichtung erst im Testmodus per Skript, Livemodus nur nach Freigabe. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
863 lines
40 KiB
Markdown
863 lines
40 KiB
Markdown
# Bienenpatenschaft: Urkunde, Abo, Medaillen und 3D-Ansicht im Konto
|
||
|
||
Datum: 2026-10-16
|
||
Status: Entwurf zur Freigabe, Implementierung ausstehend
|
||
Gitea: #31
|
||
|
||
Dieses Dokument ersetzt den bisherigen Implementierungsauftrag zur
|
||
Bienenpatenschaft vollständig. Grundlage sind die verbindlichen Vorgaben des
|
||
Inhabers vom 2026-10-16 und seine Ergänzungen vom selben Tag (Abo,
|
||
Kundenkonto, 3D-Ansicht, Medaillen, Treuestufen, Übertragung). Wo ältere
|
||
Fassungen etwas anderes sagen, gilt dieses Dokument.
|
||
|
||
## Problem und Ziel
|
||
|
||
Wabenhain verkauft symbolische Bienenpatenschaften als Geschenk oder für sich
|
||
selbst, einmalig bezahlt oder als monatliches Abo. Das zentrale Produkt ist
|
||
eine hochwertige, persönlich gestaltete Urkunde. Im Kundenkonto erleben
|
||
Kunden ihre Urkunde und ihre Medaillen in einer interaktiven 3D-Ansicht und
|
||
laden alles herunter.
|
||
|
||
Nach dem Kauf läuft alles automatisch: Zahlung, Urkunde, Medaillen,
|
||
Abo-Abrechnung, Rechnungen, Lieferaufträge für den Abo-Honig. Die Handarbeit
|
||
des Inhabers beschränkt sich auf Drucken, Verpacken und Versenden.
|
||
|
||
Erfolg heißt: Eine Testbestellung erzeugt ohne manuelle Nachbearbeitung eine
|
||
korrekt personalisierte, hochwertige und druckfähige Urkunde, die sofort im
|
||
Konto in 3D erscheint. Ein Test-Abo rechnet monatlich ab und erzeugt die
|
||
Honiglieferung erst, wenn sie bezahlt ist.
|
||
|
||
## Teilprojekte und Reihenfolge
|
||
|
||
Der Umfang ist zu groß für einen Plan. Jedes Teilprojekt bekommt einen
|
||
eigenen Umsetzungsplan und wird einzeln geprüft und ausgerollt:
|
||
|
||
| Nr. | Teilprojekt | Hängt ab von | Schätzung |
|
||
|---|---|---|---|
|
||
| 1 | Urkunde, Einmal-Patenschaft, Kontopflicht, Kontobereich mit Downloads, Admin (Druck, Korrektur) | – | 4–5 Tage |
|
||
| 2 | 3D-Ansicht von Urkunde und Medaille, Patenschafts-Medaillen je Paket, „Alles herunterladen“ | 1 | 3–4 Tage |
|
||
| 3 | Übertragung an Beschenkte per befristetem Link | 1 | 1 Tag |
|
||
| 4 | Abo: Stripe-Abrechnung, Kündigungsbutton, Lieferzyklen, Honigkontingent, Rechnungen | 1 | 5–7 Tage |
|
||
| 5 | Treuestufen: Stammkunden-Stufen, Abo-Stufen, VIP | 2, 4 | 2 Tage |
|
||
|
||
Teilprojekt 1 ist allein verkaufsfähig. Jedes weitere macht das Angebot
|
||
reicher, ohne das vorherige umzubauen.
|
||
|
||
## Nicht im Umfang
|
||
|
||
Diese Leistungen entfallen. Sie werden weder auf der Verkaufsseite noch in
|
||
E-Mails, Urkunden, FAQs oder Rechtstexten versprochen:
|
||
|
||
- Besuche beim Imker oder am Bienenstand
|
||
- Patentage, Veranstaltungen, Terminbuchungen
|
||
- Videos, individuelle Bienenfotos, Saisonberichte
|
||
- jede Pflicht zur laufenden Erstellung von Inhalten
|
||
- Veranstaltungs- oder Teilnehmerverwaltung
|
||
- Zusagen zu Naturschutzprojekten oder unbelegte Umweltversprechen
|
||
- ein Vorlagen-Auswahlschritt für Kunden (es gibt genau eine Gestaltung)
|
||
- Gastbestellungen von Patenschaften
|
||
|
||
Später möglich, jetzt nicht gebaut: Bilder oder andere Medien im
|
||
Patenschaftsbereich des Kontos. Das Datenmodell lässt dafür Platz (siehe
|
||
„Erweiterbarkeit“), es gibt aber keine Oberfläche und kein Versprechen.
|
||
|
||
## Angebote
|
||
|
||
Alle Angebote sind im Admin pflegbar: Name, Beschreibung, Leistungsliste,
|
||
Preis, aktiv/inaktiv, Reihenfolge, verknüpftes Honigprodukt, Gläser,
|
||
Steueraufteilung, Medaillenstufe. Es kann beliebig viele Angebote beider Arten
|
||
geben.
|
||
|
||
### Einmal-Patenschaften
|
||
|
||
| Paket | Testpreis | Leistungen | Versand |
|
||
|---|---:|---|---|
|
||
| Bienenfreund | 19 € | symbolische Namensgebung, PDF-Urkunde, Medaille, Konto mit 3D-Ansicht und Downloads | keiner |
|
||
| Honigfreund | 39 € | digitale Leistungen, gedruckte Urkunde, 1 × 500 g Honig, Grußkarte, Geschenkverpackung | ja |
|
||
| Wabenfreund | 59 € | digitale Leistungen, gedruckte Urkunde, 3 × 500 g Honig, Grußkarte, Geschenkverpackung | ja |
|
||
|
||
- Laufzeit zwölf Monate ab Startdatum, endet automatisch.
|
||
- Nach Ablauf trägt die Urkunde weiter ihr Von-bis-Datum. Urkunde, Medaille
|
||
und Downloads bleiben im Konto verfügbar.
|
||
- Alle Pakete bekommen dieselbe Urkunde in derselben Qualität. Sie
|
||
unterscheiden sich in den physischen Leistungen und in der Medaillenstufe.
|
||
|
||
### Abo-Patenschaften
|
||
|
||
Zwei Ausgangsangebote, Preise vom Inhaber festzulegen:
|
||
|
||
| Angebot | Zahlung | Honig | Lieferung |
|
||
|---|---|---|---|
|
||
| Patenschaft im Abo, vierteljährlich | monatlich | z. B. 2 × 500 g je Lieferung | nach jeweils 3 bezahlten Monaten |
|
||
| Patenschaft im Abo, nach der Ernte | monatlich | z. B. 3 × 500 g je Lieferung | in den Erntefenstern, frühestens nach 6 bezahlten Monaten seit der letzten Lieferung |
|
||
|
||
- Monatlich kündbar zum Ende des bezahlten Monats.
|
||
- Versand ist im Monatspreis enthalten. Die Verkaufsseite sagt das deutlich.
|
||
- Ein Abo gilt einer Biene mit einem Namen und hat eine Urkunde.
|
||
- Abo und Einmalkauf werden getrennt bezahlt (eigene Stripe-Sitzung je Abo).
|
||
- Ein Abo lässt sich in dieser Fassung nicht übertragen, weil die Zahlung am
|
||
Konto des Käufers hängt.
|
||
|
||
### Grußkarte
|
||
|
||
Vorgedruckt, nicht personalisiert, im Wabenhain-Design. Persönliche Worte
|
||
stehen in der Widmung auf der Urkunde. So entsteht kein Handschreiben.
|
||
|
||
## Kundenkonto ist Pflicht
|
||
|
||
- Patenschaften kauft nur, wer angemeldet ist. Das betrifft Einmal- und
|
||
Abo-Angebote. Für andere Produkte bleibt die Gastbestellung wie heute.
|
||
- Die Personalisierung lässt sich ohne Anmeldung ausprobieren, samt Vorschau.
|
||
Beim Klick auf „In den Warenkorb“ oder „Abo abschließen“ führt die Seite zur
|
||
Anmeldung oder Registrierung. Die Eingaben bleiben dabei erhalten
|
||
(Entwurf im `sessionStorage`, nach der Anmeldung zurückgeschrieben).
|
||
- Der Checkout prüft serverseitig, dass ein Konto angemeldet ist, sobald eine
|
||
Patenschaft im Warenkorb liegt.
|
||
|
||
## Personalisierung
|
||
|
||
### Felder
|
||
|
||
| Feld | Pflicht | Hinweis |
|
||
|---|---|---|
|
||
| Name der Patenbiene | ja | symbolischer Name |
|
||
| Name der Person auf der Urkunde | ja | für wen die Urkunde ausgestellt ist |
|
||
| Schenkende | nein | eine oder mehrere Personen als Freitext („Anna und Ben“) |
|
||
| Widmung | nein | wird unverändert übernommen |
|
||
| Anlass | ja | für mich selbst, Geburtstag, Weihnachten, Dankeschön, allgemeines Geschenk |
|
||
| Startdatum | ja | Einmal: frühestens Bestelltag, spätestens sechs Monate danach. Abo: Tag der ersten Zahlung |
|
||
|
||
Bei „für mich selbst“ blendet das Formular „Schenkende“ aus.
|
||
|
||
### Eingabelimits
|
||
|
||
Die endgültigen Limits ergeben sich aus der Layout-Testmatrix. Startwerte:
|
||
|
||
- Bienenname: 2–24 Zeichen
|
||
- Name auf der Urkunde: 2–60 Zeichen
|
||
- Schenkende: bis 80 Zeichen
|
||
- Widmung: bis 280 Zeichen und höchstens 5 Zeilenumbrüche
|
||
|
||
Das Formular zeigt jedes Limit vor der Bestellung als Zeichenzähler an. Server
|
||
und Client prüfen mit demselben zod-Schema.
|
||
|
||
### Zeichen
|
||
|
||
- Eingaben werden nach Unicode NFC normalisiert, Steuerzeichen entfernt,
|
||
Mehrfach-Leerzeichen zusammengefasst.
|
||
- Zulässig ist jedes Zeichen, für das die eingebetteten Schriften eine Glyphe
|
||
haben. Die Prüfung läuft serverseitig über die Font-Metriken (fontkit).
|
||
Fehlt eine Glyphe (zum Beispiel Emoji), lehnt das Formular die Eingabe mit
|
||
klarer Meldung ab, statt ein Ersatzkästchen zu drucken.
|
||
- Umlaute, ß, Akzente, Bindestriche und Apostrophe funktionieren.
|
||
|
||
## Urkundentext
|
||
|
||
Der Text entsteht aus hinterlegten Bausteinen. Es gibt keine KI-Anfrage pro
|
||
Bestellung. Der Kunde sieht den endgültigen Wortlaut vor dem Kauf in der
|
||
Vorschau.
|
||
|
||
### Regeln
|
||
|
||
- Eigene und verschenkte Patenschaft haben unterschiedliche Formulierungen.
|
||
- Geburtstag, Weihnachten und Dankeschön haben je eine kurze Anlasszeile.
|
||
„Für mich selbst“ und „allgemeines Geschenk“ haben keine.
|
||
- Leere Felder erzeugen keine Platzhalter, keine leeren Zeilen und keine
|
||
verwaisten Bezeichnungen wie „Von:“ ohne Namen.
|
||
- Keine erfundenen Eigenschaften, Beziehungen oder Ereignisse.
|
||
- Keine Geschlechtszuordnung: keine Pronomen, keine aus dem Namen
|
||
abgeleiteten Anreden.
|
||
- Keine Formulierung, die eine individuelle Betreuung oder Verfolgung einer
|
||
einzelnen Biene behauptet.
|
||
- Die Widmung wird wörtlich übernommen, nur sicher dargestellt (kein HTML,
|
||
kein Markup) und sauber umbrochen.
|
||
|
||
### Bausteine (Entwurf, vor Abnahme sprachlich final prüfen)
|
||
|
||
Überschrift: „Bienenpatenschaft“, darunter klein „Urkunde“.
|
||
|
||
Anlasszeile: „Zum Geburtstag“, „Zu Weihnachten“, „Als Dankeschön“.
|
||
|
||
Haupttext, eigene Patenschaft:
|
||
|
||
> {Name auf der Urkunde} hat einer Biene der Imkerei Wabenhain symbolisch den
|
||
> Namen
|
||
> **{Bienenname}**
|
||
> gegeben und unterstützt damit die Imkerei und ihre Bienenvölker.
|
||
|
||
Haupttext, verschenkte Patenschaft:
|
||
|
||
> Für {Name auf der Urkunde}
|
||
> Einer Biene der Imkerei Wabenhain wurde symbolisch der Name
|
||
> **{Bienenname}**
|
||
> gegeben. Die Patenschaft unterstützt die Imkerei und ihre Bienenvölker.
|
||
|
||
Schenkende, nur wenn ausgefüllt: „Geschenkt von {Schenkende}“.
|
||
|
||
Widmung, nur wenn ausgefüllt: eigener, typografisch abgesetzter Block.
|
||
|
||
Laufzeit:
|
||
|
||
- Einmal: „Patenschaft vom {Start} bis {Ende}“, Ende = Start plus zwölf Monate
|
||
minus ein Tag.
|
||
- Abo, aktiv: „Patenschaft seit {Start}“.
|
||
- Abo, gekündigt: „Patenschaft vom {Start} bis {Ende}“, Ende = letzter
|
||
bezahlter Tag. Diese Fassung entsteht automatisch als neue Revision, sobald
|
||
die Kündigung wirksam wird (siehe „Abo“).
|
||
|
||
Kennung: „Nr. {Patenschaftsnummer}“, Format `WH-P-JJJJ-NNNNN`, fortlaufend über
|
||
einen eigenen Zähler (wie `InvoiceCounter`).
|
||
|
||
Hinweis, immer vorhanden und gut lesbar:
|
||
|
||
> Die Namensgebung ist symbolisch. Sie gilt keiner einzeln begleiteten Biene,
|
||
> sondern unterstützt die Imkerei Wabenhain und ihre Bienenvölker.
|
||
|
||
Sprache: Die Urkunde erscheint in der beim Kauf gewählten Sprache (de/en).
|
||
Beide Fassungen durchlaufen dieselbe Testmatrix.
|
||
|
||
## Gestaltung der Urkunde
|
||
|
||
### Anspruch
|
||
|
||
Die Urkunde soll wie ein rahmenwürdiges Geschenk wirken:
|
||
|
||
- elegante Typografie mit klarer Hierarchie
|
||
- großzügiger Weißraum, ausgewogene Proportionen
|
||
- Bienenname und Name auf der Urkunde als gestalterischer Mittelpunkt
|
||
- dezente Bienen-, Blüten- oder Wabenillustration als feine Strichgrafik
|
||
- zurückhaltende Markenfarben, feine Rahmen oder Ornamente
|
||
- harmonisch eingebundene Widmung
|
||
- diskrete Patenschaftsnummer und Datumsangaben
|
||
- keine Cliparts, keine Office-Vorlagenoptik, keine erfundenen Gütesiegel,
|
||
keine Unterschrift
|
||
|
||
### Markengrundlage
|
||
|
||
- Schriften: Cormorant Garamond für Überschrift, Namen und Widmung, Inter für
|
||
Kleintext. Beide stehen unter der SIL Open Font License und dürfen in PDFs
|
||
eingebettet werden. Die TTF-Dateien kommen samt Lizenz nach `assets/fonts/`.
|
||
- Farben aus `src/app/globals.css`: Forest `#24352b` für Text, Honey Dark
|
||
`#8a6531` für Akzente und Linien, Honey `#b88a44` nur klein, Sage `#788774`
|
||
für Ornamente. Gold ist auf Papier eine flache Druckfarbe, nie Verlauf oder
|
||
Folienimitat. Die Urkunde verspricht keine Goldfolie.
|
||
- Logo: das hochgeladene Markenlogo (`getBrandAssets`), für den Druck als SVG
|
||
oder als PNG mit mindestens 300 dpi in Druckgröße. Fehlt es, nutzt die
|
||
Urkunde das gezeichnete Waben-Zeichen aus `lib/brand-icon.ts`. Das Logo
|
||
wird nicht verzerrt, umgefärbt oder nachgezeichnet.
|
||
- Weißes Papier, keine randlosen Farbflächen.
|
||
|
||
### Drei Varianten, dann eine Entscheidung
|
||
|
||
Zuerst entstehen drei Varianten mit identischen Beispieldaten:
|
||
|
||
1. Klassisch-editorial: zentrierte Achse, feiner Doppelrahmen in Honey Dark,
|
||
kleine Biene als Strichzeichnung über der Überschrift.
|
||
2. Wabe: asymmetrischer Aufbau, feines Hexagon-Linienraster als Eckmotiv,
|
||
Namen linksbündig groß.
|
||
3. Botanisch: Lindenblüten- oder Kleezweig als Strichillustration, die den
|
||
Textblock an zwei Ecken einfasst.
|
||
|
||
Alle drei werden als echte PDFs gerendert und nebeneinander beurteilt. Die
|
||
passendste Variante wird vollständig umgesetzt. Die anderen bleiben nicht im
|
||
Produktcode. Illustrationen werden selbst als Vektor gezeichnet. Es gibt
|
||
keine fremden Bildrechte und keine Rasterillustrationen.
|
||
|
||
## Druck- und PDF-Anforderungen
|
||
|
||
- A4 hochkant, genau eine Seite
|
||
- Text als echter Text mit eingebetteten Schrift-Teilmengen, Illustrationen
|
||
und Rahmen als Vektor
|
||
- Rasterbilder (nur das Logo, falls kein SVG) mit mindestens 300 dpi
|
||
- sicherer Rand: Inhalt mindestens 15 mm vom Blattrand, Rahmenlinien
|
||
mindestens 12 mm
|
||
- keine abgeschnittenen Namen, keine Überlagerungen
|
||
- kleinste Schrift 8 pt (Kennung, Hinweis), Fließtext mindestens 11 pt
|
||
- PDF-Metadaten: Titel „Bienenpatenschaft {Bienenname}“, Autor „Imkerei
|
||
Wabenhain“
|
||
|
||
Lange Inhalte löst das Layout über Regeln, nicht durch Verkleinern der ganzen
|
||
Seite:
|
||
|
||
1. Layoutvarianten: ohne Widmung, mit kurzer Widmung, mit langer Widmung. Die
|
||
Variante folgt aus der gemessenen Höhe.
|
||
2. Kontrollierte Umbrüche: Namen brechen nur an Leerzeichen oder Bindestrich,
|
||
höchstens auf zwei Zeilen, nie mitten im Wort.
|
||
3. Begrenzte Schriftstufen: jedes Feld hat eine feste Liste von Größen (zum
|
||
Beispiel Bienenname 54, 46, 40 pt). Passt der Inhalt in der kleinsten
|
||
Stufe nicht, ist das ein Validierungsfehler. Die Eingabelimits verhindern
|
||
diesen Fall im Betrieb.
|
||
|
||
## Medaillen und Treuestufen
|
||
|
||
Es gibt drei Arten von Medaillen. Alle werden deterministisch als Vektor
|
||
erzeugt (SVG), im Konto in 3D gezeigt und als PNG (2048 px, transparent) und
|
||
SVG heruntergeladen. Auf dem Bildschirm dürfen Medaillen metallisch glänzen.
|
||
Das betrifft nur die digitale Darstellung, nicht den Druck.
|
||
|
||
### 1. Patenschafts-Medaille (Teilprojekt 2)
|
||
|
||
- Eine je Patenschaft, mit Bienenname, Jahr und Patenschaftsnummer.
|
||
- Die Stufe richtet sich nach dem Angebot: Bienenfreund, Honigfreund und
|
||
Wabenfreund haben eigene Prägung und eigenes Metall (zum Beispiel Bronze,
|
||
Silber, Gold). Abo-Angebote haben eine eigene Prägung. Die Zuordnung ist am
|
||
Angebot im Admin einstellbar.
|
||
- Sie gehört zur Patenschaft und bleibt dauerhaft, auch nach Ablauf oder
|
||
Kündigung. Bei einer Übertragung wandert sie mit.
|
||
|
||
### 2. Stammkunden-Stufen (Teilprojekt 5)
|
||
|
||
- Für alle Kunden mit Konto, über den ganzen Shop.
|
||
- Grundlage: Anzahl bezahlter, nicht erstatteter oder stornierter
|
||
Bestellungen. Abo-Monatszahlungen zählen hier nicht, sie haben eigene
|
||
Stufen.
|
||
- Stufen und Schwellen im Admin pflegbar. Vorschlag: „Blütenbesuch“ ab 2,
|
||
„Wabenbau“ ab 5, „Honigschatz“ ab 10, „Goldwabe“ ab 25 Bestellungen.
|
||
- Die Stufe bleibt, sie sinkt nur, wenn Bestellungen erstattet oder storniert
|
||
werden.
|
||
|
||
### 3. Abo-Stufen und VIP (Teilprojekt 5)
|
||
|
||
- Grundlage: ununterbrochen bezahlte Abo-Monate.
|
||
- Vorgabe: Stufe 1 bis 24, je bezahltem Monat eine Stufe, danach eine Stufe
|
||
ohne Zahl, „VIP“, als Zeichen besonders hoher Wertschätzung. Die Schwellen
|
||
sind im Admin pflegbar und lassen sich ohne Codeänderung anpassen.
|
||
- VIP bekommt eine eigene Medaille und eine VIP-Kennzeichnung im Konto. Weitere
|
||
Vorteile (Rabatt, Versand) gehören nicht zum Umfang und lassen sich später
|
||
über die bestehenden Rabattcodes ergänzen.
|
||
- Wird das Abo gekündigt, verschwindet die Abo-Stufe samt Medaille, sobald die
|
||
Kündigung wirksam ist. Ein neues Abo beginnt wieder bei null.
|
||
- Ausfälle durch fehlgeschlagene Zahlung unterbrechen die Dauer nur, wenn das
|
||
Abo deshalb endet.
|
||
|
||
Stufen werden aus den Daten berechnet, nicht als Zustand gespeichert. So gibt
|
||
es keine Abweichung zwischen Stufe und tatsächlichen Bestellungen oder
|
||
Zahlungen.
|
||
|
||
## Kontobereich „Patenschaft“
|
||
|
||
Neuer Bereich `/konto/patenschaft` neben „Bestellungen“ und „Wunschliste“.
|
||
|
||
### Übersicht
|
||
|
||
- alle Patenschaften des Kontos mit Bienenname, Art (einmalig/Abo), Laufzeit
|
||
und Status (aktiv, abgelaufen, gekündigt)
|
||
- Medaillenleiste: Patenschafts-Medaillen, aktuelle Stammkunden-Stufe,
|
||
aktuelle Abo-Stufe oder VIP
|
||
- bei Abos: nächste Abbuchung, nächste Lieferung, Fortschritt bis zur
|
||
nächsten Lieferung („2 von 3 Monaten bezahlt“), Kündigungsbutton
|
||
|
||
### Detail einer Patenschaft
|
||
|
||
- 3D-Ansicht der eigenen Urkunde und der Patenschafts-Medaille (Teilprojekt 2;
|
||
in Teilprojekt 1 eine statische Ansicht)
|
||
- Downloads: Urkunde (PDF), Medaille (PNG, SVG), „Alles herunterladen“ (ZIP)
|
||
- Revisionen sind für Kunden nicht sichtbar. Sie sehen immer die aktuelle
|
||
Fassung.
|
||
- Menüpunkt „Übertragen“ (nur Einmal-Patenschaften, Teilprojekt 3)
|
||
|
||
### 3D-Ansicht (Teilprojekt 2)
|
||
|
||
Ziel: Die Ansicht soll beeindrucken und sich hochwertig anfühlen, ohne die
|
||
Urkunde zu verfälschen.
|
||
|
||
- Technik: three.js mit `@react-three/fiber` und `@react-three/drei`, nur auf
|
||
dieser Seite und erst im Browser geladen (dynamischer Import), damit der
|
||
übrige Shop nicht schwerer wird.
|
||
- Urkunde als Papierblatt mit leichter Wölbung, weichem Schatten und einem
|
||
langsam wandernden Lichtreflex. Die Textur ist ein hochaufgelöstes Bild
|
||
(2048 px breit) derselben Revision, aus demselben Layout wie die PDF und
|
||
ohne Wasserzeichen. Sie wird nur angemeldeten Besitzern ausgeliefert.
|
||
- Rückseite der Urkunde: Wabenhain-Zeichen und Patenschaftsnummer.
|
||
- Medaille als Münze mit Rand und erhabener Prägung (SVG-Pfade extrudiert),
|
||
Metall mit Umgebungsspiegelung. Die Umgebungstextur liegt lokal im Projekt,
|
||
kein Abruf von fremden Servern.
|
||
- Bewegung: im Ruhezustand sanftes Schweben und Drehen. Der Mauszeiger neigt
|
||
das Blatt leicht. Ziehen dreht mit Nachschwung. Doppelklick oder
|
||
Doppeltippen wendet Urkunde oder Medaille. Zoom per Mausrad oder Zwei-Finger-
|
||
Geste, begrenzt.
|
||
- Smartphone: Wischen dreht, Neigen des Geräts bewegt die Szene erst nach
|
||
einem Tipp auf „Bewegung aktivieren“ (iOS verlangt die Erlaubnis).
|
||
- `prefers-reduced-motion`: kein Schweben, keine automatische Drehung,
|
||
Ziehen bleibt möglich.
|
||
- Ohne WebGL oder bei Fehlern: statisches Bild der Urkunde und der Medaille,
|
||
Downloads funktionieren unverändert.
|
||
- Leistung: Pixeldichte höchstens 2, Darstellung pausiert, wenn der Tab im
|
||
Hintergrund oder die Szene außer Sicht ist. Ziel 60 fps auf einem
|
||
Mittelklasse-Smartphone.
|
||
- Bedienbarkeit: Tastatur dreht (Pfeiltasten) und wendet (Leertaste), die
|
||
Szene hat eine Textbeschreibung für Screenreader, alle Downloads sind
|
||
normale Links.
|
||
|
||
### Erweiterbarkeit
|
||
|
||
`Sponsorship` bekommt später eine Medienliste. Die Detailseite ist so
|
||
aufgebaut, dass ein weiterer Abschnitt („Bilder“) ohne Umbau hinzukommen
|
||
kann. In diesem Auftrag wird dafür nichts gebaut.
|
||
|
||
## Übertragung an Beschenkte (Teilprojekt 3)
|
||
|
||
Nur Einmal-Patenschaften lassen sich übertragen.
|
||
|
||
1. Der Besitzer wählt im Menü der Patenschaft „Übertragen“.
|
||
2. Er wählt die Gültigkeit des Links: 24 Stunden, 1 Woche oder 30 Tage.
|
||
3. Ein Bestätigungsdialog fragt: „Möchtest du den Übertragungslink wirklich
|
||
erstellen? Jede Person, die diesen Link hat, kann die Patenschaft in ihr
|
||
Konto übernehmen. Gib ihn nur an die beschenkte Person weiter. Die
|
||
Weitergabe geschieht auf eigene Verantwortung.“ (Wortlaut rechtlich
|
||
prüfen.)
|
||
4. Erst nach Bestätigung entsteht der Link. Er ist einmal nutzbar, enthält ein
|
||
zufälliges Token mit mindestens 128 Bit, gespeichert wird nur dessen Hash.
|
||
5. Bis zur Einlösung sieht der Besitzer den offenen Link mit Ablaufzeit und
|
||
kann ihn widerrufen.
|
||
6. Die beschenkte Person öffnet den Link, meldet sich an oder registriert sich
|
||
und bestätigt die Übernahme. Danach gehören Urkunde, Medaille und
|
||
Downloads ihrem Konto. Beim bisherigen Besitzer verschwindet die
|
||
Patenschaft aus dem Bereich „Patenschaft“. Bestellung und Rechnung bleiben
|
||
bei ihm.
|
||
7. Abgelaufene, widerrufene oder eingelöste Links zeigen eine neutrale Meldung
|
||
ohne Daten der Patenschaft.
|
||
8. Jede Übertragung steht im Audit-Log (erstellt, widerrufen, eingelöst, von
|
||
welchem Konto an welches).
|
||
|
||
Eine Übertragung verändert die Urkunde nicht. Die Stammkunden-Stufe zählt den
|
||
Kauf weiter beim Käufer.
|
||
|
||
## Abo (Teilprojekt 4)
|
||
|
||
### Abrechnung
|
||
|
||
- Stripe Billing: Jedes Abo-Angebot hat einen Stripe-Preis, der beim
|
||
Speichern im Admin angelegt wird. Eine Preisänderung erzeugt einen neuen
|
||
Stripe-Preis für neue Abos. Laufende Abos behalten ihren Preis.
|
||
- `Customer` bekommt eine `stripeCustomerId`.
|
||
- Der Abschluss läuft über eine Stripe-Checkout-Sitzung im Modus
|
||
`subscription`.
|
||
- Neue Webhook-Ereignisse: `customer.subscription.created`,
|
||
`customer.subscription.updated`, `customer.subscription.deleted`,
|
||
`invoice.paid`, `invoice.payment_failed`. Jedes Ereignis wird über die
|
||
Stripe-ID idempotent verarbeitet.
|
||
- Jede bezahlte Monatsrechnung erzeugt eine Wabenhain-Rechnung im bestehenden
|
||
Rechnungssystem (Nummernkreis, PDF, E-Rechnung) und eine Mail.
|
||
- Zahlungsart ändern: über das Stripe-Kundenportal, nur für die Zahlungsart.
|
||
|
||
### Schutz vor Verlust: Lieferung erst nach Bezahlung
|
||
|
||
Der Kunde kann monatlich kündigen, bekommt aber nie mehr Honig, als er bezahlt
|
||
hat:
|
||
|
||
- Vierteljährlich: Der Anspruch auf eine Lieferung entsteht nach jeweils drei
|
||
bezahlten Monaten. Wer nach zwei Monaten kündigt, hatte zwei Monate
|
||
Patenschaft, aber keinen Honig.
|
||
- Nach der Ernte: Der Inhaber legt im Admin die Erntefenster fest. Geliefert
|
||
wird im nächsten Fenster, sobald seit der letzten Lieferung mindestens sechs
|
||
Monate bezahlt sind.
|
||
- Bezahlt heißt: Stripe meldet die Rechnung als bezahlt, bei SEPA zusätzlich
|
||
die Regeln unter „SEPA-Lastschrift und Rückbuchungen“.
|
||
- Fehlgeschlagene Zahlung: Stripe versucht es automatisch erneut. Solange das
|
||
Abo im Verzug ist, entsteht keine Lieferung. Scheitern alle Versuche, endet
|
||
das Abo wie bei einer Kündigung.
|
||
- Die Verkaufsseite und die Abo-Bedingungen sagen klar: „Der Honig wird nach
|
||
jeweils drei bezahlten Monaten verschickt“ beziehungsweise die
|
||
entsprechende Regel für die Ernte-Variante.
|
||
- Widerruf innerhalb von 14 Tagen: Bis dahin ist kein Honig verschickt, es
|
||
entsteht kein Warenverlust.
|
||
|
||
### SEPA-Lastschrift und Rückbuchungen
|
||
|
||
Abos lassen sich mit Karte, Apple Pay, Google Pay und SEPA-Lastschrift
|
||
bezahlen.
|
||
|
||
Grenze, die keine Einstellung aufhebt: Bei einer SEPA-Lastschrift kann der
|
||
Kunde acht Wochen lang ohne Angabe von Gründen bei seiner Bank die Erstattung
|
||
verlangen, bei einer nicht autorisierten Lastschrift 13 Monate lang. Das ist
|
||
Bankrecht. Stripe kann es nicht verhindern und solche Rückbuchungen nicht
|
||
anfechten. Stripe berechnet dafür außerdem eine Gebühr. Der Schutz liegt
|
||
deshalb in der Lieferlogik von Wabenhain:
|
||
|
||
1. Lieferung nur gegen bezahlte Monate (siehe oben). Eine Rückbuchung kann
|
||
höchstens Honig betreffen, der schon bezahlt erschien.
|
||
2. Neukunden-Frist: Bei SEPA zählt die erste Abo-Zahlung eines Kontos erst
|
||
nach einer Frist für den Lieferanspruch. Vorgabe 56 Tage, also die
|
||
Acht-Wochen-Frist. Die erste Lieferung kommt dadurch bei SEPA etwas später,
|
||
alle weiteren normal. Die Frist ist im Admin einstellbar (0 schaltet sie
|
||
ab). Die Verkaufsseite nennt sie bei der Zahlart.
|
||
3. Rückbuchung erkannt (`charge.dispute.created`, im Webhook schon
|
||
abonniert): Das Abo geht sofort auf `IM_VERZUG`, offene Lieferungen werden
|
||
gestoppt und ihre Reservierung freigegeben, die Abo-Stufe ruht. Der Kunde
|
||
bekommt eine Mail mit der Bitte, den Betrag zu begleichen. Der Fall
|
||
erscheint in der Aufmerksamkeitsliste.
|
||
4. Wird der Betrag nicht binnen 14 Tagen bezahlt, endet das Abo wie bei einer
|
||
Kündigung. Der Anspruch auf den Betrag bleibt bestehen. Ob er eingefordert
|
||
wird, entscheidet der Inhaber.
|
||
5. Ein Konto mit einer Rückbuchung kann neue Abos nur noch mit Karte oder
|
||
Wallet abschließen. Der Admin kann diese Sperre aufheben.
|
||
|
||
### Stripe-Einrichtung
|
||
|
||
Die Einrichtung erfolgt in Teilprojekt 4, zuerst im Testmodus, dann
|
||
identisch im Livemodus. Was per API geht, legt ein Einrichtungsskript im Repo
|
||
an (wiederholbar, ohne Geheimnisse im Code). Was nur im Dashboard geht,
|
||
steht als Checkliste in `docs/EINRICHTUNG.md`.
|
||
|
||
- Zahlarten für Abo-Checkout: Karte, Apple Pay, Google Pay, SEPA-Lastschrift
|
||
(Mandat wird im Checkout erteilt).
|
||
- Billing: Smart Retries für fehlgeschlagene Zahlungen, nach dem letzten
|
||
Versuch Abo kündigen. Stripe-eigene Kundenmails zu Rechnungen aus, weil
|
||
Wabenhain eigene Rechnungen und Mails schickt.
|
||
- Kundenportal: nur Zahlungsart ändern. Kündigung und Tarifwechsel im Portal
|
||
aus, weil die Kündigung über den eigenen Kündigungsbutton läuft.
|
||
- Webhook-Endpunkt: bestehende Ereignisse plus
|
||
`customer.subscription.created`, `customer.subscription.updated`,
|
||
`customer.subscription.deleted`, `invoice.paid`,
|
||
`invoice.payment_failed`, `charge.dispute.closed`.
|
||
- Produkte und Preise der Abo-Angebote legt der Admin über Wabenhain an,
|
||
nicht von Hand im Stripe-Dashboard.
|
||
- Tests mit Stripe Test Clocks (Abo über mehrere Monate) und
|
||
SEPA-Testkonten, darunter eines, das eine Rückbuchung auslöst.
|
||
|
||
### Lieferaufträge
|
||
|
||
Ein täglicher Lauf im CronJob `wabenhain-certificates` prüft fällige
|
||
Lieferungen. Ist der Anspruch erfüllt und Bestand reserviert, legt er einen
|
||
Lieferauftrag als normale Bestellung an (Status `BEZAHLT`, Betrag 0 €, mit
|
||
Verweis auf das Abo). Er erscheint in der bestehenden Pack- und DHL-Liste. Der
|
||
Inhaber packt und versendet wie bei jeder Bestellung.
|
||
|
||
### Honigbestand und Kontingent
|
||
|
||
Kein Abo darf ohne Honig bleiben, weil der Shop zu viele Gläser einzeln
|
||
verkauft hat:
|
||
|
||
- Kontingent: Jedes Abo-Angebot hat eine Höchstzahl aktiver Abos, im Admin
|
||
pflegbar. Ist sie erreicht, zeigt die Verkaufsseite „Derzeit ausgebucht“
|
||
mit der bestehenden Benachrichtigung, sobald wieder Plätze frei sind.
|
||
- Reservierung, vierteljährlich: Für jedes aktive Abo sind die Gläser der
|
||
nächsten fälligen Lieferung im Bestand des verknüpften Honigprodukts
|
||
reserviert. Der Shop verkauft einzeln nur den freien Bestand: Bestand minus
|
||
Abo-Reservierung minus offene Bestellungen.
|
||
- Reservierung, Ernte-Variante: Der Inhaber trägt je Erntefenster die
|
||
geplanten Abo-Gläser ein. Sobald die Abfüllung im Bestand ist, wird dieser
|
||
Anteil reserviert, bevor er in den Freiverkauf geht.
|
||
- Deckungsanzeige im Admin-Dashboard: „Bestand deckt den Abo-Bedarf der
|
||
nächsten 2 Lieferungen.“ Unter einer Lieferung erscheint eine Warnung in der
|
||
Aufmerksamkeitsliste.
|
||
- Reicht die Deckung für neue Abos nicht, stoppt der Shop neue Abschlüsse
|
||
automatisch, bis der Inhaber nachlegt.
|
||
|
||
### Kündigung
|
||
|
||
- Kündigungsbutton nach § 312k BGB: „Verträge hier kündigen“. Im Konto mit
|
||
einem Klick auf die Bestätigungsseite, zusätzlich öffentlich erreichbar
|
||
unter `/vertraege-kuendigen` mit Name, E-Mail und Abo-Nummer, nach dem
|
||
Muster der bestehenden Route `vertrag-widerrufen`. Rechtlich prüfen lassen.
|
||
- Die Kündigung wirkt zum Ende des bezahlten Monats (`cancel_at_period_end`).
|
||
Eine Bestätigungsmail geht sofort hinaus.
|
||
- Wird die Kündigung wirksam:
|
||
1. Die Urkunde bekommt automatisch eine neue Revision mit „vom … bis …“.
|
||
Ersteller „System“, Grund „Abo beendet“. Sie bleibt im Konto
|
||
herunterladbar.
|
||
2. Die Abo-Stufe und ihre Medaille verschwinden.
|
||
3. Die Patenschafts-Medaille und alle Downloads bleiben.
|
||
4. Offene Reservierungen werden freigegeben.
|
||
|
||
## Architektur
|
||
|
||
### Ein Layout, mehrere Ausgaben
|
||
|
||
Vorschau, 3D-Textur und finale PDF müssen identisch umbrechen. Deshalb gibt es
|
||
genau eine Layout-Berechnung auf dem Server:
|
||
|
||
```
|
||
Personalisierung + Textbausteine + Vorlagenversion
|
||
│
|
||
▼
|
||
composeCertificateText() → aufgelöste Textblöcke (reine Funktion)
|
||
│
|
||
▼
|
||
layoutCertificate() → positionierte Elemente: Zeilen mit x/y,
|
||
Schriftgröße, Schrift, Pfade (reine Funktion,
|
||
misst mit fontkit an denselben TTF-Dateien)
|
||
│
|
||
├──► renderCertificatePdf() pdfkit, Text als Text
|
||
├──► renderCertificatePreview() SVG, Glyphen als Pfade, sharp → WebP,
|
||
│ Wasserzeichen, Bildschirmauflösung
|
||
└──► renderCertificateTexture() wie Vorschau, ohne Wasserzeichen,
|
||
2048 px, nur für Besitzer
|
||
```
|
||
|
||
Bild-Ausgaben setzen Glyphen als Pfade aus denselben Schriftdateien an
|
||
dieselben Positionen. Sie hängen nicht von Browser-Schriften ab. Ein Test
|
||
vergleicht die Zeilen aller Ausgaben.
|
||
|
||
Module unter `src/lib/certificate/`:
|
||
|
||
| Modul | Aufgabe |
|
||
|---|---|
|
||
| `schema.ts` | zod-Schema der Personalisierung, gemeinsam für Client und Server |
|
||
| `text.ts` | Bausteine je Sprache, Anlass, eigene/verschenkte Patenschaft, Laufzeitform |
|
||
| `layout.ts` | Messen, Umbrechen, Schriftstufen, Layoutvarianten |
|
||
| `templates/` | Vorlagen, je Version eine Datei, alte Versionen bleiben erhalten |
|
||
| `render-pdf.ts` | pdfkit-Ausgabe |
|
||
| `render-image.ts` | SVG-Ausgabe, Vorschau und Textur |
|
||
| `storage.ts` | Ablage der PDFs |
|
||
| `issue.ts` | Erzeugung nach Zahlung, idempotent, mit Wiederholung |
|
||
|
||
Weitere Module: `src/lib/medals/` (Medaillen-SVG, Stufenberechnung),
|
||
`src/lib/sponsorship-subscription/` (Abo, Lieferanspruch, Reservierung),
|
||
`src/lib/sponsorship-transfer.ts`.
|
||
|
||
### Vorlagenversion
|
||
|
||
Jede Vorlage hat eine feste Kennung, etwa `wabe-classic@1`. Eine
|
||
Designänderung erzeugt eine neue Version, die alte bleibt im Code. Neue
|
||
Patenschaften nutzen die aktuelle Version. Bestehende behalten ihre Version
|
||
und ihre gespeicherte PDF. Systemrevisionen (Abo-Ende) nutzen die Version der
|
||
vorherigen Revision. Medaillen sind ebenso versioniert.
|
||
|
||
### Datenmodell (Prisma, beide Provider)
|
||
|
||
- `SponsorshipOffer`: Art (`EINMALIG`, `ABO`), Name, Beschreibung,
|
||
Leistungen, Preis (einmalig) oder Monatspreis, aktiv, Reihenfolge, physisch,
|
||
verknüpftes Honigprodukt, Gläser je Lieferung, Lieferzyklus
|
||
(`VIERTELJAEHRLICH`, `ERNTE`), Kontingent, Stripe-Preis-ID,
|
||
Steueraufteilung, Medaillenstufe
|
||
- `Sponsorship`: Besitzerkonto, Angebot, Bezug auf `OrderItem` (einmalig)
|
||
oder `SponsorshipSubscription` (Abo), jeweils eindeutig als
|
||
Idempotenzschlüssel, Patenschaftsnummer, Start, Ende (leer bei aktivem Abo),
|
||
Status, aktuelle Revision, Zustellfelder `pdfAttempts`, `nextAttemptAt`,
|
||
`lastError`, `mailSentAt`, `printedAt`
|
||
- `SponsorshipRevision`: unveränderlich: Personalisierung (JSON), aufgelöster
|
||
Text, Vorlagenversion, PDF-Pfad, SHA-256, Ersteller (System, Admin),
|
||
Grund, Zeitpunkt
|
||
- `SponsorshipCounter`: fortlaufende Nummer je Jahr
|
||
- `SponsorshipSubscription`: Konto, Angebot, `stripeSubscriptionId`
|
||
(eindeutig), Status (`AKTIV`, `IM_VERZUG`, `GEKUENDIGT`, `BEENDET`),
|
||
Beginn, Kündigung wirksam zum, Ende
|
||
- `SubscriptionPayment`: Abo, `stripeInvoiceId` (eindeutig), bezahlt am,
|
||
Betrag, Zahlart, zählt für Lieferung ab (Datum, bei SEPA-Neukunden nach
|
||
der Frist), zurückgebucht am, Wabenhain-Rechnung
|
||
- `SubscriptionDelivery`: Abo, fällig am, Gläser, Status, erzeugte Bestellung
|
||
- `HarvestWindow`: Zeitraum, geplante Abo-Gläser je Angebot
|
||
- `SponsorshipTransfer`: Patenschaft, Token-Hash, gültig bis, erstellt von,
|
||
eingelöst von, eingelöst am, widerrufen am
|
||
- `LoyaltyLevel`: Art (`STAMMKUNDE`, `ABO`), Schwelle, Name, Medaillendesign;
|
||
VIP als Stufe ohne Zahl
|
||
- `Customer.stripeCustomerId`, `Customer.sepaBlockedAt` (gesetzt nach einer
|
||
Rückbuchung)
|
||
|
||
Statuswerte der Patenschaft: `AUSSTEHEND`, `FEHLER`, `BEREIT`, `GEDRUCKT`.
|
||
Aktiv, abgelaufen und gekündigt werden aus Daten berechnet.
|
||
|
||
### Warenkorb und Checkout (Einmal-Patenschaft)
|
||
|
||
- Patenschaft als Position im bestehenden Warenkorb, Menge immer 1 je
|
||
Personalisierung.
|
||
- Die Personalisierung reist mit der Position. Der Checkout prüft sie erneut
|
||
mit demselben Schema und denselben Layoutregeln und verlangt ein
|
||
angemeldetes Konto.
|
||
- Vor dem Hinzufügen bestätigt der Kunde: „Ich habe die Vorschau und die
|
||
Schreibweise geprüft.“
|
||
- Beim Anlegen der Bestellung wird die Personalisierung mit der
|
||
Vorlagenversion an der `OrderItem` gespeichert. Genau dieser Stand wird nach
|
||
der Zahlung zur ersten Revision.
|
||
- Reine Digitalbestellungen haben keine Versandkosten. Ob dafür ein neuer
|
||
`FulfillmentMethod`-Wert `DIGITAL` nötig ist, entscheidet der
|
||
Umsetzungsplan nach Lesen von Checkout, Rechnung und DHL-Logik.
|
||
- Physische Pakete laufen über die bestehenden Versandstaffeln je Kategorie
|
||
mit eigener Staffel für Patenschaftspakete.
|
||
- Der Honig eines Pakets bucht den Bestand des verknüpften Produkts über die
|
||
vorhandene Bestandslogik (einschließlich ApiCore-Abgleich), unter
|
||
Berücksichtigung der Abo-Reservierung.
|
||
|
||
### Steuer
|
||
|
||
Pakete und Abos enthalten Leistungen mit unterschiedlichen Steuersätzen
|
||
(Urkunde und Leistung, Honig). Das Angebot speichert deshalb eine Aufteilung:
|
||
Honiganteil in Cent zum Honig-Satz, Rest zum Regelsatz. Die Rechnung zeigt
|
||
beide Steuerzeilen über die vorhandene Gruppierung in `lib/vat.ts`. Die
|
||
Methode muss die Steuerberatung bestätigen. Bei Kleinunternehmerregelung
|
||
entfällt die Aufteilung wie heute.
|
||
|
||
### Ablauf nach der Zahlung (Einmal-Patenschaft)
|
||
|
||
1. Der Stripe-Webhook markiert die Bestellung wie heute über den atomaren
|
||
Claim als bezahlt. Nur dieser Lauf legt die `Sponsorship`-Zeilen an.
|
||
Ein Duplikat scheitert am eindeutigen `orderItemId` und bricht still ab.
|
||
2. Danach versucht der Webhook die Erzeugung direkt: Text, Layout, PDF,
|
||
Ablage, Hash, erste Revision.
|
||
3. Die Bestellbestätigung verlinkt auf `/konto/patenschaft/<id>`. Der
|
||
Mailversand wird über `updateMany … where mailSentAt = null` beansprucht,
|
||
damit doppelte Webhooks keine zweite Mail erzeugen. Erst danach ist der
|
||
Status `BEREIT`.
|
||
4. Scheitert die Erzeugung, antwortet der Webhook trotzdem 200 (die Zahlung
|
||
ist erfolgt). Die Patenschaft bleibt `AUSSTEHEND`. Die Mail sagt: „Deine
|
||
Urkunde wird gerade erstellt und erscheint in Kürze in deinem Konto.“
|
||
5. Der CronJob `wabenhain-certificates` (alle 10 Minuten,
|
||
`concurrencyPolicy: Forbid`, wie die Jobs in `k8s/07-backup-cronjob.yaml`)
|
||
holt offene Erzeugungen und Mails nach, mit wachsendem Abstand, höchstens
|
||
8 Versuche, danach `FEHLER` und Hinweis in der Aufmerksamkeitsliste.
|
||
|
||
Die finale Urkunde entsteht nie vor bestätigter Zahlung. SEPA-Zahlungen
|
||
erzeugen sie erst bei `async_payment_succeeded`. Beim Abo entsteht sie mit der
|
||
ersten bezahlten Rechnung.
|
||
|
||
### Ablage und Zugriff
|
||
|
||
- PDFs liegen in `CERTIFICATE_DIR`, nicht unter `UPLOAD_DIR`. Die
|
||
Startprüfung aus `lib/invoice-storage.ts` wird übernommen. Das Verzeichnis
|
||
kommt auf das gesicherte Volume und in den Sicherungs-CronJob.
|
||
- Alle Downloads und die 3D-Textur liefern Routen aus, die Anmeldung und
|
||
Besitz prüfen. Fremde IDs ergeben 404.
|
||
- Downloads liefern immer die gespeicherte PDF der aktuellen Revision.
|
||
- Kein QR-Code auf der Urkunde: Er brächte kaum Nutzen und würde die
|
||
Gestaltung stören.
|
||
|
||
### Vorschau
|
||
|
||
- `POST /api/patenschaft/vorschau`: prüft die Personalisierung, gibt ein WebP
|
||
mit Wasserzeichen „Unverbindliche Vorschau“ in Bildschirmauflösung zurück.
|
||
Rate-Limit je Besucher. Keine Anmeldung nötig.
|
||
- Der Client fordert sie etwa 400 ms nach der letzten Eingabe an und zeigt bis
|
||
dahin die letzte gültige Vorschau.
|
||
|
||
## Adminbereich
|
||
|
||
- Angebote: Einmal- und Abo-Angebote bearbeiten, Kontingent, Erntefenster,
|
||
Medaillenstufe.
|
||
- Patenschaften: Liste mit Filtern (ausstehend, Fehler, bereit, zu drucken,
|
||
gedruckt, Art, Angebot). Detail mit Vorschau, Revisionen, „Druck-PDF
|
||
öffnen“, „Als gedruckt markieren“, „Erneut erzeugen“, „Mail erneut senden“,
|
||
Übertragungshistorie.
|
||
- Abos: Liste mit Status, bezahlten Monaten, nächster Lieferung; Deckung des
|
||
Honigbedarfs.
|
||
- Treuestufen: Schwellen und Namen pflegen.
|
||
- Korrektur: Felder im Kundenformular ändern, Vorschau mit derselben
|
||
Layoutlogik, Pflichtfeld Änderungsgrund, neue Revision mit neuer PDF, alte
|
||
bleibt abrufbar, Eintrag über `logAdminAction`, optional Mail an den Kunden.
|
||
Standardmäßig mit der Vorlagenversion der bisherigen Revision.
|
||
- Druckablauf: Physische Bestellungen erscheinen nach Zahlung unter „zu
|
||
drucken“. PDF öffnen, auf festem Papier drucken, als gedruckt markieren,
|
||
wie gewohnt über DHL versenden.
|
||
|
||
## Verkaufsseite
|
||
|
||
Route `/patenschaft`, zweisprachig, im Design der Website.
|
||
|
||
Im Mittelpunkt:
|
||
|
||
- einer Biene symbolisch einen eigenen Namen geben
|
||
- ein persönlich gestaltetes Geschenk
|
||
- die regionale Imkerei Wabenhain unterstützen
|
||
- je nach Angebot eigenen Wabenhain-Honig, einmalig oder regelmäßig
|
||
|
||
Aufbau:
|
||
|
||
1. Kopfbereich mit großer, echter Urkundenvorschau
|
||
2. Umschalter „Einmalig“ / „Im Abo“ mit den Angeboten, Preis, Leistungen,
|
||
Versandkosten beziehungsweise „Versand inklusive“ und den Lieferregeln
|
||
3. Personalisierung in Schritten: Angebot, für wen und Anlass, Namen, Widmung
|
||
und Startdatum, Vorschau prüfen
|
||
4. Ausschnitt aus dem Kontobereich (3D-Urkunde und Medaille als Video oder
|
||
Bildfolge) mit dem Hinweis, dass der Kauf ein Kundenkonto braucht
|
||
5. Hinweis zur symbolischen Namensgebung, gut sichtbar
|
||
6. FAQ
|
||
|
||
Smartphone: Vorschau über dem jeweiligen Schritt, ein Tipp vergrößert sie.
|
||
Eingabefelder mindestens 16 px Schrift, Bedienelemente mindestens 44 px.
|
||
|
||
FAQ-Themen: symbolische Namensgebung, Laufzeit (einmalig zwölf Monate, Abo
|
||
monatlich kündbar), wann der Honig im Abo kommt, warum ein Konto nötig ist,
|
||
Übertragung an Beschenkte, Versandkosten, Tippfehler (Kontakt, Korrektur
|
||
durch Wabenhain), was nach Ablauf oder Kündigung bleibt. Keine FAQ verspricht
|
||
Besuche, Berichte, Fotos oder Umweltwirkungen.
|
||
|
||
## Prüfung
|
||
|
||
### Layout-Testmatrix
|
||
|
||
Automatisierte Tests rendern echte PDFs und prüfen die Layoutdaten (keine
|
||
Überlappung, alles in der Sicherheitszone, Schrift nie unter Mindestgröße,
|
||
genau eine Seite) für:
|
||
|
||
- sehr kurze Namen („Li“, „Bo“)
|
||
- maximal lange Namen in beiden Feldern
|
||
- Doppelnamen („Marie-Luise Schmidt-Habermann“)
|
||
- Umlaute und Sonderzeichen („Jürgen Weiß“, „Zoë“, „Ñúñez“, „O’Brien“)
|
||
- mehrere Schenkende („Anna, Ben, Carla und Familie Özdemir“)
|
||
- ohne Widmung und mit maximal langer Widmung samt allen Zeilenumbrüchen
|
||
- jeden Anlass, eigene und verschenkte Patenschaft, Deutsch und Englisch
|
||
- alle drei Laufzeitformen (einmalig, Abo aktiv, Abo beendet)
|
||
- Vorschau, Textur und PDF ergeben dieselben Zeilen
|
||
|
||
Die Matrix legt die endgültigen Eingabelimits fest.
|
||
|
||
### Visuelle Kontrolle
|
||
|
||
PDFs werden mit 300 dpi gerastert und angesehen: ganze Seite und Ausschnitte
|
||
in hoher Vergrößerung. Probedruck auf einem Bürodrucker. Medaillen als PNG in
|
||
Originalgröße. 3D-Ansicht auf Desktop, 390 px mobil, mit
|
||
`prefers-reduced-motion` und ohne WebGL.
|
||
|
||
### Ablauftests
|
||
|
||
- doppelter Webhook: eine Patenschaft, eine Mail
|
||
- PDF-Erzeugung scheitert: Webhook 200, CronJob holt nach
|
||
- Gastkauf einer Patenschaft wird serverseitig abgewiesen
|
||
- fremde Patenschaft, fremder Download, fremde Textur: 404
|
||
- Korrektur: neue Revision, alte unverändert, Audit-Eintrag
|
||
- neue Vorlagenversion: alte Urkunden unverändert
|
||
- Übertragung: Link läuft ab, wird widerrufen, wird genau einmal eingelöst
|
||
- Abo: Lieferung erst nach drei bezahlten Monaten; Kündigung nach zwei
|
||
Monaten erzeugt keine Lieferung; Zahlungsausfall stoppt Lieferungen;
|
||
Kündigung erzeugt Von-bis-Revision und entfernt die Abo-Stufe
|
||
- Bestand: Einzelverkauf kann reservierte Abo-Gläser nicht kaufen;
|
||
Kontingent voll stoppt neue Abos
|
||
- doppelte Stripe-Abo-Ereignisse: eine Rechnung, eine Zahlung
|
||
- SEPA: erste Zahlung zählt erst nach der Neukunden-Frist; Rückbuchung
|
||
stoppt Lieferungen, setzt das Abo in Verzug, sperrt SEPA für das Konto;
|
||
ohne Ausgleich endet das Abo nach 14 Tagen
|
||
- Treuestufen: Erstattung senkt die Stammkunden-Stufe
|
||
- E2E (Playwright): Einmalkauf mit Stripe-Testkarte bis zur 3D-Ansicht im
|
||
Konto; Abo-Abschluss mit Stripe-Testuhr (Test Clock) über drei Monate
|
||
|
||
Die Repo-Skripte `lint`, `typecheck`, `test` und `build` laufen grün.
|
||
|
||
## Abnahme
|
||
|
||
Je Teilprojekt gilt: fertig erst nach den passenden Tests, der visuellen
|
||
Kontrolle und einer Vorführung. Gesamtabnahme:
|
||
|
||
1. Verkaufsseite und Personalisierung auf Desktop und 390 px mobil
|
||
2. die drei Designvarianten und die gewählte Gestaltung
|
||
3. mehrere echte PDF-Ausgaben mit unterschiedlichen Beispieldaten
|
||
4. automatischer Ablauf vom Kauf bis zur 3D-Ansicht und zum Download
|
||
5. Medaillen aller Arten und Stufen
|
||
6. Übertragung von Konto zu Konto
|
||
7. Abo über drei Monate mit Test Clock bis zur Lieferung, dann Kündigung
|
||
8. Druck- und Korrekturablauf im Admin
|
||
9. offene geschäftliche Konfiguration (Liste unten)
|
||
|
||
## Geschäftliche Konfiguration vor Veröffentlichung
|
||
|
||
1. Preise kaufmännisch prüfen: Einmalpakete und Abo-Monatspreise mit Honig,
|
||
Papier, Verpackung, Grußkarte, Versand, Stripe-Gebühren, Arbeitszeit.
|
||
2. Gläser je Abo-Lieferung, Erntefenster und Kontingente festlegen.
|
||
3. Steueraufteilung mit der Steuerberatung abstimmen.
|
||
4. AGB, Abo-Bedingungen und Widerrufsbelehrung: personalisierte Ware
|
||
(§ 312g Abs. 2 Nr. 1 BGB), digitale Inhalte (§ 356 Abs. 5 BGB),
|
||
Abo-Laufzeit und Kündigung, Kündigungsbutton (§ 312k BGB), Lieferregel
|
||
„nach bezahlten Monaten“, Übertragung auf eigene Verantwortung. Rechtlich
|
||
prüfen lassen.
|
||
5. Datenschutzerklärung: Namen Dritter, Speicherdauer, Stripe Billing.
|
||
6. Stripe-Livemodus freigeben: Die Einrichtung (siehe „Stripe-Einrichtung“)
|
||
läuft erst im Testmodus. Den Livemodus stellt das Skript erst nach
|
||
ausdrücklicher Freigabe des Inhabers um. Neukunden-Frist für SEPA
|
||
bestätigen (Vorgabe 56 Tage).
|
||
7. Versandstaffel für Patenschaftspakete anlegen.
|
||
8. Logo als SVG oder PNG mit mindestens 300 dpi hochladen.
|
||
9. Material bevorraten: Urkundenpapier (200–250 g/m², matt, naturweiß),
|
||
Geschenkverpackung, Grußkarten. Probedruck freigeben.
|
||
10. Bestellschluss für Weihnachten festlegen.
|
||
11. Textbausteine und Medaillennamen sprachlich freigeben (de und en).
|