Add-on-Panel zeigt freie Boost-Plaetze je Stufe

slotAvailability() liefert zusaetzlich free/limit (knappste Ausgabe, ohne
den eigenen gehaltenen Slot); solange buchbar, steht unter den Kauf-Buttons
"Noch X von Y Plaetzen frei." — bei laufendem Boost weiterhin nur der
Verlaengerungs-Hinweis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-13 13:12:05 +00:00
parent 842d6a2bd0
commit 0cddf5fbdc
5 changed files with 65 additions and 12 deletions

View file

@ -71,18 +71,17 @@ class BoostService
* Slot-Verfügbarkeit der Stufe für diese PM. Eine Verlängerung ist immer
* verfügbar (die PM hält ihren Slot); sonst muss auf jeder Ausgabe, auf
* der die PM erscheint (Portal × Sprache, Kategorie-Boost zusätzlich je
* Rubrik), ein Slot frei sein. `freeAt` nennt bei „ausgebucht" den
* frühesten Zeitpunkt, zu dem wieder ein Platz frei wird.
* Rubrik), ein Slot frei sein. `free` zählt die noch freien Plätze
* (knappste Ausgabe, ohne einen eigenen gehaltenen Slot); `freeAt` nennt
* bei „ausgebucht" den frühesten Zeitpunkt, zu dem ein Platz frei wird.
*
* @return array{available: bool, freeAt: Carbon|null}
* @return array{available: bool, free: int, limit: int, freeAt: Carbon|null}
*/
public function slotAvailability(PressRelease $pressRelease, BoostPlacement $placement): array
{
if ($this->isBoosted($pressRelease, $placement)) {
return ['available' => true, 'freeAt' => null];
}
$limit = $this->slotLimit($placement);
$holdsSlot = $this->isBoosted($pressRelease, $placement);
$free = $limit;
$freeAt = null;
foreach ($this->affectedPortals($pressRelease) as $portal) {
@ -106,7 +105,9 @@ class BoostService
->selectRaw('press_release_id, MAX(ends_at) AS held_until')
->pluck('held_until');
if ($heldUntil->count() < $limit) {
$free = min($free, max(0, $limit - $heldUntil->count()));
if ($holdsSlot || $heldUntil->count() < $limit) {
continue;
}
@ -117,7 +118,12 @@ class BoostService
$freeAt = $freeAt === null ? $portalFreeAt : $freeAt->max($portalFreeAt);
}
return ['available' => $freeAt === null, 'freeAt' => $freeAt];
return [
'available' => $holdsSlot || $free > 0,
'free' => $free,
'limit' => $limit,
'freeAt' => $freeAt,
];
}
public function slotLimit(BoostPlacement $placement): int