Fix-Runde: echte Umlaute, und das Versprechen sagt "auf Wunsch"
tests / pest (push) Waiting to run Details
tests / assets (push) Waiting to run Details
tests / release (push) Blocked by required conditions Details

Befund 1: neuer deutscher Text (Kommentare, ein Testname) benutzte ae/oe/ue/ss
statt ä/ö/ü/ß — der Bestand schreibt mit echten Umlauten, das Original wird
hier nachgezogen. Betroffen: die drei Kommentare in ConfirmCancelPackage.php,
der Blade-Kommentar, sowie Kopfkommentare und ein Testname in
CancelAsksAboutExportTest.php. Der Funktionsname kuendbareInstanz() und die
Test-Fixtures (E-Mail/Subdomain "kuendigt") bleiben ASCII — ersterer ist
wörtlich aus dem Zettel übernommen, letztere sind technische Werte wie jede
andere Test-Subdomain im Bestand (acme, berger).

Befund 2 (Entscheidung des Betreibers): cancel_point_export versprach den
Datenexport unbedingt, direkt über einer Frage, die ihn an ein Ja knüpft. "auf
Wunsch" eingefügt, in beiden Sprachdateien — der Satz sagt jetzt, was der
Dialog tatsächlich tut, ohne sonst etwas am Text zu ändern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
claude/nice-moser-521659
nexxo 2026-08-04 08:44:20 +02:00
parent 7d041db5e5
commit ae8c8680bb
5 changed files with 30 additions and 30 deletions

View File

@ -55,12 +55,12 @@ class ConfirmCancelPackage extends ModalComponent
public string $note = '';
/**
* Ob der Kunde zum Laufzeitende einen Datenexport will. Drei Zustaende,
* nicht zwei: `null` heisst unbeantwortet und ist beim Kuendigen nicht
* zulaessig diese Frage ist der Angelpunkt des ganzen Vorhabens
* (Erinnerungen, Export-Vorbereitung) und darf nicht uebersprungen
* werden. `boolean` laesst `true` UND `false` durch: ein bewusstes Nein
* ist eine ebenso gueltige Antwort wie ein Ja und darf nicht wie eine
* Ob der Kunde zum Laufzeitende einen Datenexport will. Drei Zustände,
* nicht zwei: `null` heißt unbeantwortet und ist beim ndigen nicht
* zulässig diese Frage ist der Angelpunkt des ganzen Vorhabens
* (Erinnerungen, Export-Vorbereitung) und darf nicht übersprungen
* werden. `boolean` lässt `true` UND `false` durch: ein bewusstes Nein
* ist eine ebenso gültige Antwort wie ein Ja und darf nicht wie eine
* fehlende Antwort behandelt werden.
*/
#[Validate('required|boolean')]
@ -104,11 +104,11 @@ class ConfirmCancelPackage extends ModalComponent
return;
}
// Nicht ueberspringbar, aus demselben Grund wie der Kuendigungsgrund
// oben: die Kuendigung ist der einzige Moment, in dem der Kunde
// ohnehin ueber seine Daten nachdenkt, und danach fragt niemand mehr.
// Vor Stripe geprueft, wie alles andere hier — ein abgebrochener
// Versuch soll nichts anstossen, weder bei Stripe noch bei uns.
// Nicht überspringbar, aus demselben Grund wie der Kündigungsgrund
// oben: die Kündigung ist der einzige Moment, in dem der Kunde
// ohnehin über seine Daten nachdenkt, und danach fragt niemand mehr.
// Vor Stripe geprüft, wie alles andere hier — ein abgebrochener
// Versuch soll nichts anstoßen, weder bei Stripe noch bei uns.
$this->validate();
$contract = $this->contractFor($customer, $instance);
@ -140,8 +140,8 @@ class ConfirmCancelPackage extends ModalComponent
}
/**
* Eigene Meldung fuer die Exportfrage. Im Bestand liegt keine
* `lang/de/validation.php` ohne Ueberschreibung waere die eingebaute
* Eigene Meldung für die Exportfrage. Im Bestand liegt keine
* `lang/de/validation.php` ohne Überschreibung re die eingebaute
* Laravel-Meldung die einzige englische Zeile in einem sonst
* durchgehend deutschen Dialog.
*/

View File

@ -63,7 +63,7 @@ return [
'cancel_title' => 'Paket kündigen?',
'cancel_body' => 'Ihr Paket wird zum Ende der Abrechnungsperiode gekündigt.',
'cancel_point_term' => 'Wirksam zum Ende der Laufzeit — bis dahin bleibt alles verfügbar.',
'cancel_point_export' => 'Zum Laufzeitende erhalten Sie einen vollständigen Datenexport.',
'cancel_point_export' => 'Zum Laufzeitende erhalten Sie auf Wunsch einen vollständigen Datenexport.',
'cancel_point_irreversible' => 'Die Kündigung ist nach Bestätigung verbindlich.',
'cancel_reason_label' => 'Warum kündigen Sie?',
'cancel_reason_choose' => 'Bitte wählen',

View File

@ -63,7 +63,7 @@ return [
'cancel_title' => 'Cancel package?',
'cancel_body' => 'Your package will be cancelled at the end of the billing period.',
'cancel_point_term' => 'Effective at the end of the term — everything stays available until then.',
'cancel_point_export' => 'At the end of the term you receive a full data export.',
'cancel_point_export' => 'At the end of the term you receive a full data export, on request.',
'cancel_point_irreversible' => 'Once confirmed, the cancellation is binding.',
'cancel_reason_label' => 'Why are you cancelling?',
'cancel_reason_choose' => 'Please choose',

View File

@ -57,9 +57,9 @@
</div>
{{-- Zwei Auswahlfelder statt einer Checkbox (R-Vorgabe dieser Aufgabe): eine
Checkbox kennt keinen dritten Zustand, und "nicht angekreuzt" waere von
Checkbox kennt keinen dritten Zustand, und "nicht angekreuzt" wäre von
einem bewussten Nein nicht zu unterscheiden genau diese Unterscheidung
entscheidet, ob wir spaeter Erinnerungen schicken und einen Export
entscheidet, ob wir später Erinnerungen schicken und einen Export
vorbereiten. Radio-Werte "1"/"0" statt leerer Wert, damit PHP sie beim
Setzen eindeutig nach true/false wandelt und keiner der beiden mit dem
unbeantworteten null verwechselt werden kann. --}}

View File

@ -8,25 +8,25 @@ use App\Models\User;
use Livewire\Livewire;
/**
* Abweichung vom Zettel: keine der drei Pruefungen unten setzt im Original
* Abweichung vom Zettel: keine der drei Prüfungen unten setzt im Original
* `reason`. Im Bestand verlangt ConfirmCancelPackage::cancelPackage() aber
* schon laenger einen gueltigen Grund (Subscription::CANCEL_REASONS) und
* schon länger einen ltigen Grund (Subscription::CANCEL_REASONS) und
* bricht sonst VOR jeder Schreibaktion mit einem eigenen Fehler ab das war
* so, bevor diese Aufgabe begann, und diese Aufgabe aendert daran nichts. Ohne
* `->set('reason', ...)` wuerde jede der drei Pruefungen an dieser
* vorgelagerten Stelle scheitern, nicht an der Exportfrage, die hier geprueft
* werden soll. Alle drei setzen deshalb zusaetzlich einen gueltigen Grund.
* so, bevor diese Aufgabe begann, und diese Aufgabe ändert daran nichts. Ohne
* `->set('reason', ...)` würde jede der drei Prüfungen an dieser
* vorgelagerten Stelle scheitern, nicht an der Exportfrage, die hier geprüft
* werden soll. Alle drei setzen deshalb zusätzlich einen ltigen Grund.
*/
/**
* Ein aktives Paket, dessen Besitzer den Kuendigungsdialog erreichen kann
* Ein aktives Paket, dessen Besitzer den Kündigungsdialog erreichen kann
* nach dem Muster von settingsSetup() (tests/Feature/SettingsTest.php) und
* cancellablePackage() (tests/Feature/Billing/PackageCancellationTest.php):
* Nutzer, Kunde, Bestellung, aktive Instanz. Bewusst OHNE eigenen
* Subscription-Datensatz: ConfirmCancelPackage::contractFor() findet dann
* keinen Vertrag, und stopBilling(null) gibt ungefragt true zurueck (derselbe
* Weg wie bei einem geschenkten Paket) Stripe bleibt aussen vor, weil es in
* dieser Aufgabe ausschliesslich um die Exportfrage geht.
* keinen Vertrag, und stopBilling(null) gibt ungefragt true zurück (derselbe
* Weg wie bei einem geschenkten Paket) Stripe bleibt außen vor, weil es in
* dieser Aufgabe ausschließlich um die Exportfrage geht.
*
* @return array{0: User, 1: Instance}
*/
@ -83,9 +83,9 @@ it('nimmt auch ein Nein als Antwort — und nicht als fehlende Antwort', functio
->and($instance->fresh()->export_wish)->not->toBeNull();
});
it('kuendigt nicht ohne eine Antwort auf die Frage', function () {
// Eine Frage, die man ueberspringen kann, ist keine Frage — und die
// Kuendigung ist der einzige Moment, in dem der Kunde ohnehin ueber seine
it('kündigt nicht ohne eine Antwort auf die Frage', function () {
// Eine Frage, die man überspringen kann, ist keine Frage — und die
// Kündigung ist der einzige Moment, in dem der Kunde ohnehin über seine
// Daten nachdenkt.
[$user, $instance] = kuendbareInstanz();