create(); $workspace = Workspace::factory()->create(); $workspace->users()->attach($user, ['role' => 'owner']); return [$user, $workspace]; } test('can store a client with a single contact', function () { [$user, $workspace] = createWorkspaceWithUser(); session(['current_workspace_id' => $workspace->id]); $response = $this->actingAs($user)->post(route('clients.store'), [ 'company_name' => 'Test SARL', 'legal_form' => 'sarl', 'contacts' => [ [ 'full_name' => 'Ahmed Bennani', 'job_title' => 'Gérant', 'email' => 'ahmed@test.com', 'phone' => '0612345678', 'is_principal' => true, ], ], ]); $response->assertRedirect(); $client = Client::query()->where('company_name', 'Test SARL')->first(); expect($client)->not->toBeNull(); expect($client->contacts)->toHaveCount(1); expect($client->contacts->first()->full_name)->toBe('Ahmed Bennani'); expect($client->contacts->first()->is_principal)->toBeTrue(); }); test('can store a client with multiple contacts', function () { [$user, $workspace] = createWorkspaceWithUser(); session(['current_workspace_id' => $workspace->id]); $response = $this->actingAs($user)->post(route('clients.store'), [ 'company_name' => 'Multi Contact SARL', 'legal_form' => 'sarl', 'contacts' => [ [ 'full_name' => 'Contact A', 'email' => 'a@test.com', 'is_principal' => false, ], [ 'full_name' => 'Contact B', 'email' => 'b@test.com', 'is_principal' => true, ], [ 'full_name' => 'Contact C', 'email' => 'c@test.com', 'is_principal' => false, ], ], ]); $response->assertRedirect(); $client = Client::query()->where('company_name', 'Multi Contact SARL')->first(); expect($client->contacts)->toHaveCount(3); $principal = $client->contacts->firstWhere('is_principal', true); expect($principal->full_name)->toBe('Contact B'); }); test('store validation fails with no contacts', function () { [$user, $workspace] = createWorkspaceWithUser(); session(['current_workspace_id' => $workspace->id]); $response = $this->actingAs($user)->post(route('clients.store'), [ 'company_name' => 'No Contact SARL', 'legal_form' => 'sarl', 'contacts' => [], ]); $response->assertSessionHasErrors('contacts'); }); test('store validation fails with no principal contact', function () { [$user, $workspace] = createWorkspaceWithUser(); session(['current_workspace_id' => $workspace->id]); $response = $this->actingAs($user)->post(route('clients.store'), [ 'company_name' => 'No Principal SARL', 'legal_form' => 'sarl', 'contacts' => [ ['full_name' => 'Test', 'email' => 't@t.com', 'is_principal' => false], ], ]); $response->assertSessionHasErrors('contacts'); }); test('store validation fails with multiple principal contacts', function () { [$user, $workspace] = createWorkspaceWithUser(); session(['current_workspace_id' => $workspace->id]); $response = $this->actingAs($user)->post(route('clients.store'), [ 'company_name' => 'Multi Principal SARL', 'legal_form' => 'sarl', 'contacts' => [ ['full_name' => 'A', 'email' => 'a@t.com', 'is_principal' => true], ['full_name' => 'B', 'email' => 'b@t.com', 'is_principal' => true], ], ]); $response->assertSessionHasErrors('contacts'); }); test('update can add and remove contacts', function () { [$user, $workspace] = createWorkspaceWithUser(); session(['current_workspace_id' => $workspace->id]); $client = Client::factory()->create(['workspace_id' => $workspace->id]); $existingContact = $client->contacts->first(); $response = $this->actingAs($user)->put(route('clients.update', $client), [ 'company_name' => $client->company_name, 'legal_form' => $client->legal_form->value, 'contacts' => [ [ 'full_name' => 'New Contact', 'email' => 'new@test.com', 'is_principal' => true, ], ], ]); $response->assertRedirect(); $client->refresh(); expect($client->contacts)->toHaveCount(1); expect($client->contacts->first()->full_name)->toBe('New Contact'); expect(ClientContact::find($existingContact->id))->toBeNull(); }); test('primary contact email accessor returns principal contact email', function () { $client = Client::factory()->create(); $principal = $client->contacts->firstWhere('is_principal', true); expect($client->primary_contact_email)->toBe($principal->email); });