Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BCrwHHnGCB5XH968Nxokqw
40 lines
1.2 KiB
PHP
40 lines
1.2 KiB
PHP
<?php
|
|
|
|
namespace App\Scheduling;
|
|
|
|
use App\Enums\AfterDue;
|
|
use App\Enums\EventState;
|
|
use App\Models\Event;
|
|
use App\Models\User;
|
|
use Carbon\CarbonImmutable;
|
|
|
|
/**
|
|
* Состояние, которое следует из дат события и «сейчас». Используется и кроном
|
|
* (переходы), и upsert-ом (пересчёт). Терминальные Done/Withdrawn ставятся
|
|
* только действиями, сюда не входят.
|
|
*/
|
|
final class StateResolver
|
|
{
|
|
public function __construct(private readonly DueResolver $due) {}
|
|
|
|
public function resolve(Event $event, User $user, CarbonImmutable $now): EventState
|
|
{
|
|
$due = $this->due->resolve($event, $user);
|
|
|
|
if ($now->gte($due->moment)) {
|
|
return $event->after_due === AfterDue::Keep ? EventState::Overdue : EventState::Expired;
|
|
}
|
|
|
|
if ($now->gte($this->due->todayStart($due, $user))) {
|
|
return EventState::Today;
|
|
}
|
|
|
|
$fireStart = $this->due->fireStart($event, $user);
|
|
if ($fireStart->lt($due->day) && $now->gte($fireStart)) {
|
|
return EventState::Preparing;
|
|
}
|
|
|
|
return EventState::Scheduled;
|
|
}
|
|
}
|