`artist:demote-expired-options` artisan command finds every ArtistEngagement still in Option whose option_expires_at has passed, transitions it back to Draft via the existing state-machine (transitionStatus), and writes an `option_expired` activity entry with the original expiry timestamp captured in properties so the audit log distinguishes system-driven expiries from manual demotions. Idempotency: the state-machine bails when the engagement is no longer in Option, so a second run within the same minute is a no-op for any given row. The auto-logged `updated` row + the explicit `status_changed` + the `option_expired` entries are emitted only by the run that actually performs the transition. Scheduled in routes/console.php daily at 03:00 Europe/Amsterdam, matching the existing nightly low-traffic window. Notification (email project leader on demotion) is deferred to the notification framework that lands post-Accreditation; tracked under BACKLOG entry ART-DEMOTE-NOTIFICATION. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
26 lines
876 B
PHP
26 lines
876 B
PHP
<?php
|
|
|
|
use Illuminate\Foundation\Inspiring;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\Schedule;
|
|
|
|
Artisan::command('inspire', function () {
|
|
$this->comment(Inspiring::quote());
|
|
})->purpose('Display an inspiring quote');
|
|
|
|
Schedule::command('invitations:expire')->daily();
|
|
|
|
// RFC-TIMETABLE v0.2 — demote engagements whose option_expires_at has
|
|
// passed back to Draft. Daily at 03:00 Europe/Amsterdam (matches the
|
|
// scheduler's nightly window for low-traffic state changes).
|
|
Schedule::command('artist:demote-expired-options')
|
|
->dailyAt('03:00')
|
|
->timezone('Europe/Amsterdam');
|
|
|
|
// Telescope retention — dev-only (mirrors AppServiceProvider's
|
|
// environment gate). 48h is enough for debugging without filling the
|
|
// dev database.
|
|
Schedule::command('telescope:prune --hours=48')
|
|
->daily()
|
|
->environments(['local', 'testing']);
|