diff --git a/app/Models/User.php b/app/Models/User.php index 61d18b42..ddfa8dcb 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -482,4 +482,23 @@ class User extends Authenticatable implements MustVerifyEmail return in_array($companyId, $this->accessibleCompanyIds(), true); } + + /** + * Synchronisiert die Firmenzuordnungen samt Pivot-Rolle. Fehlt zu einer + * Firma eine Rolle, greift 'member'. Gemeinsamer Persistenz-Kern des + * Anlegen- und Bearbeiten-Formulars (admin/users). + * + * @param list $companyIds + * @param array $roles companyId => role + */ + public function syncCompaniesWithRoles(array $companyIds, array $roles): void + { + $payload = []; + + foreach ($companyIds as $companyId) { + $payload[$companyId] = ['role' => $roles[$companyId] ?? 'member']; + } + + $this->companies()->sync($payload); + } } diff --git a/resources/views/livewire/admin/users/create.blade.php b/resources/views/livewire/admin/users/create.blade.php index db221baf..eb02d490 100644 --- a/resources/views/livewire/admin/users/create.blade.php +++ b/resources/views/livewire/admin/users/create.blade.php @@ -127,13 +127,7 @@ new #[Layout('components.layouts.app'), Title('Benutzer anlegen')] class extends $user->syncRoles($validated['selectedRoles']); - $companySyncPayload = []; - foreach ($validated['linkedCompanyIds'] as $companyId) { - $companySyncPayload[$companyId] = [ - 'role' => $validated['companyRoles'][$companyId] ?? 'member', - ]; - } - $user->companies()->sync($companySyncPayload); + $user->syncCompaniesWithRoles($validated['linkedCompanyIds'], $validated['companyRoles']); if ($this->billingIsComplete()) { $user->billingAddress()->create([ diff --git a/resources/views/livewire/admin/users/edit.blade.php b/resources/views/livewire/admin/users/edit.blade.php index 15334c89..1c602efb 100644 --- a/resources/views/livewire/admin/users/edit.blade.php +++ b/resources/views/livewire/admin/users/edit.blade.php @@ -447,15 +447,9 @@ new #[Layout('components.layouts.app'), Title('Benutzer bearbeiten')] class exte $user->profile()->delete(); } - $companySyncPayload = []; - foreach ($validated['linkedCompanyIds'] as $companyId) { - $companySyncPayload[$companyId] = [ - 'role' => $validated['companyRoles'][$companyId] ?? 'member', - ]; - } - $user->companies()->sync($companySyncPayload); + $user->syncCompaniesWithRoles($validated['linkedCompanyIds'], $validated['companyRoles']); - $linkedCompanyIds = array_keys($companySyncPayload); + $linkedCompanyIds = $validated['linkedCompanyIds']; $contactIds = collect($validated['contactForms']) ->pluck('id') diff --git a/tests/Feature/UserSyncCompaniesTest.php b/tests/Feature/UserSyncCompaniesTest.php new file mode 100644 index 00000000..661d6b72 --- /dev/null +++ b/tests/Feature/UserSyncCompaniesTest.php @@ -0,0 +1,35 @@ +create(); + $a = Company::factory()->create(); + $b = Company::factory()->create(); + + $user->syncCompaniesWithRoles([$a->id, $b->id], [$a->id => 'owner', $b->id => 'responsible']); + + expect($user->companies()->pluck('role', 'companies.id')->all()) + ->toBe([$a->id => 'owner', $b->id => 'responsible']); +}); + +test('syncCompaniesWithRoles defaults missing roles to member', function () { + $user = User::factory()->create(); + $company = Company::factory()->create(); + + $user->syncCompaniesWithRoles([$company->id], []); + + expect($user->companies()->first()->pivot->role)->toBe('member'); +}); + +test('syncCompaniesWithRoles detaches companies no longer listed', function () { + $user = User::factory()->create(); + $a = Company::factory()->create(); + $b = Company::factory()->create(); + $user->syncCompaniesWithRoles([$a->id, $b->id], []); + + $user->syncCompaniesWithRoles([$b->id], [$b->id => 'owner']); + + expect($user->companies()->pluck('companies.id')->all())->toBe([$b->id]); +});