Request-Domain > Fallback. */ function portalResolutionApiUser(Portal $portal = Portal::Businessportal24): User { test()->seed(RolesAndPermissionsSeeder::class); config()->set('billing.enforce_booking', false); $user = User::factory()->create([ 'is_active' => true, 'portal' => $portal, ]); $user->forceFill(['registration_type' => 'apiuser'])->save(); Sanctum::actingAs($user, [ 'press-releases:read', 'press-releases:write', 'companies:read', ]); return $user; } function legacyPressReleasePayload(Company $company, Category $category, array $overrides = []): array { return [ 'press_release' => array_merge([ 'company_id' => $company->id, 'category_id' => $category->legacy_id ?? $category->id, 'language' => 'de', 'title' => 'Portal-Auflösung Test-PM', 'text' => 'Inhalt der Test-Pressemitteilung.', ], $overrides), ]; } test('legacy company creation uses the request domain portal over the user portal', function () { /** @var TestCase $this */ portalResolutionApiUser(Portal::Businessportal24); config()->set('app.theme', 'presseecho'); $this->postJson('/service/users/me/companies', [ 'company' => ['name' => 'Domain GmbH'], ])->assertCreated(); $company = Company::withoutGlobalScopes()->where('name', 'Domain GmbH')->firstOrFail(); expect($company->portal)->toBe(Portal::Presseecho); }); test('legacy company creation falls back to the user portal without domain context', function () { /** @var TestCase $this */ portalResolutionApiUser(Portal::Businessportal24); config()->set('app.theme', 'portal'); $this->postJson('/service/users/me/companies', [ 'company' => ['name' => 'Fallback GmbH'], ])->assertCreated(); $company = Company::withoutGlobalScopes()->where('name', 'Fallback GmbH')->firstOrFail(); expect($company->portal)->toBe(Portal::Businessportal24); }); test('legacy company creation accepts an explicit portal parameter over the domain', function () { /** @var TestCase $this */ portalResolutionApiUser(Portal::Businessportal24); config()->set('app.theme', 'businessportal24'); $this->postJson('/service/users/me/companies', [ 'company' => ['name' => 'Parameter GmbH', 'portal' => 'presseecho'], ])->assertCreated(); $company = Company::withoutGlobalScopes()->where('name', 'Parameter GmbH')->firstOrFail(); expect($company->portal)->toBe(Portal::Presseecho); }); test('legacy press release creation uses the request domain portal over the company portal', function () { /** @var TestCase $this */ Queue::fake(); $user = portalResolutionApiUser(Portal::Businessportal24); $company = Company::factory()->businessportal24()->create(['owner_user_id' => $user->id]); $user->companies()->attach($company->id, ['role' => 'owner']); $category = Category::factory()->create(['legacy_id' => 4711]); config()->set('app.theme', 'presseecho'); $this->postJson('/service/pressreleases', legacyPressReleasePayload($company, $category)) ->assertCreated(); $pressRelease = PressRelease::withoutGlobalScopes()->latest('id')->firstOrFail(); expect($pressRelease->portal)->toBe(Portal::Presseecho) ->and($pressRelease->slug)->toBe('portal-auflosung-test-pm'); }); test('legacy press release creation accepts an explicit portal parameter over the domain', function () { /** @var TestCase $this */ Queue::fake(); $user = portalResolutionApiUser(Portal::Businessportal24); $company = Company::factory()->businessportal24()->create(['owner_user_id' => $user->id]); $user->companies()->attach($company->id, ['role' => 'owner']); $category = Category::factory()->create(['legacy_id' => 4712]); config()->set('app.theme', 'businessportal24'); $this->postJson( '/service/pressreleases', legacyPressReleasePayload($company, $category, ['portal' => 'presseecho']), )->assertCreated(); $pressRelease = PressRelease::withoutGlobalScopes()->latest('id')->firstOrFail(); expect($pressRelease->portal)->toBe(Portal::Presseecho); }); test('legacy press release creation falls back to the company portal without domain context', function () { /** @var TestCase $this */ Queue::fake(); $user = portalResolutionApiUser(Portal::Businessportal24); $company = Company::factory()->businessportal24()->create(['owner_user_id' => $user->id]); $user->companies()->attach($company->id, ['role' => 'owner']); $category = Category::factory()->create(['legacy_id' => 4713]); config()->set('app.theme', 'portal'); $this->postJson('/service/pressreleases', legacyPressReleasePayload($company, $category)) ->assertCreated(); $pressRelease = PressRelease::withoutGlobalScopes()->latest('id')->firstOrFail(); expect($pressRelease->portal)->toBe(Portal::Businessportal24); }); test('v1 press release creation resolves the portal from parameter and domain', function () { /** @var TestCase $this */ $user = User::factory()->create(); $company = Company::factory()->businessportal24()->create(); $category = Category::factory()->withTranslations()->create(); $user->companies()->attach($company->id, ['role' => 'owner']); Sanctum::actingAs($user, ['press-releases:read', 'press-releases:write']); config()->set('app.theme', 'presseecho'); $this->postJson('/api/v1/press-releases', [ 'company_id' => $company->id, 'category_id' => $category->id, 'language' => 'de', 'title' => 'Domain bestimmt das Portal', 'text' => 'Inhalt', ])->assertCreated()->assertJsonPath('data.portal', 'presseecho'); $this->postJson('/api/v1/press-releases', [ 'portal' => 'businessportal24', 'company_id' => $company->id, 'category_id' => $category->id, 'language' => 'de', 'title' => 'Parameter schlägt Domain', 'text' => 'Inhalt', ])->assertCreated()->assertJsonPath('data.portal', 'businessportal24'); }); test('v1 press release creation rejects the portal value both', function () { /** @var TestCase $this */ $user = User::factory()->create(); $company = Company::factory()->businessportal24()->create(); $category = Category::factory()->withTranslations()->create(); $user->companies()->attach($company->id, ['role' => 'owner']); Sanctum::actingAs($user, ['press-releases:read', 'press-releases:write']); $this->postJson('/api/v1/press-releases', [ 'portal' => 'both', 'company_id' => $company->id, 'category_id' => $category->id, 'language' => 'de', 'title' => 'Beide Portale sind nicht erlaubt', 'text' => 'Inhalt', ])->assertUnprocessable()->assertJsonValidationErrors(['portal']); }); test('v1 update keeps the portal unless an explicit portal parameter is sent', function () { /** @var TestCase $this */ $user = User::factory()->create(); $company = Company::factory()->businessportal24()->create(); $user->companies()->attach($company->id, ['role' => 'owner']); $pressRelease = PressRelease::factory() ->forPortal(Portal::Businessportal24) ->create(['user_id' => $user->id, 'company_id' => $company->id]); Sanctum::actingAs($user, ['press-releases:read', 'press-releases:write']); // Update über die "falsche" Domain verschiebt die PM nicht … config()->set('app.theme', 'presseecho'); $this->patchJson("/api/v1/press-releases/{$pressRelease->id}", [ 'title' => 'Titel bleibt im Portal', ])->assertOk()->assertJsonPath('data.portal', 'businessportal24'); // … ein expliziter Parameter schon. $this->patchJson("/api/v1/press-releases/{$pressRelease->id}", [ 'portal' => 'presseecho', ])->assertOk()->assertJsonPath('data.portal', 'presseecho'); });