Fix-Runde: echte Umlaute, und das Versprechen sagt "auf Wunsch"
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
parent
7d041db5e5
commit
ae8c8680bb
|
|
@ -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 Kü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 wäre die eingebaute
|
||||
* Laravel-Meldung die einzige englische Zeile in einem sonst
|
||||
* durchgehend deutschen Dialog.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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. --}}
|
||||
|
|
|
|||
|
|
@ -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 gü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 gü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();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue