StageActiveOnEvent — checks the candidate stage_id is linked to the given event_id via stage_days. Covers performance create/update (perf.event_id ↔ stage) and the timetable move endpoint (target_stage_id ↔ resolved target event). WithinEventBounds — checks a candidate datetime is inside the event's [start_at, end_at] window. Used for performance start/end dates and move-target dates against the relevant sub-event for festivals. OptionExpiresInFuture — conditional rule fired only when booking_status === 'option'. Asserts option_expires_at is set and in the future. Implementation of RFC §10.1 transition gate at the request layer (the service layer enforces the same invariant). ContractRequiresFee — conditional rule fired only when booking_status === 'contracted'. Asserts fee_amount is set and > 0. Same dual-layer enforcement as OptionExpiresInFuture. All four pass silently when the validated field is null or the context is irrelevant — the FormRequest still owns the surrounding required/nullable/exists rules. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
43 lines
1.1 KiB
PHP
43 lines
1.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Rules\Artist;
|
|
|
|
use App\Enums\Artist\ArtistEngagementStatus;
|
|
use Carbon\CarbonImmutable;
|
|
use Closure;
|
|
use Illuminate\Contracts\Validation\ValidationRule;
|
|
|
|
/**
|
|
* Conditional rule: when `booking_status === 'option'`, the
|
|
* `option_expires_at` field must be set and in the future.
|
|
*
|
|
* Bound from the engagement FormRequest, taking the inbound
|
|
* booking_status value at construction time.
|
|
*/
|
|
final class OptionExpiresInFuture implements ValidationRule
|
|
{
|
|
public function __construct(
|
|
private readonly ?string $bookingStatus,
|
|
) {}
|
|
|
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
|
{
|
|
if ($this->bookingStatus !== ArtistEngagementStatus::Option->value) {
|
|
return;
|
|
}
|
|
|
|
if ($value === null || $value === '') {
|
|
$fail('Bij status "Optie" is een vervaldatum verplicht.');
|
|
|
|
return;
|
|
}
|
|
|
|
$candidate = CarbonImmutable::parse((string) $value);
|
|
if ($candidate->isPast()) {
|
|
$fail('De optie-vervaldatum moet in de toekomst liggen.');
|
|
}
|
|
}
|
|
}
|