diff --git a/docs/superpowers/specs/2026-10-16-bienenpatenschaft-design.md b/docs/superpowers/specs/2026-10-16-bienenpatenschaft-design.md new file mode 100644 index 0000000..33d7235 --- /dev/null +++ b/docs/superpowers/specs/2026-10-16-bienenpatenschaft-design.md @@ -0,0 +1,563 @@ +# Bienenpatenschaft mit automatisch erzeugter Urkunde + +Datum: 2026-10-16 +Status: Entwurf zur Freigabe, Implementierung ausstehend + +Dieses Dokument ersetzt den bisherigen Implementierungsauftrag zur +Bienenpatenschaft vollständig. Grundlage sind die verbindlichen Vorgaben des +Inhabers vom 2026-10-16. Wo ältere Fassungen etwas anderes sagen, gilt dieses +Dokument. + +## Problem und Ziel + +Wabenhain soll eine symbolische Bienenpatenschaft als Geschenkprodukt +verkaufen. Das zentrale Produkt ist eine hochwertige, persönlich gestaltete +Urkunde. Nach der Bestellung läuft alles automatisch: Zahlung, Erzeugung der +Urkunde, Zustellung des Downloads. Die Handarbeit des Inhabers beschränkt sich +bei physischen Paketen auf Drucken, Verpacken und Versenden. + +Erfolg heißt: Eine Testbestellung erzeugt ohne manuelle Nachbearbeitung eine +korrekt personalisierte, optisch hochwertige und druckfähige Urkunde, und der +Käufer bekommt den Download automatisch. + +## Nicht im Umfang + +Diese Leistungen entfallen vollständig. 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, Newsletter zur Patenschaft +- jede Pflicht zur laufenden Erstellung von Inhalten +- Veranstaltungs- oder Teilnehmerverwaltung +- automatische Verlängerung, Abo oder Erinnerungsmails zum Ablauf +- Zusagen zu Naturschutzprojekten oder unbelegte Umweltversprechen +- ein Vorlagen-Auswahlschritt für Kunden (es gibt genau eine Gestaltung) + +Die Patenschaftsseite zeigt nur die persönlichen Patenschaftsdaten und den +Download der Urkunde. Sie braucht keine redaktionelle Pflege. + +## Produkt + +### Pakete + +Drei Ausgangspakete, im Adminbereich bearbeitbar (Name, Preis, Beschreibung, +Leistungsliste, aktiv/inaktiv, Reihenfolge): + +| Paket | Testpreis | Leistungen | Versand | +|---|---:|---|---| +| Bienenfreund | 19 € | symbolische Namensgebung, individuell gestaltete PDF-Urkunde, sicherer Download | 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 | + +- Die Preise sind Testpreise. Vor Veröffentlichung werden sie kaufmännisch + geprüft (siehe „Geschäftliche Konfiguration vor Veröffentlichung“). +- Alle Pakete bekommen dieselbe Urkunde in derselben Qualität. Sie + unterscheiden sich nur in den physischen Leistungen. +- Die Patenschaft läuft zwölf Monate ab dem gewählten Startdatum und endet + automatisch. Danach zeigt die Patenschaftsseite den Status „abgelaufen“, der + Download bleibt erhalten. Es folgen keine weiteren Leistungen oder Mails. + +### Honig im Paket + +Jedes physische Paket verweist im Admin auf ein Honigprodukt aus dem +bestehenden Sortiment und auf eine Anzahl Gläser. Die Bestellung reserviert +und bucht den Bestand dieses Produkts über die vorhandene Bestandslogik +(einschließlich ApiCore-Abgleich). Ist das verknüpfte Produkt ausverkauft, ist +das Paket nicht bestellbar und die Verkaufsseite sagt das. Der Inhaber wechselt +die Sorte, indem er im Admin ein anderes Produkt verknüpft. + +### Grußkarte + +Die Grußkarte ist eine vorgedruckte, nicht personalisierte Karte im +Wabenhain-Design. Persönliche Worte stehen in der Widmung auf der Urkunde. +So entsteht kein Handschreiben pro Bestellung. + +## 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 | frühestens am Bestelltag, spätestens sechs Monate danach | + +Bei „für mich selbst“ blendet das Formular das Feld „Schenkende“ aus. + +### Eingabelimits + +Die endgültigen Limits ergeben sich aus der Layout-Testmatrix (siehe +„Prüfung“). Startwerte, die die Testmatrix bestätigen oder verschärfen muss: + +- 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 + einer klaren Meldung ab, statt ein Ersatzkästchen zu drucken. +- Umlaute, ß, Akzente, Bindestriche und Apostrophe müssen funktionieren. + +## Urkundentext + +Der Text entsteht aus hinterlegten, sorgfältig formulierten 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, passende + 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 Anreden wie „Liebe/Lieber“, + die aus dem Namen abgeleitet wären. +- Keine Formulierung, die eine individuelle Betreuung oder Verfolgung einer + einzelnen Biene behauptet. +- Die Widmung wird wörtlich übernommen. Erlaubt sind nur sichere Darstellung + (kein HTML, kein Markup) und sauberer Umbruch. + +### Bausteine (Entwurf, vor Abnahme sprachlich final prüfen) + +Überschrift: „Bienenpatenschaft“, darunter klein „Urkunde“. + +Anlasszeile über dem Haupttext: + +- Geburtstag: „Zum Geburtstag“ +- Weihnachten: „Zu Weihnachten“ +- Dankeschön: „Als Dankeschön“ +- allgemeines Geschenk und für mich selbst: keine Anlasszeile + +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: als eigener, typografisch abgesetzter Block. + +Laufzeit: „Patenschaft vom {Startdatum} bis {Enddatum}“, Enddatum = Startdatum +plus zwölf Monate minus ein Tag, deutsches Langformat. + +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. + +Englische Texte: Die Seite ist zweisprachig (de/en). Die Urkunde erscheint in +der beim Checkout gewählten Sprache (`Order.locale`). Beide Sprachfassungen +durchlaufen dieselbe Testmatrix. + +## Gestaltung + +### 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 schon auf der Website, beide unter SIL Open Font License, + Einbettung in PDF erlaubt). Die TTF-Dateien kommen nach `assets/fonts/` samt + Lizenzdatei. +- Farben aus `src/app/globals.css`: Forest `#24352b` für Text, Honey Dark + `#8a6531` für Akzente und Linien, Honey `#b88a44` nur flächig klein, Sage + `#788774` für Ornamente. Gold erscheint als flache Druckfarbe, nie als + Verlauf oder Folienimitat. Die Urkunde verspricht keine Goldfolie. +- Logo: das hochgeladene Markenlogo (`getBrandAssets`). Für den Druck braucht + es eine SVG-Fassung oder ein PNG mit mindestens 300 dpi in Druckgröße. Liegt + keins vor, nutzt die Urkunde das gezeichnete Waben-Zeichen aus + `lib/brand-icon.ts` als Vektor. Das Logo wird nicht verzerrt, nicht + umgefärbt und nicht nachgezeichnet. +- Papier ist weiß. Die Urkunde hat 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 zur +Marke passendste Variante wird vollständig umgesetzt. Die anderen beiden +bleiben nicht im Produktcode. + +Illustrationen werden selbst als Vektor gezeichnet (SVG-Pfade, im Code als +Pfaddaten). Es gibt keine fremden Bildrechte und keine Rasterillustrationen. + +## Druck- und PDF-Anforderungen + +- Format A4 hochkant, genau eine Seite +- Text als echter Text mit eingebetteten Schrift-Teilmengen, Illustrationen + und Rahmen als Vektor +- Rasterbilder (nur das Logo, falls es kein SVG gibt) mit mindestens 300 dpi + in Druckgröße +- sicherer Rand: aller Inhalt mindestens 15 mm vom Blattrand, Rahmenlinien + mindestens 12 mm. Übliche Büro- und Tintenstrahldrucker lassen 3–5 mm frei. +- keine abgeschnittenen Namen, keine Überlagerungen +- kleinste Schrift 8 pt (Kennung und Hinweis), Fließtext mindestens 11 pt +- PDF-Metadaten: Titel „Bienenpatenschaft {Bienenname}“, Autor „Imkerei + Wabenhain“ + +### Lange Inhalte + +Lange Inhalte löst das Layout über definierte Regeln, nicht durch +Verkleinern der ganzen Seite: + +1. Layoutvarianten: ohne Widmung (mehr Luft, größere Namen), 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. Doppelnamen bleiben möglichst + in einer Zeile. +3. Begrenzte Schriftstufen: jedes Feld hat eine feste Liste von Größen (zum + Beispiel Bienenname 54, 46, 40 pt). Passt der Inhalt auch in der kleinsten + Stufe nicht, ist das ein Validierungsfehler. Die Eingabelimits sind so + gewählt, dass dieser Fall im Betrieb nicht auftritt. + +## Architektur + +### Ein Layout, zwei Ausgaben + +Vorschau 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 mit Glyphen als Pfade, + per sharp zu WebP gerastert, + mit Wasserzeichen +``` + +Die Vorschau setzt Glyphen als Pfade aus denselben Schriftdateien an dieselben +Positionen. Sie hängt damit nicht von Browser-Schriften ab, und ein +Umbruchunterschied zwischen Vorschau und PDF ist ausgeschlossen. Ein Test +vergleicht die Zeilen beider 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 | +| `layout.ts` | Messen, Umbrechen, Schriftstufen, Layoutvarianten | +| `templates/` | Vorlagen, je Version eine Datei, alte Versionen bleiben erhalten | +| `render-pdf.ts` | pdfkit-Ausgabe | +| `render-preview.ts` | SVG-Ausgabe und Rasterung mit Wasserzeichen | +| `storage.ts` | Ablage der PDFs (eigenes Verzeichnis, siehe unten) | +| `issue.ts` | Erzeugung nach Zahlung, idempotent, mit Wiederholung | + +### Vorlagenversion + +Jede Vorlage hat eine feste Kennung, etwa `wabe-classic@1`. Eine +Designänderung erzeugt eine neue Version, die alte bleibt im Code. Neue +Bestellungen nutzen die aktuelle Version. Bereits ausgestellte Urkunden +behalten ihre Version und ihre gespeicherte PDF. + +### Datenmodell (Prisma, beide Provider) + +- `SponsorshipPackage`: Name, Beschreibung, Leistungsliste, Preis, aktiv, + Reihenfolge, physisch ja/nein, verknüpftes Honigprodukt, Anzahl Gläser, + Steueraufteilung (siehe unten) +- `Sponsorship`: eine je gekaufter Patenschaft. Bezug auf `OrderItem` + (eindeutig, das ist der Idempotenzschlüssel), Patenschaftsnummer, Start- und + Enddatum, Status, Zugriffs-Token als Hash, aktuelle Revision +- `SponsorshipRevision`: unveränderlicher Stand: Personalisierung (JSON), + aufgelöster Text, Vorlagenversion, PDF-Pfad, SHA-256 der PDF, erstellt von + (System oder Admin), Änderungsgrund, Zeitpunkt +- `SponsorshipCounter`: fortlaufende Nummer je Jahr +- Zustellfelder an `Sponsorship`: `pdfAttempts`, `nextAttemptAt`, + `lastError`, `mailSentAt`, `printedAt` + +Statuswerte der Patenschaft: `AUSSTEHEND` (bezahlt, PDF noch nicht da), +`FEHLER` (Versuche aufgebraucht, braucht Admin), `BEREIT` (PDF da, Mail +versendet), `GEDRUCKT` (nur physisch). Der Laufzeitstatus aktiv/abgelaufen +wird aus den Daten berechnet, nicht gespeichert. + +### Warenkorb und Checkout + +- Die Patenschaft kommt als Position in den bestehenden Warenkorb, Menge + immer 1 je Personalisierung. Mehrere Patenschaften sind mehrere Positionen. +- Die Personalisierung reist mit der Warenkorbposition. Der Checkout prüft sie + serverseitig erneut mit demselben Schema und denselben Layoutregeln. +- Bevor die Position in den Warenkorb darf, bestätigt der Kunde: „Ich habe die + Vorschau und die Schreibweise geprüft.“ +- Beim Anlegen der Bestellung wird die Personalisierung zusammen mit der + Vorlagenversion als Entwurf an der `OrderItem` gespeichert. Genau dieser + Stand wird nach der Zahlung zur ersten Revision. +- Reine Digitalbestellungen haben keine Versandkosten. Die Rechnungsanschrift + bleibt Pflicht wie heute. Ob dafür ein neuer `FulfillmentMethod`-Wert + `DIGITAL` nötig ist oder `VERSAND` mit 0 € genügt, entscheidet der + Implementierungsplan nach Lesen von Checkout, Rechnung und DHL-Logik. +- Physische Pakete laufen über die bestehenden Versandstaffeln je Kategorie. + Für Patenschaftspakete wird eine eigene Staffel gepflegt. + +### Steuer + +Ein physisches Paket enthält Leistungen mit unterschiedlichen Steuersätzen +(Urkunde und Leistung, Honig). Das Paket speichert deshalb eine Aufteilung des +Bruttopreises: Honiganteil in Cent zum Honig-Satz, Rest zum Regelsatz. Die +Rechnung zeigt das Paket mit beiden Steuerzeilen. Die vorhandene +Gruppierung nach Steuersätzen in `lib/vat.ts` wird dafür genutzt. Die Methode +der Aufteilung muss die Steuerberatung bestätigen. Ist +Kleinunternehmerregelung aktiv, entfällt die Aufteilung wie heute. + +### Ablauf nach der Zahlung + +1. Der Stripe-Webhook markiert die Bestellung wie heute über den atomaren + Claim als bezahlt. Nur dieser Lauf legt die `Sponsorship`-Zeilen an + (`create` mit eindeutigem `orderItemId`; ein Duplikat bricht still ab). +2. Danach versucht der Webhook die Erzeugung direkt: Text auflösen, Layout, + PDF rendern, ablegen, Hash und erste Revision speichern. +3. Die Bestellbestätigung enthält den Downloadlink. Der Versand der Mail wird + über `updateMany … where mailSentAt = null` beansprucht, damit doppelte + Webhooks keine zweite Mail erzeugen. Erst nach erfolgreichem Versand wird + der Status `BEREIT`. +4. Scheitert die Erzeugung, antwortet der Webhook trotzdem 200 (die Zahlung + ist erfolgt, wie bei der Rechnung heute). Die Patenschaft bleibt + `AUSSTEHEND` mit `nextAttemptAt`. Die Bestätigungsmail sagt dann: „Ihre + Urkunde wird gerade erstellt, der Link folgt in einer eigenen Mail.“ +5. Ein neuer CronJob `wabenhain-certificates` (alle 10 Minuten, + `concurrencyPolicy: Forbid`, wie die bestehenden Jobs in + `k8s/07-backup-cronjob.yaml`) holt offene Erzeugungen und offene Mails + nach. Wiederholung mit wachsendem Abstand, höchstens 8 Versuche, danach + `FEHLER` und Hinweis im Admin-Dashboard (bestehende Aufmerksamkeitsliste). + +Die finale Urkunde entsteht nie vor bestätigter Zahlung. Async-Zahlarten +(SEPA) erzeugen sie erst bei `async_payment_succeeded`. + +### Ablage + +PDFs liegen in einem eigenen Verzeichnis `CERTIFICATE_DIR`, nicht unter +`UPLOAD_DIR`, weil die Upload-Route alles ohne Anmeldung ausliefert. Die +Startprüfung aus `lib/invoice-storage.ts` (Verzeichnis darf nicht im +Upload-Verzeichnis liegen) wird übernommen. Das Verzeichnis kommt auf das +gesicherte Volume und in den Sicherungs-CronJob. + +### Download und Patenschaftsseite + +- Der Link enthält ein zufälliges Token mit mindestens 128 Bit. Gespeichert + wird nur der SHA-256-Hash. Die URL enthält keine Namen und keine + Bestellnummer. +- `/patenschaft/` zeigt Bienenname, Name auf der Urkunde, Laufzeit, + Status aktiv/abgelaufen und den Download. Keine Anschrift, keine + Bestelldaten. `noindex`, Rate-Limit über `lib/rate-limit.ts`. +- Angemeldete Kunden sehen ihre Patenschaften zusätzlich unter „Konto“. +- Der Download liefert immer die gespeicherte PDF der aktuellen Revision. Es + wird nicht neu gerendert. +- Der Link darf an Beschenkte weitergegeben werden. Er zeigt nur, was ohnehin + auf der Urkunde steht. + +### QR-Code + +Die Urkunde bekommt keinen QR-Code. Er brächte kaum Nutzen, stört die +Gestaltung, und ein QR-Code zur Patenschaftsseite würde den Downloadlink +jedem öffnen, der ein Foto der gerahmten Urkunde sieht. + +### Vorschau + +- Endpunkt `POST /api/patenschaft/vorschau`: nimmt die Personalisierung, + prüft sie, gibt ein WebP zurück. Rate-Limit je Besucher. +- Die Vorschau trägt sichtbar „Unverbindliche Vorschau“ als Wasserzeichen und + hat nur Bildschirmauflösung. Sie ersetzt so nicht die gekaufte PDF. +- Der Client fordert sie mit Verzögerung nach der letzten Eingabe an (etwa + 400 ms) und zeigt bis dahin die letzte gültige Vorschau. + +## Adminbereich + +### Pakete + +Pakete bearbeiten wie Produkte: Name, Preis, Beschreibung, Leistungen, aktiv, +Honigprodukt, Gläser, Steueraufteilung. + +### Patenschaften + +Liste mit Filtern nach Status (ausstehend, Fehler, bereit, zu drucken, +gedruckt) und Paket. Detailansicht: + +- Vorschau der aktuellen Revision, Liste aller Revisionen +- „Druck-PDF öffnen“: dieselbe gespeicherte PDF, die der Kunde bekommt +- „Als gedruckt markieren“ (nur physisch) +- „Erneut erzeugen“ bei Status `FEHLER` (gleiche Vorlagenversion) +- „Mail erneut senden“ + +### Korrektur + +1. Admin öffnet „Korrigieren“, ändert Felder im selben Formular wie der Kunde. +2. Die Vorschau zeigt das Ergebnis mit derselben Layoutlogik. +3. Speichern verlangt einen Änderungsgrund. +4. Es entsteht eine neue `SponsorshipRevision` mit neuer PDF. Die alte bleibt + erhalten und ist abrufbar. +5. `logAdminAction` schreibt den Vorgang ins Audit-Log (wer, wann, welche + Felder, Grund). +6. Optional per Häkchen: Mail an den Käufer „Ihre korrigierte Urkunde“. + +Eine Korrektur nutzt standardmäßig die Vorlagenversion der bisherigen +Revision. Ein Wechsel auf die aktuelle Version ist eine bewusste Auswahl im +Formular. + +### Druckablauf + +Physische Bestellungen erscheinen nach der Zahlung in der Liste „zu drucken“. +Der Inhaber öffnet die PDF, druckt sie auf festem Papier, markiert sie als +gedruckt und versendet die Bestellung wie heute über DHL. Mehr Schritte gibt +es nicht. + +## Verkaufsseite + +Route `/patenschaft`, zweisprachig, im bestehenden Design der Website. + +Im Mittelpunkt stehen: + +- einer Biene symbolisch einen eigenen Namen geben +- ein persönlich gestaltetes Geschenk +- die regionale Imkerei Wabenhain unterstützen +- je nach Paket eigenen Wabenhain-Honig verschenken + +Aufbau: + +1. Kopfbereich mit großer, echter Urkundenvorschau als zentrales Element +2. Paketwahl mit klarer Leistungsliste, Preis und Versandkosten +3. Personalisierung in Schritten: Paket, für wen und Anlass, Namen, Widmung + und Startdatum, Vorschau prüfen +4. Hinweis zur symbolischen Namensgebung, gut sichtbar und nicht im Kleingedruckten +5. FAQ + +Auf dem Smartphone steht die Vorschau über dem jeweiligen Schritt. Ein Tipp +vergrößert sie auf volle Breite. Eingabefelder haben mindestens 16 px +Schriftgröße (kein Zoom unter iOS), Bedienelemente mindestens 44 px. + +FAQ-Themen: Was bedeutet symbolische Namensgebung? Wie lange läuft die +Patenschaft? (zwölf Monate, endet automatisch, kein Abo) Wann kommt die +Urkunde? (digital direkt nach Zahlung, gedruckt mit dem Paket) Was ist im +Paket? Was kostet der Versand? Was, wenn ich mich vertippt habe? (Kontakt, +Korrektur durch Wabenhain) Keine FAQ verspricht Besuche, Berichte, Fotos oder +Umweltwirkungen. + +## Prüfung + +### Layout-Testmatrix + +Automatisierte Tests rendern echte PDFs und prüfen die Layoutdaten (keine +Überlappung von Elementboxen, alles innerhalb 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 +- maximal lange Widmung, auch mit allen erlaubten Zeilenumbrüchen +- jeden Anlass, eigene und verschenkte Patenschaft, Deutsch und Englisch +- Vorschau und PDF ergeben dieselben Zeilen + +Die Matrix legt die endgültigen Eingabelimits fest. Sie stehen danach im +Schema und im Formular. + +### Visuelle Kontrolle + +Die erzeugten PDFs werden gerastert (300 dpi) und angesehen: die ganze Seite +und Ausschnitte bei hoher Vergrößerung (Namen, Widmung, Ornament, Kleintext). +Layoutfehler werden vor Abschluss behoben. Ein Probedruck auf einem +Bürodrucker gehört dazu. + +### Ablauftests + +- Webhook doppelt zugestellt: eine Patenschaft, eine Mail +- PDF-Erzeugung schlägt fehl: Webhook 200, CronJob holt nach, Status wird `BEREIT` +- Mailversand schlägt fehl: CronJob holt nach, keine Doppelmail +- Fremdes oder falsches Token: 404 ohne Hinweis auf Existenz +- Korrektur: neue Revision, alte unverändert, Audit-Eintrag vorhanden +- Vorlagenversion erhöht: alte Urkunden liefern unverändert ihre PDF +- E2E (Playwright): Paket wählen, personalisieren, Vorschau, Checkout mit + Stripe-Testkarte, Downloadseite, PDF abrufbar + +Die Repo-Skripte `lint`, `typecheck`, `test` und `build` laufen grün. + +## Abnahme + +Fertig ist die Funktion, wenn eine Testbestellung ohne manuelle Nacharbeit +eine korrekt personalisierte, hochwertige und druckfähige Urkunde erzeugt. + +Zum Abschluss werden gezeigt: + +1. Verkaufsseite und Personalisierung auf Desktop und bei 390 px mobil +2. die drei Designvarianten und die gewählte Gestaltung +3. mehrere echte PDF-Ausgaben mit unterschiedlichen Beispieldaten +4. der automatische Ablauf vom Kauf bis zum Download +5. Druck- und Korrekturablauf im Adminbereich +6. die offene geschäftliche Konfiguration (Liste unten) + +## Geschäftliche Konfiguration vor Veröffentlichung + +Diese Punkte entscheidet der Inhaber. Die Software ist ohne sie fertig, +veröffentlicht wird erst danach. + +1. Preise kaufmännisch prüfen: Honig, Papier, Verpackung, Grußkarte, + Stripe-Gebühren, Arbeitszeit je Paket. +2. Steueraufteilung der physischen Pakete mit der Steuerberatung abstimmen. +3. AGB und Widerrufsbelehrung anpassen: Ausschluss des Widerrufs für nach + Kundenangaben angefertigte Waren (§ 312g Abs. 2 Nr. 1 BGB), Zustimmung zum + sofortigen Beginn bei digitalen Inhalten (§ 356 Abs. 5 BGB), Behandlung + des Honiganteils. Rechtlich prüfen lassen. +4. Datenschutzerklärung ergänzen: Namen Dritter (Beschenkte, Schenkende), + Speicherdauer der Personalisierung und der PDFs. +5. Versandstaffel für Patenschaftspakete im Admin anlegen. +6. Logo als SVG oder PNG mit mindestens 300 dpi hochladen. +7. Material bevorraten: Urkundenpapier (Empfehlung 200–250 g/m², matt, + naturweiß), Geschenkverpackung, vorgedruckte Grußkarten. Probedruck auf dem + eigenen Drucker freigeben. +8. Bestellschluss für Weihnachten festlegen und auf der Verkaufsseite nennen. +9. Bausteintexte sprachlich final freigeben (de und en).