瀏覽代碼

feat(unit): add active students ranges for dashboard color configuration

alvesantos 1 周之前
父節點
當前提交
24e360b866

+ 6 - 0
app/Http/Controllers/FranchiseeDashboardController.php

@@ -18,9 +18,15 @@ public function summary(): JsonResponse
 
         $students = Student::where('unit_id', $unitId)->get(['id', 'name', 'birth_date', 'created_at']);
         $contracts = StudentContract::latestVersion()->where('unit_id', $unitId)->get(['id', 'status']);
+        $unit = \App\Models\Unit::find($unitId);
 
         return $this->successResponse(payload: [
             'students_count' => $students->count(),
+            'unit_config' => [
+                'active_students_min' => $unit->active_students_min ?? 30,
+                'active_students_medium' => $unit->active_students_medium ?? 50,
+                'active_students_max' => $unit->active_students_max ?? 80,
+            ],
             'contracts' => [
                 'active' => $contracts->where('status', 'active')->count(),
                 'frozen' => $contracts->where('status', 'frozen')->count(),

+ 7 - 1
app/Http/Controllers/UnitController.php

@@ -69,7 +69,13 @@ public function updateMe(UnitRequest $request): JsonResponse
             return $this->errorResponse(message: 'Unidade não encontrada', code: 404);
         }
 
-        $item = $this->service->update($unitId, $request->safe()->only(['avatar', 'automatic_protocol']));
+        $item = $this->service->update($unitId, $request->safe()->only([
+            'avatar',
+            'automatic_protocol',
+            'active_students_min',
+            'active_students_medium',
+            'active_students_max'
+        ]));
 
         return $this->successResponse(payload: new UnitResource($item), message: __('messages.updated'));
     }

+ 8 - 5
app/Http/Requests/UnitRequest.php

@@ -28,11 +28,14 @@ public function rules(): array
             'state_id'           => 'sometimes|required|integer|exists:states,id',
             'email'              => 'sometimes|required|email|max:255',
             'secondary_email'    => 'sometimes|nullable|email|max:255',
-            'phone_number'       => 'sometimes|nullable|string|max:20',
-            'cell_number'        => 'sometimes|required|string|max:20',
-            'automatic_protocol' => 'sometimes|boolean',
-            'avatar'             => 'sometimes|nullable|image|max:20480',
-            'contracts'          => 'sometimes|nullable|array',
+            'phone_number'           => 'sometimes|nullable|string|max:20',
+            'cell_number'            => 'sometimes|required|string|max:20',
+            'automatic_protocol'     => 'sometimes|boolean',
+            'active_students_min'    => 'sometimes|integer|min:0',
+            'active_students_medium' => 'sometimes|integer|min:0',
+            'active_students_max'    => 'sometimes|integer|min:0',
+            'avatar'                 => 'sometimes|nullable|image|max:20480',
+            'contracts'              => 'sometimes|nullable|array',
             'contracts.*'        => 'file|mimes:pdf|max:20480',
 
             'partners'                   => 'sometimes|nullable|array',

+ 4 - 0
app/Http/Resources/UnitResource.php

@@ -39,6 +39,10 @@ public function toArray(Request $request): array
             'cell_number'        => $this->cell_number,
             'automatic_protocol' => (bool) ($this->automatic_protocol ?? true),
 
+            'active_students_min'    => (int) ($this->active_students_min ?? 30),
+            'active_students_medium' => (int) ($this->active_students_medium ?? 50),
+            'active_students_max'    => (int) ($this->active_students_max ?? 80),
+
             'avatar_url' => $this->avatar_url
                 ? Storage::temporaryUrl($this->avatar_url, now()->addHours(24))
                 : null,

+ 8 - 5
app/Models/Unit.php

@@ -84,11 +84,14 @@ class Unit extends Model
     protected $guarded = ['id'];
 
     protected $casts = [
-        'automatic_protocol' => 'boolean',
-        'cnpj'               => Cnpj::class,
-        'created_at'         => 'datetime',
-        'updated_at'         => 'datetime',
-        'deleted_at'         => 'datetime',
+        'automatic_protocol'     => 'boolean',
+        'active_students_min'    => 'integer',
+        'active_students_medium' => 'integer',
+        'active_students_max'    => 'integer',
+        'cnpj'                   => Cnpj::class,
+        'created_at'             => 'datetime',
+        'updated_at'             => 'datetime',
+        'deleted_at'             => 'datetime',
     ];
 
     public function city(): BelongsTo

+ 34 - 0
database/migrations/2026_08_31_120928_add_active_student_ranges_to_units_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::table('units', function (Blueprint $table) {
+            $table->integer('active_students_min')->default(30)->after('automatic_protocol');
+            $table->integer('active_students_medium')->default(50)->after('active_students_min');
+            $table->integer('active_students_max')->default(80)->after('active_students_medium');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('units', function (Blueprint $table) {
+            $table->dropColumn([
+                'active_students_min',
+                'active_students_medium',
+                'active_students_max'
+            ]);
+        });
+    }
+};

+ 58 - 0
tests/Unit/UnitSettingsTest.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace Tests\Unit;
+
+use App\Http\Requests\UnitRequest;
+use App\Http\Resources\UnitResource;
+use App\Models\Unit;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Validator;
+use Tests\TestCase;
+
+class UnitSettingsTest extends TestCase
+{
+    public function test_unit_request_validates_active_students_ranges(): void
+    {
+        $rules = (new UnitRequest)->rules();
+
+        $validValidator = Validator::make([
+            'active_students_min' => 10,
+            'active_students_medium' => 40,
+            'active_students_max' => 90,
+        ], $rules);
+        
+        $this->assertFalse($validValidator->errors()->has('active_students_min'));
+        $this->assertFalse($validValidator->errors()->has('active_students_medium'));
+        $this->assertFalse($validValidator->errors()->has('active_students_max'));
+
+        $invalidValidator = Validator::make([
+            'active_students_min' => -5, // Below 0
+            'active_students_medium' => 'string', // Not an integer
+        ], $rules);
+        
+        $this->assertTrue($invalidValidator->errors()->has('active_students_min'));
+        $this->assertTrue($invalidValidator->errors()->has('active_students_medium'));
+    }
+
+    public function test_unit_resource_includes_active_students_ranges(): void
+    {
+        $unit = current(array_filter([new class extends Unit {
+            public $active_students_min = 25;
+            public $active_students_medium = 55;
+            public $active_students_max = 85;
+            public $name = 'Teste';
+            public $social_reason = 'Teste';
+        }]));
+
+        $resource = new UnitResource($unit);
+        $array = $resource->toArray(Request::create('/'));
+
+        $this->assertArrayHasKey('active_students_min', $array);
+        $this->assertArrayHasKey('active_students_medium', $array);
+        $this->assertArrayHasKey('active_students_max', $array);
+
+        $this->assertSame(25, $array['active_students_min']);
+        $this->assertSame(55, $array['active_students_medium']);
+        $this->assertSame(85, $array['active_students_max']);
+    }
+}