Files
portal/app/app/Http/Requests/BulkProjectActionRequest.php
T
Дмитрий 54451d2ea6 feat(projects): RegionsBulkDialog — subject-level regions (89 RF subjects) #1426
Bulk regions dialog reworked from federal-district bitmask to subject/region
selection, consistent with ProjectDetailsDrawer/NewProjectDialog. Full-stack:
add_regions/remove_regions on projects.regions INT[], BulkProjectActionRequest
split validation, ProjectService model-instance update. federal-districts.ts
removed (zero consumers). +menuRepositionFix util for v-autocomplete menu.
phpstan-baseline: bump actingAs ignore count 14->15 (new validation test).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 03:41:46 +03:00

78 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class BulkProjectActionRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user() !== null;
}
public function rules(): array
{
$action = $this->input('action');
$rules = [
'action' => ['required', Rule::in([
'pause', 'resume', 'archive',
'update_regions', 'update_days', 'update_limit',
])],
'ids' => ['nullable', 'array', 'max:500'],
'ids.*' => ['integer', 'min:1'],
'scope' => ['nullable', 'array'],
'scope.filter' => ['nullable', 'array'],
'scope.filter.signal_type' => ['nullable', 'string', Rule::in(['site', 'call', 'sms'])],
'scope.filter.status' => ['nullable', 'string', Rule::in(['active', 'paused', 'archived'])],
'scope.filter.search' => ['nullable', 'string', 'max:255'],
];
if ($action === 'update_regions') {
// Plan 6.5: субъект-уровневые коды 1..89 (см. resources/js/constants/regions.ts).
$rules['add_regions'] = ['nullable', 'array'];
$rules['add_regions.*'] = ['integer', 'between:1,89'];
$rules['remove_regions'] = ['nullable', 'array'];
$rules['remove_regions.*'] = ['integer', 'between:1,89'];
}
if ($action === 'update_days') {
$rules['add'] = ['nullable', 'integer', 'min:0', 'max:127'];
$rules['remove'] = ['nullable', 'integer', 'min:0', 'max:127'];
}
if ($action === 'update_limit') {
$rules['delta'] = ['nullable', 'integer'];
$rules['replace'] = ['nullable', 'integer', 'min:0'];
}
return $rules;
}
public function withValidator($validator): void
{
$validator->after(function ($v) {
$hasIds = ! empty($this->input('ids'));
$hasScope = $this->has('scope.filter') && is_array($this->input('scope.filter'));
if (! $hasIds && ! $hasScope) {
$v->errors()->add('ids', 'Either ids or scope.filter is required.');
}
if ($this->input('action') === 'update_limit') {
$hasDelta = $this->has('delta');
$hasReplace = $this->has('replace');
if ($hasDelta && $hasReplace) {
$v->errors()->add('delta', 'Cannot use both delta and replace.');
}
if (! $hasDelta && ! $hasReplace) {
$v->errors()->add('delta', 'Either delta or replace is required for update_limit.');
}
}
});
}
}