From 5dd75dac86878d5472f2722294608d0f2cbc948f Mon Sep 17 00:00:00 2001 From: nexxo Date: Tue, 4 Aug 2026 08:07:56 +0200 Subject: [PATCH] Die Instanz merkt sich, was der Kunde zu seinen Daten gesagt hat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drei Zustaende, nicht zwei: `null` heisst "noch nicht gefragt". Jede Instanz, die vor diesem Bau gekuendigt wurde, hat die Frage nie gesehen — ihr ein "nein" zu unterstellen hiesse, still fuer Menschen zu antworten, die niemand gefragt hat. --- app/Models/Instance.php | 6 +++ ...der_kunde_sagt_ob_er_einen_export_will.php | 37 +++++++++++++++++++ tests/Feature/Cancellation/ExportWishTest.php | 22 +++++++++++ 3 files changed, 65 insertions(+) create mode 100644 database/migrations/2026_08_04_140000_der_kunde_sagt_ob_er_einen_export_will.php create mode 100644 tests/Feature/Cancellation/ExportWishTest.php diff --git a/app/Models/Instance.php b/app/Models/Instance.php index 5254b26..2b999ea 100644 --- a/app/Models/Instance.php +++ b/app/Models/Instance.php @@ -22,6 +22,7 @@ class Instance extends Model 'ram_mb', 'cores', 'restart_required_since', 'subdomain', 'custom_domain', 'nc_admin_ref', 'admin_password', 'credentials_acknowledged_at', 'route_written', 'routed_hostnames', 'routed_backend', 'cert_ok', 'status', 'suspended_at', 'cancel_requested_at', 'service_ends_at', + 'export_wish', 'export_reminded_at', 'domain_token', 'domain_verified_at', 'domain_cert_ok', 'domain_checked_at', 'domain_error', 'domain_failures', 'security_log_offset', ]; @@ -56,6 +57,11 @@ class Instance extends Model 'cores' => 'integer', 'cancel_requested_at' => 'datetime', 'service_ends_at' => 'datetime', + // export_wish fuehrt DREI Zustaende: null (nicht gefragt), true, false. + // Laravels boolean-Cast laesst null als null durch (kein (bool)null), + // deshalb unterstellt eine Bestandsinstanz ohne Antwort kein "nein". + 'export_wish' => 'boolean', + 'export_reminded_at' => 'datetime', 'restart_required_since' => 'datetime', ]; } diff --git a/database/migrations/2026_08_04_140000_der_kunde_sagt_ob_er_einen_export_will.php b/database/migrations/2026_08_04_140000_der_kunde_sagt_ob_er_einen_export_will.php new file mode 100644 index 0000000..86647f5 --- /dev/null +++ b/database/migrations/2026_08_04_140000_der_kunde_sagt_ob_er_einen_export_will.php @@ -0,0 +1,37 @@ +boolean('export_wish')->nullable()->after('service_ends_at'); + $table->timestamp('export_reminded_at')->nullable()->after('export_wish'); + }); + } + + public function down(): void + { + Schema::table('instances', function (Blueprint $table) { + $table->dropColumn(['export_wish', 'export_reminded_at']); + }); + } +}; diff --git a/tests/Feature/Cancellation/ExportWishTest.php b/tests/Feature/Cancellation/ExportWishTest.php new file mode 100644 index 0000000..3601734 --- /dev/null +++ b/tests/Feature/Cancellation/ExportWishTest.php @@ -0,0 +1,22 @@ +create()->export_wish)->toBeNull(); +}); + +it('haelt ein Ja und ein Nein auseinander', function () { + expect(Instance::factory()->create(['export_wish' => true])->export_wish)->toBeTrue() + ->and(Instance::factory()->create(['export_wish' => false])->export_wish)->toBeFalse(); +}); + +it('merkt sich, wann erinnert wurde, damit es nicht zweimal geschieht', function () { + $instance = Instance::factory()->create(['export_reminded_at' => now()]); + + expect($instance->fresh()->export_reminded_at)->not->toBeNull(); +});