diff --git a/app/Models/Seat.php b/app/Models/Seat.php index f70208f..47925a9 100644 --- a/app/Models/Seat.php +++ b/app/Models/Seat.php @@ -73,7 +73,7 @@ class Seat extends Model return; } - $this->forceFill([ + $this->fill([ 'nc_username' => $ref, 'nc_state' => self::STATE_SYNCED, 'nc_synced_at' => now(), diff --git a/database/migrations/2026_08_03_180000_add_nextcloud_columns_to_seats.php b/database/migrations/2026_08_03_180000_add_nextcloud_columns_to_seats.php index 73ef568..3a92dfb 100644 --- a/database/migrations/2026_08_03_180000_add_nextcloud_columns_to_seats.php +++ b/database/migrations/2026_08_03_180000_add_nextcloud_columns_to_seats.php @@ -1,8 +1,10 @@ customer, und ohne Eager Load waere das eine Anfrage pro - // Sitz statt einer pro Bloecken von 100 — bei owner-Sitzen (einer - // je Kunde) ist der Bestand hier so gross wie der Kundenstamm. - Seat::query()->where('role', 'owner')->with('customer')->chunkById(100, function ($sitze) { + DB::table('seats')->where('role', 'owner')->chunkById(100, function ($sitze) { foreach ($sitze as $sitz) { - $sitz->linkToInstanceAdmin(); + $roh = DB::table('instances') + ->where('customer_id', $sitz->customer_id) + ->whereIn('status', ['active', 'cancellation_scheduled']) + ->orderByDesc('id') + ->value('nc_admin_ref'); + + if ($roh === null) { + continue; + } + + try { + $ref = Crypt::decryptString($roh); + } catch (DecryptException) { + // Nicht entschluesselbar (z. B. ein Schluesselwechsel ohne + // Migration der Altwerte) wird wie „kein Konto" behandelt — + // ein Wanderungslauf darf daran nicht scheitern. + continue; + } + + if (blank($ref)) { + continue; + } + + DB::table('seats')->where('id', $sitz->id)->update([ + 'nc_username' => $ref, + 'nc_state' => 'synced', + 'nc_synced_at' => now(), + ]); } }); } diff --git a/tests/Feature/Seats/SeatModelTest.php b/tests/Feature/Seats/SeatModelTest.php index 3b11074..1d6ba4b 100644 --- a/tests/Feature/Seats/SeatModelTest.php +++ b/tests/Feature/Seats/SeatModelTest.php @@ -15,6 +15,12 @@ it('bildet jede Rolle auf genau eine Nextcloud-Gruppe ab', function () { expect(Seat::GROUPS)->toHaveKey($rolle) ->and(Seat::GROUPS[$rolle])->not->toBe(''); } + + // Nicht nur "irgendein Wert" — die Namen selbst, denn sie wandern spaeter + // woertlich in `occ group:adduser`. Ein Vertipper darin faellt sonst + // erst auf einer echten Instanz auf, nicht hier. + expect(Seat::GROUPS['member'])->toBe('mitarbeiter') + ->and(Seat::GROUPS['readonly'])->toBe('nur-lesen'); }); it('fuehrt owner und admin in die Admin-Gruppe', function () {