Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.15% covered (success)
96.15%
25 / 26
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateCompanyScorecardRequest
96.15% covered (success)
96.15%
25 / 26
50.00% covered (danger)
50.00%
1 / 2
6
0.00% covered (danger)
0.00%
0 / 1
 authorize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rules
96.00% covered (success)
96.00%
24 / 25
0.00% covered (danger)
0.00%
0 / 1
5
1<?php
2
3namespace App\Http\Requests\v2\Company;
4
5use Illuminate\Foundation\Http\FormRequest;
6
7/**
8 * Request for creating or updating a company-level scorecard configuration for a specific call type.
9 *
10 * Validates the full scorecard structure including sections and criteria.
11 * Enforces that section weights sum to 100 and each section's criteria weights sum to 100.
12 * Optionally accepts `is_forced` to lock the scorecard so users cannot override it.
13 *
14 * @property array<array{name: string, is_default: bool, weight: int, criteria: array<array{name: string, weight: int, description: string}>}> $scorecard
15 *     Array of scorecard section objects. Each section defines a scoring category
16 *     with weighted criteria. Section weights must total 100, and within each section,
17 *     criteria weights must also total 100.
18 * @property bool $is_forced Whether users in the company are prevented from overriding this scorecard (default: false)
19 */
20class UpdateCompanyScorecardRequest extends FormRequest
21{
22    /**
23     * Determine if the user is authorized to make this request.
24     *
25     * @return bool
26     */
27    public function authorize(): bool
28    {
29        return true;
30    }
31
32    /**
33     * Get the validation rules that apply to the request.
34     *
35     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
36     */
37    public function rules(): array
38    {
39        return [
40            'scorecard' => ['required', 'array', 'min:1', function ($attribute, $value, $fail) {
41                // Validate section name uniqueness
42                $names = array_column($value, 'name');
43                if (count($names) !== count(array_unique($names))) {
44                    $fail('Each section name within the scorecard must be unique.');
45                }
46
47                // Validate section weights sum to 100
48                $totalWeight = array_sum(array_column($value, 'weight'));
49                if ($totalWeight !== 100) {
50                    $fail('The total weight of all scorecard sections must equal 100.');
51                }
52            }],
53            'scorecard.*.name'        => 'required|string',
54            'scorecard.*.is_default'  => 'required|boolean',
55            'scorecard.*.weight'      => 'required|integer|min:0|max:100',
56            'scorecard.*.criteria'    => ['required', 'array', 'min:1', function ($attribute, $value, $fail) {
57                // Validate criteria name uniqueness within each section
58                $criteriaNames = array_column($value, 'name');
59                if (count($criteriaNames) !== count(array_unique($criteriaNames))) {
60                    $fail('Each criterion name within a scorecard section must be unique.');
61                }
62
63                // Validate criteria weights sum to 100
64                $totalWeight = array_sum(array_column($value, 'weight'));
65                if ($totalWeight !== 100) {
66                    $fail('The total weight of all criteria within a scorecard section must equal 100.');
67                }
68            }],
69            'scorecard.*.criteria.*.name'        => 'required|string',
70            'scorecard.*.criteria.*.weight'      => 'required|integer|min:0|max:100',
71            'scorecard.*.criteria.*.description' => 'required|string',
72            'is_forced'                          => 'sometimes|boolean',
73        ];
74    }
75}