- Kontaktformular: keine Mail mehr an die eingegebene Adresse (wurde als
Spam-Versender missbraucht); Anfrage nur an Kontakt-Adresse + Berater (BCC),
Reply-To = Absender; Eingaben in der Mail escaped
- Kontakt + Registrierung: Cloudflare Turnstile statt reCAPTCHA (Schluessel
aus dem Code in die .env), Rate-Limits, Honeypot + Mindest-Ausfuellzeit,
Namensregel (lateinische Schrift, max. 50 Zeichen), Form Requests
- Registrierung: Partner-Nummer nur fuer aktive Berater (vorher ungeprueft)
- CRM: POST /register abgeschaltet (legte ohne Captcha Benutzer an)
- Passwort-Mindestlaenge systemweit 8 Zeichen ueber Password::defaults()
- Log abgefangener Anfragen: storage/logs/form-spam-*.log
- Doku und Protokoll: dev/2026-10-09-spam/README.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kunden loeschen (Rueckmeldung "es wird nichts geloescht"):
- DSGVO-geloeschte Eintraege blieben mit Name in den Listen stehen; Kunde
61009 wurde deshalb achtmal geloescht, bei Eintrag 45013 wurde die E-Mail
danach ueber ein offenes Bearbeiten-Formular zurueckgeschrieben
- neue Spalte shopping_users.gdpr_deleted_at (Bestand per Migration markiert)
- Admin-Kundenliste blendet geloeschte Kunden aus (Filter: ausblenden /
mit anzeigen / nur geloeschte), Berater-Kundenliste immer
- Bearbeiten/Speichern im Admin und beim Berater gesperrt; ShoppingUser
verweigert das Zurueckschreiben von E-Mail und Telefon
- Modal und Erfolgsmeldung (de/en/es/fr) sagen klar, dass Name und
Rechnungsadresse wegen der Aufbewahrungspflicht bleiben
- gdpr:repair-customers [--execute] zieht protokollierte Loeschungen nach
- DSGVO-Loeschung prueft Superadmin serverseitig; Berater duerfen eine
Kunden-E-Mail nur beim eigenen Kunden nachtragen
- setFakerMail setzt faker_mail bei geloeschten Eintraegen nicht zurueck
Checkout: "Wie bist du auf uns aufmerksam geworden?" ist kein Pflichtfeld
mehr und wird farbig hervorgehoben.
Deploy: php artisan migrate && php artisan gdpr:repair-customers --execute
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Log-Analyse 26.08. (P1-4): Adressen wie "ruediger@..." mit Umlaut im
lokalen Teil lehnt der Mailer ab; Checkout-Bestaetigung und
Abo-Erinnerung scheiterten. Registrierung, Checkout, Kunden- und
Profilformulare pruefen jetzt mit email:filter. Die Abo-Erinnerung
ueberspringt bestehende Adressen dieser Art mit einem Log-Eintrag statt
einer Transport-Exception.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Die Dateien lagen im Arbeitsbaum formatiert und inhaltlich geaendert
zusammen. Dieser Commit enthaelt nur die Pint-Formatierung des alten
Stands, damit die folgenden Commits nur noch Inhalt zeigen.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Yard::weight() multiplizierte Gewicht und Menge ohne Cast. Beide Werte stammen
aus Session- bzw. Request-Daten; ein fuehrend-numerischer String wie "2,5" loeste
unter PHP 8 die ErrorException "A non-numeric value encountered" aus. Danach war
die Position dauerhaft defekt, da reCalculateShippingPrice() bei jedem Aufruf
erneut fehlschlug.
Cart::update() setzt die Menge ohne Validierung (anders als setQuantity()).
Eintrittspunkte waren das quantity-Feld im Shop-POST sowie das Textfeld fuer die
Menge im Backoffice-Warenkorb.
- Yard: neue cartItemWeight() mit explizitem int-Cast fuer Gewicht und Menge
- CardController: nicht-numerische Mengen werden uebersprungen, Schutz gegen ein
quantity-Feld, das kein Array ist
- OrderController: nutzt das bereits vorhandene $qty (int) statt $data['qty'] roh
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Karten-Update ohne Abbuchung via PAYONE creditcardcheck/pseudocardpan
(AboPaymentMethodService, CardUpdateResult/CreditCardCheckData-DTOs)
- Eingabe nur durch Abo-Inhaber: CRM- und Portal-Formular + zeitlich
begrenzter Berater→Kunde-Link (AboCardUpdateLink + Mail)
- Änderungshistorie in user_abo_card_changes, Anzeige im Admin-Abo-Detail
- Admin: Abo löschen (destroy) inkl. Test
- Portal-Fix: myOrderCreate wirft 404 statt TypeError bei ungültiger ID
- VIP-Sichtbarkeitstests für Einmalartikel-Fenster ergänzt
- Enthält bereits die Freeze-Guards für den Stripe-Notbetrieb (Folge-Commit)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Öffentliches Widerrufsformular /widerruf mit Bestell-Lookup (throttled)
- Bestätigungsmail an Kunde + Weiterleitung an bestellungen@ (config app.withdrawal_mail)
- Admin-Übersicht/-Detail unter /admin/withdrawals inkl. Sidenav-Eintrag
- Widerruf-Button in Portal-Bestellansicht und Footer-Links
- Model OrderWithdrawal + Migration + Factory + Tests
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Pay-now-Flow: bei fehlgeschlagenem Abo (Status 3) begleicht der Inhaber die
offene Rechnung im Standard-Checkout mit frei waehlbarer, abo-faehiger Zahlart
(nur eigenes Abo: Berater me-View + Kundenportal), payNow-Controller + Routen
- AboRecoveryCheckoutService baut die ShoppingInstance aus den Abo-Artikeln;
neue Spalte shopping_orders.recovery_user_abo_id verknuepft Bestellung<->Abo
- Bei Erfolg: AboHelper::advanceAboAfterRecoveryPayment schreibt das Abo fort
(Status->2, next_date) und uebernimmt die gewaehlte Zahlart als neues Token
fuer kuenftige Abbuchungen
- Neue Pay-now-Fehlermail (AboPaymentFailedMail) ersetzt die generische
Fehlermail im Abo-Cron; Link fuehrt auf die Abo-Detailseite (CRM bzw. Portal)
- Retry-/"extern erledigt"-Buttons nur noch fuer Admins; tote user/portal-
Retry-Routen entfernt
- Checkout: Recovery-Hinweis statt "Abschluss des Abonnements", Lieferadresse
vorbelegt, korrekter Zurueck-Link (Abo statt Shop)
- UserAbo::selfServiceDetailUrl zentralisiert die Abo-URL (Mail, Back-Links)
- Test-Command abo:test-recovery; Tests fuer payNow, Advance-Logik, Fehlermail
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>