api: neue Firmen dem bestehenden Newsroom zuordnen (Roadmap 1a.4)

connektar legt je Meldung eine Firma an. ApiNewsroomAssignment prüft vor
dem Anlegen, ob unter derselben Firmen-E-Mail schon dieselbe Firma steht
(Namensregel der Klassifizierung), und gibt dann deren ID zurück — der
Alt-Vertrag (201 + Location) bleibt. Nie-veröffentlicht-Adressen werden nie
zugeordnet, abweichende Namen bekommen wie bisher eine neue Firma. Liegt
die Firma auf dem anderen Portal, wird sie both; bei fremd belegtem Slug
bleibt es beim alten Verhalten.

LegacyPressReleaseController: both ist kein Ziel-Portal für eine Meldung —
dann entscheidet das Portal des API-Nutzers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-15 10:26:13 +00:00
parent 4303266841
commit 8dad652d67
8 changed files with 367 additions and 34 deletions

View file

@ -161,6 +161,31 @@ class Company extends Model
return $this->gone_at !== null;
}
/**
* Trägt eine fremde, lebende Firma auf einem ANDEREN Portal diesen Slug?
* Dann darf diese Firma nicht `both` werden: Die öffentliche Auflösung
* fragt `portal IN (eigenes, both)` und fände zwei Firmen.
*
* Die anderen Portale werden ausdrücklich aufgezählt statt `portal != ?`
* — nur so greift der Unique-Index (portal, slug).
*
* @param list<int> $exceptIds Firmen, die nicht zählen (z. B. die eigene Adressgruppe)
*/
public function slugTakenOnOtherPortals(array $exceptIds = []): bool
{
$otherPortals = array_values(array_diff(
array_map(fn (Portal $portal): string => $portal->value, Portal::cases()),
[$this->portal->value],
));
return static::query()
->withoutGlobalScope(PortalScope::class)
->whereIn('portal', $otherPortals)
->where('slug', $this->slug)
->whereKeyNot([$this->getKey(), ...$exceptIds])
->exists();
}
/**
* Normalisierte Firmen-E-Mail — der Schlüssel der Newsroom-Konsolidierung.
*